Don Reba
Don Reba

Reputation: 14031

How to fold C++-style comments in Vim?

Syntax folding in Vim makes it easy to create folds for regions, the start and end of which can be defined with regular expressions:

syn region myRegion start="#region" end="#endregion" transparent keepend extend fold

However, I am not sure how I can use syntax folding to define folds for C++-style comments, which are sets of lines beginning with "//".

Upvotes: 4

Views: 3316

Answers (2)

Tinmarino
Tinmarino

Reputation: 4041

To fold multiple line comment blocks, with foldmethod=indent you must use expresion and recode indent folding. Try this in your vimrc.

set foldmethod=expr
set foldexpr=FoldMethod(v:lnum)

function! FoldMethod(lnum)
  "get string of current line
  let crLine=getline(a:lnum)

  " check if empty line 
  if empty(crLine) "Empty line or end comment 
    return -1 " so same indent level as line before 
  endif 

  " check if comment 
  let a:data=join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )
  if a:data =~ ".*omment.*"
    return '='
  endif

  "Otherwise return foldlevel equal to indent /shiftwidth (like if
  "foldmethod=indent)
  else  "return indent base fold
    return indent(a:lnum)/&shiftwidth
endfunction

The last block :

indent(a:lnum)/&shiftwidth

Returns a foldlevel base on indent.

And the other one :

join( map(synstack(a:lnum, 1), 'synIDattr(v:val, "name")') )

Checks if the first character of the line is consider as a comment with the syntax. So it is a good way to merge indent and syntax folding with expression, the most advanced folding.

Note that you can also "set foldtext" depending on how you want the result to look like.

Upvotes: 0

Don Reba
Don Reba

Reputation: 14031

I think I found a solution:

:syn match comment "\v(^\s*//.*\n)+" fold

This is a multiline match that folds consecutive lines beginning with whitespace and double slashes. The "\v" in the beginning labels the pattern "very magic" for brevity. Seems to work.

Upvotes: 8

Related Questions