4

Simple question. I want to use the Tabular plugin to right-align end-of-line comments for arbitrary filetypes, and for that I need to write a simple nnoremap that uses the current filetype's comment character. How can I do this?

3 Answers 3

7

I usually go with the 'commentstring' option and depend on the filetype plugin to set this up correctly for me (if not, that should be added to the corresponding filetype to make at least folding work). So in that case, you can simply use:

echo split(&commentstring, '%s')[0]

which would return the beginning of a Comment. To get the end part, use index 1. Note however, that the end part might not be defined (for e.g. something like the shell comment '#'), in which case the index 1 will cause an error E684, so a robust approach would be something like this:

let comment=split(&commentstring, '%s')
if len(comment)==1
     call add(comment, '')
endif
2
  • Thanks! This is a great general answer. I have NERDCommenter installed though, so can also use the value b:NERDCommenterDelims['left'].
    – Luke Davis
    Jul 26, 2017 at 17:15
  • 1
    Based on your answer I made a PR to vim-snippets here Sep 21, 2021 at 23:45
2

Depending on the filetype, the way comments are defined can completely change. It's either :

  • a sequence that says "everything from now up to the end of the line is a comment"
  • or a sequence that says "everything from now up to another sequence is a comment".

Vim stores the information in the options 'comments' and 'commentstring'. Most commenter plugins duplicate the information as well. See @Luke Davis' answer regarding NERDCommenter.

In lh-dev, I use the following (which can be overridden if need be).

" # Comments related functions {{{2
" @move to lh/dev/comments/
" # lh#dev#_open_comment() {{{3
" @todo cache the results until :source that clears the table
function! lh#dev#_open_comment() abort
  " default asks to
  " - EnhancedCommentify
  if exists('b:ECcommentOpen') && !empty(b:ECcommentOpen) && exists('b:ECcommentClose') && !empty(b:ECcommentClose)
    return b:ECcommentOpen
  " - tComment
  " - NERDCommenter
  " - &commentstring
  elseif !empty(&commentstring) && &commentstring =~ '\v.+\%s.+'
    return matchstr(&commentstring, '\v.*\ze\%s')
  endif
  return ""
endfunction

" # lh#dev#_close_comment() {{{3
" @todo cache the results until :source that clear the table
function! lh#dev#_close_comment() abort
  " default asks to
  " - EnhancedCommentify
  if exists('b:ECcommentClose') && !empty(b:ECcommentClose)
    return b:ECcommentClose
  " - tComment
  " - NERDCommenter
  " - &commentstring
  elseif !empty(&commentstring) && &commentstring =~ '\v.+\%s.+'
    return matchstr(&commentstring, '\v.*\%s\zs.*')
  endif
  return ""
endfunction

" # lh#dev#_line_comment() {{{3
" @todo cache the results until :source that clear the table
function! lh#dev#_line_comment() abort
  " default asks to
  " - EnhancedCommentify
  if exists('b:ECcommentOpen') && !empty(b:ECcommentOpen) && (!exists('b:ECcommentClose') || empty(b:ECcommentClose))
    return b:ECcommentOpen
  " - tComment
  " - NERDCommenter
  " - &commentstring
  elseif !empty(&commentstring) && &commentstring =~ '\v.+\%s$'
    return matchstr(&commentstring, '\v.*\ze\%s.*')
  endif
  return ""
endfunction

See lh#dev#purge_comments() to see how it can be used.

0

Well, I figured out how to do this if you also use the NERDCommenter plugin. Simply query the 'left' key in the dictionary variable b:NERDCommenterDelims.

let CommentChar=b:NERDCommenterDelims['left']
echo CommentChar

b:NERDCommenterDelims also has a 'right' key-value pair to satisfy (e.g.) comments left-delimited by \* and right-delimited by *\.

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.