|
| 1 | +let s:cache = {} |
| 2 | + |
| 3 | +function! vsnip#source#snipmate#refresh(path) abort |
| 4 | + if has_key(s:cache, a:path) |
| 5 | + unlet s:cache[a:path] |
| 6 | + endif |
| 7 | +endfunction |
| 8 | + |
| 9 | +function! vsnip#source#snipmate#find(bufnr) abort |
| 10 | + let filetypes = vsnip#source#filetypes(a:bufnr) |
| 11 | + return s:find(filetypes, a:bufnr) |
| 12 | +endfunction |
| 13 | + |
| 14 | +function! s:find(filetypes, bufnr) abort |
| 15 | + let sources = [] |
| 16 | + for path in s:get_source_paths(a:filetypes, a:bufnr) |
| 17 | + if !has_key(s:cache, path) |
| 18 | + let s:cache[path] = s:create(path, a:bufnr) |
| 19 | + endif |
| 20 | + call add(sources, s:cache[path]) |
| 21 | + endfor |
| 22 | + return sources |
| 23 | +endfunction |
| 24 | + |
| 25 | +function! s:get_source_paths(filetypes, bufnr) abort |
| 26 | + let paths = [] |
| 27 | + for dir in s:get_source_dirs(a:bufnr) |
| 28 | + for filetype in a:filetypes |
| 29 | + let path = resolve(expand(printf('%s/%s.snippets', dir, filetype))) |
| 30 | + if has_key(s:cache, path) || filereadable(path) |
| 31 | + call add(paths, path) |
| 32 | + endif |
| 33 | + endfor |
| 34 | + endfor |
| 35 | + return paths |
| 36 | +endfunction |
| 37 | + |
| 38 | +function! s:get_source_dirs(bufnr) abort |
| 39 | + let dirs = [] |
| 40 | + let buf_dir = getbufvar(a:bufnr, 'vsnip_snippet_dir', '') |
| 41 | + if buf_dir !=# '' |
| 42 | + let dirs += [buf_dir] |
| 43 | + endif |
| 44 | + let dirs += getbufvar(a:bufnr, 'vsnip_snippet_dirs', []) |
| 45 | + let dirs += [g:vsnip_snippet_dir] |
| 46 | + let dirs += g:vsnip_snippet_dirs |
| 47 | + return dirs |
| 48 | +endfunction |
| 49 | + |
| 50 | +function! s:create(path, bufnr) abort |
| 51 | + let file = readfile(a:path) |
| 52 | + let file = type(file) == v:t_list ? file : [file] |
| 53 | + call map(file, { _, f -> iconv(f, 'utf-8', &encoding) }) |
| 54 | + let source = [] |
| 55 | + let i = -1 |
| 56 | + while i + 1 < len(file) |
| 57 | + let [i, line] = [i + 1, file[i + 1]] |
| 58 | + if line =~# '^\(#\|\s*$\)' |
| 59 | + " Comment, or blank line before snippets |
| 60 | + elseif line =~# '^extends\s\+\S' |
| 61 | + let filetypes = map(split(line[7:], ','), 'trim(v:val)') |
| 62 | + let source += flatten(s:find(filetypes, a:bufnr)) |
| 63 | + elseif line =~# '^snippet\s\+\S' && i + 1 < len(file) |
| 64 | + let matched = matchlist(line, '^snippet\s\+\(\S\+\)\s*\(.*\)') |
| 65 | + let [prefix, description] = [matched[1], matched[2]] |
| 66 | + let body = [] |
| 67 | + let indent = matchstr(file[i + 1], '^\s\+') |
| 68 | + while i + 1 < len(file) && file[i + 1] =~# '^\(' . indent . '\|\s*$\)' |
| 69 | + let [i, line] = [i + 1, file[i + 1]] |
| 70 | + call add(body, line[strlen(indent):]) |
| 71 | + endwhile |
| 72 | + let [prefixes, prefixes_alias] = vsnip#source#resolve_prefix(prefix) |
| 73 | + call add(source, { |
| 74 | + \ 'label': prefix, |
| 75 | + \ 'prefix': prefixes, |
| 76 | + \ 'prefix_alias': prefixes_alias, |
| 77 | + \ 'body': body, |
| 78 | + \ 'description': description |
| 79 | + \ }) |
| 80 | + else |
| 81 | + echohl ErrorMsg |
| 82 | + echomsg printf('[vsnip] Parsing error occurred on: %s#L%s', a:path, i + 1) |
| 83 | + echohl None |
| 84 | + break |
| 85 | + endif |
| 86 | + endwhile |
| 87 | + return sort(source, { a, b -> strlen(b.prefix[0]) - strlen(a.prefix[0]) }) |
| 88 | +endfunction |
0 commit comments