用于 Ultisnips+Deoplete 兼容性的 vimscript
vimscript for Ultisnips+Deoplete compatibility
我想知道如何编写重载 <TAB>
的函数。
首先它会检查是否有需要完成的片段,如果有片段,则展开它。
否则,我希望该函数在按下 Tab 之前检查光标前是否有 space(或者我们在新行上)。如果是这样,那么它应该做常规 <tab>
。
否则,我想让它调用
deoplete#manual_complete()
除非已经打开了一个菜单,在这种情况下,我应该可以通过 Tab 键浏览它。
这是我的尝试(完全失败)和一些设置供参考:
let g:ulti_expand_or_jump_res = 0 "default value, just set once
function! Ulti_ExpandOrJump_and_getRes()
call UltiSnips#ExpandSnippetOrJump()
return g:ulti_expand_or_jump_res
endfunction
inoremap <silent><expr> <tab>
\ (Ulti_ExpandOrJump_and_getRes() > 0) ? "\<C-y>"
\ : pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ deoplete#manual_complete()
function! s:check_back_space() abort "{{{
let col = col('.') - 1
return !col || getline('.')[col - 1] =~ '\s'
endfunction "}}}
奇怪的是,当我按 Tab 键时,vim 的右下角显示我输入了“^I”,这是非常奇怪的行为。
我没有 ultisnips expand trigger as "tab" 的原因是它禁止使用 tab 来 deoplete(无论出于何种原因。)
我认为您 运行 遇到的主要问题是 UltiSnips#ExpandSnippetOrJump()
会尝试移动光标,这是插入模式下 <expr>
映射的问题。使用 <C-R>=...<CR>
应该可以使它工作。 (至少那是 UltiSnips 文档中的示例所使用的。)
我还建议使用单个函数来处理所有 Tab 大小写,而不是相当长的单行代码。这样您就可以使用 if
s 并具体记录每个案例。
我还认为,对于扩展或跳转 UltiSnips 的情况,您希望扩展到空而不是 <C-y>
,对吗?
综合起来:
function! HandleTab() abort
" First, try to expand or jump on UltiSnips.
call UltiSnips#ExpandSnippetOrJump()
if g:ulti_expand_or_jump_res > 0
return ""
endif
" Then, check if we're in a completion menu
if pumvisible()
return "\<C-n>"
endif
" Then check if we're indenting.
let col = col('.') - 1
if !col || getline('.')[col - 1] =~ '\s'
return "\<Tab>"
endif
" Finally, trigger deoplete completion.
return deoplete#manual_complete()
endfunction
inoremap <silent> <Tab> <C-R>=HandleTab()<CR>
您可能想查看支票的顺序。在我看来,应该首先检查 pumvisible()
。此外,检查你是否缩进可能比检查 UltiSnips 扩展更便宜,尽管我猜你可能在有 space 时跳过字段......无论如何,调整它应该很容易使它有效。
我想知道如何编写重载 <TAB>
的函数。
首先它会检查是否有需要完成的片段,如果有片段,则展开它。
否则,我希望该函数在按下 Tab 之前检查光标前是否有 space(或者我们在新行上)。如果是这样,那么它应该做常规 <tab>
。
否则,我想让它调用
deoplete#manual_complete()
除非已经打开了一个菜单,在这种情况下,我应该可以通过 Tab 键浏览它。
这是我的尝试(完全失败)和一些设置供参考:
let g:ulti_expand_or_jump_res = 0 "default value, just set once
function! Ulti_ExpandOrJump_and_getRes()
call UltiSnips#ExpandSnippetOrJump()
return g:ulti_expand_or_jump_res
endfunction
inoremap <silent><expr> <tab>
\ (Ulti_ExpandOrJump_and_getRes() > 0) ? "\<C-y>"
\ : pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<TAB>" :
\ deoplete#manual_complete()
function! s:check_back_space() abort "{{{
let col = col('.') - 1
return !col || getline('.')[col - 1] =~ '\s'
endfunction "}}}
奇怪的是,当我按 Tab 键时,vim 的右下角显示我输入了“^I”,这是非常奇怪的行为。
我没有 ultisnips expand trigger as "tab" 的原因是它禁止使用 tab 来 deoplete(无论出于何种原因。)
我认为您 运行 遇到的主要问题是 UltiSnips#ExpandSnippetOrJump()
会尝试移动光标,这是插入模式下 <expr>
映射的问题。使用 <C-R>=...<CR>
应该可以使它工作。 (至少那是 UltiSnips 文档中的示例所使用的。)
我还建议使用单个函数来处理所有 Tab 大小写,而不是相当长的单行代码。这样您就可以使用 if
s 并具体记录每个案例。
我还认为,对于扩展或跳转 UltiSnips 的情况,您希望扩展到空而不是 <C-y>
,对吗?
综合起来:
function! HandleTab() abort
" First, try to expand or jump on UltiSnips.
call UltiSnips#ExpandSnippetOrJump()
if g:ulti_expand_or_jump_res > 0
return ""
endif
" Then, check if we're in a completion menu
if pumvisible()
return "\<C-n>"
endif
" Then check if we're indenting.
let col = col('.') - 1
if !col || getline('.')[col - 1] =~ '\s'
return "\<Tab>"
endif
" Finally, trigger deoplete completion.
return deoplete#manual_complete()
endfunction
inoremap <silent> <Tab> <C-R>=HandleTab()<CR>
您可能想查看支票的顺序。在我看来,应该首先检查 pumvisible()
。此外,检查你是否缩进可能比检查 UltiSnips 扩展更便宜,尽管我猜你可能在有 space 时跳过字段......无论如何,调整它应该很容易使它有效。