What's a quick way to comment/uncomment lines in Vim?
For those tasks I use most of the time block selection.
Put your cursor on the first #
character, press CtrlV (or CtrlQ for gVim), and go down until the last commented line and press x, that will delete all the #
characters vertically.
For commenting a block of text is almost the same:
- First, go to the first line you want to comment, press CtrlV. This will put the editor in the
VISUAL BLOCK
mode. - Then using the arrow key and select until the last line
- Now press ShiftI, which will put the editor in
INSERT
mode and then press #. This will add a hash to the first line. - Then press Esc (give it a second), and it will insert a
#
character on all other selected lines.
For the stripped-down version of vim shipped with debian/ubuntu by default, type : s/^/#
in the third step instead (any remaining highlighting of the first character of each line can be removed with :nohl
).
Here are two small screen recordings for visual reference.
Comment:
Uncomment:
To comment out blocks in vim:
- press Esc (to leave editing or other mode)
- hit ctrl+v (visual block mode)
- use the ↑/↓ arrow keys to select lines you want (it won't highlight everything - it's OK!)
- Shift+i (capital I)
- insert the text you want, e.g.
%
- press EscEsc
To uncomment blocks in vim:
- press Esc (to leave editing or other mode)
- hit ctrl+v (visual block mode)
- use the ↑/↓ arrow keys to select the lines to uncomment.
If you want to select multiple characters, use one or combine these methods:
- use the left/right arrow keys to select more text
- to select chunks of text use shift + ←/→ arrow key
- you can repeatedly push the delete keys below, like a regular delete button
- press d or x to delete characters, repeatedly if necessary
Sometimes I'm shelled into a remote box where my plugins and .vimrc cannot help me, or sometimes NerdCommenter gets it wrong (eg JavaScript embedded inside HTML).
In these cases a low-tech alternative is the built-in norm
command, which just runs any arbitrary vim commands at each line in your specified range. For example:
Commenting with #
:
1. visually select the text rows (using V as usual)
2. :norm i#
This inserts "#" at the start of each line. Note that when you type : the range will be filled in, so it will really look like :'<,'>norm i#
Uncommenting #
:
1. visually select the text as before (or type gv to re-select the previous selection)
2. :norm x
This deletes the first character of each line. If I had used a 2-char comment such as // then I'd simply do :norm xx
to delete both chars.
If the comments are indented as in the OP's question, then you can anchor your deletion like this:
:norm ^x
which means "go to the first non-space character, then delete one character". Note that unlike block selection, this technique works even if the comments have uneven indentation!
Note: Since norm
is literally just executing regular vim commands, you're not limited to comments, you could also do some complex editing to each line. If you need the escape character as part of your command sequence, type ctrl-v then hit the escape key (or even easier, just record a quick macro and then use norm to execute that macro on each line).
Note 2: You could of course also add a mapping if you find yourself using norm
a lot. Eg putting the following line in ~/.vimrc lets you type ctrl-n
instead of :norm
after making your visual selection
vnoremap <C-n> :norm
Note 3: Bare-bones vim sometimes doesn't have the norm
command compiled into it, so be sure to use the beefed up version, ie typically /usr/bin/vim, not /bin/vi
(Thanks to @Manbroski and @rakslice for improvements incorporated into this answer)