Fixed motion and improved change

This commit is contained in:
Karl Yngve Lervåg 2013-10-06 13:39:25 +02:00
parent 164fc42e8b
commit ae45837c41
2 changed files with 132 additions and 104 deletions

View File

@ -1,32 +1,35 @@
" {{{1 latex#change#init " {{{1 latex#change#init
function! latex#change#init(initialized) function! latex#change#init(initialized)
if g:latex_default_mappings if g:latex_default_mappings
nnoremap <silent><buffer> <f5> nnoremap <silent><buffer> dse :call latex#change#env('')<cr>
\ :call latex#change#environment_prompt()<cr> nnoremap <silent><buffer> cse :call latex#change#env_prompt()<cr>
nnoremap <silent><buffer> <f6> nnoremap <silent><buffer> tse :call latex#change#env_toggle_star()<cr>
\ :call latex#change#environment_toggle_star()<cr>
endif endif
endfunction endfunction
" {{{1 latex#change#environment " {{{1 latex#change#env
function! latex#change#environment(new_env) function! latex#change#env(new_env)
let [env, l1, c1, l2, c2] = latex#util#get_env(1) let [env, l1, c1, l2, c2] = latex#util#get_env(1)
if a:new_env == '\[' || a:new_env == '[' if a:new_env == ''
let beg = ''
let end = ''
elseif a:new_env == '\[' || a:new_env == '['
let beg = '\[' let beg = '\['
let end = '\]' let end = '\]'
let n1 = 1
let n2 = 1
elseif a:new_env == '\(' || a:new_env == '(' elseif a:new_env == '\(' || a:new_env == '('
let beg = '\(' let beg = '\('
let end = '\)' let end = '\)'
let n1 = 1
let n2 = 1
else else
let beg = '\begin{' . a:new_env . '}' let beg = '\begin{' . a:new_env . '}'
let end = '\end{' . a:new_env . '}' let end = '\end{' . a:new_env . '}'
let n1 = len(env) + 7 endif
let n2 = len(env) + 5
let n1 = len(env) - 1
let n2 = len(env) - 1
if env != '\[' && env != '\('
let n1 += 8
let n2 += 6
endif endif
let line = getline(l1) let line = getline(l1)
@ -37,19 +40,19 @@ function! latex#change#environment(new_env)
call setline(l2, line) call setline(l2, line)
endfunction endfunction
" {{{1 latex#change#environment_prompt " {{{1 latex#change#env_prompt
function! latex#change#environment_prompt() function! latex#change#env_prompt()
let new_env = input('Change ' . latex#util#get_env() . ' for: ', '', let new_env = input('Change ' . latex#util#get_env() . ' for: ', '',
\ 'customlist,' . s:sidwrap('input_complete')) \ 'customlist,' . s:sidwrap('input_complete'))
if empty(new_env) if empty(new_env)
return return
else else
call latex#change#environment(new_env) call latex#change#env(new_env)
endif endif
endfunction endfunction
" {{{1 latex#change#environment_toggle_star " {{{1 latex#change#env_toggle_star
function! latex#change#environment_toggle_star() function! latex#change#env_toggle_star()
let env = latex#util#get_env() let env = latex#util#get_env()
if env == '\(' if env == '\('
@ -62,7 +65,7 @@ function! latex#change#environment_toggle_star()
let new_env = env . '*' let new_env = env . '*'
endif endif
call latex#change#environment(new_env) call latex#change#env(new_env)
endfunction endfunction
" {{{1 latex#change#wrap_selection " {{{1 latex#change#wrap_selection

View File

@ -3,10 +3,10 @@ function! latex#motion#init(initialized)
if !g:latex_motion_enabled | return | endif if !g:latex_motion_enabled | return | endif
if g:latex_default_mappings if g:latex_default_mappings
nnoremap <silent><buffer> % :call latex#motion#find_matching_pair('n')<cr> nnoremap <silent><buffer> % :call latex#motion#find_matching_pair()<cr>
vnoremap <silent><buffer> % vnoremap <silent><buffer> %
\ :<c-u>call latex#motion#find_matching_pair('v')<cr> \ :<c-u>call latex#motion#find_matching_pair(1)<cr>
onoremap <silent><buffer> % :call latex#motion#find_matching_pair('o')<cr> onoremap <silent><buffer> % :normal v%<cr>
nnoremap <silent><buffer> ]] :call latex#motion#next_sec(0,0,0)<cr> nnoremap <silent><buffer> ]] :call latex#motion#next_sec(0,0,0)<cr>
nnoremap <silent><buffer> ][ :call latex#motion#next_sec(1,0,0)<cr> nnoremap <silent><buffer> ][ :call latex#motion#next_sec(1,0,0)<cr>
@ -47,119 +47,72 @@ function! latex#motion#init(initialized)
\ 3match none | unlet! g:loaded_matchparen | au! matchparen \ 3match none | unlet! g:loaded_matchparen | au! matchparen
" Enable latex matchparen functionality " Enable latex matchparen functionality
autocmd! CursorMoved *.tex call latex#motion#find_matching_pair('h') autocmd! CursorMoved *.tex call s:highlight_matching_pair(1)
autocmd! CursorMovedI *.tex call latex#motion#find_matching_pair('i') autocmd! CursorMovedI *.tex call s:highlight_matching_pair()
augroup END augroup END
endif endif
endfunction endfunction
" {{{1 latex#motion#find_matching_pair " {{{1 latex#motion#find_matching_pair
function! latex#motion#find_matching_pair(mode) function! latex#motion#find_matching_pair(...)
" "
" Note: This code is ugly, but it seems to work. " Note: This code is ugly, but it seems to work.
" "
if a:mode =~ 'h\|i' if a:0 > 0
2match none
elseif a:mode == 'v'
normal! gv normal! gv
endif endif
if latex#util#in_comment() | return | endif if latex#util#in_comment() | return | endif
let lnum = line('.') " Save position
let cnum = searchpos('\A', 'cbnW', lnum)[1] let nl = line('.')
let nc = col('.')
" Check if previous char is a backslash " Combine all open/close pats
if strpart(getline(lnum), cnum-2, 1) == '\'
let cnum = cnum-1
endif
" Make pattern to combine all open/close pats
let all_pats = join(g:latex_motion_open_pats+g:latex_motion_close_pats, '\|') let all_pats = join(g:latex_motion_open_pats+g:latex_motion_close_pats, '\|')
let all_pats = '\(' . all_pats . '\|\$\)' let all_pats = '\C\(' . all_pats . '\|\$\)'
let delim = matchstr(getline(lnum), '\C^'. all_pats, cnum-1) " Find delimiter under cursor
if empty(delim) || strlen(delim)+cnum-1 < col('.') let [lnum, cnum] = searchpos(all_pats, 'cbnW', nl-2)
if a:mode =~ 'n\|v\|o' let delim = matchstr(getline(lnum), '^'. all_pats, cnum-1)
" if not found, search forward
let cnum = match(getline(lnum), '\C'. all_pats, col('.') - 1) + 1 " If delimiter not found, try to search forward instead
if cnum == 0 | return | endif if empty(delim)
call cursor(lnum, cnum) let [lnum, cnum] = searchpos(all_pats, 'cnW', nl+2)
let delim = matchstr(getline(lnum), '\C^'. all_pats, cnum - 1) let delim = matchstr(getline(lnum), '^'. all_pats, cnum-1)
elseif a:mode =~ 'i' if empty(delim)
" if not found, move one char bacward and search
let cnum = searchpos('\A', 'bnW', lnum)[1]
" if the previous char is a backslash
if strpart(getline(lnum), cnum-2, 1) == '\'
let cnum = cnum-1
endif
let delim = matchstr(getline(lnum), '\C^'. all_pats, cnum - 1)
if empty(delim) || strlen(delim)+cnum< col('.')
return
endif
elseif a:mode =~ 'h'
return return
endif endif
endif endif
" Utility pattern to NOT match the current cursor position
let not_cursor = '\%(\%'. lnum . 'l\%' . cnum . 'c\)\@!'
" Finally, find the matching delimiter
if delim =~ '^\$' if delim =~ '^\$'
" match $-pairs let inline = b:notcomment . b:notbslash . '\$'
" check if next character is in inline math
let [lnum0, cnum0] = searchpos('.', 'nW') let [lnum0, cnum0] = searchpos('.', 'nW')
if lnum0 && latex#util#has_syntax('texMathZoneX', lnum0, cnum0) if lnum0 && latex#util#has_syntax('texMathZoneX', lnum0, cnum0)
let [lnum2, cnum2] = searchpos(b:notcomment . b:notbslash . '\$', let [lnum2, cnum2] = searchpos(inline, 'nW', 0, 200)
\ 'nW', line('w$')*(a:mode =~ 'h\|i'), 200)
else else
let [lnum2, cnum2] = searchpos('\%(\%'. lnum . 'l\%' let [lnum2, cnum2] = searchpos(not_cursor . inline, 'bnW', 0, 200)
\ . cnum . 'c\)\@!'. b:notcomment . b:notbslash . '\$',
\ 'bnW', line('w0')*(a:mode =~ 'h\|i'), 200)
endif endif
if a:mode =~ 'h\|i' call cursor(lnum2,cnum2)
execute '2match MatchParen /\%(\%' . lnum . 'l\%'
\ . cnum . 'c\$' . '\|\%' . lnum2 . 'l\%' . cnum2 . 'c\$\)/'
elseif a:mode =~ 'n\|v\|o'
call cursor(lnum2,cnum2)
endif
else else
" match other pairs
for i in range(len(g:latex_motion_open_pats)) for i in range(len(g:latex_motion_open_pats))
let open_pat = b:notbslash . g:latex_motion_open_pats[i] let open_pat = '\C' . b:notbslash . g:latex_motion_open_pats[i]
let close_pat = b:notbslash . g:latex_motion_close_pats[i] let close_pat = '\C' . b:notbslash . g:latex_motion_close_pats[i]
if delim =~# '^' . open_pat if delim =~# '^' . open_pat
" if on opening pattern, search for closing pattern call searchpairpos(open_pat, '', close_pat,
let [lnum2, cnum2] = searchpairpos('\C' . open_pat, '', '\C' \ 'W', 'latex#util#in_comment()', 0, 200)
\ . close_pat, 'nW', 'latex#util#in_comment()', call search(close_pat, 'ce')
\ line('w$')*(a:mode =~ 'h\|i'), 200) return
if a:mode =~ 'h\|i'
execute '2match MatchParen /\%(\%' . lnum . 'l\%' . cnum
\ . 'c' . g:latex_motion_open_pats[i] . '\|\%'
\ . lnum2 . 'l\%' . cnum2 . 'c'
\ . g:latex_motion_close_pats[i] . '\)/'
elseif a:mode =~ 'n\|v\|o'
call cursor(lnum2,cnum2)
if strlen(close_pat)>1 && a:mode =~ 'o'
call cursor(lnum2, matchend(getline('.'), '\C'
\ . close_pat, col('.')-1))
endif
endif
break
elseif delim =~# '^' . close_pat elseif delim =~# '^' . close_pat
" if on closing pattern, search for opening pattern call searchpairpos(open_pat, '', not_cursor . close_pat,
let [lnum2, cnum2] = searchpairpos('\C' . open_pat, '', \ 'bW', 'latex#util#in_comment()', 0, 200)
\ '\C\%(\%'. lnum . 'l\%' . cnum . 'c\)\@!' return
\ . close_pat, 'bnW', 'latex#util#in_comment()',
\ line('w0')*(a:mode =~ 'h\|i'), 200)
if a:mode =~ 'h\|i'
execute '2match MatchParen /\%(\%' . lnum2 . 'l\%' . cnum2
\ . 'c' . g:latex_motion_open_pats[i] . '\|\%'
\ . lnum . 'l\%' . cnum . 'c'
\ . g:latex_motion_close_pats[i] . '\)/'
elseif a:mode =~ 'n\|v\|o'
call cursor(lnum2,cnum2)
endif
break
endif endif
endfor endfor
endif endif
@ -272,4 +225,76 @@ function! latex#motion#select_inline_math(seltype)
endfunction endfunction
" }}}1 " }}}1
" {{{1 s:highlight_matching_pair
function! s:highlight_matching_pair(...)
if latex#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)
" Combine all open/close pats
let all_pats = join(g:latex_motion_open_pats+g:latex_motion_close_pats, '\|')
let all_pats = '\C\(' . all_pats . '\|\$\)'
" Find delimiter under cursor
let cnum = searchpos(all_pats, 'cbnW', nl)[1]
let delim = matchstr(line, '^'. all_pats, cnum-1)
" 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 && latex#util#has_syntax('texMathZoneX', lnum0, cnum0)
let [lnum2, cnum2] = searchpos(b:notcomment . b:notbslash . '\$',
\ 'nW', line('w$'), 200)
else
let [lnum2, cnum2] = searchpos('\%(\%'. nl . 'l\%'
\ . cnum . 'c\)\@!'. b:notcomment . b: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(g:latex_motion_open_pats))
let open_pat = '\C' . b:notbslash . g:latex_motion_open_pats[i]
let close_pat = '\C' . b:notbslash . g:latex_motion_close_pats[i]
if delim =~# '^' . open_pat
let [lnum2, cnum2] = searchpairpos(open_pat, '', close_pat,
\ 'nW', 'latex#util#in_comment()', line('w$'), 200)
execute '2match MatchParen /\%(\%' . nl . 'l\%' . cnum
\ . 'c' . g:latex_motion_open_pats[i] . '\|\%'
\ . lnum2 . 'l\%' . cnum2 . 'c'
\ . g:latex_motion_close_pats[i] . '\)/'
return
elseif delim =~# '^' . close_pat
let [lnum2, cnum2] = searchpairpos(open_pat, '',
\ '\C\%(\%'. nl . 'l\%' . cnum . 'c\)\@!' . close_pat,
\ 'bnW', 'latex#util#in_comment()', line('w0'), 200)
execute '2match MatchParen /\%(\%' . lnum2 . 'l\%' . cnum2
\ . 'c' . g:latex_motion_open_pats[i] . '\|\%'
\ . nl . 'l\%' . cnum . 'c'
\ . g:latex_motion_close_pats[i] . '\)/'
return
endif
endfor
endif
endfunction
" }}}1
" vim:fdm=marker:ff=unix " vim:fdm=marker:ff=unix