diff options
Diffstat (limited to 'autoload/vimtex/imaps.vim')
-rw-r--r-- | autoload/vimtex/imaps.vim | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/autoload/vimtex/imaps.vim b/autoload/vimtex/imaps.vim new file mode 100644 index 00000000..6b682f0c --- /dev/null +++ b/autoload/vimtex/imaps.vim @@ -0,0 +1,192 @@ +if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1 + +" vimtex - LaTeX plugin for Vim +" +" Maintainer: Karl Yngve LervÄg +" Email: karl.yngve@gmail.com +" + +function! vimtex#imaps#init_buffer() abort " {{{1 + if !g:vimtex_imaps_enabled | return | endif + + " + " Create imaps + " + let l:maps = g:vimtex_imaps_list + for l:disable in g:vimtex_imaps_disabled + let l:maps = filter(l:maps, 'v:val.lhs !=# ''' . l:disable . '''') + endfor + for l:map in l:maps + get(s:, 'custom_maps', []) + call s:create_map(l:map) + endfor + + " + " Add mappings and commands + " + command! -buffer VimtexImapsList call vimtex#imaps#list() + nnoremap <buffer> <plug>(vimtex-imaps-list) :call vimtex#imaps#list()<cr> +endfunction + +" }}}1 + +function! vimtex#imaps#add_map(map) abort " {{{1 + let s:custom_maps = get(s:, 'custom_maps', []) + [a:map] + + if exists('s:created_maps') + call s:create_map(a:map) + endif +endfunction + +" }}}1 +function! vimtex#imaps#list() abort " {{{1 + silent new vimtex\ imaps + + for l:map in s:created_maps + call append('$', printf('%5S -> %-30S %S', + \ get(l:map, 'leader', get(g:, 'vimtex_imaps_leader', '`')) . l:map.lhs, + \ l:map.rhs, + \ get(l:map, 'wrapper', 'vimtex#imaps#wrap_math'))) + endfor + 0delete _ + + nnoremap <silent><nowait><buffer> q :bwipeout<cr> + nnoremap <silent><nowait><buffer> <esc> :bwipeout<cr> + + setlocal bufhidden=wipe + setlocal buftype=nofile + setlocal concealcursor=nvic + setlocal conceallevel=0 + setlocal cursorline + setlocal nobuflisted + setlocal nolist + setlocal nospell + setlocal noswapfile + setlocal nowrap + setlocal nonumber + setlocal norelativenumber + setlocal nomodifiable + + syntax match VimtexImapsLhs /^.*\ze->/ nextgroup=VimtexImapsArrow + syntax match VimtexImapsArrow /->/ contained nextgroup=VimtexImapsRhs + syntax match VimtexImapsRhs /\s*\S*/ contained nextgroup=VimtexImapsWrapper + syntax match VimtexImapsWrapper /.*/ contained +endfunction + +" }}}1 + +" +" The imap generator +" +function! s:create_map(map) abort " {{{1 + if index(s:created_maps, a:map) >= 0 | return | endif + + let l:leader = get(a:map, 'leader', get(g:, 'vimtex_imaps_leader', '`')) + if l:leader !=# '' && !hasmapto(l:leader, 'i') + silent execute 'inoremap <silent><nowait><buffer>' l:leader . l:leader l:leader + endif + let l:lhs = l:leader . a:map.lhs + + let l:wrapper = get(a:map, 'wrapper', 'vimtex#imaps#wrap_math') + if ! exists('*' . l:wrapper) + echoerr 'vimtex error: imaps wrapper does not exist!' + echoerr ' ' . l:wrapper + return + endif + + " Some wrappers use a context which must be made available to the wrapper + " function at run time. + if has_key(a:map, 'context') + execute 'let l:key = "' . escape(l:lhs, '<') . '"' + let l:key .= a:map.rhs + if !exists('b:vimtex_context') + let b:vimtex_context = {} + endif + let b:vimtex_context[l:key] = a:map.context + endif + + " The rhs may be evaluated before being passed to wrapper, unless expr is + " disabled (which it is by default) + if !get(a:map, 'expr') + let a:map.rhs = string(a:map.rhs) + endif + + silent execute 'inoremap <expr><silent><nowait><buffer>' l:lhs + \ l:wrapper . '("' . escape(l:lhs, '\') . '", ' . a:map.rhs . ')' + + let s:created_maps += [a:map] +endfunction + +" }}}1 + +" +" Wrappers +" +function! vimtex#imaps#wrap_trivial(lhs, rhs) abort " {{{1 + return a:rhs +endfunction + +" }}}1 +function! vimtex#imaps#wrap_math(lhs, rhs) abort " {{{1 + return s:is_math() ? a:rhs : a:lhs +endfunction + +" }}}1 +function! vimtex#imaps#wrap_environment(lhs, rhs) abort " {{{1 + let l:return = a:lhs + let l:cursor = vimtex#pos#val(vimtex#pos#get_cursor()) + let l:value = 0 + + for l:context in b:vimtex_context[a:lhs . a:rhs] + if type(l:context) == type('') + let l:envs = [l:context] + let l:rhs = a:rhs + elseif type(l:context) == type({}) + let l:envs = l:context.envs + let l:rhs = l:context.rhs + endif + + for l:env in l:envs + let l:candidate_value = vimtex#pos#val(vimtex#env#is_inside(l:env)) + if l:candidate_value > l:value + let l:value = l:candidate_value + let l:return = l:rhs + endif + endfor + + unlet l:context + endfor + + return l:return +endfunction + +" }}}1 + +" +" Special rhs styles +" +function! vimtex#imaps#style_math(command) " {{{1 + return s:is_math() + \ ? '\' . a:command . '{' . nr2char(getchar()) . '}' + \ : '' +endfunction + +" }}}1 + +" +" Helpers +" +function! s:is_math() abort " {{{1 + return match(map(synstack(line('.'), max([col('.') - 1, 1])), + \ 'synIDattr(v:val, ''name'')'), '^texMathZone') >= 0 +endfunction + +" }}}1 + + +" {{{1 Initialize module + +let s:created_maps = [] + +" }}}1 + +endif |