Vim has various built-in completion systems, e.g.:
<C-x C-l>: Line<C-x C-i>: From current and included files<C-x C-]>: Tags<C-x C-f>: Filenames<C-x C-n> or <C-n>: From after cursor position<C-x C-p> or <C-p>: From before cursor positionCan any of these be used to select a snippet? For example, I have various snippets defined as ifvariable, iffileexists, etc... I'd like be able to just type if then a trigger (like C-x C-p), and then select from a list of my snippets that begin with if. Is that possible?
Thanks!
FWIW, I use something similar to this:
ino <silent> <c-x><c-z> <c-r>=<sid>ulti_complete()<cr>
fu! s:ulti_complete() abort
if empty(UltiSnips#SnippetsInCurrentScope(1))
return ''
endif
let word_to_complete = matchstr(strpart(getline('.'), 0, col('.') - 1), '\S\+$')
let contain_word = 'stridx(v:val, word_to_complete)>=0'
let candidates = map(filter(keys(g:current_ulti_dict_info), contain_word),
\ "{
\ 'word': v:val,
\ 'menu': '[snip] '. g:current_ulti_dict_info[v:val]['description'],
\ 'dup' : 1,
\ }")
let from_where = col('.') - len(word_to_complete)
if !empty(candidates)
call complete(from_where, candidates)
endif
return ''
endfu
It installs a mapping on C-x C-z which should complete the text before the cursor using the tab triggers you defined for the current filetype.
For more information, see:
:help complete()
:help UltiSnips#SnippetsInCurrentScope
Thanks lacygoill! I was able to set this up and it looks like it's working. I'd still prefer it if there were a way to use one of Vim's many existing completion systems to complete snippets, but this is the next best thing!
@robenkleene I do not know of a way of extending Vim's built in completion with custom completion (i.e. snippets). @lacygoill Solution is the closest you can get.
@robenkleene You can write a custom completefunc to use with built-in <C-x C-u>.
I use the following function for markdown files (based on @lacygoill and this SO answer):
function! functions#ListSnippets(findstart, base) abort
if empty(UltiSnips#SnippetsInCurrentScope(1))
return ''
endif
if a:findstart
" locate the start of the word
let line = getline('.')
let start = col('.') - 1
while start > 0 && (line[start - 1] =~ '\a')
let start -= 1
endwhile
return start
else
" find classes matching "a:base"
let res = []
for m in keys(g:current_ulti_dict_info)
if m =~ a:base
let n = {
\ 'word': m,
\ 'menu': '[snip] '. g:current_ulti_dict_info[m]['description']
\ }
call add(res, n)
endif
endfor
return res
endif
endfunction
and then in ftplugin/markdown.vim:
setlocal completefunc=functions#ListSnippets
it still needs some tweaking, but it gets the job done quite well.
Thanks for sharing this @wolloda! I've switched to this method and so far it's working great.
If we want to match from beginning:
if m =~ "^" . a:base
" ...
endif
@wolloda Thanks for sharing.
can ultisnips has this function as built-in function? can be better than the prompt way
can ultisnips has this function as built-in function? can be better than the prompt way
Yeah man, would be great
Most helpful comment
@robenkleene You can write a custom completefunc to use with built-in
<C-x C-u>.I use the following function for markdown files (based on @lacygoill and this SO answer):
and then in
ftplugin/markdown.vim:setlocal completefunc=functions#ListSnippetsit still needs some tweaking, but it gets the job done quite well.