hakononakani
hakononakani

Reputation: 305

Vim: language independent fall back to syntax folding with foldmethod=expr

My goal is to extend the foldmethod=syntax with an additional custom defined rule of my own.

My approach in doing so is to use foldmethod=expr and define this rule in my foldexpr (e.g. add a fold for '///' comments). After that the resources I found usually fall back to something similar to indentation folding. So is there a good way to fall back to syntax folding after the custom rules, without reproducing the complete grammar for whatever language I am using?

My attempt so far is this, which is not a very satisfying approximation of syntax folding:

function! GetFold(lnum)
  let this_line=getline(a:lnum)
  let pprev_i=indent(a:lnum - 2)/&shiftwidth
  let prev_i=indent(a:lnum - 1)/&shiftwidth
  let this_i=indent(a:lnum)/&shiftwidth
  " comments
  if this_line =~? '^\s*\/\/\/.*'
    return this_i + 1
  endif
  " like indent folding, but includes the closing bracket line to the fold
  if empty(this_line) 
    if prev_i < pprev_i
      return prev_i
    endif
    return -1
  endif 
  if this_i < prev_i
    return prev_i
  endif
  return this_i
endfunction

Upvotes: 1

Views: 278

Answers (2)

Ingo Karkat
Ingo Karkat

Reputation: 172510

No, there isn't a way to make Vim "fall back"; only one 'foldmethod' can be active at a time, and there's no API to evaluate another fold method "as if".

You could temporarily switch to syntax folding, store the generated folds, and then use that information in your fold information, extended with what your algorithm determines. (Or you could keep the same buffer in a window split, have syntax folding enabled there, and query it from the; this would save the complete re-creation of the folds, but you'd probably need to synchronize the cursor positions.)

This is cumbersome and possibly slow; I wouldn't recommend it.

Upvotes: 0

B.G.
B.G.

Reputation: 6016

The solution is to just use set fold=syntax and add a syntax region for the comments to your .vimrc. There you can use the fold keyword to mark the region as foldable (see :h syn-fold for more information):

 syn region myFold start="///" end="///" transparent fold  

(Note, take also a look at :h syn-transparent it is quite useful here)

Upvotes: 1

Related Questions