194

I was wondering if there was any key mapping in Vim to allow me to indent certain lines of code (whether those lines have been selected in visual mode, or n lines above/below current cursor position).

So basically something that converts the following

def my_fun(x, y):
    return x + y

to

#def my_fun(x, y):
#    return x + y

I am okay with using either # or """ for commenting out the relevant lines. Ideally, I would also like the same keymapping to uncomment the lines if the given lines have been commented out.

Keith Pinson
  • 7,162
  • 5
  • 54
  • 97
Rishabh Manocha
  • 2,837
  • 3
  • 16
  • 15
  • No need to reinvent the wheel, there is a [plugin: tComment](https://github.com/tomtom/tcomment_vim) for you, which supports (un)comment code for multiple languages. – Meow Feb 12 '15 at 14:41

13 Answers13

426

Step 1: Go to the the first column of the first line you want to comment.

Initial State

Step 2: Press: Ctrl+v and select the lines you want to comment:

Select lines

Step 3: Shift-I#space (Enter Insert-at-left mode, type chars to insert. The selection will disappear, but all lines within it will be modified after Step 4.)

Comment

Step 4: Esc

<Esc>

Community
  • 1
  • 1
theosp
  • 7,069
  • 3
  • 21
  • 24
  • 4
    Commenting the lines this way works great. Is there some way to uncomment these lines? `Shift-I # ` didn't work (maybe I'm doing it wrong). – Rishabh Manocha Apr 01 '10 at 16:14
  • 43
    @rishabh-manocha: use visual block (Ctrl-V) to select all the added # and type x to delete them. – theosp Apr 01 '10 at 16:18
  • 3
    You gotta remember that Shift-I means "insert at the first non-blank in the line", so it can't be used to delete. Doing a visual selection with Ctrl-V marks the characters to modify, then "x" deletes one character in the selected area, ending up deleting the '#' characters. See ":h I" and ":h CTRL-V" in vim for more information. – the Tin Man Apr 02 '10 at 09:39
  • Hmm... when I press Ctrl+v, I get a `;` character...? What am I doing wrong? I also tried Shift+v and then Shift+i but that does not work, I go into insert mode, and when I type // and press ESC, it only puts it on the first line. – Samaursa Mar 25 '11 at 20:13
  • 5
    @Samaursa Ctrl-V is probably not working on Windows. Try Ctrl-Q instead. – AZ. Apr 10 '12 at 22:57
  • When I try to comment out the line all SHIFT-I does is put me into insert mode and clear the visual selection. Does this really work on Linux? – sayth Jun 11 '13 at 11:12
  • That's what is supposed to happen. Once you hit Shift-I, type some characters, and hit escape, the characters will appear in all the lines. While typing, they only show up on one line. – Achal Dave Nov 15 '13 at 22:43
  • Doesn't work for me on OS X (Mavericks) with Vim 7.3. I used `r` instead of Shift `i` and it worked. – iconoclast Jul 31 '14 at 15:24
  • 1
    To delete 2 characters (if you inserted '# '), locate the cursor at the top line you want to modify, press ctrl-v to enter visual block mode, press j (or down arrow) to highlight all lines to modify, press l (or right arrow) to highlight a 2-char width (press once per column to highlight), and then press d to delete the highlighted text. – thinkmassive Aug 26 '14 at 18:46
  • Step 3 could use a description, especially since the `:h I` description isn't really descriptive of what happens when selecting a block-- it actually describes inserting at the line beginning, while this selection mode inserts at the left side of the selection. So, Step 3: `I` to switch to insert mode, where the characters entered are inserted to the left side of the selection, followed by the characters to insert on the left, followed by Step 4: Esc to finish. Similarly, `A` appends characters after the right side of the selection block, which is useful for something like `*/` or `-->` – stevesliva Feb 18 '15 at 18:30
  • Also, a replacement for step3 & step4 if you prefer not to move the code to the right: `r#` -- this is replace selected chars with '#'. No Esc is required because unlike `I` and `A` you do not leave command mode and enter insert mode. – stevesliva Feb 18 '15 at 18:50
  • it doesn't work quite well when the block to be commented out contains empty lines. ideavim misses a code line per empty line found in the block :( – architectonic Dec 11 '15 at 10:29
  • Thanks you very much – akbarbin Feb 03 '17 at 02:07
74

one way manually

:set number
:10,12s/^/#
ghostdog74
  • 286,686
  • 52
  • 238
  • 332
51

You could add the following mapping to your .vimrc

vnoremap <silent> # :s/^/#/<cr>:noh<cr>
vnoremap <silent> -# :s/^#//<cr>:noh<cr>

Highlight your block with:

Shift+v

# to comment your lines from the first column.

-# to uncomment the same way.

cdated
  • 1,603
  • 1
  • 14
  • 24
  • 5
    Simple is brilliant! Thanks you! – I159 Feb 20 '14 at 09:50
  • Any way to make this not update the search term? With `hlsearch` on, this ends up highlight the the first character of ever line. – ajwood Jul 24 '15 at 14:59
  • this one overrides # which is a valid and used command in the command mode though – architectonic Dec 11 '15 at 10:36
  • 1
    @architectonic it doesn't have an effect unless you are in visual mode, and '#' is unbound in visual mode http://vimdoc.sourceforge.net/htmldoc/visual.html#visual-operators – cdated Dec 13 '15 at 05:16
  • @ajwood Added ':noh' to the end of the replace. noh clears highlighting until the next search so it will no longer highlight the first column on every line or affect future highlighting. – cdated Dec 13 '15 at 05:25
  • 1
    I have modified a bit : Ctrl + k for comment "vnoremap :s#^#\##:noh" > Ctrl + u for uncomment : "vnoremap :s#^\###:noh" – Pradip Das Mar 21 '16 at 10:15
  • Could someone unpack this for me, I can't understand how it works. Is it an example of the substitute command? i.e. `:s/{pattern}/{string}/[flags]` - but there are no `/` characters! – Jonathan Hartley Sep 21 '16 at 21:42
  • 1
    @JonathanHartley you don't have to use '/' in this case '#' is the delimiter. So :s/^/#/ and :s/^#// are the equivalent substitutions. So replace beginning of line with '#' and replace '#' at first column with ''. :noh just clears the search string so nothing is left highlighted when you are done. – cdated Sep 22 '16 at 16:06
  • @cdated Thank you! I get it now. Why would you choose delimiters which are also characters that are heavily involved in the substitution? Aren't the ones using '/' delimiters easier to read? Anyhow, best answer on the page, have all my votes. – Jonathan Hartley Sep 27 '16 at 13:07
  • 1
    @JonathanHartley honestly I think I just followed a pattern without thinking about it. Now I'm surprised # vs / didn't come up sooner. Changed the answer based on common sense. Thanks! – cdated Sep 28 '16 at 20:30
  • 1
    Just recovered my password so I could let you know that you are my hero. – anshanno Mar 15 '17 at 14:58
31

Highlight your block with: ShiftV

Comment the selected block out with: :norm i# (lower case i)

To uncomment, highlight your block again, and uncomment with: :norm ^x

The :norm command performs an action for every selected line. Commenting will insert a # at the start of every line, and uncommenting will delete that #.

K.Dᴀᴠɪs
  • 9,384
  • 11
  • 31
  • 39
user2437225
  • 626
  • 7
  • 5
  • With an up-to-date Vim and a plain config, selecting lines in visual mode (with `Shift+v`) and then using `:norm i#` only changes the first selected line. This works for me to comment lines 389 to 391: `:389,391norm i #` – mmell Nov 05 '14 at 22:21
23

I usually sweep out a visual block (<C-V>), then search and replace the first character with:

:'<,'>s/^/#

(Entering command mode with a visual block selected automatically places '<,'> on the command line) I can then uncomment the block by sweeping out the same visual block and:

:'<,'>s/^#//
19

There are some good plugins to help comment/uncomment lines. For example The NERD Commenter.

Geoff Reedy
  • 31,995
  • 3
  • 51
  • 75
9

I have the following lines in my .vimrc:

" comment line, selection with Ctrl-N,Ctrl-N
au BufEnter *.py nnoremap  <C-N><C-N>    mn:s/^\(\s*\)#*\(.*\)/\1#\2/ge<CR>:noh<CR>`n
au BufEnter *.py inoremap  <C-N><C-N>    <C-O>mn<C-O>:s/^\(\s*\)#*\(.*\)/\1#\2/ge<CR><C-O>:noh<CR><C-O>`n
au BufEnter *.py vnoremap  <C-N><C-N>    mn:s/^\(\s*\)#*\(.*\)/\1#\2/ge<CR>:noh<CR>gv`n

" uncomment line, selection with Ctrl-N,N
au BufEnter *.py nnoremap  <C-N>n     mn:s/^\(\s*\)#\([^ ]\)/\1\2/ge<CR>:s/^#$//ge<CR>:noh<CR>`n
au BufEnter *.py inoremap  <C-N>n     <C-O>mn<C-O>:s/^\(\s*\)#\([^ ]\)/\1\2/ge<CR><C-O>:s/^#$//ge<CR><C-O>:noh<CR><C-O>`n
au BufEnter *.py vnoremap  <C-N>n     mn:s/^\(\s*\)#\([^ ]\)/\1\2/ge<CR>gv:s/#\n/\r/ge<CR>:noh<CR>gv`n

The shortcuts preserve your cursor position and your comments as long as they start with # (there is space after #). For example:

# variable x
x = 0

After commenting:

# variable x
#x = 0

After uncomennting:

# variable x
x = 0
Lukas Cenovsky
  • 5,130
  • 2
  • 26
  • 38
  • Nice, but I think you'd be better off using the simpler ```s/^/#/``` regexp. I prefer the comment char to occur at the beginning of the line... but much more importantly, 'commenting comments' is really rather important. I'd also drop the ```au BufEnter *.py```, since `#` comments are general enough for the commands to be used in all buffers by default. – travc Oct 11 '14 at 12:09
5

Frankly I use a tcomment plugin for that link. It can handle almost every syntax. It defines nice movements, using it with some text block matchers specific for python makes it a powerful tool.

Darek
  • 2,705
  • 4
  • 26
  • 52
5

NERDcommenter is an excellent plugin for commenting which automatically detects a number of filetypes and their associated comment characters. Ridiculously easy to install using Pathogen.

Comment with <leader>cc. Uncomment with <leader>cu. And toggle comments with <leader>c<space>.

(The default <leader> key in vim is \)

Abid H. Mujtaba
  • 1,604
  • 1
  • 20
  • 19
5

No plugins or mappings required. Try the built-in "norm" command, which literally executes anything you want on every selected line.

Add # Comments

1. shift V to visually select lines
2. :norm i#

Remove # Comments

1. visually select region as before
2. :norm x

Or if your comments are indented you can do :norm ^x

Notice that these are just ordinary vim commands being preceded by ":norm" to execute them on each line.

More detailed answer for using "norm" command in one of the answers here

What's a quick way to comment/uncomment lines in Vim?

Magnus
  • 9,320
  • 4
  • 38
  • 51
3

There's a lot of comment plugins for vim - a number of which are multi-language - not just python. If you use a plugin manager like Vundle then you can search for them (once you've installed Vundle) using e.g.:

:PluginSearch comment

And you will get a window of results. Alternatively you can just search vim-scripts for comment plugins.

Pierz
  • 4,579
  • 35
  • 45
2

A very minimal light weight plugin: vim-commentary.

gcc to comment a line
gcgc to uncomment. check out the plugin page for more.

v+k/j highlight the block then gcc to comment that block.

yantaq
  • 3,618
  • 2
  • 28
  • 34
0

CtrlK for comment (Visual Mode):

vnoremap <silent> <C-k> :s#^#\##<cr>:noh<cr>

CtrlU for uncomment (Visual Mode):

vnoremap <silent> <C-u> :s#^\###<cr>:noh<cr>
K.Dᴀᴠɪs
  • 9,384
  • 11
  • 31
  • 39
Pradip Das
  • 696
  • 1
  • 7
  • 16