A huge refactoring of the delimiter engine

See entry on 2016-02-06 in the changelog in doc/vimtex.txt,
:h vimtex-changelog, for more details.

Issues:
  #258
  #314
  #316
  #329
This commit is contained in:
Karl Yngve Lervåg 2016-02-06 20:21:27 +01:00
parent bb49c3e946
commit 490a24daf0
11 changed files with 1141 additions and 977 deletions

View File

@ -37,7 +37,7 @@ disabled if desired.
- Change the surrounding command or environment with `csc`/`cse`
- Toggle starred environment with `tse`
- Toggle between e.g. `()` and `\left(\right)` with `tsd`
- Close the current environment in insert mode with `]]`
- Close the current environment/delimiter in insert mode with `]]`
- Insert new command with `<F7>`
- Convenient insert mode mappings for faster typing of e.g. maths
- Improved folding (`:h 'foldexpr'`)

View File

@ -341,15 +341,17 @@ function! s:init_mappings() " {{{1
call s:map('n', '<localleader>lx', '<plug>(vimtex-reload)')
call s:map('n', '<localleader>ls', '<plug>(vimtex-toggle-main)')
call s:map('n', 'dse', '<plug>(vimtex-delete-env)')
call s:map('n', 'dsc', '<plug>(vimtex-delete-cmd)')
call s:map('n', 'cse', '<plug>(vimtex-change-env)')
call s:map('n', 'csc', '<plug>(vimtex-change-cmd)')
call s:map('n', 'tse', '<plug>(vimtex-toggle-star)')
call s:map('n', 'tsd', '<plug>(vimtex-toggle-delim)')
call s:map('n', '<F7>', '<plug>(vimtex-create-cmd)')
call s:map('i', '<F7>', '<plug>(vimtex-create-cmd)')
call s:map('i', ']]', '<plug>(vimtex-close-env)')
call s:map('n', 'dse', '<plug>(vimtex-env-delete)')
call s:map('n', 'cse', '<plug>(vimtex-env-change)')
call s:map('n', 'tse', '<plug>(vimtex-env-toggle-star)')
call s:map('n', 'dsc', '<plug>(vimtex-cmd-delete)')
call s:map('n', 'csc', '<plug>(vimtex-cmd-change)')
call s:map('n', '<F7>', '<plug>(vimtex-cmd-create)')
call s:map('i', '<F7>', '<plug>(vimtex-cmd-create)')
call s:map('n', 'tsd', '<plug>(vimtex-delim-toggle-modifier)')
call s:map('i', ']]', '<plug>(vimtex-delim-close)')
if g:vimtex_latexmk_enabled
call s:map('n', '<localleader>ll', '<plug>(vimtex-compile-toggle)')

View File

@ -1,483 +0,0 @@
" vimtex - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email: karl.yngve@gmail.com
"
function! vimtex#change#init_options() " {{{1
call vimtex#util#set_default('g:vimtex_change_complete_envs', [
\ 'itemize',
\ 'enumerate',
\ 'description',
\ 'center',
\ 'figure',
\ 'table',
\ 'equation',
\ 'multline',
\ 'align',
\ 'split',
\ '\[',
\ ])
call vimtex#util#set_default('g:vimtex_change_toggled_delims',
\ [['\\left', '\\right']])
call vimtex#util#set_default('g:vimtex_change_ignored_delims_pattern',
\ '\c\\bigg\?')
endfunction
" }}}1
function! vimtex#change#init_script() " {{{1
endfunction
" }}}1
function! vimtex#change#init_buffer() " {{{1
nnoremap <silent><buffer> <plug>(vimtex-delete-env)
\ :call vimtex#change#env('')<cr>
nnoremap <silent><buffer> <plug>(vimtex-delete-cmd)
\ :call vimtex#change#command_delete()<cr>
nnoremap <silent><buffer> <plug>(vimtex-change-env)
\ :call vimtex#change#env_prompt()<cr>
nnoremap <silent><buffer> <plug>(vimtex-change-cmd)
\ :call vimtex#change#command()<cr>
nnoremap <silent><buffer> <plug>(vimtex-toggle-star)
\ :call vimtex#change#toggle_env_star()<cr>
nnoremap <silent><buffer> <plug>(vimtex-toggle-delim)
\ :call vimtex#change#toggle_delim()<cr>
nnoremap <silent><buffer> <plug>(vimtex-create-cmd)
\ :call vimtex#change#to_command()<cr>i
inoremap <silent><buffer> <plug>(vimtex-create-cmd)
\ <c-r>=vimtex#change#to_command()<cr>
inoremap <silent><buffer> <plug>(vimtex-close-env)
\ <c-r>=vimtex#change#close_environment()<cr>
endfunction
" }}}1
function! vimtex#change#get_command(...) " {{{1
let l:position = a:0 > 0 ? a:1 : searchpos('\S', 'bcn')
let l:line = getline(l:position[0])
let l:char = l:line[l:position[1]-1]
" Lists of relevant syntax regions
let l:commands = [
\ 'texStatement',
\ 'texTypeSize',
\ 'texTypeStyle',
\ 'texBeginEnd',
\ ]
let l:argument = [
\ 'texMatcher',
\ 'texItalStyle',
\ 'texRefZone',
\ 'texBeginEndName',
\ ]
for l:syntax in reverse(map(call('synstack', l:position),
\ 'synIDattr(v:val, ''name'')'))
if index(l:commands, l:syntax) >= 0
let l:p = searchpos('\\', 'bcn')
let l:c = matchstr(l:line, '\\\zs\w\+', l:p[1]-1)
return [l:c] + l:p
elseif index(l:argument, l:syntax) >= 0
\ || (l:syntax ==# 'Delimiter' && l:char =~# '{\|}')
let l:curpos = exists('*getcurpos') ? getcurpos() : getpos('.')
keepjumps normal! vaBoh
let l:result = vimtex#change#get_command(searchpos('\S', 'bcn'))
call setpos('.', l:curpos)
return l:result
endif
endfor
return ['', 0, 0]
endfunction
function! vimtex#change#command() " {{{1
" Get old command
let [l:old, l:line, l:col] = vimtex#change#get_command()
if l:old ==# '' | return | endif
" Get new command
let l:new = input('Change ' . old . ' for: ')
let l:new = empty(l:new) ? l:old : l:new
" Store current cursor position
let l:curpos = exists('*getcurpos') ? getcurpos() : getpos('.')
if l:line == l:curpos[1]
let l:curpos[2] += len(l:new) - len(l:old)
endif
" This is a hack to make undo restore the correct position
normal! ix
normal! x
" Perform the change
let l:tmppos = copy(l:curpos)
let l:tmppos[1:2] = [l:line, l:col+1]
cal setpos('.', l:tmppos)
let l:savereg = @a
let @a = l:new
normal! cea
let @a = l:savereg
" Restore cursor position and create repeat hook
call setpos('.', l:curpos)
silent! call repeat#set("\<plug>(vimtex-change-cmd)" . new . ' ', v:count)
endfunction
function! vimtex#change#command_delete() " {{{1
" Get old command
let [l:old, l:line, l:col] = vimtex#change#get_command()
if l:old ==# '' | return | endif
" Store current cursor position
let l:curpos = exists('*getcurpos') ? getcurpos() : getpos('.')
if l:line == l:curpos[1]
let l:curpos[2] -= len(l:old)+1
endif
" Save selection
let l:vstart = [l:curpos[0], line("'<"), col("'<"), l:curpos[3]]
let l:vstop = [l:curpos[0], line("'<"), col("'>"), l:curpos[3]]
" This is a hack to make undo restore the correct position
normal! ix
normal! x
" Use temporary cursor position
let l:tmppos = copy(l:curpos)
let l:tmppos[1:2] = [l:line, l:col]
call setpos('.', l:tmppos)
normal! de
" Delete surrounding braces if present
if getline('.')[l:col-1 :] =~# '^\s*{'
call searchpos('{', 'c')
keepjumps normal! vaBomzoxg`zx
if l:line == l:curpos[1]
let l:curpos[2] -= 1
if l:curpos[2] < 0
let l:curpos[2] = 0
endif
endif
endif
" Restore cursor position and visual selection
call setpos('.', l:curpos)
call setpos("'<", l:vstart)
call setpos("'>", l:vstop)
" Create repeat hook
silent! call repeat#set("\<plug>(vimtex-delete-cmd)", v:count)
endfunction
function! vimtex#change#close_environment() " {{{1
" Get environment and delimiter info
let [env, env_l1, env_c1, env_l2, env_c2] = vimtex#util#get_env(1,0)
let [del_l1, del_c1] = searchpairpos('\C\\left\>', '', '\C\\right\>', 'bnW',
\ 'vimtex#util#in_comment()')
" Calculate scores
let env_score = env_l1*1000 + env_c1
let del_score = del_l1*1000 + del_c1
" Complete environment or delimiter, if any
if env_score > del_score
if env ==# '\['
return '\]'
elseif env ==# '\('
return '\)'
elseif env !=# ''
return '\end{' . env . '}'
endif
elseif del_score > 0
let line = strpart(getline(del_l1), del_c1 - 1)
let bracket = matchstr(line, '^\\left\zs\((\|\[\|\\{\||\|\.\)\ze')
for [open, close] in [
\ ['(', ')'],
\ ['\[', '\]'],
\ ['\\{', '\\}'],
\ ['|', '|'],
\ ['\.', '|'],
\ ]
let bracket = substitute(bracket, open, close, 'g')
endfor
return '\right' . bracket
endif
return ''
endfunction
function! vimtex#change#delim(open, close) " {{{1
let [d1, l1, c1, d2, l2, c2] = vimtex#util#get_delim()
let line = getline(l1)
let line = strpart(line,0,c1 - 1) . a:open . strpart(line, c1 + len(d1) - 1)
call setline(l1, line)
if l1 ==# l2
let n = len(a:open) - len(d1)
let c2 += n
let pos = getpos('.')
let pos[2] += n
call setpos('.', pos)
endif
let line = getline(l2)
let line = strpart(line,0,c2 - 1) . a:close . strpart(line, c2 + len(d2) - 1)
call setline(l2, line)
endfunction
function! vimtex#change#env(new) " {{{1
let [env, l1, c1, l2, c2] = vimtex#util#get_env(1)
if a:new ==# ''
let beg = ''
let end = ''
elseif a:new ==# '\[' || a:new ==# '['
let beg = '\['
let end = '\]'
elseif a:new ==# '\(' || a:new ==# '('
let beg = '\('
let end = '\)'
else
let beg = '\begin{' . a:new . '}'
let end = '\end{' . a:new . '}'
endif
let n1 = len(env) - 1
let n2 = len(env) - 1
if env !=# '\[' && env !=# '\('
let n1 += 8
let n2 += 6
endif
let line = getline(l1)
let line = strpart(line, 0, c1 - 1) . l:beg . strpart(line, c1 + n1)
call setline(l1, line)
let line = getline(l2)
let line = strpart(line, 0, c2 - 1) . l:end . strpart(line, c2 + n2)
call setline(l2, line)
if a:new ==# ''
silent! call repeat#set("\<plug>(vimtex-delete-env)", v:count)
else
silent! call repeat#set(
\ "\<plug>(vimtex-change-env)" . a:new . ' ', v:count)
endif
endfunction
function! vimtex#change#env_prompt() " {{{1
let new_env = input('Change ' . vimtex#util#get_env() . ' for: ', '',
\ 'customlist,' . s:sidwrap('input_complete'))
if empty(new_env)
return
else
call vimtex#change#env(new_env)
endif
endfunction
function! vimtex#change#to_command() " {{{1
" Get current line
let line = getline('.')
" Get cursor position
let pos = getpos('.')
" Return if there is no word at cursor
if mode() ==# 'n'
let column = pos[2] - 1
else
let column = pos[2] - 2
endif
if column <= 1 || line[column] =~# '\s'
return ''
endif
" Prepend a backslash to beginning of the current word
normal! B
let column = getpos('.')[2]
if line[column - 1] !=# '\'
let line = strpart(line, 0, column - 1) . '\' . strpart(line, column - 1)
call setline('.', line)
endif
" Append opening braces to the end of the current word
normal! E
let column = getpos('.')[2]
let pos[2] = column + 1
if line[column - 1] !=# '{'
let line = strpart(line, 0, column) . '{' . strpart(line, column)
call setline('.', line)
let pos[2] += 1
endif
" Restore cursor position
call setpos('.', pos)
return ''
endfunction
function! vimtex#change#toggle_delim() " {{{1
"
" Toggle \left and \right variants of delimiters
"
let [d1, l1, c1, d2, l2, c2] = vimtex#util#get_delim()
let [newd1, newd2] = s:toggle_delim_get_new(d1, d2)
if newd1 ==# '' | return 0 | endif
let line = getline(l1)
let line = strpart(line, 0, c1 - 1) . newd1 . strpart(line, c1 + len(d1) - 1)
call setline(l1, line)
if l1 ==# l2
let n = len(newd1) - len(d1)
let c2 += n
let pos = getpos('.')
let pos[2] += n
call setpos('.', pos)
endif
let line = getline(l2)
let line = strpart(line, 0, c2 - 1) . newd2 . strpart(line, c2 + len(d2) - 1)
call setline(l2, line)
silent! call repeat#set("\<plug>(vimtex-toggle-delim)", v:count)
endfunction
function! vimtex#change#toggle_env_star() " {{{1
let env = vimtex#util#get_env()
if env ==# '\('
return
elseif env ==# '\['
let new_env = equation
elseif env[-1:] ==# '*'
let new_env = env[:-2]
else
let new_env = env . '*'
endif
call vimtex#change#env(new_env)
silent! call repeat#set("\<plug>(vimtex-toggle-star)", v:count)
endfunction
function! vimtex#change#wrap_selection(wrapper) " {{{1
keepjumps normal! `>a}
execute 'keepjumps normal! `<i\' . a:wrapper . '{'
endfunction
function! vimtex#change#wrap_selection_prompt(...) " {{{1
let env = input('Environment: ', '',
\ 'customlist,' . s:sidwrap('input_complete'))
if empty(env)
return
endif
" Make sure custom indentation does not interfere
let ieOld = &indentexpr
setlocal indentexpr=""
if visualmode() ==# 'V'
execute 'keepjumps normal! `>o\end{' . env . '}'
execute 'keepjumps normal! `<O\begin{' . env . '}'
" indent and format, if requested.
if a:0 && a:1
normal! gv>
normal! gvgq
endif
else
execute 'keepjumps normal! `>a\end{' . env . '}'
execute 'keepjumps normal! `<i\begin{' . env . '}'
endif
exe 'setlocal indentexpr=' . ieOld
endfunction
" }}}1
function! s:sidwrap(func) " {{{1
return matchstr(expand('<sfile>'), '\zs<SNR>\d\+_\ze.*$') . a:func
endfunction
function! s:input_complete(lead, cmdline, pos) " {{{1
return filter(g:vimtex_change_complete_envs, 'v:val =~# ''^' . a:lead . '''')
endfunction
function! s:search_and_skip_comments(pat, ...) " {{{1
" Usage: s:search_and_skip_comments(pat, [flags, stopline])
let flags = a:0 >= 1 ? a:1 : ''
let stopline = a:0 >= 2 ? a:2 : 0
let saved_pos = getpos('.')
" search once
let ret = search(a:pat, flags, stopline)
if ret
" do not match at current position if inside comment
let flags = substitute(flags, 'c', '', 'g')
" keep searching while in comment
while vimtex#util#in_comment()
let ret = search(a:pat, flags, stopline)
if !ret
break
endif
endwhile
endif
if !ret
" if no match found, restore position
call setpos('.', saved_pos)
endif
return ret
endfunction
" }}}1
function! s:toggle_delim_get_new(d1,d2) " {{{1
if a:d1 =~# g:vimtex_change_ignored_delims_pattern
return ['', '']
endif
let newd1 = ''
let newd2 = ''
let delim = g:vimtex_change_toggled_delims
for i in range(len(delim))
let d1_1 = type(delim[i]) == 3 ? delim[i][0] : delim[i]
let d2_1 = type(delim[i]) == 3 ? delim[i][1] : delim[i]
if a:d1 =~# d1_1 . '\>'
if i+1 == len(delim)
let newd1 = substitute(a:d1, d1_1, '', '')
let newd2 = substitute(a:d2, d2_1, '', '')
else
let d1_2 = type(delim[i+1]) == 3 ? delim[i+1][0] : delim[i+1]
let d2_2 = type(delim[i+1]) == 3 ? delim[i+1][1] : delim[i+1]
let newd1 = substitute(a:d1, d1_1, d1_2, '')
let newd2 = substitute(a:d2, d2_1, d2_2, '')
endif
break
endif
endfor
if newd1 ==# ''
if len(a:d1) > 0
let d1_1 = type(delim[0]) == 3 ? delim[0][0] : delim[0]
let d2_1 = type(delim[0]) == 3 ? delim[0][1] : delim[0]
let newd1 = substitute(a:d1, '^', d1_1, '')
let newd2 = substitute(a:d2, '^', d2_1, '')
endif
endif
return [newd1, newd2]
endfunction
" }}}1
" vim: fdm=marker sw=2

190
autoload/vimtex/cmd.vim Normal file
View File

@ -0,0 +1,190 @@
" vimtex - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email: karl.yngve@gmail.com
"
function! vimtex#cmd#init_options() " {{{1
endfunction
" }}}1
function! vimtex#cmd#init_script() " {{{1
endfunction
" }}}1
function! vimtex#cmd#init_buffer() " {{{1
nnoremap <silent><buffer> <plug>(vimtex-cmd-delete)
\ :call vimtex#cmd#delete()<cr>
nnoremap <silent><buffer> <plug>(vimtex-cmd-change)
\ :call vimtex#cmd#change()<cr>
nnoremap <silent><buffer> <plug>(vimtex-cmd-create)
\ :call vimtex#cmd#create()<cr>i
inoremap <silent><buffer> <plug>(vimtex-cmd-create)
\ <c-r>=vimtex#cmd#create()<cr>
endfunction
" }}}1
function! vimtex#cmd#get_command(...) " {{{1
let l:position = a:0 > 0 ? a:1 : searchpos('\S', 'bcn')
let l:line = getline(l:position[0])
let l:char = l:line[l:position[1]-1]
" Lists of relevant syntax regions
let l:commands = [
\ 'texStatement',
\ 'texTypeSize',
\ 'texTypeStyle',
\ 'texBeginEnd',
\ ]
let l:argument = [
\ 'texMatcher',
\ 'texItalStyle',
\ 'texRefZone',
\ 'texBeginEndName',
\ ]
for l:syntax in reverse(map(call('synstack', l:position),
\ 'synIDattr(v:val, ''name'')'))
if index(l:commands, l:syntax) >= 0
let l:p = searchpos('\\', 'bcn')
let l:c = matchstr(l:line, '\\\zs\w\+', l:p[1]-1)
return [l:c] + l:p
elseif index(l:argument, l:syntax) >= 0
\ || (l:syntax ==# 'Delimiter' && l:char =~# '{\|}')
let l:curpos = exists('*getcurpos') ? getcurpos() : getpos('.')
keepjumps normal! vaBoh
let l:result = vimtex#cmd#get_command()
call setpos('.', l:curpos)
return l:result
endif
endfor
return ['', 0, 0]
endfunction
function! vimtex#cmd#change() " {{{1
" Get old command
let [l:old, l:line, l:col] = vimtex#cmd#get_command()
if l:old ==# '' | return | endif
" Get new command
let l:new = input('Change ' . old . ' for: ')
let l:new = empty(l:new) ? l:old : l:new
" Store current cursor position
let l:curpos = exists('*getcurpos') ? getcurpos() : getpos('.')
if l:line == l:curpos[1]
let l:curpos[2] += len(l:new) - len(l:old)
endif
" This is a hack to make undo restore the correct position
normal! ix
normal! x
" Perform the change
let l:tmppos = copy(l:curpos)
let l:tmppos[1:2] = [l:line, l:col+1]
cal setpos('.', l:tmppos)
let l:savereg = @a
let @a = l:new
normal! cea
let @a = l:savereg
" Restore cursor position and create repeat hook
call setpos('.', l:curpos)
silent! call repeat#set("\<plug>(vimtex-cmd-change)" . new . ' ', v:count)
endfunction
function! vimtex#cmd#delete() " {{{1
" Get old command
let [l:old, l:line, l:col] = vimtex#cmd#get_command()
if l:old ==# '' | return | endif
" Store current cursor position
let l:curpos = exists('*getcurpos') ? getcurpos() : getpos('.')
if l:line == l:curpos[1]
let l:curpos[2] -= len(l:old)+1
endif
" Save selection
let l:vstart = [l:curpos[0], line("'<"), col("'<"), l:curpos[3]]
let l:vstop = [l:curpos[0], line("'<"), col("'>"), l:curpos[3]]
" This is a hack to make undo restore the correct position
normal! ix
normal! x
" Use temporary cursor position
let l:tmppos = copy(l:curpos)
let l:tmppos[1:2] = [l:line, l:col]
call setpos('.', l:tmppos)
normal! de
" Delete surrounding braces if present
if getline('.')[l:col-1 :] =~# '^\s*{'
call searchpos('{', 'c')
keepjumps normal! vaBomzoxg`zx
if l:line == l:curpos[1]
let l:curpos[2] -= 1
if l:curpos[2] < 0
let l:curpos[2] = 0
endif
endif
endif
" Restore cursor position and visual selection
call setpos('.', l:curpos)
call setpos("'<", l:vstart)
call setpos("'>", l:vstop)
" Create repeat hook
silent! call repeat#set("\<plug>(vimtex-cmd-delete)", v:count)
endfunction
function! vimtex#cmd#create() " {{{1
" Get current line
let line = getline('.')
" Get cursor position
let pos = getpos('.')
" Return if there is no word at cursor
if mode() ==# 'n'
let column = pos[2] - 1
else
let column = pos[2] - 2
endif
if column <= 1 || line[column] =~# '\s'
return ''
endif
" Prepend a backslash to beginning of the current word
normal! B
let column = getpos('.')[2]
if line[column - 1] !=# '\'
let line = strpart(line, 0, column - 1) . '\' . strpart(line, column - 1)
call setline('.', line)
endif
" Append opening braces to the end of the current word
normal! E
let column = getpos('.')[2]
let pos[2] = column + 1
if line[column - 1] !=# '{'
let line = strpart(line, 0, column) . '{' . strpart(line, column)
call setline('.', line)
let pos[2] += 1
endif
" Restore cursor position
call setpos('.', pos)
return ''
endfunction
" }}}1
" vim: fdm=marker sw=2

640
autoload/vimtex/delim.vim Normal file
View File

@ -0,0 +1,640 @@
" vimtex - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email: karl.yngve@gmail.com
"
function! vimtex#delim#init_options() " {{{1
endfunction
" }}}1
function! vimtex#delim#init_script() " {{{1
let s:delims = {}
let s:re = {}
let s:delims.env = {
\ 'list' : [
\ ['begin', 'end'],
\ ['\(', '\)'],
\ ['\[', '\]'],
\ ['$$', '$$'],
\ ['$', '$'],
\ ],
\ 're' : [
\ ['\\begin\s*{[^}]*}', '\\end\s*{[^}]*}'],
\ ['\\(', '\\)'],
\ ['\\\[', '\\\]'],
\ ['\$\$', '\$\$'],
\ ['\$', '\$'],
\ ],
\}
let s:delims.delim_tex = {
\ 'list' : [
\ ['(', ')'],
\ ['[', ']'],
\ ['{', '}'],
\ ],
\ 're' : [
\ ['(', ')'],
\ ['\[', '\]'],
\ ['{', '}'],
\ ],
\}
let s:delims.delim_mods = {
\ 'list' : [
\ ['\left', '\right'],
\ ['\bigl', '\bigr'],
\ ['\Bigl', '\Bigr'],
\ ['\biggl', '\biggr'],
\ ['\Biggl', '\Biggr'],
\ ['\big', '\big'],
\ ['\Big', '\Big'],
\ ['\bigg', '\bigg'],
\ ['\Bigg', '\Bigg'],
\ ],
\ 're' : [
\ ['\\left', '\\right'],
\ ['\\bigl', '\\bigr'],
\ ['\\Bigl', '\\Bigr'],
\ ['\\biggl', '\\biggr'],
\ ['\\Biggl', '\\Biggr'],
\ ['\\big', '\\big'],
\ ['\\Big', '\\Big'],
\ ['\\bigg', '\\bigg'],
\ ['\\Bigg', '\\Bigg'],
\ ],
\}
let s:delims.delim_math = {
\ 'list' : [
\ ['(', ')'],
\ ['[', ']'],
\ ['\{', '\}'],
\ ['\|', '\|'],
\ ['|', '|'],
\ ['\langle', '\rangle'],
\ ['\lvert', '\rvert'],
\ ['\lfloor', '\rfloor'],
\ ['\lceil', '\rceil'],
\ ['\ulcorner', '\urcorner'],
\ ],
\ 're' : [
\ ['(', ')'],
\ ['\[', '\]'],
\ ['\\{', '\\}'],
\ ['\\|', '\\|'],
\ ['|', '|'],
\ ['\\langle', '\\rangle'],
\ ['\\lvert', '\\rvert'],
\ ['\\lfloor', '\\rfloor'],
\ ['\\lceil', '\\rceil'],
\ ['\\ulcorner', '\\urcorner'],
\ ],
\}
let s:re.env = {
\ 'open' : '\%('
\ . join(map(copy(s:delims.env.re), 'v:val[0]'), '\|')
\ . '\)',
\ 'close' : '\%('
\ . join(map(copy(s:delims.env.re), 'v:val[1]'), '\|')
\ . '\)',
\ 'both' : '\%('
\ . join(map(copy(s:delims.env.re), 'v:val[0]'), '\|') . '\|'
\ . join(map(copy(s:delims.env.re), 'v:val[1]'), '\|')
\ . '\)'
\}
let s:re.delim_tex = {
\ 'open' : '\%('
\ . join(map(copy(s:delims.delim_tex.re), 'v:val[0]'), '\|')
\ . '\)',
\ 'close' : '\%('
\ . join(map(copy(s:delims.delim_tex.re), 'v:val[1]'), '\|')
\ . '\)',
\ 'both' : '\%('
\ . join(map(copy(s:delims.delim_tex.re), 'v:val[0]'), '\|') . '\|'
\ . join(map(copy(s:delims.delim_tex.re), 'v:val[1]'), '\|')
\ . '\)'
\}
let s:re.delim_mods = {
\ 'open' : '\\left\|\\[bB]igg\?l\?',
\ 'close' : '\\right\|\\[bB]igg\?r\?',
\ 'both' : '\\left\|\\right\|\\[bB]igg\?[lr]\?',
\}
let s:re.delim_math = {
\ 'open' : '\%(\%(' . s:re.delim_mods.open . '\)\s*\)\?\%('
\ . join(map(copy(s:delims.delim_math.re), 'v:val[0]'), '\|')
\ . '\)',
\ 'close' : '\%(\%(' . s:re.delim_mods.close . '\)\s*\)\?\%('
\ . join(map(copy(s:delims.delim_math.re), 'v:val[1]'), '\|')
\ . '\)',
\ 'both' : '\%(\%(' . s:re.delim_mods.both . '\)\s*\)\?\%('
\ . join(map(copy(s:delims.delim_math.re), 'v:val[0]'), '\|') . '\|'
\ . join(map(copy(s:delims.delim_math.re), 'v:val[1]'), '\|')
\ . '\)'
\}
let s:delims.delim_all = {}
let s:delims.all = {}
let s:re.delim_all = {}
let s:re.all = {}
for k in ['list', 're']
let s:delims.delim_all[k] = s:delims.delim_math[k]
let s:delims.all[k] = s:delims.env[k] + s:delims.delim_all[k]
endfor
for k in ['open', 'close', 'both']
let s:re.delim_all[k] = s:re.delim_math[k]
let s:re.all[k] = s:re.env[k] . '\|' . s:re.delim_all[k]
endfor
let s:types = [
\ {
\ 're' : '\\\%(begin\|end\)\>',
\ 'parser' : function('s:parser_env'),
\ },
\ {
\ 're' : '\$\$\?',
\ 'parser' : function('s:parser_tex'),
\ },
\ {
\ 're' : '\\\%((\|)\|\[\|\]\)',
\ 'parser' : function('s:parser_latex'),
\ },
\ {
\ 're' : s:re.delim_all.both,
\ 'parser' : function('s:parser_delim'),
\ },
\]
endfunction
" }}}1
function! vimtex#delim#init_buffer() " {{{1
nnoremap <silent><buffer> <plug>(vimtex-delim-toggle-modifier)
\ :call vimtex#delim#toggle_modifier()<cr>
inoremap <silent><buffer> <plug>(vimtex-delim-close)
\ <c-r>=vimtex#delim#close()<cr>
endfunction
" }}}1
function! vimtex#delim#get_valid_regexps(...) " {{{1
"
" Arguments: (Optional)
" line number
" column number
"
" Returns:
" [regexp_open_delims, regexp_close_delims]
"
return call('vimtex#util#in_mathzone', a:000)
\ ? [s:re.delim_math.open, s:re.delim_math.close]
\ : [s:re.delim_tex.open, s:re.delim_tex.close]
endfunction
" }}}1
function! vimtex#delim#close() " {{{1
let l:delim = vimtex#delim#get_prev('all', 'open')
return empty(l:delim)
\ || get(l:delim, 'name', '') ==# 'document'
\ ? ''
\ : l:delim.corr
endfunction
" }}}1
function! vimtex#delim#toggle_modifier() " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding('delim_math')
if empty(l:open) | return | endif
let newmods = []
let modlist = [['', '']]
\ + get(g:, 'vimtex_delim_toggle_mod_list',
\ s:delims.delim_mods.list)
let n = len(modlist)
for i in range(n)
let j = (i + 1) % n
if l:open.mod ==# modlist[i][0]
let newmods = modlist[j]
break
endif
endfor
let line = getline(l:open.lnum)
let line = strpart(line, 0, l:open.cnum - 1)
\ . newmods[0]
\ . strpart(line, l:open.cnum + len(l:open.mod) - 1)
call setline(l:open.lnum, line)
let l:cnum = l:close.cnum
if l:open.lnum == l:close.lnum
let n = len(newmods[0]) - len(l:open.mod)
let l:cnum += n
let pos = getpos('.')
if pos[2] > l:open.cnum + len(l:open.mod)
let pos[2] += n
call setpos('.', pos)
endif
endif
let line = getline(l:close.lnum)
let line = strpart(line, 0, l:cnum - 1)
\ . newmods[1]
\ . strpart(line, l:cnum + len(l:close.mod) - 1)
call setline(l:close.lnum, line)
silent! call repeat#set("\<plug>(vimtex-delim-toggle-modifier)", v:count)
endfunction
" }}}1
function! vimtex#delim#get_next(type, side) " {{{1
return s:get_delim('next', a:type, a:side)
endfunction
" }}}1
function! vimtex#delim#get_prev(type, side) " {{{1
return s:get_delim('prev', a:type, a:side)
endfunction
" }}}1
function! vimtex#delim#get_current(type, side) " {{{1
return s:get_delim('current', a:type, a:side)
endfunction
" }}}1
function! vimtex#delim#get_matching(delim) " {{{1
if empty(a:delim) || !has_key(a:delim, 'lnum') | return {} | endif
"
" Get the matching position
"
let l:save_pos = getpos('.')
call setpos('.', [0, a:delim.lnum, a:delim.cnum, 0])
let [l:match, l:lnum, l:cnum] = a:delim.get_matching()
call setpos('.', l:save_pos)
"
" Create the match result
"
let l:matching = deepcopy(a:delim)
let l:matching.lnum = l:lnum
let l:matching.cnum = l:cnum
let l:matching.match = l:match
let l:matching.corr = a:delim.match
let l:matching.side = a:delim.is_open ? 'close' : 'open'
let l:matching.is_open = !a:delim.is_open
if l:matching.type ==# 'delim'
let l:matching.corr_delim = a:delim.delim
let l:matching.corr_mod = a:delim.mod
let l:matching.delim = a:delim.corr_delim
let l:matching.mod = a:delim.corr_mod
endif
return l:matching
endfunction
" }}}1
function! vimtex#delim#get_surrounding(type) " {{{1
let l:save_pos = getpos('.')
let l:lnum = l:save_pos[1]
let l:pos_val_cursor = 10000*l:save_pos[1] + l:save_pos[2]
while l:lnum > 1
let l:open = vimtex#delim#get_prev(a:type, 'open')
if empty(l:open) | break | endif
let l:close = vimtex#delim#get_matching(l:open)
let l:pos_val_try = 10000*l:close.lnum
\ + l:close.cnum + strlen(l:close.match)
if l:pos_val_try > l:pos_val_cursor
call setpos('.', l:save_pos)
return [l:open, l:close]
else
let l:lnum = l:open.lnum
call setpos('.', s:pos_prev(l:open.lnum, l:open.cnum))
endif
endwhile
call setpos('.', l:save_pos)
return [{}, {}]
endfunction
" }}}1
function! s:get_delim(direction, type, side) " {{{1
"
" Arguments:
" direction next
" prev
" current
" type env
" delim_tex
" delim_math
" delim_all
" all
" side open
" close
" both
"
" Returns:
" delim = {
" type : env | delim | $ | $$ | \( | \[
" side : open | close
" name : name of environment [only for type env]
" lnum : number
" cnum : number
" match : unparsed matched delimiter
" corr : corresponding delimiter
" re : {
" open : regexp for the opening part
" close : regexp for the closing part
" }
" }
"
let l:re = s:re[a:type][a:side]
let [l:lnum, l:cnum] = a:direction ==# 'next'
\ ? searchpos(l:re, 'cnW')
\ : a:direction ==# 'prev'
\ ? searchpos(l:re, 'bcnW')
\ : searchpos(l:re, 'bcnW', line('.'))
let l:match = matchstr(getline(l:lnum), '^' . l:re, l:cnum-1)
if a:direction ==# 'current'
\ && l:cnum + strlen(l:match) + (mode() ==# 'i' ? 1 : 0) <= col('.')
let l:match = ''
let l:lnum = 0
let l:cnum = 0
endif
let l:result = {
\ 'type' : '',
\ 'lnum' : l:lnum,
\ 'cnum' : l:cnum,
\ 'match' : l:match,
\}
for l:type in s:types
if l:match =~# '^' . l:type.re
let l:result = extend(
\ l:type.parser(l:match, l:lnum, l:cnum, a:side, a:type, a:direction),
\ l:result, 'keep')
break
endif
endfor
return empty(l:result.type) ? {} : l:result
endfunction
" }}}1
function! s:parser_env(match, lnum, cnum, ...) " {{{1
let result = {}
let result.type = 'env'
let result.name = matchstr(a:match, '{\zs.*\ze}')
let result.side = a:match =~# '\\begin' ? 'open' : 'close'
let result.is_open = result.side ==# 'open'
let result.get_matching = function('s:get_matching_env')
let result.corr = result.is_open
\ ? substitute(a:match, 'begin', 'end', '')
\ : substitute(a:match, 'end', 'begin', '')
let result.re = {
\ 'open' : '\\begin\s*{' . result.name . '}',
\ 'close' : '\\end\s*{' . result.name . '}',
\}
let result.re.this = result.is_open ? result.re.open : result.re.close
let result.re.corr = result.is_open ? result.re.close : result.re.open
return result
endfunction
" }}}1
function! s:parser_tex(match, lnum, cnum, side, type, direction) " {{{1
"
" TeX shorthand are these
"
" $ ... $ (inline math)
" $$ ... $$ (displayed equations)
"
" The notation does not provide the delimiter side directly, which provides
" a slight problem. However, we can utilize the syntax information to parse
" the side.
"
let result = {}
let result.type = a:match
let result.corr = a:match
let result.get_matching = function('s:get_matching_tex')
let result.re = {
\ 'this' : escape(a:match, '$'),
\ 'corr' : escape(a:match, '$'),
\ 'open' : escape(a:match, '$'),
\ 'close' : escape(a:match, '$'),
\}
let result.side = vimtex#util#in_syntax(
\ (a:match ==# '$' ? 'texMathZoneX' : 'texMathZoneY'),
\ a:lnum, a:cnum+1)
\ ? 'open' : 'close'
let result.is_open = result.side ==# 'open'
if (a:side !=# 'both') && (a:side !=# result.side)
"
" The current match ($ or $$) is not the correct side, so we must
" continue the search recursively. We do this by changing the cursor
" position, since the function searchpos relies on the current cursor
" position.
"
let l:save_pos = getpos('.')
" Move the cursor
call setpos('.', a:direction ==# 'next'
\ ? s:pos_next(a:lnum, a:cnum)
\ : s:pos_prev(a:lnum, a:cnum))
" Get new result
let result = s:get_delim(a:direction, a:type, a:side)
" Restore the cursor
call setpos('.', l:save_pos)
endif
return result
endfunction
" }}}1
function! s:parser_latex(match, lnum, cnum, ...) " {{{1
let result = {}
let result.type = a:match =~# '\\(\|\\)' ? '\(' : '\['
let result.side = a:match =~# '\\(\|\\\[' ? 'open' : 'close'
let result.is_open = result.side ==# 'open'
let result.get_matching = function('s:get_matching_latex')
let result.corr = result.is_open
\ ? substitute(substitute(a:match, '\[', ']', ''), '(', ')', '')
\ : substitute(substitute(a:match, '\]', '[', ''), ')', '(', '')
let result.re = {
\ 'open' : result.type ==# '\(' ? '\\(' : '\\\[',
\ 'close' : result.type ==# '\(' ? '\\)' : '\\\]',
\}
let result.re.this = result.is_open ? result.re.open : result.re.close
let result.re.corr = result.is_open ? result.re.close : result.re.open
return result
endfunction
" }}}1
function! s:parser_delim(match, lnum, cnum, ...) " {{{1
let result = {}
let result.type = 'delim'
let result.side = a:match =~# s:re.delim_all.open ? 'open' : 'close'
let result.is_open = result.side ==# 'open'
let result.get_matching = function('s:get_matching_delim')
"
" Find corresponding delimiter and the regexps
"
if a:match =~# '^' . s:re.delim_mods.both
let m1 = matchstr(a:match, '^' . s:re.delim_mods.both)
let d1 = substitute(strpart(a:match, len(m1)), '^\s*', '', '')
let m2 = s:parser_delim_get_corr(m1, 'delim_mods')
let d2 = s:parser_delim_get_corr(d1, 'delim_math')
let re = [
\ s:parser_delim_get_regexp(m1, 'delim_mods')
\ . '\s*' . s:parser_delim_get_regexp(d1, 'delim_math'),
\ s:parser_delim_get_regexp(m2, 'delim_mods')
\ . '\s*' . s:parser_delim_get_regexp(d2, 'delim_math')
\]
else
let d1 = a:match
let m1 = ''
let d2 = s:parser_delim_get_corr(a:match)
let m2 = ''
let re = [
\ s:parser_delim_get_regexp(a:match),
\ s:parser_delim_get_regexp(d2)
\]
endif
let result.delim = d1
let result.mod = m1
let result.corr = m2 . d2
let result.corr_delim = d2
let result.corr_mod = m2
let result.re = {
\ 'this' : re[0],
\ 'corr' : re[1],
\ 'open' : result.is_open ? re[0] : re[1],
\ 'close' : result.is_open ? re[1] : re[0],
\}
return result
endfunction
" }}}1
function! s:parser_delim_get_regexp(delim, ...) " {{{1
let l:type = a:0 > 0 ? a:1 : 'delim_all'
" Check open delimiters
let index = index(map(copy(s:delims[l:type].list), 'v:val[0]'), a:delim)
if index >= 0
return s:delims[l:type].re[index][0]
endif
" Check close delimiters
let index = index(map(copy(s:delims[l:type].list), 'v:val[1]'), a:delim)
if index >= 0
return s:delims[l:type].re[index][1]
endif
endfunction
" }}}1
function! s:parser_delim_get_corr(delim, ...) " {{{1
let l:type = a:0 > 0 ? a:1 : 'delim_all'
for l:pair in s:delims[l:type].list
if a:delim ==# l:pair[0]
return l:pair[1]
elseif a:delim ==# l:pair[1]
return l:pair[0]
endif
endfor
endfunction
" }}}1
function! s:get_matching_env() dict " {{{1
let [re, flags] = self.is_open
\ ? [self.re.close, 'nW']
\ : [self.re.open, 'bnW']
let [lnum, cnum] = searchpairpos(self.re.open, '', self.re.close, flags)
let match = matchstr(getline(lnum), '^' . re, cnum-1)
return [match, lnum, cnum]
endfunction
" }}}1
function! s:get_matching_tex() dict " {{{1
let [re, flags] = self.is_open
\ ? [self.re.open, 'nW']
\ : [self.re.open, 'bnW']
let [lnum, cnum] = searchpos(re, flags)
let match = matchstr(getline(lnum), '^' . re, cnum-1)
return [match, lnum, cnum]
endfunction
" }}}1
function! s:get_matching_latex() dict " {{{1
let [re, flags] = self.is_open
\ ? [self.re.close, 'nW']
\ : [self.re.open, 'bnW']
let [lnum, cnum] = searchpos(re, flags)
let match = matchstr(getline(lnum), '^' . re, cnum-1)
return [match, lnum, cnum]
endfunction
" }}}1
function! s:get_matching_delim() dict " {{{1
let [re, flags] = self.is_open
\ ? [self.re.close, 'nW']
\ : [self.re.open, 'bnW']
let [lnum, cnum] = searchpairpos(self.re.open, '', self.re.close, flags,
\ 'vimtex#util#in_comment()')
let match = matchstr(getline(lnum), '^' . re, cnum-1)
return [match, lnum, cnum]
endfunction
" }}}1
function! s:pos_next(lnum, cnum) " {{{1
return a:cnum < strlen(getline(a:lnum))
\ ? [0, a:lnum, a:cnum+1, 0]
\ : [0, a:lnum+1, 1, 0]
endfunction
" }}}1
function! s:pos_prev(lnum, cnum) " {{{1
return a:cnum > 1
\ ? [0, a:lnum, a:cnum-1, 0]
\ : [0, max([a:lnum-1, 1]), strlen(getline(a:lnum-1)), 0]
endfunction
" }}}1
" vim: fdm=marker sw=2

135
autoload/vimtex/env.vim Normal file
View File

@ -0,0 +1,135 @@
" vimtex - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email: karl.yngve@gmail.com
"
function! vimtex#env#init_options() " {{{1
call vimtex#util#set_default('g:vimtex_env_complete_list', [
\ 'itemize',
\ 'enumerate',
\ 'description',
\ 'center',
\ 'figure',
\ 'table',
\ 'equation',
\ 'multline',
\ 'align',
\ 'split',
\ '\[',
\ ])
endfunction
" }}}1
function! vimtex#env#init_script() " {{{1
endfunction
" }}}1
function! vimtex#env#init_buffer() " {{{1
nnoremap <silent><buffer> <plug>(vimtex-env-delete)
\ :call vimtex#env#change('')<cr>
nnoremap <silent><buffer> <plug>(vimtex-env-change)
\ :call vimtex#env#change_prompt()<cr>
nnoremap <silent><buffer> <plug>(vimtex-env-toggle-star)
\ :call vimtex#env#toggle_star()<cr>
endfunction
" }}}1
function! vimtex#env#change(new) " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding('env')
"
" Set target environment
"
if a:new ==# ''
let [l:beg, l:end] = ['', '']
elseif a:new ==# '$'
let [l:beg, l:end] = ['$', '$']
elseif a:new ==# '$$'
let [l:beg, l:end] = ['$$', '$$']
elseif a:new ==# '\['
let [l:beg, l:end] = ['\[', '\]']
elseif a:new ==# '\('
let [l:beg, l:end] = ['\(', '\)']
else
let l:beg = '\begin{' . a:new . '}'
let l:end = '\end{' . a:new . '}'
endif
let l:line = getline(l:open.lnum)
call setline(l:open.lnum,
\ strpart(l:line, 0, l:open.cnum-1)
\ . l:beg
\ . strpart(l:line, l:open.cnum + len(l:open.match) - 1))
let l:c1 = l:close.cnum
let l:c2 = l:close.cnum + len(l:close.match) - 1
if l:open.lnum == l:close.lnum
let n = len(l:beg) - len(l:open.match)
let l:c1 += n
let l:c2 += n
let pos = getpos('.')
if pos[2] > l:open.cnum + len(l:open.match) - 1
let pos[2] += n
call setpos('.', pos)
endif
endif
let l:line = getline(l:close.lnum)
call setline(l:close.lnum,
\ strpart(l:line, 0, l:c1-1) . l:end . strpart(l:line, l:c2))
if a:new ==# ''
silent! call repeat#set("\<plug>(vimtex-env-delete)", v:count)
else
silent! call repeat#set(
\ "\<plug>(vimtex-env-change)" . a:new . ' ', v:count)
endif
endfunction
function! vimtex#env#change_prompt() " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding('env')
let l:name = l:open.type ==# 'env' ? l:open.name : l:open.type
call vimtex#echo#status(['Change surrounding environment: ',
\ ['VimtexWarning', l:name]])
echohl VimtexMsg
let l:new_env = input('> ', '', 'customlist,' . s:sidwrap('input_complete'))
echohl None
if empty(l:new_env)
return
else
call vimtex#env#change(l:new_env)
endif
endfunction
function! vimtex#env#toggle_star() " {{{1
let [l:open, l:close] = vimtex#delim#get_surrounding('env')
if l:open.type !=# 'env' | return | endif
call vimtex#env#change(l:open.name[-1:] ==# '*'
\ ? l:open.name[:-2]
\ : l:open.name . '*'
\)
silent! call repeat#set("\<plug>(vimtex-env-toggle-star)", v:count)
endfunction
" }}}1
function! s:sidwrap(func) " {{{1
return matchstr(expand('<sfile>'), '\zs<SNR>\d\+_\ze.*$') . a:func
endfunction
" }}}1
function! s:input_complete(lead, cmdline, pos) " {{{1
return filter(g:vimtex_env_complete_list, 'v:val =~# ''^' . a:lead . '''')
endfunction
" }}}1
" vim: fdm=marker sw=2

View File

@ -19,7 +19,7 @@ function! vimtex#motion#init_script() " {{{1
if g:vimtex_motion_matchparen
augroup vimtex_motion
autocmd!
autocmd! CursorMoved *.tex call s:highlight_matching_pair(1)
autocmd! CursorMoved *.tex call s:highlight_matching_pair()
autocmd! CursorMovedI *.tex call s:highlight_matching_pair()
augroup END
endif
@ -34,32 +34,6 @@ function! vimtex#motion#init_script() " {{{1
" Not in a comment
let s:notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
" Patterns to match opening and closing delimiters/environments
let s:delimiters_open = [
\ '{',
\ '(',
\ '\[',
\ '\\{',
\ '\\(',
\ '\\\[',
\ '\\\Cbegin\s*{.\{-}}',
\ '\\\Cleft\s*\%([^\\a-zA-Z0-9]\|\\.\|\\\a*\)',
\ '\\\cbigg\?\((\|\[\|\\{\)',
\ ]
let s:delimiters_close = [
\ '}',
\ ')',
\ '\]',
\ '\\}',
\ '\\)',
\ '\\\]',
\ '\\\Cend\s*{.\{-}}',
\ '\\\Cright\s*\%([^\\a-zA-Z0-9]\|\\.\|\\\a*\)',
\ '\\\cbigg\?\()\|\]\|\\}\)',
\ ]
let s:delimiters = join(s:delimiters_open + s:delimiters_close, '\|')
let s:delimiters = '\(' . s:delimiters . '\|\$\)'
" Pattern to match section/chapter/...
let s:section = s:notcomment . '\v\s*\\'
let s:section .= '((sub)*section|chapter|part|'
@ -130,54 +104,19 @@ function! vimtex#motion#find_matching_pair(...) " {{{1
if vimtex#util#in_comment() | return | endif
" Save position
let nl = line('.')
let nc = col('.')
" Find delimiter under cursor
let [lnum, cnum] = searchpos(s:delimiters, 'cbnW', nl-2)
let delim = matchstr(getline(lnum), '^' . s:delimiters, cnum-1)
" If delimiter not found, try to search forward instead
let delim = vimtex#delim#get_current('all', 'both')
if empty(delim)
let [lnum, cnum] = searchpos(s:delimiters, 'cnW', nl+2)
let delim = matchstr(getline(lnum), '^'. s:delimiters, cnum-1)
if empty(delim)
return
endif
let delim = vimtex#delim#get_next('all', 'both')
if empty(delim) | return | endif
endif
" Utility pattern to NOT match the current cursor position
let not_cursor = '\%(\%'. lnum . 'l\%' . cnum . 'c\)\@!'
let delim = vimtex#delim#get_matching(delim)
if empty(delim) | return | endif
" Finally, find the matching delimiter
if delim =~# '^\$'
let inline = s:notcomment . s:notbslash . '\$'
let [lnum0, cnum0] = searchpos('.', 'nW')
if lnum0 && vimtex#util#in_syntax('texMathZoneX', lnum0, cnum0)
let [lnum2, cnum2] = searchpos(inline, 'nW', 0, 200)
else
let [lnum2, cnum2] = searchpos(not_cursor . inline, 'bnW', 0, 200)
endif
call cursor(lnum2,cnum2)
else
for i in range(len(s:delimiters))
let open_pat = '\C' . s:notbslash . s:delimiters_open[i]
let close_pat = '\C' . s:notbslash . s:delimiters_close[i]
if delim =~# '^' . open_pat
call searchpairpos(open_pat, '', close_pat,
\ 'W', 'vimtex#util#in_comment()', 0, 200)
call search(close_pat, 'ce')
return
elseif delim =~# '^' . close_pat
call searchpairpos(open_pat, '', not_cursor . close_pat,
\ 'bW', 'vimtex#util#in_comment()', 0, 200)
return
endif
endfor
endif
call cursor(delim.lnum,
\ (delim.is_open
\ ? delim.cnum
\ : delim.cnum + strlen(delim.match) - 1))
endfunction
" }}}1
@ -252,70 +191,21 @@ endfunction
" }}}1
function! s:highlight_matching_pair(...) " {{{1
function! s:highlight_matching_pair() " {{{1
if vimtex#util#in_comment() | return | endif
let hmode = a:0 > 0 ? 1 : 0
2match none
" Save position
let nl = line('.')
let nc = col('.')
let line = getline(nl)
let l:d1 = vimtex#delim#get_current('all', 'both')
let l:d2 = vimtex#delim#get_matching(l:d1)
if empty(l:d2) | return | endif
" Find delimiter under cursor
let cnum = searchpos(s:delimiters, 'cbnW', nl)[1]
let delim = matchstr(line, '^'. s:delimiters, cnum-1)
let [l1, c1, l2, c2] = l:d1.side ==# 'open'
\ ? [l:d1.lnum, l:d1.cnum, l:d2.lnum, l:d2.cnum]
\ : [l:d2.lnum, l:d2.cnum, l:d1.lnum, l:d1.cnum]
" Only highlight when cursor is on delimiters
if empty(delim) || strlen(delim)+cnum-hmode < nc
return
endif
if delim =~# '^\$'
"
" Match inline math
"
let [lnum0, cnum0] = searchpos('.', 'nW')
if lnum0 && vimtex#util#in_syntax('texMathZoneX', lnum0, cnum0)
let [lnum2, cnum2] = searchpos(s:notcomment . s:notbslash . '\$',
\ 'nW', line('w$'), 200)
else
let [lnum2, cnum2] = searchpos('\%(\%'. nl . 'l\%'
\ . cnum . 'c\)\@!'. s:notcomment . s:notbslash . '\$',
\ 'bnW', line('w0'), 200)
endif
execute '2match MatchParen /\%(\%' . nl . 'l\%'
\ . cnum . 'c\$' . '\|\%' . lnum2 . 'l\%' . cnum2 . 'c\$\)/'
else
"
" Match other delimitors
"
for i in range(len(s:delimiters_open))
let open_pat = '\C' . s:notbslash . s:delimiters_open[i]
let close_pat = '\C' . s:notbslash . s:delimiters_close[i]
if delim =~# '^' . open_pat
let [lnum2, cnum2] = searchpairpos(open_pat, '', close_pat,
\ 'nW', 'vimtex#util#in_comment()', line('w$'), 200)
execute '2match MatchParen /\%(\%' . nl . 'l\%' . cnum
\ . 'c' . s:delimiters_open[i] . '\|\%'
\ . lnum2 . 'l\%' . cnum2 . 'c'
\ . s:delimiters_close[i] . '\)/'
return
elseif delim =~# '^' . close_pat
let [lnum2, cnum2] = searchpairpos(open_pat, '',
\ '\C\%(\%'. nl . 'l\%' . cnum . 'c\)\@!' . close_pat,
\ 'bnW', 'vimtex#util#in_comment()', line('w0'), 200)
execute '2match MatchParen /\%(\%' . lnum2 . 'l\%' . cnum2
\ . 'c' . s:delimiters_open[i] . '\|\%'
\ . nl . 'l\%' . cnum . 'c'
\ . s:delimiters_close[i] . '\)/'
return
endif
endfor
endif
execute '2match MatchParen /'
\ . '\%' . l1 . 'l\%' . c1 . 'c' . l:d1.re.open
\ . '\|\%' . l2 . 'l\%' . c2 . 'c' . l:d1.re.close . '/'
endfunction
" }}}1

View File

@ -56,108 +56,43 @@ endfunction
" }}}1
function! vimtex#text_obj#delimiters(...) " {{{1
let inner = a:0 > 0
let [d1, l1, c1, d2, l2, c2] = vimtex#delim#get_surrounding()
if inner
let c1 += len(d1)
if c1 != len(getline(l1))
let l1 += 1
let c1 = 1
endif
endif
if inner
let c2 -= 1
if c2 < 1
let l2 -= 1
let c2 = len(getline(l2))
endif
else
let c2 += len(d2) - 1
endif
if l1 < l2 || (l1 == l2 && c1 < c2)
call cursor(l1,c1)
if visualmode() ==# 'V'
normal! V
else
normal! v
endif
call cursor(l2,c2)
endif
let [l:open, l:close] = vimtex#delim#get_surrounding('delim_all')
call s:text_obj_delim(l:open, l:close, a:0 > 0)
endfunction
" }}}1
function! vimtex#text_obj#environments(...) " {{{1
let inner = a:0 > 0
let l:inner = a:0 > 0
let [env, lnum, cnum, lnum2, cnum2] = vimtex#util#get_env(1)
call cursor(lnum, cnum)
if inner
if env =~# '^\'
call search('\\.\_\s*\S', 'eW')
else
call search('}\(\_\s*\(\[\_[^]]*\]\|{\_\S\{-}}\)\)\?\_\s*\S', 'eW')
endif
let [l:open, l:close] = vimtex#delim#get_surrounding('env')
if l:open.type !=# 'env' | return | endif
if l:inner
call cursor(l:open.lnum, l:open.cnum + strlen(l:open.match))
call search('}\%(\_\s*\%(\[\_[^]]*\]\)\)\?\_\s*\S', 'eW')
else
call cursor(l:open.lnum, l:open.cnum)
endif
if visualmode() ==# 'V'
normal! V
else
normal! v
endif
call cursor(lnum2, cnum2)
if inner
if l:inner
call cursor(l:close.lnum, l:close.cnum)
call search('\S\_\s*', 'bW')
else
if env =~# '^\'
normal! l
else
call search('}', 'eW')
endif
call cursor(l:close.lnum, l:close.cnum + strlen(l:close.match) - 1)
endif
endfunction
" }}}1
function! vimtex#text_obj#inline_math(...) " {{{1
let l:inner = a:0 > 0
let l:flags = 'bW'
let l:dollar = 0
let l:dollar_pat = '\\\@<!\$'
if vimtex#util#in_syntax('texMathZoneX')
let l:dollar = 1
let l:pattern = [l:dollar_pat, l:dollar_pat]
let l:flags .= 'c'
elseif getline('.')[col('.') - 1] ==# '$'
let l:dollar = 1
let l:pattern = [l:dollar_pat, l:dollar_pat]
elseif vimtex#util#in_syntax('texMathZoneV')
let l:pattern = ['\\(', '\\)']
let l:flags .= 'c'
elseif getline('.')[col('.') - 2:col('.') - 1] ==# '\)'
let l:pattern = ['\\(', '\\)']
else
return
endif
call s:search_and_skip_comments(l:pattern[0], l:flags)
if l:inner
execute 'normal! ' l:dollar ? 'l' : 'll'
endif
execute 'normal! ' visualmode() ==# 'V' ? 'V' : 'v'
call s:search_and_skip_comments(l:pattern[1], 'W')
if l:inner
normal! h
elseif !l:dollar
normal! l
endif
let [l:open, l:close] = vimtex#delim#get_surrounding('env')
if empty(l:open) || l:open.type ==# 'env' | return | endif
call s:text_obj_delim(l:open, l:close, a:0 > 0)
endfunction
" }}}1
function! vimtex#text_obj#paragraphs(...) " {{{1
@ -177,34 +112,33 @@ endfunction
" }}}1
function! s:search_and_skip_comments(pat, ...) " {{{1
" Usage: s:search_and_skip_comments(pat, [flags, stopline])
let flags = a:0 >= 1 ? a:1 : ''
let stopline = a:0 >= 2 ? a:2 : 0
let saved_pos = getpos('.')
function! s:text_obj_delim(open, close, inner) " {{{1
let [l1, c1, l2, c2] = [a:open.lnum, a:open.cnum, a:close.lnum, a:close.cnum]
" search once
let ret = search(a:pat, flags, stopline)
if ret
" do not match at current position if inside comment
let flags = substitute(flags, 'c', '', 'g')
" keep searching while in comment
while vimtex#util#in_comment()
let ret = search(a:pat, flags, stopline)
if !ret
break
endif
endwhile
if a:inner
let c1 += len(a:open.match)
let c2 -= 1
if c1 >= len(getline(l1))
let l1 += 1
let c1 = 1
endif
if c2 < 1
let l2 -= 1
let c2 = len(getline(l2))
endif
else
let c2 += len(a:close.match) - 1
endif
if !ret
" if no match found, restore position
call setpos('.', saved_pos)
if l1 < l2 || (l1 == l2 && c1 < c2)
call cursor(l1, c1)
if visualmode() ==# 'V'
normal! V
else
normal! v
endif
call cursor(l2, c2)
endif
return ret
endfunction
" }}}1

View File

@ -9,21 +9,6 @@ endfunction
" }}}1
function! vimtex#util#init_script() " {{{1
let s:delimiters_open = [
\ '(',
\ '\[',
\ '\\{',
\ '\\\Cleft\s*\%([^\\a-zA-Z0-9]\|\\.\|\\\a*\)',
\ '\\\cbigg\?\((\|\[\|\\{\)',
\ ]
let s:delimiters_close = [
\ ')',
\ '\]',
\ '\\}',
\ '\\\Cright\s*\%([^\\a-zA-Z0-9]\|\\.\|\\\a*\)',
\ '\\\cbigg\?\()\|\]\|\\}\)',
\ ]
endfunction
" }}}1
@ -141,133 +126,6 @@ function! vimtex#util#shellescape(cmd) " {{{1
endif
endfunction
" }}}1
function! vimtex#util#get_env(...) " {{{1
" vimtex#util#get_env([with_pos])
" Returns:
" - environment
" if with_pos is not given
" - [environment, lnum_begin, cnum_begin, lnum_end, cnum_end]
" if with_pos is nonzero
let with_pos = a:0 > 0 ? a:1 : 0
let move_crs = a:0 > 1 ? a:2 : 1
let begin_pat = '\C\\begin\_\s*{[^}]*}\|\\\@<!\\\[\|\\\@<!\\('
let end_pat = '\C\\end\_\s*{[^}]*}\|\\\@<!\\\]\|\\\@<!\\)'
let saved_pos = getpos('.')
" move to the left until on a backslash (this is necessary to match the
" current environment when the cursor is on the \end command)
let [bufnum, lnum, cnum, off] = getpos('.')
if move_crs
let line = getline(lnum)
while cnum > 1 && line[cnum - 1] !=# '\'
let cnum -= 1
endwhile
call cursor(lnum, cnum)
endif
" match begin/end pairs but skip comments
let flags = 'bnW'
if strpart(getline('.'), col('.') - 1) =~ '^\%(' . begin_pat . '\)'
let flags .= 'c'
endif
let [lnum1, cnum1] = searchpairpos(begin_pat, '', end_pat, flags,
\ 'vimtex#util#in_comment()')
let env = ''
if lnum1
let line = strpart(getline(lnum1), cnum1 - 1)
if empty(env)
let env = matchstr(line, '^\C\\begin\_\s*{\zs[^}]*\ze}')
endif
if empty(env)
let env = matchstr(line, '^\\\[')
endif
if empty(env)
let env = matchstr(line, '^\\(')
endif
endif
if with_pos == 1
let flags = 'nW'
if !(lnum1 == lnum && cnum1 == cnum)
let flags .= 'c'
endif
let [lnum2, cnum2] = searchpairpos(begin_pat, '', end_pat, flags,
\ 'vimtex#util#in_comment()')
call setpos('.', saved_pos)
return [env, lnum1, cnum1, lnum2, cnum2]
else
call setpos('.', saved_pos)
return env
endif
endfunction
" }}}1
function! vimtex#util#get_delim() " {{{1
" Save position in order to restore before finishing
let pos_original = getpos('.')
" Save position for more work later
let pos_save = getpos('.')
" Check if the cursor is on top of a closing delimiter
let close_pats = '\(' . join(s:delimiters_close, '\|') . '\)'
let lnum = pos_save[1]
let cnum = pos_save[2]
let [lnum, cnum] = searchpos(close_pats, 'cbnW', lnum)
let delim = matchstr(getline(lnum), '^'. close_pats, cnum-1)
if pos_save[2] <= (cnum + len(delim) - 1)
let pos_save[1] = lnum
let pos_save[2] = cnum
call setpos('.', pos_save)
endif
let d1=''
let d2=''
let l1=1000000
let l2=1000000
let c1=1000000
let c2=1000000
for i in range(len(s:delimiters_open))
call setpos('.', pos_save)
let open = s:delimiters_open[i]
let close = s:delimiters_close[i]
let flags = 'W'
" Check if the cursor is on top of an opening delimiter. If it is not,
" then we want to include matches at cursor position to match closing
" delimiters.
if searchpos(open, 'cn') != pos_save[1:2]
let flags .= 'c'
endif
" Search for closing delimiter
let pos = searchpairpos(open, '', close, flags, 'vimtex#util#in_comment()')
" Check if the current is pair is the closest pair
if pos[0] && pos[0]*1000 + pos[1] < l2*1000 + c2
let l2=pos[0]
let c2=pos[1]
let d2=matchstr(strpart(getline(l2), c2 - 1), close)
let pos = searchpairpos(open,'',close,'bW', 'vimtex#util#in_comment()')
let l1=pos[0]
let c1=pos[1]
let d1=matchstr(strpart(getline(l1), c1 - 1), open)
endif
endfor
" Restore cursor position and return delimiters and positions
call setpos('.', pos_original)
return [d1,l1,c1,d2,l2,c2]
endfunction
" }}}1
function! vimtex#util#get_os() " {{{1
if has('win32')

View File

@ -103,7 +103,7 @@ Feature overview~
- Change the surrounding command or environment with `csc`/`cse`
- Toggle starred environment with `tse`
- Toggle between e.g. `()` and `\left(\right)` with `tsd`
- Close the current environment in insert mode with `]]`
- Close the current environment/delimiter in insert mode with `]]`
- Insert new command with `<F7>`
- Convenient insert mode mappings for faster typing of e.g. maths
- Folding
@ -276,53 +276,53 @@ In addition to the mappings listed below, |vimtex| provides convenient insert
mode mappings to make it easier and faster to type mathematical equations.
This feature is explained in more detail later, see |vimtex-imaps|.
-----------------------------------------------------------~
LHS RHS MODE~
-----------------------------------------------------------~
<localleader>li |<plug>(vimtex-info)| `n`
<localleader>lI |<plug>(vimtex-info-full)| `n`
<localleader>lt |<plug>(vimtex-toc-open)| `n`
<localleader>lT |<plug>(vimtex-toc-toggle)| `n`
<localleader>ly |<plug>(vimtex-labels-open)| `n`
<localleader>lY |<plug>(vimtex-labels-toggle)| `n`
<localleader>lv |<plug>(vimtex-view)| `n`
<localleader>lr |<plug>(vimtex-reverse-search)| `n`
<localleader>ll |<plug>(vimtex-compile-toggle)| `n`
<localleader>lk |<plug>(vimtex-stop)| `n`
<localleader>lK |<plug>(vimtex-stop-all)| `n`
<localleader>le |<plug>(vimtex-errors)| `n`
<localleader>lo |<plug>(vimtex-compile-output)| `n`
<localleader>lg |<plug>(vimtex-status)| `n`
<localleader>lG |<plug>(vimtex-status-all)| `n`
<localleader>lc |<plug>(vimtex-clean)| `n`
<localleader>lC |<plug>(vimtex-clean-full)| `n`
<localleader>lm |<plug>(vimtex-imaps-list)| `n`
<localleader>lx |<plug>(vimtex-reload)| `n`
<localleader>ls |<plug>(vimtex-toggle-main)| `n`
dse |<plug>(vimtex-delete-env)| `n`
dsc |<plug>(vimtex-delete-cmd)| `n`
cse |<plug>(vimtex-change-env)| `n`
csc |<plug>(vimtex-change-cmd)| `n`
tse |<plug>(vimtex-toggle-star)| `n`
tsd |<plug>(vimtex-toggle-delim)| `n`
<F7> |<plug>(vimtex-create-cmd)| `ni`
]] |<plug>(vimtex-close-env)| `i`
a$ |<plug>(vimtex-a$)| `nxo`
i$ |<plug>(vimtex-i$)| `nxo`
ae |<plug>(vimtex-ae)| `nxo`
ie |<plug>(vimtex-ie)| `nxo`
ad |<plug>(vimtex-ad)| `nxo`
id |<plug>(vimtex-id)| `nxo`
ap |<plug>(vimtex-ap)| `nxo`
ip |<plug>(vimtex-ip)| `nxo`
% |<plug>(vimtex-%)| `nxo`
]] |<plug>(vimtex-]])| `nxo`
][ |<plug>(vimtex-][)| `nxo`
[] |<plug>(vimtex-[])| `nxo`
[[ |<plug>(vimtex-[[)| `nxo`
} |<plug>(vimtex-})| `nxo`
{ |<plug>(vimtex-{)| `nxo`
-----------------------------------------------------------~
-------------------------------------------------------------~
LHS RHS MODE~
-------------------------------------------------------------~
<localleader>li |<plug>(vimtex-info)| `n`
<localleader>lI |<plug>(vimtex-info-full)| `n`
<localleader>lt |<plug>(vimtex-toc-open)| `n`
<localleader>lT |<plug>(vimtex-toc-toggle)| `n`
<localleader>ly |<plug>(vimtex-labels-open)| `n`
<localleader>lY |<plug>(vimtex-labels-toggle)| `n`
<localleader>lv |<plug>(vimtex-view)| `n`
<localleader>lr |<plug>(vimtex-reverse-search)| `n`
<localleader>ll |<plug>(vimtex-compile-toggle)| `n`
<localleader>lk |<plug>(vimtex-stop)| `n`
<localleader>lK |<plug>(vimtex-stop-all)| `n`
<localleader>le |<plug>(vimtex-errors)| `n`
<localleader>lo |<plug>(vimtex-compile-output)| `n`
<localleader>lg |<plug>(vimtex-status)| `n`
<localleader>lG |<plug>(vimtex-status-all)| `n`
<localleader>lc |<plug>(vimtex-clean)| `n`
<localleader>lC |<plug>(vimtex-clean-full)| `n`
<localleader>lm |<plug>(vimtex-imaps-list)| `n`
<localleader>lx |<plug>(vimtex-reload)| `n`
<localleader>ls |<plug>(vimtex-toggle-main)| `n`
dse |<plug>(vimtex-env-delete)| `n`
dsc |<plug>(vimtex-cmd-delete)| `n`
cse |<plug>(vimtex-env-change)| `n`
csc |<plug>(vimtex-cmd-change)| `n`
tse |<plug>(vimtex-env-toggle-star)| `n`
tsd |<plug>(vimtex-delim-toggle-modifier)| `n`
<F7> |<plug>(vimtex-cmd-create)| `ni`
]] |<plug>(vimtex-delim-close)| `i`
a$ |<plug>(vimtex-a$)| `nxo`
i$ |<plug>(vimtex-i$)| `nxo`
ae |<plug>(vimtex-ae)| `nxo`
ie |<plug>(vimtex-ie)| `nxo`
ad |<plug>(vimtex-ad)| `nxo`
id |<plug>(vimtex-id)| `nxo`
ap |<plug>(vimtex-ap)| `nxo`
ip |<plug>(vimtex-ip)| `nxo`
% |<plug>(vimtex-%)| `nxo`
]] |<plug>(vimtex-]])| `nxo`
][ |<plug>(vimtex-][)| `nxo`
[] |<plug>(vimtex-[])| `nxo`
[[ |<plug>(vimtex-[[)| `nxo`
} |<plug>(vimtex-})| `nxo`
{ |<plug>(vimtex-{)| `nxo`
-------------------------------------------------------------~
------------------------------------------------------------------------------
Options~
@ -363,12 +363,12 @@ Options~
Default value: 0
*g:vimtex_change_complete_envs*
*g:vimtex_env_complete_list*
Define a list of environments that will be completed when changing the
surrounding environments (see |<plug>(vimtex-change-env)|).
surrounding environments (see |<plug>(vimtex-env-change)|).
Default value: >
let g:vimtex_change_complete_envs = [
let g:vimtex_env_complete_list = [
\ 'itemize',
\ 'enumerate',
\ 'description',
@ -382,21 +382,17 @@ Options~
\ '\[',
\ ]
<
*g:vimtex_change_toggled_delims*
Define a list of delimiters to toggle through with
|<plug>(vimtex-toggle-delim)|.
*g:vimtex_delim_toggle_mod_list*
Define list of delimiter modifiers to toggle through with
|<plug>(vimtex-delim-toggle-modifier)|. If the list is not defined, then it uses
a default match list.
Default value: >
let g:vimtex_change_toggled_delims = [['\\left', '\\right']]
For example, to only toggle between no modifier and the `\left/\right` pair,
use: >
let g:vimtex_delim_toggle_mod_list = [['\\left', '\\right']]
<
*g:vimtex_change_ignored_delims_pattern*
A pattern for delimiters that will be ignored when toggling delimiters, see
|<plug>(vimtex-toggle-delim)|.
Default value: `Undefined`
Default value: >
let g:vimtex_change_ignored_delims_pattern = '\c\\bigg\?'
<
*g:vimtex_format_enabled*
If enabled, |vimtex| uses a custom |formatexpr| that should handle inline
comments. That is, if it is enabled, then comments at end of lines will not
@ -1082,32 +1078,31 @@ Map definitions~
(|g:vimtex_fold_manual|), then |vimtex| remaps |zx| and |zX| in such that
the folds are refreshed appropriately.
*<plug>(vimtex-delete-env)*
*<plug>(vimtex-change-env)*
*<plug>(vimtex-env-delete)*
*<plug>(vimtex-env-change)*
Delete/Change surrounding environment.
*<plug>(vimtex-delete-cmd)*
*<plug>(vimtex-change-cmd)*
Delete/Change surrounding command. Note: <plug>(vimtex-delete-cmd) depends
*<plug>(vimtex-cmd-delete)*
*<plug>(vimtex-cmd-change)*
Delete/Change surrounding command. Note: |<plug>(vimtex-cmd-delete)| depends
on |surround.vim| (https://github.com/tpope/vim-surround).
*<plug>(vimtex-toggle-star)*
*<plug>(vimtex-env-toggle-star)*
Toggle starred environment.
*<plug>(vimtex-toggle-delim)*
Toggle delimiters, for instance between `(...)` and `\left(...\right)`. The
behaviour is controlled through |g:vimtex_change_toggled_delims| and
|g:vimtex_change_ignored_delims_pattern|.
*<plug>(vimtex-delim-toggle-modifier)*
Toggle delimiter modifiers, for instance between `(...)` and `\left(...\right)`.
See also |g:vimtex_delim_toggle_mod_list|.
*<plug>(vimtex-create-cmd)*
*<plug>(vimtex-cmd-create)*
Convert the current word (word under or right before the cursor) into
a LaTeX command. That is, it prepends a backslash and adds an opening brace.
From normal mode, the mapping will leave you in insert mode. The mapping
works both in normal and in insert mode. It is by default mapped to <f7>
(see |vimtex-default-mappings| for a list of the default mappings).
*<plug>(vimtex-close-env)*
Close the current environment (insert mode).
*<plug>(vimtex-delim-close)*
Close the current environment or delimiter (insert mode).
*<plug>(vimtex-a$)*
Text object for inline math (inclusive).
@ -1784,6 +1779,34 @@ The following changelog only logs particularly important changes, such as
changes that break backwards compatibility. See the git log for the detailed
changelog.
2016-02-06: Large refactoring of delimiter parsing~
I've refactored a lot of the code in order to make the parsing of delimiters
and features that rely on delimiter detection and similar more consistent.
This results in some changes in option names and similar, but it should make
it easier to provide improved and more robust features.
There is one feature change: The delimiter toggle now consistently toggles the
modifier, not the delimiter itself, and it toggles between a range of
modifiers by default. For customization, see |g:vimtex_delim_toggle_mod_list|.
The following options have changed names:
*g:vimtex_change_set_formatexpr* ---> |g:vimtex_format_enabled|
*g:vimtex_change_complete_envs* ---> |g:vimtex_env_complete_list|
*g:vimtex_change_toggled_delims* ---> |g:vimtex_delim_toggle_mod_list|
The following options have been removed:
*g:vimtex_change_ignored_delims_pattern* --- It was no longer necessary
The following mappings have been renamed:
*<plug>(vimtex-delete-env)* ---> |<plug>(vimtex-env-delete)|
*<plug>(vimtex-delete-cmd)* ---> |<plug>(vimtex-cmd-delete)|
*<plug>(vimtex-change-env)* ---> |<plug>(vimtex-env-change)|
*<plug>(vimtex-change-cmd)* ---> |<plug>(vimtex-cmd-change)|
*<plug>(vimtex-toggle-star)* ---> |<plug>(vimtex-env-toggle-star)|
*<plug>(vimtex-toggle-delim)* ---> |<plug>(vimtex-delim-toggle-modifier)|
*<plug>(vimtex-create-cmd)* ---> |<plug>(vimtex-cmd-create)|
*<plug>(vimtex-close-env)* ---> |<plug>(vimtex-delim-close)|
2015-10-19: Added convenient insert mode mappings~
I've merged the `math_mappings` branch (see #172 and #251). It adds the
feature that is explained in |vimtex-imaps|.

View File

@ -89,13 +89,10 @@ function! VimtexIndent() " {{{1
endif
" Indent opening and closing delimiters
let l:delims = match(map(synstack(v:lnum, max([col('.') - 1, 1])),
\ 'synIDattr(v:val, ''name'')'), '^texMathZone') >= 0
\ ? [s:delimiters_open_math, s:delimiters_close_math]
\ : [s:delimiters_open_tex, s:delimiters_close_tex]
let [l:re_open, l:re_close] = vimtex#delim#get_valid_regexps(v:lnum, col('.'))
let ind += &sw*(
\ max([s:count(pline, l:delims[0]) - s:count(pline, l:delims[1]), 0])
\ - max([s:count(cline, l:delims[1]) - s:count(cline, l:delims[0]), 0]))
\ max([s:count(pline, l:re_open) - s:count(pline, l:re_close), 0])
\ - max([s:count(cline, l:re_close) - s:count(cline, l:re_open), 0]))
" Indent list items
if pline =~# '^\s*\\\(bib\)\?item'
@ -138,28 +135,6 @@ let s:tikz_indented = 0
" Define some common patterns
let s:envs_lists = 'itemize\|description\|enumerate\|thebibliography'
let s:envs_noindent = 'document\|verbatim\|lstlisting'
let s:delimiters_open_tex = '\(' . join([
\ '{',
\ '\[',
\ '\\(',
\ ], '\|') . '\)'
let s:delimiters_close_tex = '\(' . join([
\ '}',
\ '\]',
\ '\\)',
\ ], '\|') . '\)'
let s:delimiters_open_math = '\(' . join([
\ '\\\[\s*$',
\ '\\{',
\ '\\\Cleft\s*\%([^\\]\|\\.\|\\\a*\)',
\ '\\\cbigg\?\((\|\[\|\\{\)',
\ ], '\|') . '\)'
let s:delimiters_close_math = '\(' . join([
\ '\\\]\s*$',
\ '\\}',
\ '\\\Cright\s*\%([^\\]\|\\.\|\\\a*\)',
\ '\\\cbigg\?\()\|\]\|\\}\)',
\ ], '\|') . '\)'
let s:tikz_commands = '\\\(' . join([
\ 'draw',
\ 'fill',