Repeating characters in VIM insert mode - vim

Is there a way of repeating a character while in Vim's insert mode? For example, say I would like to insert 80 dashes, in something like emacs I would type:
Ctrl+U 8 0 -
The only way I know how to do it in VIM is to exit normal mode for the repeat argument, then go back into insert mode to type the dash, then exit to insert the actual dashes, AND then go back into insert mode to carry on typing. The sequence is a really long:
Esc 8 0 a - Esc a
It would be nice not to switch in and out of modes.

If you are OK with leaving INSERT mode only once (at the end), this sequence works:
Ctrl+o 80i- Esc
Ctrl+o is used to issue normal commands without leaving INSERT mode,
80 the repetition,
i to insert,
- the character you want to insert,
Esc to leave INSERT mode.
Another one without EVER leaving INSERT mode:
Ctrl+o :norm 8ia Return

Esc nic Esc .
E.g. Esc 4iJ Esc will output JJJJ.

Through single repeat:
Press: i to enter into Insert mode
Press: -
Press: Esc
Press: 80.
It will output: 81 -, like this:
---------------------------------------------------------------------------------
More details about single repeat: :help .

Slightly different version of Eelvex's solution:
function! Repeat()
let times = input("Count: ")
let char = input("Char: ")
exe ":normal a" . repeat(char, times)
endfunction
imap <C-u> <C-o>:call Repeat()<cr>

<ESC>
<the number of times you want to repeat>
i
<the char you want to repeat>
<ESC>
for example: <ESC>12ia<ESC> will insert 12 a's.

You can also do,
Escnihello there EscEsc
where,
n is the number of repeats.
e.g.,
Esc5ihello there EscEsc

I'm surprised no one has suggested this yet:
In Insert mode, use <C-r>=repeat('-', 80)<CR>
That is:
Press Ctrl-r=
At the resulting prompt, enter repeat('-', 80)
Press Enter
Works for repeating any character any number of times.
This uses more keystrokes than #romainl's answer, but does not leave Insert mode at all.

There are many other ways but AFAIK the one you describe is the shortest one. In vim you are mostly supposed to spend your time in command mode, so that would be just 3 keystrokes + the number of repeats (80i-).
However, if you find that you very often use this repeat thing, you can make yourself a function or macro to that end; maybe something like:
:function Repeat(char)
: let counter = input("How many times?: ")
: call feedkeys("i")
: call feedkeys(repeat(a:char,counter))
:endfunction
:imap <C-U> <ESC>h"ryl :call Repeat(#r)<CR>

You said it would be 'nice' to stay in 'Insert' mode, however in Command Mode the following method would avoid your 2nd ESC :-
While I know this post is old, it seems a shame to miss the obvious 'Cut/Copy and Paste' option...
x ...cut
80 ...number of copies
p Paste
Note : This is similar to the method suggested by Martin Beckett, however I get a delay when issuing that command, perhaps because it switches modes several times, this command executes instantly.

Late answer but for what it's worth, if you wanna hand spam it, you can use the
"repeat last command" command: .
i "Phrase" Esc - i to insert, enter phrase/character, esc to go normal mode
. - Spam till you are satisfied. Will repeatedly input the phrase you typed (it repeats your last command).
I find this especially useful when I don't know exactly how many repeats I want to do, but know visually how long I want it to be. Basically blast the . till my eyes are content.

In addition to writing function that will repeat text multiple times, you could use <C-x><C-l>: if you already have line that contains 80 dashes, writing a few dashes at the start of new line and then pressing <C-x><C-l> will complete lines which start with these few dashes which will be likely that line with 80 dashes. I used to write horizontal lines (78 dashes) in help files in a such way.

For such an easy task abbreviation should do the trick. Add the following to your .vimrc
iab <expr> -- repeat('-', 80)
and from now, when you type -- followed by a space (while you are in insert mode), the -- will be automatically converted to - 80 times.
By using the function repeat you are able to repeat the string as many time you want.
Note that you can test it before updating the .vimrc by entering in command mode then issuing the following :iab <expr> -- repeat('-', 80)

I did this without exiting the INSERT mode using the below steps.
Enable INSERT mode.
Type one dash "-".
Ctrl + O
lowercase 'v' (to enter -- (insert) VISUAL -- mode)
lowercase 'y' (to copy)
Ctrl + O
Type 80
Then, followed by lowercase 'p' (for paste).
i - Ctrl+o v y Ctrl+o 80 p
This will print all the dashes horizontally in a single line.

Related

How to switch modes when operating on multiple selected lines

I have created a line selection in Vim by Shift+V and followed by jjjj.
I can do something against all lines separately like :normal ^i//, which moves the cursor to the beginning of each line and enter insert mode, then insert two /.
Is it possible to switch back to normal mode after this?
The example in the question is just to demonstrate the problem and I only want to discuss the Vim usage skills.
I tried :normal ^i//<Esc>A// in the hope of adding two / to the end of each line, but it didn't work.
Is this possible?
The :normal command does not interpret special characters. In your last try, all the chars after i would be interpreted as normal text then inserted at the beginning of each selected line: //<Esc>A//.
The Esc character is a special char (actually the ASCII code 27), so you have to ask Vim to insert this char in a different way (because hitting Esc would escape the command line).
In order to do this (either in Command mode or Insert mode), press Ctrl + V then the wanted key, e.g. Esc. This will insert the real <esc> character in you flow, then perform the desired behaviour.
To summarize:
Press Shift + V followed by jjjj...
Type :normal ^i//Ctrl + VEscA//
Hit Return to validate the command

why vnoremap a A takes seconds to complete?

i have this in my config file:
nnoremap a a
vnoremap a A
and pressing a in visual mode takes 2 seconds to do the action
why is this happening? is this a bad practice?
This problem is being caused by the fact that you have something else mapped (either in visual mode or in all modes) that starts with 'a'.
Imagine I map 2 different commands in my .vimrc (or as you called it, config file)
vnoremap a A
vnoremap ab D
Here, when I press 'a' in visual mode, I want it to append text.
When I press 'ab' I want it to delete a row for me instead.
I now reach over to my keyboard and I press 'ab'. How does vim know I wanted to delete a line and not just append the letter 'b' to the text? Both require the same keypresses.
So to tell the difference, when I hit the 'a' key, vim waits a second to see which command I choose, If I press 'b' quickly it will realize that this is actually the instruction 'ab' which means 'D' which means delete.
If I press 'a' and wait a second, vim will accept that I was issuing the instruction 'a' which means 'A' which means append. I then hit 'b' and the letter 'b' is appended to the text.
If you want it to stop, you will have to go through your .vimrc and change your mappings to not overlap (start with the same letters) as much, or you can type
:h leader
in vim and learn about mapleaders, which will make it much easier for you to plan your mappings. I have my mapleader set to space personally but many people also like to use commas or some other key of their choosing.
tldr: Vim is waiting a second to see if you are going to press another key and issue a different command

Opposite of newline in vim

In vim, is there a command to delete the newline, and all empty space behind the cursor?
Say I stand in the middle of a text in insert mode and press Enter, what command would the reverse what I just did?
A) An example:
"some code{ in here }"
B) After pressing Enter:
"some code{
in here }"
Now pressing backspace will delete one space of the indentation. I would rather have it delete all indentation, and jump back to A.
Can this be done in a command or by doing some remapping to the backspace key?
It's tragic how unknown the J command is. It joins lines in normal mode.
In insert mode, you can press <C-U> twice; first, it'll delete the indent before the cursor, then it'll join with the previous line. Note that this requires
:set backspace=indent,eol,start
did you try J (uppercase) ? it will give exactly what you want.
"some code{ cursor on this line, pressJ
in here }"
You can do ᴇꜱᴄ, K, Shift+J.
K jumps up to the previous line and Shift+J joins the two lines.
However, with properly configured indentation and syntax, a backspace doesn’t just delete a space, it deletes the full previous indentation block.
One easy way is up one line, to end of that line and just delete. As long as you still are in insert mode it will do the same thing as J when deleting at the last position - like most other editors. For me that is the quickest alternative because I'm used to it from other editors.
That is: ↑, End, Delete (when still in insert mode)
One quick alternative (the VIM-way) is (when still in insert mode):
↑, Ctrl+o, J (when still in insert mode)
(Ctrl+o is used in insert mode to enter one normal mode command.)
It's also possible to use a remapping of the backspace key:
inoremap <expr> <bs> getline('.')[:col('.')-2]=~'^\s\+$' ? "<c-u><c-u>" : "<bs>"
Note that this mapping completely overrides the normal behavior the backspace key. This will only be useful when you don't intend to use its normal behavior. This is not recommended if you can easily access the other options (c-u or J)
However, (as far as I know) there's no way to distinguish between manually added leading white spaces and auto indent. If you use noexpandtab, you can edit the regex to only match tabs.
This also does not work in some modes of auto-indent (for example, in block comment in C, vim automatically start a new line starts with *)

How do I insert a linebreak where the cursor is without entering into insert mode in Vim?

Is possible to insert a line break where the cursor is in Vim without entering into insert mode? Here's an example ([x] means cursor is on x):
if (some_condition) {[ ]return; }
Occasionally, I might want to enter some more code. So I'd press i to get into insert mode, press Enter to insert the line break and then delete the extra space. Next, I'd enter normal mode and position the cursor before the closing brace and then do the same thing to get it on its own line.
I've been doing this a while, but there's surely a better way to do it?
For the example you've given, you could use rEnter to replace a single character (the space) with Enter. Then, fspace. to move forward to the next space and repeat the last command.
Depending on your autoindent settings, the above may or may not indent the return statement properly. If not, then use sEnterTabEsc instead to replace the space with a newline, indent the line, and exit insert mode. You would have to replace the second space with a different command so you couldn't use '.' in this case.
A simple mapping to break the line at the cursor by pressing Ctrl+Enter:
:nmap <c-cr> i<cr><Esc>
essentially enters 'insert' mode, inserts a line break and goes back to normal mode.
put it in your .vimrc file for future use.
Here's how to create a macro that inserts a newline at the cursor whenever you press 'g' while not in insert mode:
From within vim, type:
:map g i[Ctrl+V][Enter][Ctrl+V][Esc][Enter]
Where:
[Ctrl+V] means hold the Ctrl key and press 'v'
[Enter] means press the Enter key
[Esc] means press the Esc key
You'll see the following at the bottom of your vim window until you press the final Enter:
:map g i^M^[
Explanation:
[Ctrl+V] means "quote the following character" -- it allows you to embed the newline and escape characters in the command.
So you're mapping the 'g' key to the sequence: i [Enter] [Escape]
This is vim for insert a newline before the cursor, then exit insert mode.
Tweaks:
You can replace the 'g' with any character that's not already linked to a command you use.
Add more to the command, e.g. f}i^M^[O -- This will find the } and insert another newline, then escape from insert mode and Open an empty line for you to enter more code.
You can add the command to your .vimrc or .exrc file to make it permanent. Just omit the colon from the beginning, so the command starts with "map"
Enjoy!
If you're usually expanding a one line block to three lines, try substitution. Change the opening bracket into bracket/return, and the closing bracket into return/bracket.
The command for substituting bracket/return for bracket looks like this:
:s/{/{\r/
Since you want to use this often, you could map the full sequence to an unused keystroke like this:
:map <F7> :s/{/{\r/ ^M :s/}/\r}/ ^M
Where you see ^M in the sequence, type [Ctrl-V], then press enter.
Now with your cursor anywhere on your sample line, press the mapped key, and the carriage returns are added.
Check :help map-which-keys for advice on selecting unused keystrokes to map.
Assuming you're okay with mapping K to something else (choose a different key of your liking), and using marker ' as a temporary marker is okay why not do this?
:nmap K m'a<CR><Esc>`'
now pressing K in normal mode over the character after which you want the line break to occur will split the line and leave the cursor where it was.
Basically, when you split a line you either want to just insert a carriage return, or in the case that you're on a space, replace that with a carriage return. Well, why settle for one or the other? Here's my mapping for K:
"Have K split lines the way J joins lines
nnoremap <expr>K getline('.')[col('.')-1]==' ' ? "r<CR>" : "i<CR><Esc>"
I use the ternary operator to condense the two actions into one key map. Breaking it down, <expr> means the key map's output can dynamic and in this case hinges on the condition getline('.')[col('.')-1]==' ' which is the long winded way to ask vim if the character under the cursor is a space. Finally, the familiar ternary operator ? : either replaces the space with linebreak (r<CR>) or inserts a new one (i<CR><Esc>)
Now you have a lovely sister key map to the J command.
Vim will automatically kill any whitespace to the right of the cursor if you break a line in two while autoindent (or any other indentation aid) is enabled.
If you do not want to use any of those settings, use s instead of i in order to substitute your new text for the blank rather than just inserting. (If there are multiple blanks, put the cursor on the leftmost and use cw instead.)
In fact you need the following combined operations:
Press v to enter Visual Mode
Select the line you want to split
Press : to enter in Command Mode
s/\s/\r/g
Done
If you have the input:
aaa bbb ccc ddd
and want to output
aaa
bbb
ccc
ddd
You can use the command
f r<ENTER>;.;.
o ESC command will do it for you.
Set this key mapping in your vimrc
:map <C-m> i<CR><Esc>h
Then press Ctrl+m if you want to use it in your vim.
IMHO, the built-in mapping gs is not a useful mapping (put vim to sleep), one could use this for splitting:
nmap gs i<CR><ESC>
In Vrapper you can use gql which will split a line without entering insert mode, but may not always maintain indentation.
I found this to be the most faithful implementation of what I'd expect the opposite behaviour to J
nnoremap S i<cr><esc>^mwgk:silent! s/\v +$//<cr>:noh<cr>`w
It does the simplistic new line at cursor, takes care of any trailing whitespace on the previous line if there are any present and then returns the cursor to the correct position.
i <cr> <esc> - this is one of the most common solutions suggested, it doesn't delete non-whitespace characters under your cursor but it also leaves you with trailing whitespace
^mw - goto start of new line and create a mark under w
gk - go up one line
:silent! s/\v +$//<cr> - regex replace any whitespace at the end of the line
:noh<cr> - Clear any search highlighting that the regex might have turned on
`w - return the the mark under w
Essentially combines the best of both r<esc><cr> and i<cr><esc>
Note: I have this bound to S which potentially overwrites a useful key but it is a synonym for cc and since I don't use it as often as I do splits I am okay with overwriting it.
This mapping will break up any one-line function you have. Simply put your cursor on the line and hit 'g' in normal mode:
:map g ^f{malr<CR>`a%hr<CR>`a
This assumes that you have a space after the opening brace and a space before the closing brace. See if that works for you.

Vim / vi Survival Guide

What are the essential vim commands? What does a new-user need to know to keep themselves from getting into trouble? One command per comment, please.
What I find irreplaceable (because it works in vi also, unlike vim's visual mode) are marks. You can mark various spots with m (lower case) and then a letter of your choice (eg x). Then you go elsewhere, and can go back with ``x(backquote letter) to the exact spot, or with'x` (apostrophe letter) to go to the line.
These movements can be used as arguments to commands (yank, delete, etc). For example, you want to delete 10 lines; instead of counting and then moving to the topmost line and entering 10dd, you go to either the start or the end of the block, press mm (mark m), then go to the other end of the block, and press d'm (delete apostrophe m). If you use backquote instead of apostrophe in this example, then the deletion will work character-wise, not line-wise. Try marking in the middle of the line with "mark m", moving to the middle of another line, then entering "d backquote m" and you will see what I mean.
I was very happy the day I learned about using * or # to search, down or up respectively, for the word under the cursor. Make sure to :set incsearch and :set hlsearch first.
I like this QRC!
http://www.fsckin.com/wp-content/uploads/2007/10/vi-vim_cheat_sheet.gif
When you have some repetitive action to take Macros are usually faster than regex.
Just type
q[0-9a-z] in normal mode
Many people use
qq
because it's fast.
Press
q in normal mode
again to stop recording.
Then just type
#[0-9a-z] in normal mode
to repeat what you just recorded.
#q
for the example like above.
Edited to add: you can also repeat the macro. Let's say you programed a macro to jump to the head of a line, insert a tab, and then jump down one line. You then test your macro by typing "#q" to run it once. Then you can repeat the action nine more times by typing "9#q".
:q -> quit
:w -> save
:q! -> quit and don't save
:x -> save and quit
:[number] -> go to line number
G -> go to end of file
dd -> delete line
p -> "put" line
yy -> "copy" line
:s/[searchfor] -> search
I guess those are the basic one to start from
Use the 'J' (J for Join; upper-case) command to delete the newline at the end of a line. You'll find it tricky otherwise.
This recent Vim tutorial from IBM is pretty good
First of all you need to know how to close vi:
ctrl-c : q!
Rest can be found from vimtutor. Launch vimtutor by typing vimtutor at your command line
Although this is a matter of personal preference I've found that one of the essential things to do is to remap Esc to something else.
I find it very uncomfortable to reach for the Esc key to exit insert mode, but the beautiful thing about Vim is that allows key mappings.
I'm currently using the following mapping using Control + S:
inoremap <C-s> <Esc>:w<CR>
This has the advantage of being a key mapping I have already committed to memory and has the added value of saving my work every time I go to normal mode. Yeah, I know it is crazy but I would be hitting the save command that frequently anyway. It's like a bad habit, you know.
" ~/.vimrc
" Turn on line numbering
set nu
" Turn on syntax highlighting
syntax on
" Set 4 space expanding tabs
set tabstop=4
set shiftwidth=4
set softtabstop=4
set expandtab
"turn off line wrapping
set nowrap
" Map CTRL-N to create a new tab
:map <C-n> <ESC>:tabnew<RETURN>
" Map Tab and CTRL-Tab to move between tabs
:map <Tab> <ESC>:tabn<RETURN>
:map <C-Tab> <ESC>:tabp<RETURN>
If you're using vim, the 'u' command (in command mode) will Undo the last command you typed. You can use this command repeatedly to undo mistakes you may have made before saving the file.
See http://www.rayninfo.co.uk/vimtips.html for a great collection of Vim tips, from the basic can't-live-without to very sophisticated stuff that you might never have thought of trying.
Lots of great commands are listed at the Vim Tips Wiki.
It's also good to run the vimtutor when learning these commands
alias vi nedit :)
all humor aside..
for vi WHEN NOT using nedit..
i (switch to insert mode)
a (append = move to end of line and switch to insert mode)
esc (exit insert mode)
dd delete a line
x delete a character
:wq (save and quit)
/ start a search
n find Next
? search backwards..
yy (yank) copy a line to the buffer
pp (paste) paste it here
r (replace a character)
<N> <command> this is a neat - but aggravating feature that lets you type digits and then a command so
5dd will delete 5 lines
but at this point you might as well
- man vi and refresh your memory
While there are LOTS more, I switched from Vi to nedit several years ago, which I find has more features I can use on a regular basis more easily. Tabbed editing, incremental search bar, column select, copy and paste. sort selected lines, search and destroy within selection, whole doc or all open docs..
tear-off drop down menus..
and it supports syntax highlighting for all the languages I use.. (with pattern files I've used a long time over the years. VIM many now be equivalent, but It has to introduce a feature that Nedit doesn't and an easy way to migrate my pattern files before I switch again.
I like the Vim 5.6 Reference Guide, by Bram Moolenaar and Oleg Raisky.
You can directly print it in booklet form, easy to read, I always have it laying around.
It's a tad old, but what are 8 years in Vi's lifespan ?
:set ignorecase smartcase
Makes searching case-insensitive, unless your search includes a capital letter. Not the most indispensable perhaps, but I find myself setting this option any time I'm editing in a new place. It's in any vimrc file I own.
:%!xxd
View the contents of a buffer in hexadecimal. To revert:
:%!xxd -r
My biggest tip: ctrl+q saves the day when you accidentally hit ctrl+s to save the file you are working on
I have this in my vimrc
set number
set relativenumber
This gives me a line numbering system which makes j, k keys really productive.
I use vi very lightly, and I only use the following commands:
a - switch to insert mode (after the cursor)
esc - return to command mode
:wq - save and quit
:q - quit (no save, only without modification)
:q! - force quit (no save, also with modification)
x - delete one character (in command mode)
dd - delete the whole line (in command mode)
I know there are many many more, but those are enough to get you by.
One of my favourite commands is %G which takes to directly to the end of a file. Especially useful in log-files.
How to switch between modes (i to enter insert mode (one of many ways), esc to exit insert mode, colon for command mode) and how to save and exit. (:wq)
Another useful command is to search something: /
e.g. /Mon will search (and in case of vim highlight) any occurences of Mon in your file.
As a couple of other people have already mentioned, vimtutor is the way to go. It will teach you everything you need to know in vim. The one piece of general advice I would give you is to stay out of insert mode as much as possible. There is enormous power in the other modes, it just takes a little bit of practice to get used to it.
i - insert mode (escape to exit)
dd - delete line
shift-y - 'Yank' (copy) line
p - 'Put' (paste) line(s)
shift-v - Visual mode used to select text (tryin 'yanking' this text and 'putting' it somewhere.
ctrl-w n - create new window (you can open a file or start new file here)
ctrl-w v - split existing window vertically
ctrl-n (in insert mode) - autocomplete (if supported)
:! to run a shell command, usually with standard in as the file or a selection (shift-V)
Useful plugins to look at:
* Buffer Explorer - use \be to view files in the buffer (and select to re-open)
NB vi is not vim! vim is rapidly turning into the emacs of the new century. nvi is probably the closest thing to the original vi. Here's a nice hint: "xp" will exchange two characters (try it).
replace 'foo' with 'bar' everywhere in the file
:%s/foo/bar/gc
The real power is in the searching. Here are the essential commands:
/Steve will find the first instance of "Steve" in the text.
n will find the next "Steve" in the text.
:%s//Stephen/g will replace all those instances of "Steve" you just searched for with "Stephen".
Not to promote myself, but I wrote a blog post on this subject. It focuses on the critical parts of Vim for a beginner.
My favorites:
% find matching bracket/brace
* and # next/previous match
gg top of page
G end of the page
<Ctrl-v> Change to visual mode and select column
<Ctrl-a> increase current number by 1
<Ctrl-x> decrease current number by 1
Running macros

Resources