I'm trying to cerate a function who toggle a block of code into comments. I did this:

" Commenting blocks of code.
filetype on
augroup commentgroup
  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

fun! TestFunc()
  if (synIDattr(synID(line("."), col("."), 0), "name") =~ 'comment\c')
    exe ':s/^'escape(b:comment_leader,'\/')'//e'
    exe ':s/^/'escape(b:comment_leader,'\/')'/e'
map <C-t> :call TestFunc() <CR>

It's inspired from this answer to get the comment character depending the file type, and this answer to get the condition who permit to know if we are in a commented line.

The problem is, it add spaces around the escape(...) part, and in C language if the // is not at the first column, it's not considered as commented. So, this function is always commenting, and never uncommenting.

I thought to use a variable like:

let var=escape(b:comment_leader,'\/')
exe ':s/^/var/e'

But it's considered as text, not as a variable. And I don't know if we can use a variable in a command like this.

So, is there a way to achieve what I'm trying to do ?

  • 1
    I applaud your efforts to come up with your own commenting solution. Commenting is a fun exercise. However, if you are "just trying to get work done", I would recommend a commenting plugin as it is best to stand on the shoulders of giants. I use commentary.vim. Related answer and gist Commented Jul 5, 2018 at 14:26

1 Answer 1


There are several things to consider, so I'll try to provide an answer first and then elaborate on various choices you have at your disposal instead of doing this yourself in this crude manner.

The solution to embedding your variable within your command while using exec is straight forward, you can do this for the same :

exec ':s/^/' . var . '/e'

It should be fairly straight forward to understand what's going on, essentially we're just concatenating strings to form the actual command that we want to execute.

Now with regards to how you've chosen to get this done I have a few pointers to add :

  • You should look up a few vim options that are at your disposal to get information with regards to how commenting works in the current filetype, which will enable you to avoid hard coding the comment characters the way you're doing right now. The options being : commentstring, comments.
  • You can leverage existing solutions in place of building your own, again for the reason as they would add support for a wider variety of programming languages etc out of the box, making your life easier. The one I would recommend being https://github.com/tpope/vim-commentary
  • Thanks. I haven't seen anythings about comments or commentstring, that's why I didn't tried to use it. And it seems it's not working, I maybe don't have the good features. And for the plugging, I already tried one (I don't remember which one), it seems it didn't work, I don't know why. :s
    – Phantom
    Commented Jul 5, 2018 at 14:11
  • Another nice plugin for that: github.com/scrooloose/nerdcommenter
    – fievel
    Commented Jul 5, 2018 at 14:16
  • @Phantom check :h 'comments' and :h 'commentstring', these are buffer local settings and are usually set from within filetype plugins that either ship with vim, or of which you may add custom language runtime files (that aren't supported out of the box by vim). Commented Jul 5, 2018 at 20:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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