1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
let s:sigil = nr2char(31)
let snipmate#legacy#sigil = s:sigil
" Prepare snippet to be processed by s:BuildTabStops
function! snipmate#legacy#process_snippet(snip) abort
let snippet = a:snip
let esc_bslash = '\%(\\\@<!\%(\\\\\)*\)\@<='
if exists('b:snipmate_visual')
let visual = substitute(b:snipmate_visual, "\n$", '', '')
unlet b:snipmate_visual
else
let visual = ''
endif
let snippet = s:substitute_visual(snippet, visual)
" Evaluate eval (`...`) expressions.
" Backquotes prefixed with a backslash "\" are ignored.
" And backslash can be escaped by doubling it.
" Using a loop here instead of a regex fixes a bug with nested "\=".
if stridx(snippet, '`') != -1
let new = []
let snip = split(snippet, esc_bslash . '`', 1)
let isexp = 0
for i in snip
if isexp
call add(new, substitute(snipmate#util#eval(i),
\ "\n\\%$", '', ''))
else
call add(new, i)
endif
let isexp = !isexp
endfor
let snippet = join(new, '')
let snippet = substitute(snippet, "\r", "\n", 'g')
let snippet = substitute(snippet, '\\`', "`", 'g')
endif
" Place all text after a colon in a tab stop after the tab stop
" (e.g. "${#:foo}" becomes "${:foo}foo").
" This helps tell the position of the tab stops later.
let snippet = substitute(snippet, esc_bslash . '\$\({\d\+:\(.\{-}\)}\|{\d\+}\)', s:sigil . '\1\2', 'g')
let snippet = substitute(snippet, esc_bslash . '\$\(\d\+\)', s:sigil . '\1', 'g')
let snippet = substitute(snippet, esc_bslash . '\\\$', '$', 'g')
let snippet = substitute(snippet, '\\\\', "\\", 'g')
" Update the a:snip so that all the $# become the text after
" the colon in their associated ${#}.
" (e.g. "${1:foo}" turns all "$1"'s into "foo")
let i = 0
if snippet !~ s:sigil . '{0'
let snippet .= s:sigil . '{0}'
endif
while snippet =~ s:sigil.'{'.i
let s = matchstr(snippet, s:sigil . '{' . i . ':\zs.\{-}\ze}')
if s != ''
let snippet = substitute(snippet, s:sigil . i, s.'&', 'g')
endif
let i += 1
endw
if &et " Expand tabs to spaces if 'expandtab' is set.
return substitute(snippet, '\t', repeat(' ', snipmate#util#tabwidth()), 'g')
endif
return snippet
endfunction
" Builds a list of a list of each tab stop in the snippet containing:
" 1.) The tab stop's line number.
" 2.) The tab stop's column number
" (by getting the length of the string between the last "\n" and the
" tab stop).
" 3.) The length of the text after the colon for the current tab stop
" (e.g. "${1:foo}" would return 3).
" 4.) If the "${#:}" construct is given, another list containing all
" the matches of "$#", to be replaced with the placeholder. This list is
" composed the same way as the parent; the first item is the line number,
" and the second is the column.
function! snipmate#legacy#build_stops(snip, lnum, col, indent) abort
let stops = {}
let i = 0
let withoutVars = substitute(a:snip, s:sigil . '\d\+', '', 'g')
while a:snip =~ s:sigil . '{' . i
let beforeTabStop = matchstr(withoutVars, '^.*\ze'.s:sigil .'{'.i.'\D')
let withoutOthers = substitute(withoutVars, ''.s:sigil .'{\('.i.'\D\)\@!\d\+.\{-}}', '', 'g')
let stops[i] = {}
let stops[i].line = a:lnum + s:count(beforeTabStop, "\n")
let stops[i].col = a:indent + len(matchstr(withoutOthers, '[^\n]\{-}\ze'.s:sigil .'{'.i.'\D'))
let stops[i].placeholder = 0
let stops[i].mirrors = []
if stops[i].line == a:lnum
let stops[i].col += a:col
endif
" Get all $# matches in another list, if ${#:name} is given
if withoutVars =~ printf('%s{%d:', s:sigil, i)
let stops[i].placeholder = len(matchstr(withoutVars, ''.s:sigil .'{'.i.':\zs.\{-}\ze}'))
let withoutOthers = substitute(a:snip, ''.s:sigil .'{\d\+.\{-}}\|'.s:sigil .''.i.'\@!\d\+', '', 'g')
while match(withoutOthers, ''.s:sigil .''.i.'\(\D\|$\)') != -1
let stops[i].mirrors = get(stops[i], 'mirrors', [])
let beforeMark = matchstr(withoutOthers,
\ printf('^.\{-}\ze%s%s%d\(\D\|$\)',
\ repeat('.', stops[i].placeholder), s:sigil, i))
let line = a:lnum + s:count(beforeMark, "\n")
let col = a:indent + (line > a:lnum
\ ? len(matchstr(beforeMark, '.*\n\zs.*'))
\ : a:col + len(beforeMark))
call add(stops[i].mirrors, { 'line' : line, 'col' : col })
let withoutOthers = substitute(withoutOthers, ''.s:sigil .''.i.'\ze\(\D\|$\)', '', '')
endw
endif
let i += 1
endw
let stops[i] = stops[0]
return [stops, i + 1]
endfunction
function! s:substitute_visual(snippet, visual) abort
let lines = []
for line in split(a:snippet, "\n")
let indent = matchstr(line, '^\t\+')
call add(lines, substitute(line, '{VISUAL}',
\ substitute(escape(a:visual, '%\'), "\n", "\n" . indent, 'g'), 'g'))
endfor
return join(lines, "\n")
endfunction
" Counts occurences of haystack in needle
function! s:count(haystack, needle) abort
let counter = 0
let index = stridx(a:haystack, a:needle)
while index != -1
let index = stridx(a:haystack, a:needle, index+1)
let counter += 1
endw
return counter
endfunction
|