What's a quick way to comment/uncomment lines in Vim?
What's a quick way to comment/uncomment lines in Vim?
Question
I have a Ruby code file open in vi, there are lines commented out with #
:
class Search < ActiveRecord::Migration
def self.up
# create_table :searches do |t|
# t.integer :user_id
# t.string :name
# t.string :all_of
# t.string :any_of
# t.string :none_of
# t.string :exact_phrase
#
# t.timestamps
# end
end
def self.down
# drop_table :searches
end
end
Say I want to uncomment all the lines in the first def ... end
section. What's an efficient way to do that in Vim?
In general, I'm looking for an easy and fluid way to comment and uncomment lines. Here I'm dealing with Ruby code, but it could be JavaScript (//
) or Haml (-#
).
Accepted Answer
I use the NERD Commenter script. It lets you easily comment, uncomment or toggle comments in your code.
As mentioned in the comments:
for anyone who is confused by the usage, default leader is "\" so 10\cc will comment ten lines and 10\cu will uncomment those ten lines
Popular Answer
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.
Read more… Read less…
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)
I have the following in my .vimrc
:
" Commenting blocks of code.
augroup commenting_blocks_of_code
autocmd!
autocmd FileType c,cpp,java,scala let b:comment_leader = '// '
autocmd FileType sh,ruby,python let b:comment_leader = '# '
autocmd FileType conf,fstab let b:comment_leader = '# '
autocmd FileType tex let b:comment_leader = '% '
autocmd FileType mail let b:comment_leader = '> '
autocmd FileType vim let b:comment_leader = '" '
augroup END
noremap <silent> ,cc :<C-B>silent <C-E>s/^/<C-R>=escape(b:comment_leader,'\/')<CR>/<CR>:nohlsearch<CR>
noremap <silent> ,cu :<C-B>silent <C-E>s/^\V<C-R>=escape(b:comment_leader,'\/')<CR>//e<CR>:nohlsearch<CR>
Now you can type ,cc
to comment a line and ,cu
to uncomment a line (works both in normal and visual mode).
(I stole it from some website many years ago so I can't completely explain how it works anymore :). There is a comment where it is explained.)
Specify which lines to comment in vim:
Reveal the line numbers:
:set number
then
:5,17s/^/#/ this will comment out line 5-17
or this:
:%s/^/#/ will comment out all lines in file
Here is how I do it:
Go to first character on the first line you want to comment out.
Hit Ctrl+q in GVIM or Ctrl+v in VIM, then go down to select first character on the lines to comment out.
Then press c, and add the comment character.
Uncommenting works the same way, just type a space instead of the comment character.