" {{{1 latex#motion#init function! latex#motion#init(initialized) if !g:latex_motion_enabled | return | endif if g:latex_default_mappings nnoremap % :call latex#motion#find_matching_pair('n') vnoremap % \ :call latex#motion#find_matching_pair('v') onoremap % :call latex#motion#find_matching_pair('o') nnoremap ]] :call latex#motion#next_sec(0,0,0) nnoremap ][ :call latex#motion#next_sec(1,0,0) nnoremap [] :call latex#motion#next_sec(1,1,0) nnoremap [[ :call latex#motion#next_sec(0,1,0) vnoremap ]] :call latex#motion#next_sec(0,0,1) vnoremap ][ :call latex#motion#next_sec(1,0,1) vnoremap [] :call latex#motion#next_sec(1,1,1) vnoremap [[ :call latex#motion#next_sec(0,1,1) onoremap ]] :normal v]] onoremap ][ :normal v][ onoremap [] :normal v[] onoremap [[ :normal v[[ vnoremap ie :latex#motion#select_current_env('inner') vnoremap ae :latex#motion#select_current_env('outer') onoremap ie :normal vie onoremap ae :normal vae vnoremap i$ :latex#motion#select_inline_math('inner') vnoremap a$ :latex#motion#select_inline_math('outer') onoremap i$ :normal vi$ onoremap a$ :normal va$ endif " " Highlight matching parens ($, (), ...) " if !a:initialized && g:latex_motion_matchparen augroup latex_motion autocmd! " Disable matchparen autocommands autocmd BufEnter *.tex \ if !exists("g:loaded_matchparen") || !g:loaded_matchparen \ | runtime plugin/matchparen.vim \ | endif autocmd BufEnter *.tex \ 3match none | unlet! g:loaded_matchparen | au! matchparen " Enable latex matchparen functionality autocmd! CursorMoved *.tex call latex#motion#find_matching_pair('h') autocmd! CursorMovedI *.tex call latex#motion#find_matching_pair('i') augroup END endif endfunction " {{{1 latex#motion#find_matching_pair function! latex#motion#find_matching_pair(mode) " " Note: This code is ugly, but it seems to work. " if a:mode =~ 'h\|i' 2match none elseif a:mode == 'v' normal! gv endif if latex#util#in_comment() | return | endif let lnum = line('.') let cnum = searchpos('\A', 'cbnW', lnum)[1] " Check if previous char is a backslash 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 = '\(' . all_pats . '\|\$\)' let delim = matchstr(getline(lnum), '\C^'. all_pats, cnum-1) if empty(delim) || strlen(delim)+cnum-1 < col('.') if a:mode =~ 'n\|v\|o' " if not found, search forward let cnum = match(getline(lnum), '\C'. all_pats, col('.') - 1) + 1 if cnum == 0 | return | endif call cursor(lnum, cnum) let delim = matchstr(getline(lnum), '\C^'. all_pats, cnum - 1) elseif a:mode =~ 'i' " 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 endif endif if delim =~ '^\$' " match $-pairs " check if next character is in 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$')*(a:mode =~ 'h\|i'), 200) else let [lnum2, cnum2] = searchpos('\%(\%'. lnum . 'l\%' \ . cnum . 'c\)\@!'. b:notcomment . b:notbslash . '\$', \ 'bnW', line('w0')*(a:mode =~ 'h\|i'), 200) endif if a:mode =~ 'h\|i' execute '2match MatchParen /\%(\%' . lnum . 'l\%' \ . cnum . 'c\$' . '\|\%' . lnum2 . 'l\%' . cnum2 . 'c\$\)/' elseif a:mode =~ 'n\|v\|o' call cursor(lnum2,cnum2) endif else " match other pairs for i in range(len(g:latex_motion_open_pats)) let open_pat = b:notbslash . g:latex_motion_open_pats[i] let close_pat = b:notbslash . g:latex_motion_close_pats[i] if delim =~# '^' . open_pat " if on opening pattern, search for closing pattern let [lnum2, cnum2] = searchpairpos('\C' . open_pat, '', '\C' \ . close_pat, 'nW', 'latex#util#in_comment()', \ line('w$')*(a:mode =~ 'h\|i'), 200) 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 " if on closing pattern, search for opening pattern let [lnum2, cnum2] = searchpairpos('\C' . open_pat, '', \ '\C\%(\%'. lnum . 'l\%' . cnum . 'c\)\@!' \ . 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 endfor endif endfunction " {{{1 latex#motion#next_sec function! latex#motion#next_sec(type, backwards, visual) " Restore visual mode if desired if a:visual normal! gv endif " For the [] and ][ commands we move up or down before the search if a:type == 1 if a:backwards normal! k else normal! j endif endif " Define search pattern and do the search while preserving "/ let save_search = @/ let flags = 'W' if a:backwards let flags = 'b' . flags endif " Define section pattern let sec_pat = join([ \ '(sub)*section', \ 'chapter', \ 'part', \ 'appendix', \ '(front|back|main)matter', \ ], '|') let sec_pat = b:notcomment . '\v\s*\\(' . sec_pat . ')>' " Perform the search call search(sec_pat, flags) let @/ = save_search " For the [] and ][ commands we move down or up after the search if a:type == 1 if a:backwards normal! j else normal! k endif endif endfunction " {{{1 latex#motion#select_current_env function! latex#motion#select_current_env(seltype) let [env, lnum, cnum, lnum2, cnum2] = latex#util#get_env(1) call cursor(lnum, cnum) if a:seltype == 'inner' if env =~ '^\' call search('\\.\_\s*\S', 'eW') else call search('}\(\_\s*\[\_[^]]*\]\)\?\_\s*\S', 'eW') endif endif if visualmode() ==# 'V' normal! V else normal! v endif call cursor(lnum2, cnum2) if a:seltype == 'inner' call search('\S\_\s*', 'bW') else if env =~ '^\' normal! l else call search('}', 'eW') endif endif endfunction " {{{1 latex#motion#select_inline_math function! latex#motion#select_inline_math(seltype) " seltype is either 'inner' or 'outer' let dollar_pat = '\\\@