89 lines
2.7 KiB
VimL
89 lines
2.7 KiB
VimL
let s:cache = {}
|
|
|
|
function! vsnip#source#snipmate#refresh(path) abort
|
|
if has_key(s:cache, a:path)
|
|
unlet s:cache[a:path]
|
|
endif
|
|
endfunction
|
|
|
|
function! vsnip#source#snipmate#find(bufnr) abort
|
|
let filetypes = vsnip#source#filetypes(a:bufnr)
|
|
return s:find(filetypes, a:bufnr)
|
|
endfunction
|
|
|
|
function! s:find(filetypes, bufnr) abort
|
|
let sources = []
|
|
for path in s:get_source_paths(a:filetypes, a:bufnr)
|
|
if !has_key(s:cache, path)
|
|
let s:cache[path] = s:create(path, a:bufnr)
|
|
endif
|
|
call add(sources, s:cache[path])
|
|
endfor
|
|
return sources
|
|
endfunction
|
|
|
|
function! s:get_source_paths(filetypes, bufnr) abort
|
|
let paths = []
|
|
for dir in s:get_source_dirs(a:bufnr)
|
|
for filetype in a:filetypes
|
|
let path = resolve(expand(printf('%s/%s.snippets', dir, filetype)))
|
|
if has_key(s:cache, path) || filereadable(path)
|
|
call add(paths, path)
|
|
endif
|
|
endfor
|
|
endfor
|
|
return paths
|
|
endfunction
|
|
|
|
function! s:get_source_dirs(bufnr) abort
|
|
let dirs = []
|
|
let buf_dir = getbufvar(a:bufnr, 'vsnip_snippet_dir', '')
|
|
if buf_dir !=# ''
|
|
let dirs += [buf_dir]
|
|
endif
|
|
let dirs += getbufvar(a:bufnr, 'vsnip_snippet_dirs', [])
|
|
let dirs += [g:vsnip_snippet_dir]
|
|
let dirs += g:vsnip_snippet_dirs
|
|
return dirs
|
|
endfunction
|
|
|
|
function! s:create(path, bufnr) abort
|
|
let file = readfile(a:path)
|
|
let file = type(file) == v:t_list ? file : [file]
|
|
call map(file, { _, f -> iconv(f, 'utf-8', &encoding) })
|
|
let source = []
|
|
let i = -1
|
|
while i + 1 < len(file)
|
|
let [i, line] = [i + 1, file[i + 1]]
|
|
if line =~# '^\(#\|\s*$\)'
|
|
" Comment, or blank line before snippets
|
|
elseif line =~# '^extends\s\+\S'
|
|
let filetypes = map(split(line[7:], ','), 'trim(v:val)')
|
|
let source += flatten(s:find(filetypes, a:bufnr))
|
|
elseif line =~# '^snippet\s\+\S' && i + 1 < len(file)
|
|
let matched = matchlist(line, '^snippet\s\+\(\S\+\)\s*\(.*\)')
|
|
let [prefix, description] = [matched[1], matched[2]]
|
|
let body = []
|
|
let indent = matchstr(file[i + 1], '^\s\+')
|
|
while i + 1 < len(file) && file[i + 1] =~# '^\(' . indent . '\|\s*$\)'
|
|
let [i, line] = [i + 1, file[i + 1]]
|
|
call add(body, line[strlen(indent):])
|
|
endwhile
|
|
let [prefixes, prefixes_alias] = vsnip#source#resolve_prefix(prefix)
|
|
call add(source, {
|
|
\ 'label': prefix,
|
|
\ 'prefix': prefixes,
|
|
\ 'prefix_alias': prefixes_alias,
|
|
\ 'body': body,
|
|
\ 'description': description
|
|
\ })
|
|
else
|
|
echohl ErrorMsg
|
|
echomsg printf('[vsnip] Parsing error occurred on: %s#L%s', a:path, i + 1)
|
|
echohl None
|
|
break
|
|
endif
|
|
endwhile
|
|
return sort(source, { a, b -> strlen(b.prefix[0]) - strlen(a.prefix[0]) })
|
|
endfunction
|