13

I'm coming from Atom, and with that I can highlight multiple lines and hit ctrl/ and it'll toggle comments for those lines. I how easy this is.

Can I do something similar using ctrl/ with vim? I don't want to be doing ctrlv, highlight rows, //, escape. That's too much effort.

3

2 Answers 2

13

It all depends on how extensive you want it to be. What type of files are you editing? I have the following in my .vimrc that works with python files:

let Comment='#'

xnoremap # :norm 0i<C-r>=Comment<CR><CR>
xnoremap & :norm ^<C-r>=len(Comment)<CR>x<CR>

This works well, but you have to manually setup each filetype, so a little bit of a pain.

Would a plugin work for you? tpope/commentary is a very useful and popular plugin for comments. It has this mapping:

                                                *v_gc*
{Visual}gc              Comment or uncomment the highlighted lines.

You could easily add

xnoremap <C-\> gc

to your vimrc, and this would do what exactly what you describe.

As well as many other useful mappings so you don't need to even enter visual mode. For exampe:

gc}                     Comment or uncomment a paragraph
2
  • 5
    +1 for tpope/commentary; the xmap could be to <Plug>Commentary, leaving the gc combination free for other mappings
    – mMontu
    Jun 7, 2016 at 19:12
  • It was good if you wrote what key is assigned with your first code
    – Ahmad
    Jun 29, 2020 at 9:18
4

Unfortunately, as far as I know Ctrl+/ cannot be bound to in vim. :(

But if you're not attached to that particular mapping the rest is pretty simple. Here's an example that uses Ctrl+M (simply because it's close to you're mapping):

noremap <C-m> :normal! I//<CR>

This works for C like files, but we can do better.

noremap <C-m> :<S-Left>exe "<S-Right>normal! I".b:commentType<CR>

autocmd BufReadPost *.[ch] let b:commentType='//' "C files
autocmd BufReadPost *.pl let b:commentType='#'    "Perl files

This is a bit longer but it allows us to specify different types of comments for different types of files.

This works because when you visually select something and then press :, vim automatically fills in the a range of '<,'> for you. This is the range of the selection. The <S-Left> and <S-Right> moves above are simply navigating around this pre-filled text.

EDIT

Making it a toggle button adds quite a bit of complexity. The big problem is determining whether or not the lines you have selected are comments or not. This becomes increasingly harder when we don't know what syntax starts a comment. I believe that the most robust way to do this will be to rely on vim's syntax highlighter to tell us when we are in a comment or not. Here's what I've got:

noremap <expr> <C-m> (synIDattr(synID(line("."), col("."), 0), "name") =~ 'comment\c') ?
\ ':<S-Left>exe "<S-Right>normal! ".b:unCommentCommand<CR>' :
\ ':<S-Left>exe "<S-Right>normal! ".b:commentCommand<CR>'

autocmd BufReadPost *.[ch] let b:commentCommand='I//'   "Comment for C files
autocmd BufReadPost *.[ch] let b:unCommentCommand='^xx' "un-Comment for C files
autocmd BufReadPost *.pl   let b:commentCommand='I#'    "Comment for perl files
autocmd BufReadPost *.pl   let b:unCommentCommand='^x'  "un-Comment for perl

This will decide whether or not to comment or uncomment based on if your cursor is in a comment region or not. This isn't perfect because if your cursor is perhaps in the initial indentation of a comment it will not register as a comment. But this works reasonably well.

  • synIDattr(...) finds the syntax group under the cursor
  • <expr> allows us to do a conditional mapping

Of course for each file type you want to edit you will have to add another autocmd for the b:commentCommand and b:unCommentCommand. This takes the form of a normal command that will do the comment/un-comment for that file type.

Note: I relized that I could simplify all my <Left> calls to a single <S-Left> and have updated my answer above as well.

1
  • 1
    How can i have it so pressing ctrl+m again will remove the comments? Toggle them on and off.
    – ditto
    Jun 9, 2016 at 18:19

Not the answer you're looking for? Browse other questions tagged or ask your own question.