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:
parent
bb49c3e946
commit
490a24daf0
@ -37,7 +37,7 @@ disabled if desired.
|
|||||||
- Change the surrounding command or environment with `csc`/`cse`
|
- Change the surrounding command or environment with `csc`/`cse`
|
||||||
- Toggle starred environment with `tse`
|
- Toggle starred environment with `tse`
|
||||||
- Toggle between e.g. `()` and `\left(\right)` with `tsd`
|
- 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>`
|
- Insert new command with `<F7>`
|
||||||
- Convenient insert mode mappings for faster typing of e.g. maths
|
- Convenient insert mode mappings for faster typing of e.g. maths
|
||||||
- Improved folding (`:h 'foldexpr'`)
|
- Improved folding (`:h 'foldexpr'`)
|
||||||
|
@ -341,15 +341,17 @@ function! s:init_mappings() " {{{1
|
|||||||
call s:map('n', '<localleader>lx', '<plug>(vimtex-reload)')
|
call s:map('n', '<localleader>lx', '<plug>(vimtex-reload)')
|
||||||
call s:map('n', '<localleader>ls', '<plug>(vimtex-toggle-main)')
|
call s:map('n', '<localleader>ls', '<plug>(vimtex-toggle-main)')
|
||||||
|
|
||||||
call s:map('n', 'dse', '<plug>(vimtex-delete-env)')
|
call s:map('n', 'dse', '<plug>(vimtex-env-delete)')
|
||||||
call s:map('n', 'dsc', '<plug>(vimtex-delete-cmd)')
|
call s:map('n', 'cse', '<plug>(vimtex-env-change)')
|
||||||
call s:map('n', 'cse', '<plug>(vimtex-change-env)')
|
call s:map('n', 'tse', '<plug>(vimtex-env-toggle-star)')
|
||||||
call s:map('n', 'csc', '<plug>(vimtex-change-cmd)')
|
|
||||||
call s:map('n', 'tse', '<plug>(vimtex-toggle-star)')
|
call s:map('n', 'dsc', '<plug>(vimtex-cmd-delete)')
|
||||||
call s:map('n', 'tsd', '<plug>(vimtex-toggle-delim)')
|
call s:map('n', 'csc', '<plug>(vimtex-cmd-change)')
|
||||||
call s:map('n', '<F7>', '<plug>(vimtex-create-cmd)')
|
call s:map('n', '<F7>', '<plug>(vimtex-cmd-create)')
|
||||||
call s:map('i', '<F7>', '<plug>(vimtex-create-cmd)')
|
call s:map('i', '<F7>', '<plug>(vimtex-cmd-create)')
|
||||||
call s:map('i', ']]', '<plug>(vimtex-close-env)')
|
|
||||||
|
call s:map('n', 'tsd', '<plug>(vimtex-delim-toggle-modifier)')
|
||||||
|
call s:map('i', ']]', '<plug>(vimtex-delim-close)')
|
||||||
|
|
||||||
if g:vimtex_latexmk_enabled
|
if g:vimtex_latexmk_enabled
|
||||||
call s:map('n', '<localleader>ll', '<plug>(vimtex-compile-toggle)')
|
call s:map('n', '<localleader>ll', '<plug>(vimtex-compile-toggle)')
|
||||||
|
@ -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
190
autoload/vimtex/cmd.vim
Normal 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
640
autoload/vimtex/delim.vim
Normal 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
135
autoload/vimtex/env.vim
Normal 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
|
@ -19,7 +19,7 @@ function! vimtex#motion#init_script() " {{{1
|
|||||||
if g:vimtex_motion_matchparen
|
if g:vimtex_motion_matchparen
|
||||||
augroup vimtex_motion
|
augroup vimtex_motion
|
||||||
autocmd!
|
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()
|
autocmd! CursorMovedI *.tex call s:highlight_matching_pair()
|
||||||
augroup END
|
augroup END
|
||||||
endif
|
endif
|
||||||
@ -34,32 +34,6 @@ function! vimtex#motion#init_script() " {{{1
|
|||||||
" Not in a comment
|
" Not in a comment
|
||||||
let s:notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
|
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/...
|
" Pattern to match section/chapter/...
|
||||||
let s:section = s:notcomment . '\v\s*\\'
|
let s:section = s:notcomment . '\v\s*\\'
|
||||||
let s:section .= '((sub)*section|chapter|part|'
|
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
|
if vimtex#util#in_comment() | return | endif
|
||||||
|
|
||||||
" Save position
|
let delim = vimtex#delim#get_current('all', 'both')
|
||||||
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
|
|
||||||
if empty(delim)
|
if empty(delim)
|
||||||
let [lnum, cnum] = searchpos(s:delimiters, 'cnW', nl+2)
|
let delim = vimtex#delim#get_next('all', 'both')
|
||||||
let delim = matchstr(getline(lnum), '^'. s:delimiters, cnum-1)
|
if empty(delim) | return | endif
|
||||||
if empty(delim)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Utility pattern to NOT match the current cursor position
|
let delim = vimtex#delim#get_matching(delim)
|
||||||
let not_cursor = '\%(\%'. lnum . 'l\%' . cnum . 'c\)\@!'
|
if empty(delim) | return | endif
|
||||||
|
|
||||||
" Finally, find the matching delimiter
|
call cursor(delim.lnum,
|
||||||
if delim =~# '^\$'
|
\ (delim.is_open
|
||||||
let inline = s:notcomment . s:notbslash . '\$'
|
\ ? delim.cnum
|
||||||
let [lnum0, cnum0] = searchpos('.', 'nW')
|
\ : delim.cnum + strlen(delim.match) - 1))
|
||||||
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
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
@ -252,70 +191,21 @@ endfunction
|
|||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
|
|
||||||
function! s:highlight_matching_pair(...) " {{{1
|
function! s:highlight_matching_pair() " {{{1
|
||||||
if vimtex#util#in_comment() | return | endif
|
if vimtex#util#in_comment() | return | endif
|
||||||
let hmode = a:0 > 0 ? 1 : 0
|
|
||||||
|
|
||||||
2match none
|
2match none
|
||||||
|
|
||||||
" Save position
|
let l:d1 = vimtex#delim#get_current('all', 'both')
|
||||||
let nl = line('.')
|
let l:d2 = vimtex#delim#get_matching(l:d1)
|
||||||
let nc = col('.')
|
if empty(l:d2) | return | endif
|
||||||
let line = getline(nl)
|
|
||||||
|
|
||||||
" Find delimiter under cursor
|
let [l1, c1, l2, c2] = l:d1.side ==# 'open'
|
||||||
let cnum = searchpos(s:delimiters, 'cbnW', nl)[1]
|
\ ? [l:d1.lnum, l:d1.cnum, l:d2.lnum, l:d2.cnum]
|
||||||
let delim = matchstr(line, '^'. s:delimiters, cnum-1)
|
\ : [l:d2.lnum, l:d2.cnum, l:d1.lnum, l:d1.cnum]
|
||||||
|
|
||||||
" Only highlight when cursor is on delimiters
|
execute '2match MatchParen /'
|
||||||
if empty(delim) || strlen(delim)+cnum-hmode < nc
|
\ . '\%' . l1 . 'l\%' . c1 . 'c' . l:d1.re.open
|
||||||
return
|
\ . '\|\%' . l2 . 'l\%' . c2 . 'c' . l:d1.re.close . '/'
|
||||||
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
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
|
@ -56,108 +56,43 @@ endfunction
|
|||||||
" }}}1
|
" }}}1
|
||||||
|
|
||||||
function! vimtex#text_obj#delimiters(...) " {{{1
|
function! vimtex#text_obj#delimiters(...) " {{{1
|
||||||
let inner = a:0 > 0
|
let [l:open, l:close] = vimtex#delim#get_surrounding('delim_all')
|
||||||
|
call s:text_obj_delim(l:open, l:close, 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
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
function! vimtex#text_obj#environments(...) " {{{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)
|
let [l:open, l:close] = vimtex#delim#get_surrounding('env')
|
||||||
call cursor(lnum, cnum)
|
if l:open.type !=# 'env' | return | endif
|
||||||
if inner
|
|
||||||
if env =~# '^\'
|
if l:inner
|
||||||
call search('\\.\_\s*\S', 'eW')
|
call cursor(l:open.lnum, l:open.cnum + strlen(l:open.match))
|
||||||
else
|
call search('}\%(\_\s*\%(\[\_[^]]*\]\)\)\?\_\s*\S', 'eW')
|
||||||
call search('}\(\_\s*\(\[\_[^]]*\]\|{\_\S\{-}}\)\)\?\_\s*\S', 'eW')
|
else
|
||||||
endif
|
call cursor(l:open.lnum, l:open.cnum)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if visualmode() ==# 'V'
|
if visualmode() ==# 'V'
|
||||||
normal! V
|
normal! V
|
||||||
else
|
else
|
||||||
normal! v
|
normal! v
|
||||||
endif
|
endif
|
||||||
call cursor(lnum2, cnum2)
|
|
||||||
if inner
|
if l:inner
|
||||||
|
call cursor(l:close.lnum, l:close.cnum)
|
||||||
call search('\S\_\s*', 'bW')
|
call search('\S\_\s*', 'bW')
|
||||||
else
|
else
|
||||||
if env =~# '^\'
|
call cursor(l:close.lnum, l:close.cnum + strlen(l:close.match) - 1)
|
||||||
normal! l
|
|
||||||
else
|
|
||||||
call search('}', 'eW')
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
function! vimtex#text_obj#inline_math(...) " {{{1
|
function! vimtex#text_obj#inline_math(...) " {{{1
|
||||||
let l:inner = a:0 > 0
|
let [l:open, l:close] = vimtex#delim#get_surrounding('env')
|
||||||
|
if empty(l:open) || l:open.type ==# 'env' | return | endif
|
||||||
let l:flags = 'bW'
|
call s:text_obj_delim(l:open, l:close, a:0 > 0)
|
||||||
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
|
|
||||||
endfunction
|
endfunction
|
||||||
" }}}1
|
" }}}1
|
||||||
function! vimtex#text_obj#paragraphs(...) " {{{1
|
function! vimtex#text_obj#paragraphs(...) " {{{1
|
||||||
@ -177,34 +112,33 @@ endfunction
|
|||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
|
|
||||||
function! s:search_and_skip_comments(pat, ...) " {{{1
|
function! s:text_obj_delim(open, close, inner) " {{{1
|
||||||
" Usage: s:search_and_skip_comments(pat, [flags, stopline])
|
let [l1, c1, l2, c2] = [a:open.lnum, a:open.cnum, a:close.lnum, a:close.cnum]
|
||||||
let flags = a:0 >= 1 ? a:1 : ''
|
|
||||||
let stopline = a:0 >= 2 ? a:2 : 0
|
|
||||||
let saved_pos = getpos('.')
|
|
||||||
|
|
||||||
" search once
|
if a:inner
|
||||||
let ret = search(a:pat, flags, stopline)
|
let c1 += len(a:open.match)
|
||||||
|
let c2 -= 1
|
||||||
if ret
|
if c1 >= len(getline(l1))
|
||||||
" do not match at current position if inside comment
|
let l1 += 1
|
||||||
let flags = substitute(flags, 'c', '', 'g')
|
let c1 = 1
|
||||||
|
endif
|
||||||
" keep searching while in comment
|
if c2 < 1
|
||||||
while vimtex#util#in_comment()
|
let l2 -= 1
|
||||||
let ret = search(a:pat, flags, stopline)
|
let c2 = len(getline(l2))
|
||||||
if !ret
|
endif
|
||||||
break
|
else
|
||||||
endif
|
let c2 += len(a:close.match) - 1
|
||||||
endwhile
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !ret
|
if l1 < l2 || (l1 == l2 && c1 < c2)
|
||||||
" if no match found, restore position
|
call cursor(l1, c1)
|
||||||
call setpos('.', saved_pos)
|
if visualmode() ==# 'V'
|
||||||
|
normal! V
|
||||||
|
else
|
||||||
|
normal! v
|
||||||
|
endif
|
||||||
|
call cursor(l2, c2)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return ret
|
|
||||||
endfunction
|
endfunction
|
||||||
" }}}1
|
" }}}1
|
||||||
|
|
||||||
|
@ -9,21 +9,6 @@ endfunction
|
|||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
function! vimtex#util#init_script() " {{{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
|
endfunction
|
||||||
|
|
||||||
" }}}1
|
" }}}1
|
||||||
@ -141,133 +126,6 @@ function! vimtex#util#shellescape(cmd) " {{{1
|
|||||||
endif
|
endif
|
||||||
endfunction
|
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
|
" }}}1
|
||||||
function! vimtex#util#get_os() " {{{1
|
function! vimtex#util#get_os() " {{{1
|
||||||
if has('win32')
|
if has('win32')
|
||||||
|
175
doc/vimtex.txt
175
doc/vimtex.txt
@ -103,7 +103,7 @@ Feature overview~
|
|||||||
- Change the surrounding command or environment with `csc`/`cse`
|
- Change the surrounding command or environment with `csc`/`cse`
|
||||||
- Toggle starred environment with `tse`
|
- Toggle starred environment with `tse`
|
||||||
- Toggle between e.g. `()` and `\left(\right)` with `tsd`
|
- 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>`
|
- Insert new command with `<F7>`
|
||||||
- Convenient insert mode mappings for faster typing of e.g. maths
|
- Convenient insert mode mappings for faster typing of e.g. maths
|
||||||
- Folding
|
- 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.
|
mode mappings to make it easier and faster to type mathematical equations.
|
||||||
This feature is explained in more detail later, see |vimtex-imaps|.
|
This feature is explained in more detail later, see |vimtex-imaps|.
|
||||||
|
|
||||||
-----------------------------------------------------------~
|
-------------------------------------------------------------~
|
||||||
LHS RHS MODE~
|
LHS RHS MODE~
|
||||||
-----------------------------------------------------------~
|
-------------------------------------------------------------~
|
||||||
<localleader>li |<plug>(vimtex-info)| `n`
|
<localleader>li |<plug>(vimtex-info)| `n`
|
||||||
<localleader>lI |<plug>(vimtex-info-full)| `n`
|
<localleader>lI |<plug>(vimtex-info-full)| `n`
|
||||||
<localleader>lt |<plug>(vimtex-toc-open)| `n`
|
<localleader>lt |<plug>(vimtex-toc-open)| `n`
|
||||||
<localleader>lT |<plug>(vimtex-toc-toggle)| `n`
|
<localleader>lT |<plug>(vimtex-toc-toggle)| `n`
|
||||||
<localleader>ly |<plug>(vimtex-labels-open)| `n`
|
<localleader>ly |<plug>(vimtex-labels-open)| `n`
|
||||||
<localleader>lY |<plug>(vimtex-labels-toggle)| `n`
|
<localleader>lY |<plug>(vimtex-labels-toggle)| `n`
|
||||||
<localleader>lv |<plug>(vimtex-view)| `n`
|
<localleader>lv |<plug>(vimtex-view)| `n`
|
||||||
<localleader>lr |<plug>(vimtex-reverse-search)| `n`
|
<localleader>lr |<plug>(vimtex-reverse-search)| `n`
|
||||||
<localleader>ll |<plug>(vimtex-compile-toggle)| `n`
|
<localleader>ll |<plug>(vimtex-compile-toggle)| `n`
|
||||||
<localleader>lk |<plug>(vimtex-stop)| `n`
|
<localleader>lk |<plug>(vimtex-stop)| `n`
|
||||||
<localleader>lK |<plug>(vimtex-stop-all)| `n`
|
<localleader>lK |<plug>(vimtex-stop-all)| `n`
|
||||||
<localleader>le |<plug>(vimtex-errors)| `n`
|
<localleader>le |<plug>(vimtex-errors)| `n`
|
||||||
<localleader>lo |<plug>(vimtex-compile-output)| `n`
|
<localleader>lo |<plug>(vimtex-compile-output)| `n`
|
||||||
<localleader>lg |<plug>(vimtex-status)| `n`
|
<localleader>lg |<plug>(vimtex-status)| `n`
|
||||||
<localleader>lG |<plug>(vimtex-status-all)| `n`
|
<localleader>lG |<plug>(vimtex-status-all)| `n`
|
||||||
<localleader>lc |<plug>(vimtex-clean)| `n`
|
<localleader>lc |<plug>(vimtex-clean)| `n`
|
||||||
<localleader>lC |<plug>(vimtex-clean-full)| `n`
|
<localleader>lC |<plug>(vimtex-clean-full)| `n`
|
||||||
<localleader>lm |<plug>(vimtex-imaps-list)| `n`
|
<localleader>lm |<plug>(vimtex-imaps-list)| `n`
|
||||||
<localleader>lx |<plug>(vimtex-reload)| `n`
|
<localleader>lx |<plug>(vimtex-reload)| `n`
|
||||||
<localleader>ls |<plug>(vimtex-toggle-main)| `n`
|
<localleader>ls |<plug>(vimtex-toggle-main)| `n`
|
||||||
dse |<plug>(vimtex-delete-env)| `n`
|
dse |<plug>(vimtex-env-delete)| `n`
|
||||||
dsc |<plug>(vimtex-delete-cmd)| `n`
|
dsc |<plug>(vimtex-cmd-delete)| `n`
|
||||||
cse |<plug>(vimtex-change-env)| `n`
|
cse |<plug>(vimtex-env-change)| `n`
|
||||||
csc |<plug>(vimtex-change-cmd)| `n`
|
csc |<plug>(vimtex-cmd-change)| `n`
|
||||||
tse |<plug>(vimtex-toggle-star)| `n`
|
tse |<plug>(vimtex-env-toggle-star)| `n`
|
||||||
tsd |<plug>(vimtex-toggle-delim)| `n`
|
tsd |<plug>(vimtex-delim-toggle-modifier)| `n`
|
||||||
<F7> |<plug>(vimtex-create-cmd)| `ni`
|
<F7> |<plug>(vimtex-cmd-create)| `ni`
|
||||||
]] |<plug>(vimtex-close-env)| `i`
|
]] |<plug>(vimtex-delim-close)| `i`
|
||||||
a$ |<plug>(vimtex-a$)| `nxo`
|
a$ |<plug>(vimtex-a$)| `nxo`
|
||||||
i$ |<plug>(vimtex-i$)| `nxo`
|
i$ |<plug>(vimtex-i$)| `nxo`
|
||||||
ae |<plug>(vimtex-ae)| `nxo`
|
ae |<plug>(vimtex-ae)| `nxo`
|
||||||
ie |<plug>(vimtex-ie)| `nxo`
|
ie |<plug>(vimtex-ie)| `nxo`
|
||||||
ad |<plug>(vimtex-ad)| `nxo`
|
ad |<plug>(vimtex-ad)| `nxo`
|
||||||
id |<plug>(vimtex-id)| `nxo`
|
id |<plug>(vimtex-id)| `nxo`
|
||||||
ap |<plug>(vimtex-ap)| `nxo`
|
ap |<plug>(vimtex-ap)| `nxo`
|
||||||
ip |<plug>(vimtex-ip)| `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`
|
[] |<plug>(vimtex-[])| `nxo`
|
||||||
[[ |<plug>(vimtex-[[)| `nxo`
|
[[ |<plug>(vimtex-[[)| `nxo`
|
||||||
} |<plug>(vimtex-})| `nxo`
|
} |<plug>(vimtex-})| `nxo`
|
||||||
{ |<plug>(vimtex-{)| `nxo`
|
{ |<plug>(vimtex-{)| `nxo`
|
||||||
-----------------------------------------------------------~
|
-------------------------------------------------------------~
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
Options~
|
Options~
|
||||||
@ -363,12 +363,12 @@ Options~
|
|||||||
|
|
||||||
Default value: 0
|
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
|
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: >
|
Default value: >
|
||||||
let g:vimtex_change_complete_envs = [
|
let g:vimtex_env_complete_list = [
|
||||||
\ 'itemize',
|
\ 'itemize',
|
||||||
\ 'enumerate',
|
\ 'enumerate',
|
||||||
\ 'description',
|
\ 'description',
|
||||||
@ -382,21 +382,17 @@ Options~
|
|||||||
\ '\[',
|
\ '\[',
|
||||||
\ ]
|
\ ]
|
||||||
<
|
<
|
||||||
*g:vimtex_change_toggled_delims*
|
*g:vimtex_delim_toggle_mod_list*
|
||||||
Define a list of delimiters to toggle through with
|
Define list of delimiter modifiers to toggle through with
|
||||||
|<plug>(vimtex-toggle-delim)|.
|
|<plug>(vimtex-delim-toggle-modifier)|. If the list is not defined, then it uses
|
||||||
|
a default match list.
|
||||||
|
|
||||||
|
For example, to only toggle between no modifier and the `\left/\right` pair,
|
||||||
Default value: >
|
use: >
|
||||||
let g:vimtex_change_toggled_delims = [['\\left', '\\right']]
|
let g:vimtex_delim_toggle_mod_list = [['\\left', '\\right']]
|
||||||
<
|
<
|
||||||
*g:vimtex_change_ignored_delims_pattern*
|
Default value: `Undefined`
|
||||||
A pattern for delimiters that will be ignored when toggling delimiters, see
|
|
||||||
|<plug>(vimtex-toggle-delim)|.
|
|
||||||
|
|
||||||
Default value: >
|
|
||||||
let g:vimtex_change_ignored_delims_pattern = '\c\\bigg\?'
|
|
||||||
<
|
|
||||||
*g:vimtex_format_enabled*
|
*g:vimtex_format_enabled*
|
||||||
If enabled, |vimtex| uses a custom |formatexpr| that should handle inline
|
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
|
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
|
(|g:vimtex_fold_manual|), then |vimtex| remaps |zx| and |zX| in such that
|
||||||
the folds are refreshed appropriately.
|
the folds are refreshed appropriately.
|
||||||
|
|
||||||
*<plug>(vimtex-delete-env)*
|
*<plug>(vimtex-env-delete)*
|
||||||
*<plug>(vimtex-change-env)*
|
*<plug>(vimtex-env-change)*
|
||||||
Delete/Change surrounding environment.
|
Delete/Change surrounding environment.
|
||||||
|
|
||||||
*<plug>(vimtex-delete-cmd)*
|
*<plug>(vimtex-cmd-delete)*
|
||||||
*<plug>(vimtex-change-cmd)*
|
*<plug>(vimtex-cmd-change)*
|
||||||
Delete/Change surrounding command. Note: <plug>(vimtex-delete-cmd) depends
|
Delete/Change surrounding command. Note: |<plug>(vimtex-cmd-delete)| depends
|
||||||
on |surround.vim| (https://github.com/tpope/vim-surround).
|
on |surround.vim| (https://github.com/tpope/vim-surround).
|
||||||
|
|
||||||
*<plug>(vimtex-toggle-star)*
|
*<plug>(vimtex-env-toggle-star)*
|
||||||
Toggle starred environment.
|
Toggle starred environment.
|
||||||
|
|
||||||
*<plug>(vimtex-toggle-delim)*
|
*<plug>(vimtex-delim-toggle-modifier)*
|
||||||
Toggle delimiters, for instance between `(...)` and `\left(...\right)`. The
|
Toggle delimiter modifiers, for instance between `(...)` and `\left(...\right)`.
|
||||||
behaviour is controlled through |g:vimtex_change_toggled_delims| and
|
See also |g:vimtex_delim_toggle_mod_list|.
|
||||||
|g:vimtex_change_ignored_delims_pattern|.
|
|
||||||
|
|
||||||
*<plug>(vimtex-create-cmd)*
|
*<plug>(vimtex-cmd-create)*
|
||||||
Convert the current word (word under or right before the cursor) into
|
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.
|
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
|
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>
|
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).
|
(see |vimtex-default-mappings| for a list of the default mappings).
|
||||||
|
|
||||||
*<plug>(vimtex-close-env)*
|
*<plug>(vimtex-delim-close)*
|
||||||
Close the current environment (insert mode).
|
Close the current environment or delimiter (insert mode).
|
||||||
|
|
||||||
*<plug>(vimtex-a$)*
|
*<plug>(vimtex-a$)*
|
||||||
Text object for inline math (inclusive).
|
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
|
changes that break backwards compatibility. See the git log for the detailed
|
||||||
changelog.
|
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~
|
2015-10-19: Added convenient insert mode mappings~
|
||||||
I've merged the `math_mappings` branch (see #172 and #251). It adds the
|
I've merged the `math_mappings` branch (see #172 and #251). It adds the
|
||||||
feature that is explained in |vimtex-imaps|.
|
feature that is explained in |vimtex-imaps|.
|
||||||
|
@ -89,13 +89,10 @@ function! VimtexIndent() " {{{1
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
" Indent opening and closing delimiters
|
" Indent opening and closing delimiters
|
||||||
let l:delims = match(map(synstack(v:lnum, max([col('.') - 1, 1])),
|
let [l:re_open, l:re_close] = vimtex#delim#get_valid_regexps(v:lnum, col('.'))
|
||||||
\ 'synIDattr(v:val, ''name'')'), '^texMathZone') >= 0
|
|
||||||
\ ? [s:delimiters_open_math, s:delimiters_close_math]
|
|
||||||
\ : [s:delimiters_open_tex, s:delimiters_close_tex]
|
|
||||||
let ind += &sw*(
|
let ind += &sw*(
|
||||||
\ max([s:count(pline, l:delims[0]) - s:count(pline, l:delims[1]), 0])
|
\ max([s:count(pline, l:re_open) - s:count(pline, l:re_close), 0])
|
||||||
\ - max([s:count(cline, l:delims[1]) - s:count(cline, l:delims[0]), 0]))
|
\ - max([s:count(cline, l:re_close) - s:count(cline, l:re_open), 0]))
|
||||||
|
|
||||||
" Indent list items
|
" Indent list items
|
||||||
if pline =~# '^\s*\\\(bib\)\?item'
|
if pline =~# '^\s*\\\(bib\)\?item'
|
||||||
@ -138,28 +135,6 @@ let s:tikz_indented = 0
|
|||||||
" Define some common patterns
|
" Define some common patterns
|
||||||
let s:envs_lists = 'itemize\|description\|enumerate\|thebibliography'
|
let s:envs_lists = 'itemize\|description\|enumerate\|thebibliography'
|
||||||
let s:envs_noindent = 'document\|verbatim\|lstlisting'
|
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([
|
let s:tikz_commands = '\\\(' . join([
|
||||||
\ 'draw',
|
\ 'draw',
|
||||||
\ 'fill',
|
\ 'fill',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user