"====================================================================== " " leaderf_snippet.vim - " " Created by skywind on 2021/02/01 " Last Modified: 2021/02/13 21:07:12 " "====================================================================== "---------------------------------------------------------------------- " Query SnipMate Database "---------------------------------------------------------------------- function! SnipMateQuery(word, exact) abort let matches = snipMate#GetSnippetsForWordBelowCursor(a:word, a:exact) let result = [] let size = 4 for [trigger, dict] in matches let body = '' for key in keys(dict) let value = dict[key] if type(value) == v:t_list if len(value) > 0 let body = value[0] break endif endif endfor if body != '' let size = max([size, len(trigger)]) let result += [[trigger, body]] endif endfor for item in result let t = item[0] . repeat(' ', size - len(item[0])) call extend(item, [t]) endfor call sort(result) return result endfunc "---------------------------------------------------------------------- " Simplify Snippet Body "---------------------------------------------------------------------- function! SnipMateDescription(body, width) abort let text = join(split(a:body, '\n')[:4], ' ; ') let text = substitute(text, '^\s*\(.\{-}\)\s*$', '\1', '') let text = substitute(text, '\${[^{}]*}', '...', 'g') let text = substitute(text, '\${[^{}]*}', '...', 'g') let text = substitute(text, '\s\+', ' ', 'g') let text = strcharpart(text, 0, a:width) return text endfunc "---------------------------------------------------------------------- " Query Snippets "---------------------------------------------------------------------- function! UltiSnipsQuery() call UltiSnips#SnippetsInCurrentScope(1) let list = [] let size = 4 for [key, info] in items(g:current_ulti_dict_info) let desc = info.description if desc == '' let desc = '...' endif let size = max([size, len(key)]) let list += [[key, desc]] endfor call sort(list) for item in list let t = item[0] . repeat(' ', size - len(item[0])) call extend(item, [t]) endfor return list endfunc function! UltiSnipsQuery2() call s:init_python() if g:Lf_PythonVersion == 2 let matches = pyeval('leaderf_snippet.usnip_query()') else let matches = py3eval('leaderf_snippet.usnip_query()') endif let width = 100 for item in matches let desc = item[1] if desc == '' " let desc = SnipMateDescription(item[3], width) " let item[1] = desc endif endfor return matches endfunc "---------------------------------------------------------------------- " checks "---------------------------------------------------------------------- function! s:check_snipmate() return (exists(':SnipMateOpenSnippetFiles') == 2) endfunc function! s:check_ultisnips() return (exists(':UltiSnipsEdit') == 2) endfunc "---------------------------------------------------------------------- " internal "---------------------------------------------------------------------- let s:bufid = -1 let s:filetype = '' let s:accept = '' let s:snips = {} let s:snip_engine = -1 let s:inited = 0 let g:Lf_Extensions = get(g:, 'Lf_Extensions', {}) let s:home = fnamemodify(resolve(expand(':p')), ':h') function! s:init_python() if s:inited != 0 return 0 endif if s:check_snipmate() let s:snip_engine = 0 let s:inited = 1 return 0 elseif s:check_ultisnips() let s:snip_engine = 1 call UltiSnips#SnippetsInCurrentScope(1) else let s:snip_engine = -1 let s:inited = 1 return 0 endif exec g:Lf_py 'import sys, vim' exec g:Lf_py '_pp = vim.eval("s:home")' exec g:Lf_py 'if _pp not in sys.path: sys.path.append(_pp)' exec g:Lf_py 'import leaderf_snippet' if g:Lf_PythonVersion == 2 exec 'py2' 'import imp' exec 'py2' 'imp.reload(leaderf_snippet)' else exec 'py3' 'import importlib' exec 'py3' 'importlib.reload(leaderf_snippet)' endif exec g:Lf_py 'leaderf_snippet.init()' let s:inited = 1 return 1 endfunc function! s:lf_snippet_source(...) let source = [] if s:inited == 0 call s:init_python() let s:inited = 1 endif if s:snip_engine == 0 let matches = SnipMateQuery('', 0) elseif s:snip_engine == 1 " let matches = UltiSnipsQuery() let matches = UltiSnipsQuery2() else let error = "ERROR: Require UltiSnip (recommended) or SnipMate !!" redraw echohl ErrorMsg echom error echohl None let source += [error] let source += [error] let source += [error] return source endif let snips = {} let width = 100 for item in matches let trigger = item[0] if trigger =~ '^\u' continue endif if s:snip_engine == 0 let desc = SnipMateDescription(item[1], width) let snips[trigger] = item[1] else let desc = item[1] let snips[trigger] = item[3] endif let text = item[2] . ' ' . ' : ' . desc let source += [text] endfor let s:snips = snips return source endfunc " echo s:lf_snippet_source() function! s:lf_snippet_accept(line, arg) let pos = stridx(a:line, ':') if pos < 0 return endif let name = strpart(a:line, 0, pos) let name = substitute(name, '^\s*\(.\{-}\)\s*$', '\1', '') redraw if name != '' let s:accept = name . "\snipMateTrigger" if s:snip_engine == 0 if mode(1) =~ 'i' call feedkeys(name . "\snipMateTrigger", '!') " call feedkeys(name . "\=snipMate#TriggerSnippet(1)\", '!') else call feedkeys('a' . name . "\snipMateTrigger", '!') endif elseif s:snip_engine == 1 if mode(1) =~ 'i' call feedkeys("\", '!') " call feedkeys("" . name . "\", '!') call feedkeys(name . "\=UltiSnips#ExpandSnippet()\", '!') " unsilent echom "col: ". col('.') else call feedkeys('a' . name . "\=UltiSnips#ExpandSnippet()\", '!') endif endif endif endfunc function! s:lf_snippet_preview(orig_buf_nr, orig_cursor, line, args) let text = a:line let pos = stridx(text, ':') if pos < 0 return [] endif let name = strpart(text, 0, pos) let name = substitute(name, '^\s*\(.\{-}\)\s*$', '\1', '') let body = get(s:snips, name, '') if body == '' unsilent echom "SUCK" return [] endif if s:bufid < 0 let s:bufid = bufadd('') let bid = s:bufid call bufload(bid) call setbufvar(bid, '&buflisted', 0) call setbufvar(bid, '&bufhidden', 'hide') call setbufvar(bid, '&modifiable', 1) call deletebufline(bid, 1, '$') call setbufvar(bid, '&modified', 0) call setbufvar(bid, 'current_syntax', '') call setbufvar(bid, '&filetype', '') endif let bid = s:bufid let textlist = split(body, '\n') call setbufvar(bid, '&modifiable', 1) call setbufline(bid, 1, textlist) call setbufvar(bid, '&modified', 0) call setbufvar(bid, '&modifiable', 0) return [bid, 1, ''] endfunc function! s:lf_win_init(...) setlocal nonumber nowrap endfunc let g:Lf_Extensions.snippet = { \ 'source': string(function('s:lf_snippet_source'))[10:-3], \ 'accept': string(function('s:lf_snippet_accept'))[10:-3], \ 'preview': string(function('s:lf_snippet_preview'))[10:-3], \ 'highlights_def': { \ 'Lf_hl_funcScope': '^\S\+', \ }, \ 'after_enter': string(function('s:lf_win_init'))[10:-3], \ }