Repository: neovim
Issue: expression folding (foldexpr) bug
Labels: bug-vim,core,needs:vim-patch

<!-- Before reporting: search existing issues and check the FAQ. -->

- `nvim --version`: NVIM v0.4.4
- `vim -u DEFAULTS` (version: 8.1) behaves differently? No
- Operating system/version: macOS
- Terminal name/version: alacritty 0.5.0
- `$TERM`: xterm-256color

### Steps to reproduce using `nvim -u NORC`

Put the following in `nvim/ftplugin/tex/folding.vim` or `nvim/after/ftplugin/tex/folding.vim`

```vim
setlocal foldmethod=expr
setlocal foldexpr=LaTeXFoldsExpr(v:lnum)

" Sections to be folded
let g:LaTeXFolds_fold_sections = [
  \ 'part',
  \ 'chapter',
  \ 'section',
  \ 'subsection',
  \ 'subsubsection'
  \ ]

" Join all section names in a single regex
let s:sections_regex = '^\s*\\\(' . join(g:LaTeXFolds_fold_sections, '\|') . '\){\(.*\)}\s*$'

function! s:find_sections()
  " This function finds which sections in g:LaTeXFolds_fold_sections are
  " actually present in the document, and returns a dictionary where the keys
  " are the section names and the values are their foldlevel in the document.

  let fold_levels = {}

  let level = 1
  for section in g:LaTeXFolds_fold_sections
    let i = 1
    while i <= line('$')
      if getline(i) =~# '^\s*\\' . section . '{.*'
        let fold_levels[section] = level
        let level += 1
        break
      endif
      let i += 1
    endwhile
  endfor

  return fold_levels
endfunction

" s:find_sections() returns a dictionary where the keys are the section names
" and the values are their foldlevel in the document.
let s:fold_levels = s:find_sections()

function! LaTeXFoldsExpr(lnum)
  let line = getline(a:lnum)

  " If the line is blank return the fold level of the previous or the next
  " line, whichever is the lowest.
  if line =~ '^\s*$' | return '-1' | endif

  " Let \begin{document} and \end{document} remain unfolded
  if line =~# '^\s*\\\(begin\|end\)\s*{document}' | return '0' | endif

  " If this is a 'regular' line, return the fold level of the previous line
  if line !~# s:sections_regex | return '=' | endif

  " If I get here it means the line contains a sectioning command. Find which
  " one it is and return its fold level.
  let line_section = substitute(line, s:sections_regex, '\1', '')
  return '>' . s:fold_levels[line_section]
endfunction
```
 and open the LaTeX document

```latex
\documentclass{book}

\begin{document}

\chapter{A chapter}

\subsection{A subsection after a chapter, no section in between}

Foo bar baz.

\section{A section}

Foo bar baz.

\section{Another section}

Foo bar baz.

\chapter{Another chapter}

Foo bar baz.

\end{document}
```

### Actual behaviour

I have 3 questions:

1. line 7 of the test document contains a `subsection` (fold level = 3) right after a chapter (fold level = 1), with no sections in between. Now when I first open the document, this is what I get:

[![enter image description here][1]][1]

you can see that the fold text of that line contains 3 dashes, same as lines that contain sections. That indicates that neovim thinks that is a second level fold, instead of a third level one, as it should be.

Indeed, once I toggle the fold with `za`, I don't get to see its contents, instead the fold is now recognized as a level 3 fold, and another dash appears (I'm not going to post another screenshot, it's easy to check that that's what happens).

Once that fold is expanded for the first time it then behaves as expected. I suspect that is a bug, correct?

2. I return `-1` on every blank line. That means the fold level of that line is not yet defined, and it will be set to the fold level of the line before it or after it, whichever is smallest.

If that's what's happening, then why does line 14 have a foldlevel of 1, when lines 13 and 15 both have a fold level of 2 (to get the foldlevel of a line simply run `:echo foldlevel(14)`)? 


3. line 18, which is also blank, is assigned the foldlevel of 1, which is correct since the following line, line 19, starts a new chapter, i.e. a level 1 fold. But then why is it that the fold associated with the first chapter doesn't include it?

[![enter image description here][2]][2]

Shouldn't lines 5-18 all be in the same level 1 fold? I suspect what is happening is line 18 is in its own level 1 fold, and the fold associated with the first chapter goes from line 5 to 17.


  [1]: https://i.stack.imgur.com/JSvIG.png
  [2]: https://i.stack.imgur.com/Svq2b.png

### Expected behaviour

1. The subsection gets unfolded when I toggle the fold with `za`;
2. `:echo foldlevel(14)` returns `2`;
3. Lines 5-18 are all in the same level 1 fold.