diff options
Diffstat (limited to 'autoload/vimtex/fold')
| -rw-r--r-- | autoload/vimtex/fold/cmd_addplot.vim | 51 | ||||
| -rw-r--r-- | autoload/vimtex/fold/cmd_multi.vim | 51 | ||||
| -rw-r--r-- | autoload/vimtex/fold/cmd_single.vim | 52 | ||||
| -rw-r--r-- | autoload/vimtex/fold/cmd_single_opt.vim | 53 | ||||
| -rw-r--r-- | autoload/vimtex/fold/comments.vim | 46 | ||||
| -rw-r--r-- | autoload/vimtex/fold/env_options.vim | 53 | ||||
| -rw-r--r-- | autoload/vimtex/fold/envs.vim | 188 | ||||
| -rw-r--r-- | autoload/vimtex/fold/markers.vim | 60 | ||||
| -rw-r--r-- | autoload/vimtex/fold/preamble.vim | 36 | ||||
| -rw-r--r-- | autoload/vimtex/fold/sections.vim | 180 | 
10 files changed, 770 insertions, 0 deletions
| diff --git a/autoload/vimtex/fold/cmd_addplot.vim b/autoload/vimtex/fold/cmd_addplot.vim new file mode 100644 index 00000000..9e997681 --- /dev/null +++ b/autoload/vimtex/fold/cmd_addplot.vim @@ -0,0 +1,51 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#cmd_addplot#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config).init() +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'cmd_addplot', +      \ 're' : {}, +      \ 'opened' : 0, +      \ 'cmds' : [], +      \} +function! s:folder.init() abort dict " {{{1 +  let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\s*%(\[[^\]]*\])?' + +  let self.re.start = l:re . '\s*\w+\s*%(\[[^\]]*\])?\s*\ze\{\s*%($|\%)' +  let self.re.end = '^\s*}' +  let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')' + +  return self +endfunction + +" }}}1 +function! s:folder.level(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.start +    let self.opened = 1 +    return 'a1' +  elseif self.opened && a:line =~# self.re.end +    let self.opened = 0 +    return 's1' +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  return matchstr(a:line, self.re.start) . '{...}' +        \ . substitute(getline(v:foldend), self.re.end, '', '') +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/cmd_multi.vim b/autoload/vimtex/fold/cmd_multi.vim new file mode 100644 index 00000000..cb84d09e --- /dev/null +++ b/autoload/vimtex/fold/cmd_multi.vim @@ -0,0 +1,51 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#cmd_multi#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config).init() +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'cmd_multi', +      \ 're' : {}, +      \ 'opened' : 0, +      \ 'cmds' : [], +      \} +function! s:folder.init() abort dict " {{{1 +  let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\*?' + +  let self.re.start = l:re . '.*(\{|\[)\s*(\%.*)?$' +  let self.re.end = '\v^\s*%(\}\s*\{)*\}\s*%(\%|$)' +  let self.re.text = l:re . '\{[^}]*\}' +  let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')' + +  return self +endfunction + +" }}}1 +function! s:folder.level(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.start +    let self.opened += 1 +    return 'a1' +  elseif self.opened > 0 && a:line =~# self.re.end +    let self.opened -= 1 +    return 's1' +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  return a:line +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/cmd_single.vim b/autoload/vimtex/fold/cmd_single.vim new file mode 100644 index 00000000..1403ad9b --- /dev/null +++ b/autoload/vimtex/fold/cmd_single.vim @@ -0,0 +1,52 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#cmd_single#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config).init() +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'cmd_single', +      \ 're' : {}, +      \ 'opened' : 0, +      \ 'cmds' : [], +      \} +function! s:folder.init() abort dict " {{{1 +  let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\*?\s*%(\[.*\])?' + +  let self.re.start = l:re . '\s*\{\s*%($|\%)' +  let self.re.end = '^\s*}' +  let self.re.text = l:re +  let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')' + +  return self +endfunction + +" }}}1 +function! s:folder.level(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.start +    let self.opened = 1 +    return 'a1' +  elseif self.opened && a:line =~# self.re.end +    let self.opened = 0 +    return 's1' +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  return matchstr(a:line, self.re.text) . '{...}' +        \ . substitute(getline(v:foldend), self.re.end, '', '') +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/cmd_single_opt.vim b/autoload/vimtex/fold/cmd_single_opt.vim new file mode 100644 index 00000000..8def0234 --- /dev/null +++ b/autoload/vimtex/fold/cmd_single_opt.vim @@ -0,0 +1,53 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#cmd_single_opt#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config).init() +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'cmd_single_opt', +      \ 're' : {}, +      \ 'opened' : 0, +      \ 'cmds' : [], +      \} +function! s:folder.init() abort dict " {{{1 +  let l:re = '\v^\s*\\%(' . join(self.cmds, '|') . ')\*?' + +  let self.re.start = l:re . '\s*\[\s*%($|\%)' +  let self.re.end = '^\s*\]{' +  let self.re.text = l:re +  let self.re.fold_re = '\\%(' . join(self.cmds, '|') . ')' + +  return self +endfunction + +" }}}1 +function! s:folder.level(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.start +    let self.opened = 1 +    return 'a1' +  elseif self.opened && a:line =~# self.re.end +    let self.opened = 0 +    return 's1' +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  let l:col = strlen(matchstr(a:line, '^\s*')) + 1 +  return matchstr(a:line, self.re.text) . '[...]{' +        \ . vimtex#cmd#get_at(v:foldstart, l:col).args[0].text . '}' +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/comments.vim b/autoload/vimtex/fold/comments.vim new file mode 100644 index 00000000..4a313064 --- /dev/null +++ b/autoload/vimtex/fold/comments.vim @@ -0,0 +1,46 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#comments#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config) +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'comments', +      \ 're' : {'start' : '^\s*%'}, +      \ 'opened' : 0, +      \} +function! s:folder.level(line, lnum) abort dict " {{{1 +  if exists('b:vimtex.fold_types_dict.markers.opened') +        \ && b:vimtex.fold_types_dict.markers.opened | return | endif + +  if a:line =~# self.re.start +    let l:next = getline(a:lnum-1) !~# self.re.start +    let l:prev = getline(a:lnum+1) !~# self.re.start +    if l:next && !l:prev +      let self.opened = 1 +      return 'a1' +    elseif l:prev && !l:next +      let self.opened = 0 +      return 's1' +    endif +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  let l:lines = map(getline(v:foldstart, v:foldend), 'matchstr(v:val, ''%\s*\zs.*\ze\s*'')') +  return matchstr(a:line, '^.*\s*%') . join(l:lines, ' ') +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/env_options.vim b/autoload/vimtex/fold/env_options.vim new file mode 100644 index 00000000..eab339bf --- /dev/null +++ b/autoload/vimtex/fold/env_options.vim @@ -0,0 +1,53 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#env_options#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config) +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'envs with options', +      \ 're' : { +      \   'start' : g:vimtex#re#not_comment . '\\begin\s*\{.{-}\}\[\s*($|\%)', +      \   'end' : '\s*\]\s*$', +      \ }, +      \ 'opened' : 0, +      \} +function! s:folder.level(line, lnum) abort dict " {{{1 +  return self.opened +        \ ? self.fold_closed(a:line, a:lnum) +        \ : self.fold_opened(a:line, a:lnum) +endfunction + +" }}}1 +function! s:folder.fold_opened(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.start +    let self.opened = 1 +    return 'a1' +  endif +endfunction + +" }}}1 +function! s:folder.fold_closed(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.end +    let self.opened = 0 +    return 's1' +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  return a:line . '...] ' +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/envs.vim b/autoload/vimtex/fold/envs.vim new file mode 100644 index 00000000..1eb70f3c --- /dev/null +++ b/autoload/vimtex/fold/envs.vim @@ -0,0 +1,188 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#envs#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config).init() +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'environments', +      \ 're' : { +      \   'start' : g:vimtex#re#not_comment . '\\begin\s*\{.{-}\}', +      \   'end' : g:vimtex#re#not_comment . '\\end\s*\{.{-}\}', +      \   'name' : g:vimtex#re#not_comment . '\\%(begin|end)\s*\{\zs.{-}\ze\}' +      \ }, +      \ 'whitelist' : [], +      \ 'blacklist' : [], +      \} +function! s:folder.init() abort dict " {{{1 +  " Define the validator as simple as possible +  if empty(self.whitelist) && empty(self.blacklist) +    function! self.validate(env) abort dict +      return 1 +    endfunction +  elseif empty(self.whitelist) +    function! self.validate(env) abort dict +      return index(self.blacklist, a:env) < 0 +    endfunction +  elseif empty(self.blacklist) +    function! self.validate(env) abort dict +      return index(self.whitelist, a:env) >= 0 +    endfunction +  else +    function! self.validate(env) abort dict +      return index(self.whitelist, a:env) >= 0 && index(self.blacklist, a:env) < 0 +    endfunction +  endif + +  return self +endfunction + +" }}}1 +function! s:folder.level(line, lnum) abort dict " {{{1 +  let l:env = matchstr(a:line, self.re.name) + +  if !empty(l:env) && self.validate(l:env) +    if a:line =~# self.re.start +      if a:line !~# '\\end' +        return 'a1' +      endif +    elseif a:line =~# self.re.end +      if a:line !~# '\\begin' +        return 's1' +      endif +    endif +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  let env = matchstr(a:line, self.re.name) +  if !self.validate(env) | return | endif + +  " Set caption/label based on type of environment +  if env ==# 'frame' +    let label = '' +    let caption = self.parse_caption_frame(a:line) +  elseif env ==# 'table' +    let label = self.parse_label() +    let caption = self.parse_caption_table(a:line) +  else +    let label = self.parse_label() +    let caption = self.parse_caption(a:line) +  endif + +  let width_ind = len(matchstr(a:line, '^\s*')) +  let width = winwidth(0) - (&number ? &numberwidth : 0) - 4 - width_ind + +  let width_env = 19 +  let width_lab = len(label) + 2 > width - width_env +        \ ? width - width_env +        \ : len(label) + 2 +  let width_cap = width - width_env - width_lab + +  if !empty(label) +    let label = printf('(%.*S)', width_lab, label) +  endif + +  if !empty(caption) +    if strchars(caption) > width_cap +      let caption = strpart(caption, 0, width_cap - 4) . '...' +    endif +  else +    let width_env += width_cap +    let width_cap = 0 +  endif + +  if strlen(env) > width_env - 8 +    let env = strpart(env, 0, width_env - 11) . '...' +  endif +  let env = '\begin{' . env . '}' + +  let title = printf('%*S%-*S %-*S  %*S', +        \ width_ind, '', +        \ width_env, env, +        \ width_cap, caption, +        \ width_lab, label) + +  return substitute(title, '\s\+$', '', '') +endfunction + +" }}}1 +function! s:folder.parse_label() abort dict " {{{1 +  let i = v:foldend +  while i >= v:foldstart +    if getline(i) =~# '^\s*\\label' +      return matchstr(getline(i), '^\s*\\label\%(\[.*\]\)\?{\zs.*\ze}') +    end +    let i -= 1 +  endwhile +  return '' +endfunction + +" }}}1 +function! s:folder.parse_caption(line) abort dict " {{{1 +  let i = v:foldend +  while i >= v:foldstart +    if getline(i) =~# '^\s*\\caption' +      return matchstr(getline(i), +            \ '^\s*\\caption\(\[.*\]\)\?{\zs.\{-1,}\ze\(}\s*\)\?$') +    end +    let i -= 1 +  endwhile + +  " If no caption found, check for a caption comment +  return matchstr(a:line,'\\begin\*\?{.*}\s*%\s*\zs.*') +endfunction + +" }}}1 +function! s:folder.parse_caption_table(line) abort dict " {{{1 +  let i = v:foldstart +  while i <= v:foldend +    if getline(i) =~# '^\s*\\caption' +      return matchstr(getline(i), +            \ '^\s*\\caption\s*\(\[.*\]\)\?\s*{\zs.\{-1,}\ze\(}\s*\)\?$') +    end +    let i += 1 +  endwhile + +  " If no caption found, check for a caption comment +  return matchstr(a:line,'\\begin\*\?{.*}\s*%\s*\zs.*') +endfunction + +" }}}1 +function! s:folder.parse_caption_frame(line) abort dict " {{{1 +  " Test simple variants first +  let caption1 = matchstr(a:line,'\\begin\*\?{.*}\(\[[^]]*\]\)\?{\zs.\+\ze}') +  let caption2 = matchstr(a:line,'\\begin\*\?{.*}\(\[[^]]*\]\)\?{\zs.\+') +  if !empty(caption1) +    return caption1 +  elseif !empty(caption2) +    return caption2 +  endif + +  " Search for \frametitle command +  let i = v:foldstart +  while i <= v:foldend +    if getline(i) =~# '^\s*\\frametitle' +      return matchstr(getline(i), +            \ '^\s*\\frametitle\(\[.*\]\)\?{\zs.\{-1,}\ze\(}\s*\)\?$') +    end +    let i += 1 +  endwhile + +  " If no caption found, check for a caption comment +  return matchstr(a:line,'\\begin\*\?{.*}\s*%\s*\zs.*') +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/markers.vim b/autoload/vimtex/fold/markers.vim new file mode 100644 index 00000000..00aa1fce --- /dev/null +++ b/autoload/vimtex/fold/markers.vim @@ -0,0 +1,60 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#markers#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config).init() +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'markers', +      \ 'open' : '{{{', +      \ 'close' : '}}}', +      \ 're' : {}, +      \ 'opened' : 0, +      \} +function! s:folder.init() abort dict " {{{1 +  let self.re.start = '%.*' . self.open +  let self.re.end = '%.*' . self.close +  let self.re.text = [ +        \ [self.re.start . '\d\?\s*\zs.*', '% ' . self.open . ' '], +        \ ['%\s*\zs.*\ze' . self.open, '% ' . self.open . ' '], +        \ ['^.*\ze\s*%', ''], +        \] + +  let self.re.fold_re = escape(self.open . '|' . self.close, '{}%+*.') + +  return self +endfunction + +" }}}1 +function! s:folder.level(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.start +    let s:self.opened = 1 +    return 'a1' +  elseif a:line =~# self.re.end +    let s:self.opened = 0 +    return 's1' +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  for [l:re, l:pre] in self.re.text +    let l:text = matchstr(a:line, l:re) +    if !empty(l:text) | return l:pre . l:text | endif +  endfor + +  return '% ' . self.open . ' ' . getline(v:foldstart + 1) +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/preamble.vim b/autoload/vimtex/fold/preamble.vim new file mode 100644 index 00000000..434064ee --- /dev/null +++ b/autoload/vimtex/fold/preamble.vim @@ -0,0 +1,36 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#preamble#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config) +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'preamble', +      \ 're' : { +      \   'start' : '^\s*\\documentclass', +      \   'fold_re' : '\\documentclass', +      \ }, +      \} +function! s:folder.level(line, lnum) abort dict " {{{1 +  if a:line =~# self.re.start +    return '>1' +  endif +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  return '      Preamble' +endfunction + +" }}}1 + +endif diff --git a/autoload/vimtex/fold/sections.vim b/autoload/vimtex/fold/sections.vim new file mode 100644 index 00000000..2929a728 --- /dev/null +++ b/autoload/vimtex/fold/sections.vim @@ -0,0 +1,180 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve Lervåg +" Email:      karl.yngve@gmail.com +" + +function! vimtex#fold#sections#new(config) abort " {{{1 +  return extend(deepcopy(s:folder), a:config).init() +endfunction + +" }}}1 + + +let s:folder = { +      \ 'name' : 'sections', +      \ 'parse_levels' : 0, +      \ 're' : {}, +      \ 'folds' : [], +      \ 'sections' : [], +      \ 'parts' : [], +      \ 'time' : 0, +      \} +function! s:folder.init() abort dict " {{{1 +  let self.re.parts = '\v^\s*\\%(' . join(self.parts, '|') . ')' +  let self.re.sections = '\v^\s*\\%(' . join(self.sections, '|') . ')' +  let self.re.fake_sections = '\v^\s*\% Fake%(' +        \ . join(self.sections, '|') . ').*' +  let self.re.any_sections = '\v^\s*%(\\|\% Fake)%(' +        \ . join(self.sections, '|') . ').*' + +  let self.re.start = self.re.parts +        \ . '|' . self.re.sections +        \ . '|' . self.re.fake_sections + +  let self.re.secpat1 = self.re.sections . '\*?\s*\{\zs.*' +  let self.re.secpat2 = self.re.sections . '\*?\s*\[\zs.*' + +  let self.re.fold_re = '\\%(' . join(self.parts + self.sections, '|') . ')' + +  return self +endfunction + +" }}}1 +function! s:folder.level(line, lnum) abort dict " {{{1 +  call self.refresh() + +  " Fold chapters and sections +  for [l:part, l:level] in self.folds +    if a:line =~# l:part +      return '>' . l:level +    endif +  endfor +endfunction + +" }}}1 +function! s:folder.text(line, level) abort dict " {{{1 +  if a:line =~# '\\frontmatter' +    let l:title = 'Frontmatter' +  elseif a:line =~# '\\mainmatter' +    let l:title = 'Mainmatter' +  elseif a:line =~# '\\backmatter' +    let l:title = 'Backmatter' +  elseif a:line =~# '\\appendix' +    let l:title = 'Appendix' +  elseif a:line =~# self.re.secpat1 +    let l:title = self.parse_title(matchstr(a:line, self.re.secpat1), 0) +  elseif a:line =~# self.re.secpat2 +    let l:title = self.parse_title(matchstr(a:line, self.re.secpat2), 1) +  elseif a:line =~# self.re.fake_sections +    let l:title = matchstr(a:line, self.re.fake_sections) +  endif + +  let l:level = self.parse_level(v:foldstart, a:level) + +  return printf('%-5s %-s', l:level, +        \ substitute(strpart(l:title, 0, winwidth(0) - 7), '\s\+$', '', '')) +endfunction + +" }}}1 +function! s:folder.parse_level(lnum, level) abort dict " {{{1 +  if !self.parse_levels | return a:level | endif + +  if !has_key(self, 'toc') +    let self.toc = vimtex#toc#new({ +        \ 'name' : 'Fold text ToC', +        \ 'layers' : ['content'], +        \ 'refresh_always' : 0, +        \}) +    let self.toc_updated = 0 +    let self.file_updated = {} +  endif + +  let l:file = expand('%') +  let l:ftime = getftime(l:file) + +  if l:ftime > get(self.file_updated, l:file) +        \ || localtime() > self.toc_updated + 300 +    call self.toc.get_entries(1) +    let self.toc_entries = filter( +          \ self.toc.get_visible_entries(), +          \ '!empty(v:val.number)') +    let self.file_updated[l:file] = l:ftime +    let self.toc_updated = localtime() +  endif + +  let l:entries = filter(deepcopy(self.toc_entries), 'v:val.line == a:lnum') +  if len(l:entries) > 1 +    call filter(l:entries, "v:val.file ==# expand('%:p')") +  endif + +  return empty(l:entries) ? '' : self.toc.print_number(l:entries[0].number) +endfunction + +" }}}1 +function! s:folder.parse_title(string, type) abort dict " {{{1 +  let l:idx = -1 +  let l:length = strlen(a:string) +  let l:level = 1 +  while l:level >= 1 +    let l:idx += 1 +    if l:idx > l:length +      break +    elseif a:string[l:idx] ==# ['}',']'][a:type] +      let l:level -= 1 +    elseif a:string[l:idx] ==# ['{','['][a:type] +      let l:level += 1 +    endif +  endwhile +  let l:parsed = strpart(a:string, 0, l:idx) +  return empty(l:parsed) +        \ ? '<untitled>' : l:parsed +endfunction + +" }}}1 +function! s:folder.refresh() abort dict " {{{1 +  " +  " Parse current buffer to find which sections to fold and their levels.  The +  " patterns are predefined to optimize the folding. +  " +  " We ignore top level parts such as \frontmatter, \appendix, \part, and +  " similar, unless there are at least two such commands in a document. +  " + +  " Only refresh if file has been changed +  let l:time = getftime(expand('%')) +  if l:time == self.time | return | endif +  let self.time = l:time + +  " Initialize +  let self.folds = [] +  let level = 0 +  let buffer = getline(1,'$') + +  " Parse part commands (frontmatter, appendix, etc) +  " Note: We want a minimum of two top level parts +  let lines = filter(copy(buffer), 'v:val =~ ''' . self.re.parts . '''') +  if len(lines) >= 2 +    let level += 1 +    call insert(self.folds, [self.re.parts, level]) +  endif + +  " Parse section commands (part, chapter, [sub...]section) +  let lines = filter(copy(buffer), 'v:val =~ ''' . self.re.any_sections . '''') +  for part in self.sections +    let partpattern = '^\s*\%(\\\|% Fake\)' . part . ':\?\>' +    for line in lines +      if line =~# partpattern +        let level += 1 +        call insert(self.folds, [partpattern, level]) +        break +      endif +    endfor +  endfor +endfunction + +" }}}1 + +endif | 
