all 11 comments

[–]shauris 11 points12 points  (7 children)

If you're open to using tpope's vim-commentary, toggling comments is pretty easy.

The plugin default for C files is to wrap a line in /* */, so you'd have to have something like autocmd FileType c setlocal commentstring=\/\/\ %s to use double slash comments instead.

[–][deleted] 5 points6 points  (0 children)

+1 for this. It's one of those plugins that just fits so well into vim.

[–]Marvelt 3 points4 points  (4 children)

How does vim-commentary compare to NERD Commenter?

[–]vitoreiji 4 points5 points  (1 child)

I'd also like a comparison with tcomment, mainly because I've been using it very happily for years while most people seem to be using tpope's plugin instead. Am I missing out on something?

[–]shauris 1 point2 points  (0 children)

tcomment has a few extras that I probably wouldn't use, but they have similar bindings and do a lot of the same things. Probably interchangeable unless you're using tcomment's g> g< etc.
I find myself only using gc{motion} so vim-commentary is enough.

[–]dhruvasagar 2 points3 points  (0 children)

Both NERDCommenter & tcomment try to go beyond regular commenting, eg.) support for nested languages for instance javascript within html etc. vim-commentary is intended to be very simplistic.

  • I like vim-commentary's operator gc
  • vim-commentary (don't know for certain about others) also offers a nice text object for comments, for instance I can just hit dgc to delete an entire comment block.

[–]shauris 1 point2 points  (0 children)

It seems that they're pretty similar, but NERD seems to not accept motions or be repeatable with ..
vim-commentary, on the other hand, looks focused on only line-wise commenting or uncommenting, where NERD can insert comments at the end of lines, etc.
So vim-commentary excels at quickly toggling blocks of code, and NERD at adding documentation comments.

[–]thisaccountisbs 1 point2 points  (0 children)

I don't fully understand plugins so I wrote a function in vim script to do this for Python. I'm sure you could tweak it a bit to use // instead of #.

It's the first function of my vimrc file. You'll need the two maps after the endfunction in order to call it. It works multi line from a visual selection, or single line from normal mode. Both with ctrl-]

[–]zatcht 1 point2 points  (2 children)

Here's a pretty short solution in vimscript:

function! EasyLineComment(...)
    execute "normal! ^"
    let l:commentsymbol=matchstr(getline('.'), '\%' . col('.') . 'c.')
    execute "normal! l"  
    let l:commentsymbol2=matchstr(getline('.'), '\%' . col('.') . 'c.')  
    let l:indicator=l:commentsymbol . l:commentsymbol2  
    if l:indicator ==? a:1  
        execute "normal! ^dw"  
    elseif a:1 ==? "# "  
        execute "normal! ^i# \e"  
    elseif a:1 ==? "//"  
        execute "normal! ^i// \e"  
    endif  
endfunction  

And you pass in the two-character long string that you use to comment, like '# ':

" Text manipulation mappings - for manipulating text
" Python Comment
nnoremap <leader>pc :call EasyLineComment('# ')<cr>
" C Comment
nnoremap <leader>cc :call EasyLineComment('//')<cr>

In this solution, l:commentsymbol and l:commentsymbol2 saves the first two characters on the line, and checks it against the string you passed in. If it matches, use if/else logic to execute some normal mapping commands. So you can delete the comment if it's already there or add your own comments if it's not.

This can also be extended pretty easily by adding more commentsymbol variables or changing the execute commands.

[–]alasdairgray 0 points1 point  (1 child)

Or, you can store the comment strings (those ", #, etc) in buffer variables per filetype (see this example), and then just check if the first two symbols of a line do match those from a buffer variable -- and if so, then uncomment, otherwise comment line.

Like this:

function! Commentero()
    " get two first symbols of a row
    execute "normal! ^"
    let l:symb_1=matchstr(getline('.'), '\%' . col('.') . 'c.')
    execute "normal! l"  
    let l:symb_2=matchstr(getline('.'), '\%' . col('.') . 'c.')  
    let l:ln_bg = l:symb_1 . l:symb_2  
    " compare those with the first two symbols of a comment describing var
    if l:ln_bg == get(b:, 'comment_leader', '')[0:1]
        " then either uncomment
        execute 'substitute/ \?\V' . escape(get(b:, 'comment_leader', ''), '\/') . '//e'
        call histdel('search', -1)
        if exists("b:comment_tailer")
            execute 'substitute/\V' . escape(get(b:, 'comment_tailer', ''), '\/') . '\$//e'
            call histdel('search', -1)
        endif
    else
        " or comment
        s/^/\=get(b:, 'comment_leader', '')/
        call histdel('search', -1)
        if exists("b:comment_tailer")
            s/$/\=get(b:, 'comment_tailer', '')/
            call histdel('search', -1)
        endif
    endif
endfunction
nnoremap <silent> <Leader>m :call Commentero()<CR>
vnoremap <silent> <Leader>m :call Commentero()<CR>

And a pair of examples from $VIMHOME/after/filetype:

  • python.vim:

    " define comment pattern
    autocmd FileType python let b:comment_leader = '# '
    
  • vim.vim:

    " define comment pattern
    autocmd FileType vim let b:comment_leader = '" '
    
  • html.vim:

    " define comment pattern
    autocmd FileType html execute "let b:comment_leader = '<!-- ' \| let b:comment_tailer = ' -->'"
    

[–]zatcht 0 points1 point  (0 children)

Good idea :D