How to switch modes when operating on multiple selected lines - vim

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

Related

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 *)

Repeating characters in VIM insert mode

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.

How to paste yanked text into the Vim command line

I'd like to paste yanked text into Vim's command line. Is it possible?
Yes. Hit Ctrl-R then ". If you have literal control characters in what you have yanked, use Ctrl-R, Ctrl-O, ".
Here is an explanation of what you can do with registers. What you can do with registers is extraordinary, and once you know how to use them you cannot live without them.
Registers are basically storage locations for strings. Vim has many registers that work in different ways:
0 (yank register: when you use y in normal mode, without specifying a register, yanked text goes there and also to the default register),
1 to 9 (shifting delete registers, when you use commands such as c or d, what has been deleted goes to register 1, what was in register 1 goes to register 2, etc.),
" (default register, also known as unnamed register. This is where the " comes in Ctrl-R, "),
a to z for your own use (capitalized A to Z are for appending to corresponding registers).
_ (acts like /dev/null (Unix) or NUL (Windows), you can write to it but it's discarded and when you read from it, it is always empty),
- (small delete register),
/ (search pattern register, updated when you look for text with /, ?, * or # for instance; you can also write to it to dynamically change the search pattern),
: (stores last VimL typed command via Q or :, readonly),
+ and * (system clipboard registers, you can write to them to set the clipboard and read the clipboard contents from them)
See :help registers for the full reference.
You can, at any moment, use :registers to display the contents of all registers. Synonyms and shorthands for this command are :display, :reg and :di.
In Insert or Command-line mode, Ctrl-R plus a register name, inserts the contents of this register. If you want to insert them literally (no auto-indenting, no conversion of control characters like 0x08 to backspace, etc), you can use Ctrl-R, Ctrl-O, register name.
See :help i_CTRL-R and following paragraphs for more reference.
But you can also do the following (and I probably forgot many uses for registers).
In normal mode, hit ":p. The last command you used in vim is pasted into your buffer.
Let's decompose: " is a Normal mode command that lets you select what register is to be used during the next yank, delete or paste operation. So ": selects the colon register (storing last command). Then p is a command you already know, it pastes the contents of the register.
cf. :help ", :help quote_:
You're editing a VimL file (for instance your .vimrc) and would like to execute a couple of consecutive lines right now: yj:#"Enter.
Here, yj yanks current and next line (this is because j is a linewise motion but this is out of scope of this answer) into the default register (also known as the unnamed register). Then the :# Ex command plays Ex commands stored in the register given as argument, and " is how you refer to the unnamed register. Also see the top of this answer, which is related.
Do not confuse " used here (which is a register name) with the " from the previous example, which was a Normal-mode command.
cf. :help :# and :help quote_quote
Insert the last search pattern into your file in Insert mode, or into the command line, with Ctrl-R, /.
cf. :help quote_/, help i_CTRL-R
Corollary: Keep your search pattern but add an alternative: / Ctrl-R, / \|alternative.
You've selected two words in the middle of a line in visual mode, yanked them with y, they are in the unnamed register. Now you want to open a new line just below where you are, with those two words: :pu. This is shorthand for :put ". The :put command, like many Ex commands, works only linewise.
cf. :help :put
You could also have done: :call setreg('"', #", 'V') then p. The setreg function sets the register of which the name is given as first argument (as a string), initializes it with the contents of the second argument (and you can use registers as variables with the name #x where x is the register name in VimL), and turns it into the mode specified in the third argument, V for linewise, nothing for characterwise and literal ^V for blockwise.
cf. :help setreg(). The reverse functions are getreg() and getregtype().
If you have recorded a macro with qa...q, then :echo #a will tell you what you have typed, and #a will replay the macro (probably you knew that one, very useful in order to avoid repetitive tasks)
cf. :help q, help #
Corollary from the previous example: If you have 8go in the clipboard, then #+ will play the clipboard contents as a macro, and thus go to the 8th byte of your file. Actually this will work with almost every register. If your last inserted string was dd in Insert mode, then #. will (because the . register contains the last inserted string) delete a line. (Vim documentation is wrong in this regard, since it states that the registers #, %, : and . will only work with p, P, :put and Ctrl-R).
cf. :help #
Don't confuse :# (command that plays Vim commands from a register) and # (normal-mode command that plays normal-mode commands from a register).
Notable exception is #:. The command register does not contain the initial colon neither does it contain the final carriage return. However in Normal mode, #: will do what you expect, interpreting the register as an Ex command, not trying to play it in Normal mode. So if your last command was :e, the register contains e but #: will reload the file, not go to end of word.
cf. :help #:
Show what you will be doing in Normal mode before running it: #='dd' Enter. As soon as you hit the = key, Vim switches to expression evaluation: as you enter an expression and hit Enter, Vim computes it, and the result acts as a register content. Of course the register = is read-only, and one-shot. Each time you start using it, you will have to enter a new expression.
cf. :help quote_=
Corollary: If you are editing a command, and you realize that you should need to insert into your command line some line from your current buffer: don't press Esc! Use Ctrl-R =getline(58) Enter. After that you will be back to command line editing, but it has inserted the contents of the 58th line.
Define a search pattern manually: :let #/ = 'foo'
cf. :help :let
Note that doing that, you needn't to escape / in the pattern. However you need to double all single quotes of course.
Copy all lines beginning with foo, and afterwards all lines containing bar to clipboard, chain these commands: qaq (resets the a register storing an empty macro inside it), :g/^foo/y A, :g/bar/y A, :let #+ = #a.
Using a capital register name makes the register work in append mode
Better, if Q has not been remapped by mswin.vim, start Ex mode with Q, chain those “colon commands” which are actually better called “Ex commands”, and go back to Normal mode by typing visual.
cf. :help :g, :help :y, :help Q
Double-space your file: :g/^/put _. This puts the contents of the black hole register (empty when reading, but writable, behaving like /dev/null) linewise, after each line (because every line has a beginning!).
Add a line containing foo before each line: :g/^/-put ='foo'. This is a clever use of the expression register. Here, - is a synonym for .-1 (cf. :help :range). Since :put puts the text after the line, you have to explicitly tell it to act on the previous one.
Copy the entire buffer to the system clipboard: :%y+.
cf. :help :range (for the % part) and :help :y.
If you have misrecorded a macro, you can type :let #a=' Ctrl-R =replace(#a,"'","''",'g') Enter ' and edit it. This will modify the contents of the macro stored in register a, and it's shown here how you can use the expression register to do that. Another, simpler, way of modifying a macro is to paste it in a buffer ("ap), edit it, and put it again into the register, by selecting it and "ay.
If you did dddd, you might do uu in order to undo. With p you could get the last deleted line. But actually you can also recover up to 9 deletes with the registers #1 through #9.
Even better, if you do "1P, then . in Normal mode will play "2P, and so on.
cf. :help . and :help quote_number
If you want to insert the current date in Insert mode: Ctrl-R=strftime('%y%m%d')Enter.
cf. :help strftime()
Once again, what can be confusing:
:# is a command-line command that interprets the contents of a register as vimscript and sources it
# in normal mode command that interprets the contents of a register as normal-mode keystrokes (except when you use : register, that contains last played command without the initial colon: in this case it replays the command as if you also re-typed the colon and the final return key).
" in normal mode command that helps you select a register for yank, paste, delete, correct, etc.
" is also a valid register name (the default, or unnamed, register) and therefore can be passed as an arguments for commands that expect register names
For pasting something that is the system clipboard you can just use SHIFT - INS.
It works in Windows, but I am guessing it works well in Linux too.
"I'd like to paste yanked text into Vim command line."
While the top voted answer is very complete, I prefer editing the command history.
In normal mode, type: q:. This will give you a list of recent commands, editable and searchable with normal vim commands. You'll start on a blank command line at the bottom.
For the exact thing that the article asks, pasting a yanked line (or yanked anything) into a command line, yank your text and then: q:p (get into command history edit mode, and then (p)ut your yanked text into a new command line. Edit at will, enter to execute.
To get out of command history mode, it's the opposite. In normal mode in command history, type: :q + enter
For pasting something from the system clipboard into the Vim command line ("command mode"), use Ctrl+R followed by +. For me, at least on Ubuntu, Shift+Ins is not working.
PS: I am not sure why Ctrl+R followed by *, which is theoretically the same as Ctrl+R followed by + doesn't seem to work always. I searched and discovered the + version and it seems to work always, at least on my box.
It's worth noting also that the yank registers are the same as the macro buffers. In other words, you can simply write out your whole command in your document (including your pasted snippet), then "by to yank it to the b register, and then run it with #b.
For context, this information comes from out-of-the-box, no plugins, no .vimrc Vim 7.4 behavior in Linux Mint with the default options.
You can always select text with the mouse (or using V or v and placing the selection in the "* register), and paste it into the command line with Shift + Ctrl + v.
Typing Ctrl + r in the command line will cause a prompt for a register name. so typing :CTRL-r* will place the content register * into the command line. It will paste any register, not just "*. See :help c_CTRL-R.
Furthermore, the middle mouse button will paste into the command line.
See :help->quote-plus for a description of the how X Window deals with selection. Even in a plain, out-of-the-box Vim (again, in Vim 7.4 in Linux Mint, anyway), any selection made with the left mouse button can be pasted in the command line with the middle mouse button.
In addition, the middle mouse button will also paste text selected in Vim into many other X Window applications, even GUI ones (for example, Firefox and Thunderbird) and pasting text into the command line is also possible where the text was selected from other apps.
See :help->x11-selection for addl information.
tl;dr
Try the :CTRL-r approach first, and then use Shift + Ctrl + v or the middle mouse button if you need something else.
It is conceded that it can be confusing.
I was having a similar problem. I wanted the selected text to end up in a command, but not rely on pasting it in. Here's the command I was trying to write a mapping for:
:call VimuxRunCommand("python")
The docs for this plugin only show using string literals. The following will break if you try to select text that contains doublequotes:
vnoremap y:call VimuxRunCommand("<c-r>"")<cr>
To get around this, you just reference the contents of the macro using # :
vnoremap y:call VimuxRunCommand(#")<cr>
Passes the contents of the unnamed register in and works with my double quote and multiline edgecases.
OS X
If you are using Vim in Mac OS X, unfortunately it comes with older version, and not complied with clipboard options. Luckily, Homebrew can easily solve this problem.
Install Vim:
brew install vim --with-lua --with-override-system-vi
Install the GUI version of Vim:
brew install macvim --with-lua --with-override-system-vi
Restart the terminal for it to take effect.
Append the following line to ~/.vimrc
set clipboard=unnamed
Now you can copy the line in Vim with yy and paste it system-wide.
"[a-z]y: Copy text to the [a-z] register
Use :! to go to the edit command
Ctrl + R: Follow the register identity to paste what you copy.
It used to CentOS 7.
If you have two values yanked into two different registers (for example register a and register b) then you can simply set a variable c and do the operation on it.
For example, :set c = str2float(#a) + str2float(#b) and then you can paste the content of c anywhere.
For example whilst in INSERT mode, CTRL + R then type = to enter into the expression register and just type c after equal sign and hit ENTER. Done you should now have the total of a and b registers.
All these can be recorded in a macro and repeated over!
The str2float function is used if you are working with floats, if you don't, you will get integers instead.
I am not sure if this is idiomatic but it worked for my case where I needed to add 2 numbers in a row and repeat it for 500 more lines.
I like to use Control-v to paste from the system clipboard, so I use:
cnoremap <C-v> <C-r>+

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.

How to insert text at beginning of a multi-line selection in vi/Vim

In Vim, how do I insert characters at the beginning of each line in a selection?
For instance, I want to comment out a block of code by prepending // at the beginning of each line assuming my language's comment system doesn't allow block commenting like /* */. How would I do this?
Press Esc to enter 'command mode'
Use Ctrl+V to enter visual block mode
Move Up/Downto select the columns of text in the lines you want to
comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line.
For further information and reading, check out "Inserting text in multiple lines" in the Vim Tips Wiki.
This replaces the beginning of each line with "//":
:%s!^!//!
This replaces the beginning of each selected line (use visual mode to select) with "//":
:'<,'>s!^!//!
Note that gv (in normal mode) restores the last visual selection, this comes in handy from time to time.
The general pattern for search and replace is:
:s/search/replace/
Replaces the first occurrence of 'search' with 'replace' for current line
:s/search/replace/g
Replaces all occurrences of 'search' with 'replace' for current line, 'g' is short for 'global'
This command will replace each occurrence of 'search' with 'replace' for the current line only. The % is used to search over the whole file. To confirm each replacement interactively append a 'c' for confirm:
:%s/search/replace/c
Interactive confirm replacing 'search' with 'replace' for the entire file
Instead of the % character you can use a line number range (note that the '^' character is a special search character for the start of line):
:14,20s/^/#/
Inserts a '#' character at the start of lines 14-20
If you want to use another comment character (like //) then change your command delimiter:
:14,20s!^!//!
Inserts a '//' character sequence at the start of lines 14-20
Or you can always just escape the // characters like:
:14,20s/^/\/\//
Inserts a '//' character sequence at the start of lines 14-20
If you are not seeing line numbers in your editor, simply type the following
:set nu
Another way that might be easier for newcomers:
some█
code
here
Place the cursor on the first line, e.g. by
gg
and type the following to get into insert mode and add your text:
I / / Space
// █some
code
here
Press Esc to get back to command mode and use the digraph:
j . j .
// some
// code
//█here
j is a motion command to go down one line and . repeats the last editing command you made.
And yet another way:
Move to the beginning of a line
enter Visual Block mode (CTRL-v)
select the lines you want (moving up/down with j/k, or jumping to a line with [line]G)
press I (that's capital i)
type the comment character(s)
press ESC
This adds # at the beginning of every line:
:%s/^/#/
And people will stop complaining about your lack of properly commenting scripts.
If you want to get super fancy about it, put this in your .vimrc:
vmap \c :s!^!//!<CR>
vmap \u :s!^//!!<CR>
Then, whenever in visual mode, you can hit \c to comment the block and \u to uncomment it. Of course, you can change those shortcut keystrokes to whatever.
Yet another way:
:'<,'>g/^/norm I//
/^/ is just a dummy pattern to match every line. norm lets you run the normal-mode commands that follow. I// says to enter insert-mode while jumping the cursor to the beginning of the line, then insert the following text (two slashes).
:g is often handy for doing something complex on multiple lines, where you may want to jump between multiple modes, delete or add lines, move the cursor around, run a bunch of macros, etc. And you can tell it to operate only on lines that match a pattern.
To insert "ABC" at the begining of each line:
Go to command mode
% norm I ABC
For commenting blocks of code, I like the NERD Commenter plugin.
Select some text:
Shift-V
...select the lines of text you want to comment....
Comment:
,cc
Uncomment:
,cu
Or just toggle the comment state of a line or block:
,c<space>
I can recommend the EnhCommentify plugin.
eg. put this to your vimrc:
let maplocalleader=','
vmap <silent> <LocalLeader>c <Plug>VisualTraditional
nmap <silent> <LocalLeader>c <Plug>Traditional
let g:EnhCommentifyBindInInsert = 'No'
let g:EnhCommentifyMultiPartBlocks = 'Yes'
let g:EnhCommentifyPretty = 'Yes'
let g:EnhCommentifyRespectIndent = 'Yes'
let g:EnhCommentifyUseBlockIndent = 'Yes'
you can then comment/uncomment the (selected) lines with ',c'
Mark the area to be comment as a visual block (<C-V)
and do c#<ESC>p
change it to "#"
put it back
If you do it often, define a short cut (example \q) in your .vimrc
:vmap \q c#<ESC>p
In case someone's multi-line-selection is actually a paragraph, there is no need to manually select the lines. vim can do that for you:
vip: select and mark the whole paragraph
shift-i: insert text at line beginning
escape: leave insert mode/enter normal mode [line beginnings still selected]
escape: unselect line beginnings
Mapping of most voted answer:
1st visual select the desired lines, then execute <leader>zzz, which values:
vnoremap <leader>zzz <C-V>^I-<Space><Esc>
<C-V> to enter visual mode
^ goes to start of line ( or use '0' to 1st non blank)
I to insert in block mode
-<Space> to insert '- ' (for example, edit as you need)
<Esc> to apply same insert to all visual block lines
Or of last visual selection from normal mode:
nnoremap <leader>zzz gv<C-V>^I-<Space><Esc>

Resources