<commit_before>" vimtex - LaTeX plugin for Vim
"
" Maintainer: <NAME>
" Email:      <EMAIL>
"

function! vimtex#fold#init_options() " {{{1
  call vimtex#util#set_default('g:vimtex_fold_enabled', 0)
  call vimtex#util#set_default('g:vimtex_fold_manual', 0)
  call vimtex#util#set_default('g:vimtex_fold_comments', 0)
  call vimtex#util#set_default('g:vimtex_fold_preamble', 1)
  call vimtex#util#set_default('g:vimtex_fold_envs', 1)
  call vimtex#util#set_default('g:vimtex_fold_parts',
        \ [
        \   'part',
        \   'appendix',
        \   'frontmatter',
        \   'mainmatter',
        \   'backmatter',
        \ ])
  call vimtex#util#set_default('g:vimtex_fold_sections',
        \ [
        \   'chapter',
        \   'section',
        \   'subsection',
        \   'subsubsection',
        \ ])

  " Disable manual mode in vimdiff
  let g:vimtex_fold_manual = &diff ? 0 : g:vimtex_fold_manual
endfunction

" }}}1
function! vimtex#fold#init_script() " {{{1
  let s:parts = '\v^\s*(\\|\% Fake)(' . join(g:vimtex_fold_parts, '|') . ')>'
  let s:secs  = '\v^\s*(\\|\% Fake)(' . join(g:vimtex_fold_sections,  '|') . ')>'
  let s:notbslash = '\%(\\\@<!\%(\\\\\)*\)\@<='
  let s:notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
endfunction

" }}}1
function! vimtex#fold#init_buffer() " {{{1
  if !g:vimtex_fold_enabled | return | endif
  if s:foldmethod_in_modeline() | return | endif

  " Initialize local work vars
  let b:vimtex_fold = {}

  " Set fold options
  setlocal foldmethod=expr
  setlocal foldexpr=vimtex#fold#level(v:lnum)
  setlocal foldtext=vimtex#fold#text()

  if g:vimtex_fold_manual
    " Remap zx to refresh fold levels
    nnoremap <silent><buffer> zx :call vimtex#fold#refresh('zx')<cr>
    nnoremap <silent><buffer> zX :call vimtex#fold#refresh('zX')<cr>

    " Define commands
    command! -buffer VimtexRefreshFolds call vimtex#fold#refresh('zx')

    " Set options for automatic/manual folding mode
    let s:fold_manual_id = get(s:, 'fold_manual_id', 0) + 1
    let b:fold_manual_augroup = 'vimtex_fold_' . s:fold_manual_id
    execute 'augroup' b:fold_manual_augroup
      autocmd!
      " vint: -ProhibitAutocmdWithNoGroup
      autocmd CursorMoved <buffer> call s:fold_manual_refresh()
      " vint: +ProhibitAutocmdWithNoGroup
    augroup END

    function! s:fold_manual_refresh()
      call vimtex#fold#refresh('zx')
      if exists('b:fold_manual_augroup')
        execute 'autocmd!' b:fold_manual_augroup
        execute 'augroup!' b:fold_manual_augroup
        unlet b:fold_manual_augroup
      endif
    endfunction
  endif
endfunction

function! s:foldmethod_in_modeline()
  let l:cursor_pos = getpos('.')
  let l:fdm_modeline = 'vim:.*\%(foldmethod\|fdm\)'

  call cursor(1, 1)
  let l:check_top = search(l:fdm_modeline, 'cn', &modelines)

  normal! G$
  let l:check_btm = search(l:fdm_modeline, 'b', line('$') + 1 - &modelines)

  call setpos('.', l:cursor_pos)
  return l:check_top || l:check_btm
endfunction

" }}}1

function! vimtex#fold#refresh(map) " {{{1
  setlocal foldmethod=expr
  execute 'normal! ' . a:map
  setlocal foldmethod=manual
endfunction

" }}}1
function! vimtex#fold#level(lnum) " {{{1
  " Refresh fold levels for section commands
  call s:refresh_folded_sections()

  " Check for normal lines first (optimization)
  let line = getline(a:lnum)
  if line !~# '^\s*%\|\\\%(document\|begin\|end\|'
        \ . 'front\|main\|back\|app\|sub\|section\|chapter\|part\)'
    return '='
  endif

  " Fold preamble
  if g:vimtex_fold_preamble
    if line =~# '^\s*\\documentclass'
      return '>1'
    elseif line =~# '^\s*\\begin\s*{\s*document\s*}'
      return '0'
    endif
  endif

  " Fold chapters and sections
  for [part, level] in b:vimtex_fold.parts
    if line =~# part
      return '>' . level
    endif
  endfor

  " Fold comments
  if g:vimtex_fold_comments
    if line =~# '^\s*%'
      let l:next = getline(a:lnum-1) !~# '^\s*%'
      let l:prev = getline(a:lnum+1) !~# '^\s*%'
      if l:next && ! l:prev
        return 'a1'
      elseif l:prev && ! l:next
        return 's1'
      endif
    endif
  endif

  " Never fold \end{document}
  if line =~# '^\s*\\end{document}'
    return 0
  endif

  " Fold environments
  if g:vimtex_fold_envs
    if line =~# s:notcomment . s:notbslash . '\\begin\s*{.\{-}}'
      if line !~# '\\end'
        return 'a1'
      endif
    elseif line =~# s:notcomment . s:notbslash . '\\end\s*{.\{-}}'
      if line !~# '\\begin'
        return 's1'
      endif
    endif
  endif

  " Return foldlevel of previous line
  return '='
endfunction

"
" 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.
"
function! s:refresh_folded_sections()
  " Only refresh if file has been changed
  let l:time = getftime(expand('%'))
  if l:time == get(b:vimtex_fold, 'time', 0) | return | endif
  let b:vimtex_fold.time = l:time

  " Initialize
  let b:vimtex_fold.parts = []
  let buffer = readfile(expand('%'))

  " Parse part commands (frontmatter, appendix, part, etc)
  let lines = filter(copy(buffer), 'v:val =~ ''' . s:parts . '''')
  for part in g:vimtex_fold_parts
    let partpattern = '^\s*\%(\\\|% Fake\)' . part . ':\?\>'
    for line in lines
      if line =~# partpattern
        call insert(b:vimtex_fold.parts, [partpattern, 1])
        break
      endif
    endfor
  endfor

  " We want a minimum of two top level parts
  if len(b:vimtex_fold.parts) >= 2
    let level = 1
  else
    let level = 0
    let b:vimtex_fold.parts = []
  endif

  " Parse section commands (chapter, [sub...]section)
  let lines = filter(copy(buffer), 'v:val =~ ''' . s:secs . '''')
  for part in g:vimtex_fold_sections
    let partpattern = '^\s*\%(\\\|% Fake\)' . part . ':\?\>'
    for line in lines
      if line =~# partpattern<commit_msg>Use getline instead of readfile<commit_after>" vimtex - LaTeX plugin for Vim
"
" Maintainer: <NAME>
" Email:      <EMAIL>
"

function! vimtex#fold#init_options() " {{{1
  call vimtex#util#set_default('g:vimtex_fold_enabled', 0)
  call vimtex#util#set_default('g:vimtex_fold_manual', 0)
  call vimtex#util#set_default('g:vimtex_fold_comments', 0)
  call vimtex#util#set_default('g:vimtex_fold_preamble', 1)
  call vimtex#util#set_default('g:vimtex_fold_envs', 1)
  call vimtex#util#set_default('g:vimtex_fold_parts',
        \ [
        \   'part',
        \   'appendix',
        \   'frontmatter',
        \   'mainmatter',
        \   'backmatter',
        \ ])
  call vimtex#util#set_default('g:vimtex_fold_sections',
        \ [
        \   'chapter',
        \   'section',
        \   'subsection',
        \   'subsubsection',
        \ ])

  " Disable manual mode in vimdiff
  let g:vimtex_fold_manual = &diff ? 0 : g:vimtex_fold_manual
endfunction

" }}}1
function! vimtex#fold#init_script() " {{{1
  let s:parts = '\v^\s*(\\|\% Fake)(' . join(g:vimtex_fold_parts, '|') . ')>'
  let s:secs  = '\v^\s*(\\|\% Fake)(' . join(g:vimtex_fold_sections,  '|') . ')>'
  let s:notbslash = '\%(\\\@<!\%(\\\\\)*\)\@<='
  let s:notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
endfunction

" }}}1
function! vimtex#fold#init_buffer() " {{{1
  if !g:vimtex_fold_enabled | return | endif
  if s:foldmethod_in_modeline() | return | endif

  " Initialize local work vars
  let b:vimtex_fold = {}

  " Set fold options
  setlocal foldmethod=expr
  setlocal foldexpr=vimtex#fold#level(v:lnum)
  setlocal foldtext=vimtex#fold#text()

  if g:vimtex_fold_manual
    " Remap zx to refresh fold levels
    nnoremap <silent><buffer> zx :call vimtex#fold#refresh('zx')<cr>
    nnoremap <silent><buffer> zX :call vimtex#fold#refresh('zX')<cr>

    " Define commands
    command! -buffer VimtexRefreshFolds call vimtex#fold#refresh('zx')

    " Set options for automatic/manual folding mode
    let s:fold_manual_id = get(s:, 'fold_manual_id', 0) + 1
    let b:fold_manual_augroup = 'vimtex_fold_' . s:fold_manual_id
    execute 'augroup' b:fold_manual_augroup
      autocmd!
      " vint: -ProhibitAutocmdWithNoGroup
      autocmd CursorMoved <buffer> call s:fold_manual_refresh()
      " vint: +ProhibitAutocmdWithNoGroup
    augroup END

    function! s:fold_manual_refresh()
      call vimtex#fold#refresh('zx')
      if exists('b:fold_manual_augroup')
        execute 'autocmd!' b:fold_manual_augroup
        execute 'augroup!' b:fold_manual_augroup
        unlet b:fold_manual_augroup
      endif
    endfunction
  endif
endfunction

function! s:foldmethod_in_modeline()
  let l:cursor_pos = getpos('.')
  let l:fdm_modeline = 'vim:.*\%(foldmethod\|fdm\)'

  call cursor(1, 1)
  let l:check_top = search(l:fdm_modeline, 'cn', &modelines)

  normal! G$
  let l:check_btm = search(l:fdm_modeline, 'b', line('$') + 1 - &modelines)

  call setpos('.', l:cursor_pos)
  return l:check_top || l:check_btm
endfunction

" }}}1

function! vimtex#fold#refresh(map) " {{{1
  setlocal foldmethod=expr
  execute 'normal! ' . a:map
  setlocal foldmethod=manual
endfunction

" }}}1
function! vimtex#fold#level(lnum) " {{{1
  " Refresh fold levels for section commands
  call s:refresh_folded_sections()

  " Check for normal lines first (optimization)
  let line = getline(a:lnum)
  if line !~# '^\s*%\|\\\%(document\|begin\|end\|'
        \ . 'front\|main\|back\|app\|sub\|section\|chapter\|part\)'
    return '='
  endif

  " Fold preamble
  if g:vimtex_fold_preamble
    if line =~# '^\s*\\documentclass'
      return '>1'
    elseif line =~# '^\s*\\begin\s*{\s*document\s*}'
      return '0'
    endif
  endif

  " Fold chapters and sections
  for [part, level] in b:vimtex_fold.parts
    if line =~# part
      return '>' . level
    endif
  endfor

  " Fold comments
  if g:vimtex_fold_comments
    if line =~# '^\s*%'
      let l:next = getline(a:lnum-1) !~# '^\s*%'
      let l:prev = getline(a:lnum+1) !~# '^\s*%'
      if l:next && ! l:prev
        return 'a1'
      elseif l:prev && ! l:next
        return 's1'
      endif
    endif
  endif

  " Never fold \end{document}
  if line =~# '^\s*\\end{document}'
    return 0
  endif

  " Fold environments
  if g:vimtex_fold_envs
    if line =~# s:notcomment . s:notbslash . '\\begin\s*{.\{-}}'
      if line !~# '\\end'
        return 'a1'
      endif
    elseif line =~# s:notcomment . s:notbslash . '\\end\s*{.\{-}}'
      if line !~# '\\begin'
        return 's1'
      endif
    endif
  endif

  " Return foldlevel of previous line
  return '='
endfunction

"
" 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.
"
function! s:refresh_folded_sections()
  " Only refresh if file has been changed
  let l:time = getftime(expand('%'))
  if l:time == get(b:vimtex_fold, 'time', 0) | return | endif
  let b:vimtex_fold.time = l:time

  " Initialize
  let b:vimtex_fold.parts = []
  let buffer = getline(1,'$')

  " Parse part commands (frontmatter, appendix, part, etc)
  let lines = filter(copy(buffer), 'v:val =~ ''' . s:parts . '''')
  for part in g:vimtex_fold_parts
    let partpattern = '^\s*\%(\\\|% Fake\)' . part . ':\?\>'
    for line in lines
      if line =~# partpattern
        call insert(b:vimtex_fold.parts, [partpattern, 1])
        break
      endif
    endfor
  endfor

  " We want a minimum of two top level parts
  if len(b:vimtex_fold.parts) >= 2
    let level = 1
  else
    let level = 0
    let b:vimtex_fold.parts = []
  endif

  " Parse section commands (chapter, [sub...]section)
  let lines = filter(copy(buffer), 'v:val =~ ''' . s:secs . '''')
  for part in g:vimtex_fold_sections
    let partpattern = '^\s*\%(\\\|% Fake\)' . part . ':\?\>'
    for line in lines
      if line =~# partpattern
{'fraction_non_alphanumeric': 0.15771840187620403, 'fraction_numerical': 0.005779378507412681, 'mean_word_length': 3.04883011190234, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4477634', 'n_tokens_mistral': 4659, 'n_tokens_neox': 4400, 'n_words': 1007}