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#init_buffer() abort " {{{1
  if !g:vimtex_fold_enabled
        \ || s:foldmethod_in_modeline() | return | endif
  " 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><nowait><buffer> zx :call vimtex#fold#refresh('zx')<cr>
    nnoremap <silent><nowait><buffer> zX :call vimtex#fold#refresh('zX')<cr>
    " Define commands
    command! -buffer VimtexRefreshFolds call vimtex#fold#refresh('zx')
    " Ensure that folds are refreshed on startup
    augroup vimtex_temporary
      autocmd! * <buffer>
      autocmd CursorMoved <buffer>
            \   call vimtex#fold#refresh('zx')
            \ | autocmd! vimtex_temporary CursorMoved <buffer>
    augroup END
  endif
endfunction
" }}}1
function! vimtex#fold#init_state(state) abort " {{{1
  "
  " Initialize the enabled fold types
  "
  let a:state.fold_types_dict = {}
  for [l:key, l:val] in items(g:vimtex_fold_types_defaults)
    let l:config = extend(deepcopy(l:val), get(g:vimtex_fold_types, l:key, {}))
    if get(l:config, 'enabled', 1)
      let a:state.fold_types_dict[l:key] = vimtex#fold#{l:key}#new(l:config)
    endif
  endfor
  "
  " Define ordered list and the global fold regex
  "
  let a:state.fold_types_ordered = []
  let a:state.fold_re = '\v'
        \ .  '\\%(begin|end)>'
        \ . '|^\s*\%'
        \ . '|^\s*\]\s*%(\{|$)'
        \ . '|^\s*}'
  for l:name in [
        \ 'preamble',
        \ 'cmd_single',
        \ 'cmd_single_opt',
        \ 'cmd_multi',
        \ 'cmd_addplot',
        \ 'sections',
        \ 'markers',
        \ 'comments',
        \ 'envs',
        \ 'env_options',
        \]
    let l:type = get(a:state.fold_types_dict, l:name, {})
    if !empty(l:type)
      call add(a:state.fold_types_ordered, l:type)
      if exists('l:type.re.fold_re')
        let a:state.fold_re .= '|' . l:type.re.fold_re
      endif
    endif
  endfor
endfunction
" }}}1
function! vimtex#fold#refresh(map) abort " {{{1
  setlocal foldmethod=expr
  execute 'normal!' a:map
  setlocal foldmethod=manual
endfunction
" }}}1
function! vimtex#fold#level(lnum) abort " {{{1
  let l:line = getline(a:lnum)
  " Filter out lines that do not start any folds (optimization)
  if l:line !~# b:vimtex.fold_re | return '=' | endif
  " Never fold \begin|end{document}
  if l:line =~# '^\s*\\\%(begin\|end\){document}'
    return 0
  endif
  for l:type in b:vimtex.fold_types_ordered
    let l:value = l:type.level(l:line, a:lnum)
    if !empty(l:value) | return l:value | endif
  endfor
  " Return foldlevel of previous line
  return '='
endfunction
" }}}1
function! vimtex#fold#text() abort " {{{1
  let l:line = getline(v:foldstart)
  let l:level = v:foldlevel > 1
        \ ? repeat('-', v:foldlevel-2) . g:vimtex_fold_levelmarker
        \ : ''
  for l:type in b:vimtex.fold_types_ordered
    if l:line =~# l:type.re.start
      let l:text = l:type.text(l:line, l:level)
      if !empty(l:text) | return l:text | endif
    endif
  endfor
endfunction
" }}}1
function! s:foldmethod_in_modeline() abort " {{{1
  let l:cursor_pos = vimtex#pos#get_cursor()
  let l:fdm_modeline = 'vim:.*\%(foldmethod\|fdm\)'
  call vimtex#pos#set_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 vimtex#pos#set_cursor(l:cursor_pos)
  return l:check_top || l:check_btm
endfunction
" }}}1
endif