3

vim provides the methods foldclosed() and foldclosedend() to get the first and last line of a closed fold. The problem is: It does not respect nested folds.

For example this file:

line 1
  line 2
  line 3
    line 4
    line 5
  line 6
line 7

has manual folds:

  1. line 1 - 6
  2. line 3 - 5

All of them are closed (first the second, inner, fold, then the first, outer, fold). When calling foldclosed(4) and foldclosedend(4) I would expect to get the values 3 and 5, since this is the fold line 4 is contained in. However it returns 1 and 6 for all lines except 7 (which is not in a fold).

Is there a way to get the fold state of each fold that respects nested folds? I expect something like what mkview does, which remembers the correct nested folds:

3,5fold
1,6fold
1
normal! zo
3
normal! zc
1
normal! zc

1 Answer 1

2

There is no builtin vim-script function which provides that. But you can make your own using builtin foldclosed foldclosedend and foldlevel functions. Here is a snippet I made:

function NestFoldClosed(lnum)
  let b = foldlevel(a:lnum)
  let lnum = a:lnum
  if b > 1 
    let temp = b
    " find the previous line that has foldlevel one less than the current line
    while(temp == b)
      let lnum = lnum - 1
      let temp = foldlevel(lnum)
    endwhile
    return lnum + 1
  endif
  return foldclosed(a:lnum)
endfunction

function NestFoldClosedEnd(lnum)
  let b = foldlevel(a:lnum)
  let lnum = a:lnum
  if b > 1 
    let temp = b
    " find the next line that has foldlevel one less than the current line
    while(temp == b)
      let lnum = lnum + 1
      let temp = foldlevel(lnum)
    endwhile
    return lnum - 1
  endif
  return foldclosed(a:lnum)
endfunction

Now if you do the following and call NestFoldClosed(4) and NestFoldClosedEnd(4) you will get the correct line numbers.

:3,5fold 
:1,6fold 
:1 
:normal! zo 
:3 
:normal! zc 
:1 
:normal! zc
5
  • Wow, that works very vell! Many thanks!
    – radlan
    Mar 21 at 10:39
  • 1
    There is a simple mistate in the code that the # is used as comment character instead of ", but stackexchange won't let me edit that since it is less than 6 characters to be changed…
    – radlan
    Mar 21 at 10:40
  • Hmm, apart from the first impression, it does not fully work, unfortunately. If all folds (in this example) are closed, it returns the correct values. If only the outer one is closed, it still returns the same values. Even worse, if all folds are open it still returns 3 and 5 for the inner fold.
    – radlan
    Mar 21 at 10:53
  • @radlan after replacing # with " syntax highlighting does not work properly so I am keeping # instead for readability.
    – Coder_H
    Mar 21 at 10:59
  • 1
    @Coder_H StackExchange (unfortunately) does not have vimscript highlighting yet, but we would still prefer the correct code.
    – D. Ben Knoble
    Mar 21 at 12:32

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.