5

Does anyone know a way to highlight only comments in vim?

Requirements:

  • For any colour scheme.
  • Without having to clear and re-add only the comment syntax group in each language's ftplugin.

I suppose I want something that loops over the syntax groups and removes them if it doesn't equal "Comment". Is this possible?

Thanks

  • 1
    You could write your own colorscheme. – romainl Nov 30 '16 at 16:45
  • 1
    Yes, but as the question states: "for any colour scheme". – Edd Barrett Nov 30 '16 at 16:49
3

Something like this perhaps:

func! ClearSyntax()
    let syn=split(execute('syn list'), "\n")[1:]
    call filter(syn, {idx, val -> match(val, '^\w') > -1})
    call map(syn, {idx, val -> split(val)[0]})
    for item in syn
        if match(item, '\c\mcomment') == -1
            try
                exe 'syn clear' item
                " ignore E28 (no such highlight group)
            catch /^Vim\%((\a\+)\)\=:E28/
            endtry
        endif
    endfor
endfu

com! ClearSyntaxExceptComments :call ClearSyntax()

This loops over the currently defined syntax items and undefines them, if they do not match comment

Note: only barely tested and needs Vim8

  • Undefined variable idx. I'm using nvim fwiw, – Edd Barrett Nov 30 '16 at 17:13
  • @EddBarrett it's not undefined. It's a lambda expression. As I said, needs a Vim8. – Christian Brabandt Nov 30 '16 at 18:00
  • @EddBarrett Is this not the solution you are looking for? – Christian Brabandt Dec 2 '16 at 8:44
  • It works for vim8, but not for nvim. I guess over time it will work in nvim too? – Edd Barrett Dec 2 '16 at 17:51
  • @EddBarrett it can be trivially adjusted for nvim, but that was not part of the question. Also lambda support will probably be merged evenutally – Christian Brabandt Dec 2 '16 at 19:36
2

If you can live with an imperfect solution, there is a simple way of achieving this effect.

In addition to syntax highlighting, Vim has a second mechanism for colouring text: Match Highlighting. We can use this to colour comments with the Comment colouring, and then switch off syntax highlighting entirely:

e.g. for Python:

function! ClearSyntax()
  match Comment /#.*$/
  syntax off
endfunction

command! ClearSyntax :call ClearSyntax()

The problems with this approach are:

  1. The code as pasted above only deals with a single language. If you need the function to work in different languages, you're going to need to change the match expression depending on the language.

    e.g. to support Python and HTML:

    function! ClearSyntax()
      if &ft ==? "python"
        match Comment /#.*$/
      elseif &ft ==? "html"
        match Comment /<!--\_.\{-}-->/
      endif
    
      syntax off
    endfunction
    
    command! ClearSyntax :call ClearSyntax()
    

    Depending on how many languages you need it to support, this ranges from "a little clunky" to "completely untenable", but really, the bigger problem is:

  2. It requires matching the comments with a regular expression.

    For a few languages, this is trivial, but for most, a complete solution can be difficult or even impossible.

    For instance, the sample regular expression I've used to match Python comments will erroneously find comments in lines that include a # character within a string:

    s = "This is not a comment: #"
    

    Single regular expressions are not a great tool for parsing source code, and hacking together something that works even most of the time can be fiddly, but there's no shortage of people trying online, so if your regex-fu isn't up to the task, it's fairly easy to find examples that handle most cases for most languages.

  • @edd-barrett Ugh. Re-reading your question, I think I may have misinterpreted your second requirement. Oh well. – Rich Jan 25 '17 at 16:45
1

Not sure exactly what you mean by highlight, but a simple approach would be:

hi clear Comment
hi link Comment Search

This makes it so that whatever the color scheme, it highlights comments the same way it would highlight a search.

You could put this in a function and bind it to a key if you didn't want to always have comments like this.

Here's a function that toggles between hilighted and regular comments:

let g:origComment = ''
" Save away the original Comment
redir =>> g:origComment
silent hi Comment
redir END
" Strip out the part we want
let g:origComment = matchstr(g:origComment, '\(\_.*Comment.*xxx\s*\)\@<=.*')

let g:commentsHighlighted = 0
function ToggleCommentHilight()
   if g:commentsHighlighted
      hi clear Comment
      exe "hi Comment " . g:origComment
      let g:commentsHighlighted = 0
   else
      hi clear Comment
      hi link Comment Search
      let g:commentsHighlighted = 1
   endif
endfunction
  • To clarify, I would like to highlight nothing but comments and for many different languages. – Edd Barrett Nov 30 '16 at 16:43
  • Ah, Looks like Christian's got the answer for that. :) – Tumbler41 Nov 30 '16 at 16:52
  • I got something close. I don't care to toggle. And I want to clear all other highlights but comments. I removed the toggle functionality and use syn clear to kill all other highlight. The problem I think is that we kill the language specific syntax group. – Edd Barrett Nov 30 '16 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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