mirror of
https://github.com/amix/vimrc
synced 2025-06-16 09:35:01 +08:00
Updated plugins
This commit is contained in:
@ -14,6 +14,7 @@ additional contributions from:
|
||||
* [asymmetric](https://github.com/asymmetric)
|
||||
* [bpugh](https://github.com/bpugh)
|
||||
* [bruno-](https://github.com/bruno-)
|
||||
* [CharlesGueunet](https://github.com/CharlesGueunet)
|
||||
* [darkwise](https://github.com/darkwise)
|
||||
* [dreviejo](https://github.com/dreviejo)
|
||||
* [fish-face](https://github.com/fish-face)
|
||||
@ -40,6 +41,7 @@ additional contributions from:
|
||||
* [redpill](https://github.com/redpill)
|
||||
* [rglassett](http://github.com/rglassett)
|
||||
* [robhudson](https://github.com/robhudson)
|
||||
* [shinymayhem](https://github.com/shinymayhem)
|
||||
* [Shraymonks](https://github.com/shraymonks)
|
||||
* [sickill](https://github.com/sickill)
|
||||
* [statik](https://github.com/statik)
|
||||
|
@ -87,7 +87,7 @@ languages. For this we provide two options: scope aliases and the
|
||||
`:SnipMateLoadScope` command. Scope aliases simply say "whenever this scope is
|
||||
loaded, also load this other scope:
|
||||
|
||||
let g:snipMate = {}
|
||||
let g:snipMate = get(g:, 'snipMate', {}) " Allow for vimrc re-sourcing
|
||||
let g:snipMate.scope_aliases = {}
|
||||
let g:snipMate.scope_aliases['ruby'] = 'ruby,rails'
|
||||
|
||||
@ -98,6 +98,16 @@ does `:SnipMateLoadScope rails` when editing a Rails project for example.
|
||||
|
||||
## Release Notes ##
|
||||
|
||||
### 0.89 - 2016-05-29 ###
|
||||
|
||||
* Various regex updates to legacy parser
|
||||
* Addition of double bang syntax to completely remove a snippet from lookup
|
||||
* Group various SnipMate autocommands
|
||||
* Support setting 'shiftwidth' to 0
|
||||
* Parser now operates linewise, adding some flexibility
|
||||
* Mirror substitutions are more literal
|
||||
* Mirror length is calculated correctly when substitutions occur
|
||||
|
||||
### 0.88 - 2015-04-04 ###
|
||||
|
||||
* Implement simple caching
|
||||
|
@ -28,7 +28,8 @@ function! snipMate#expandSnip(snip, version, col) abort
|
||||
let [snippet, b:snip_state.stops] = snipmate#parse#snippet(a:snip)
|
||||
" Build stop/mirror info
|
||||
let b:snip_state.stop_count = s:build_stops(snippet, b:snip_state.stops, lnum, col, indent)
|
||||
let snipLines = snipMate#sniplist_str(snippet, b:snip_state.stops)
|
||||
let snipLines = map(copy(snippet),
|
||||
\ 'snipMate#sniplist_str(v:val, b:snip_state.stops)')
|
||||
else
|
||||
let snippet = snipmate#legacy#process_snippet(a:snip)
|
||||
let [b:snip_state.stops, b:snip_state.stop_count] = snipmate#legacy#build_stops(snippet, lnum, col - indent, indent)
|
||||
@ -77,11 +78,11 @@ function! snipMate#expandSnip(snip, version, col) abort
|
||||
endfunction
|
||||
|
||||
function! snipMate#placeholder_str(num, stops) abort
|
||||
return snipMate#sniplist_str(a:stops[a:num].placeholder, a:stops)[0]
|
||||
return snipMate#sniplist_str(a:stops[a:num].placeholder, a:stops)
|
||||
endfunction
|
||||
|
||||
function! snipMate#sniplist_str(snippet, stops) abort
|
||||
let lines = ['']
|
||||
let str = ''
|
||||
let pos = 0
|
||||
let add_to = 1
|
||||
let seen_stops = []
|
||||
@ -90,110 +91,82 @@ function! snipMate#sniplist_str(snippet, stops) abort
|
||||
let item = a:snippet[pos]
|
||||
|
||||
if type(item) == type('')
|
||||
if add_to
|
||||
let lines[-1] .= item
|
||||
else
|
||||
call add(lines, item)
|
||||
endif
|
||||
let add_to = 0
|
||||
let str .= item
|
||||
elseif type(item) == type([])
|
||||
let lines[-1] .= snipMate#placeholder_str(item[0], a:stops)
|
||||
let add_to = 1
|
||||
let str .= snipMate#placeholder_str(item[0], a:stops)
|
||||
endif
|
||||
|
||||
let pos += 1
|
||||
unlet item " avoid E706
|
||||
endwhile
|
||||
|
||||
return lines
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! s:build_stops(snippet, stops, lnum, col, indent) abort
|
||||
let stops = a:stops
|
||||
let line = a:lnum
|
||||
let lnum = a:lnum
|
||||
let col = a:col
|
||||
|
||||
for [id, dict] in items(stops)
|
||||
for i in dict.instances
|
||||
if len(i) > 1 && type(i[1]) != type({})
|
||||
if !has_key(dict, 'placeholder')
|
||||
let dict.placeholder = i[1:]
|
||||
else
|
||||
unlet i[1:]
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
if !has_key(dict, 'placeholder')
|
||||
let dict.placeholder = []
|
||||
let j = 0
|
||||
while len(dict.instances[j]) > 1
|
||||
let j += 1
|
||||
endwhile
|
||||
call add(dict.instances[j], '')
|
||||
for line in a:snippet
|
||||
let col = s:build_loc_info(line, stops, lnum, col, [])
|
||||
if line isnot line[-1]
|
||||
let lnum += 1
|
||||
let col = a:indent
|
||||
endif
|
||||
unlet dict.instances
|
||||
endfor
|
||||
|
||||
let [line, col] = s:build_loc_info(a:snippet, stops, line, col, a:indent)
|
||||
|
||||
" add zero tabstop if it doesn't exist and then link it to the highest stop
|
||||
" number
|
||||
let stops[0] = get(stops, 0,
|
||||
\ { 'placeholder' : [], 'line' : line, 'col' : col })
|
||||
\ { 'placeholder' : [], 'line' : lnum, 'col' : col })
|
||||
let stop_count = max(keys(stops)) + 2
|
||||
let stops[stop_count - 1] = stops[0]
|
||||
|
||||
return stop_count
|
||||
endfunction
|
||||
|
||||
function! s:build_loc_info(snippet, stops, line, col, indent) abort
|
||||
function! s:build_loc_info(snippet, stops, lnum, col, seen_items) abort
|
||||
let stops = a:stops
|
||||
let line = a:line
|
||||
let lnum = a:lnum
|
||||
let col = a:col
|
||||
let pos = 0
|
||||
let in_text = 0
|
||||
let seen_items = a:seen_items
|
||||
|
||||
while pos < len(a:snippet)
|
||||
let item = a:snippet[pos]
|
||||
|
||||
for item in a:snippet
|
||||
if type(item) == type('')
|
||||
if in_text
|
||||
let line += 1
|
||||
let col = a:indent
|
||||
endif
|
||||
let col += len(item)
|
||||
let in_text = 1
|
||||
elseif type(item) == type([])
|
||||
let id = item[0]
|
||||
if len(item) > 1 && type(item[1]) != type({})
|
||||
let stops[id].line = line
|
||||
let stops[id].col = col
|
||||
let [line, col] = s:build_loc_info(item[1:], stops, line, col, a:indent)
|
||||
let stub = item[-1]
|
||||
let stub.line = lnum
|
||||
let stub.col = col
|
||||
call s:add_update_objects(stub, seen_items)
|
||||
|
||||
if len(item) > 2 && type(item[1]) != type({})
|
||||
let col = s:build_loc_info(item[1:-2], stops, lnum, col, seen_items)
|
||||
else
|
||||
call s:add_mirror(stops, id, line, col, item)
|
||||
let col += len(snipMate#placeholder_str(id, stops))
|
||||
endif
|
||||
|
||||
let in_text = 0
|
||||
endif
|
||||
|
||||
let pos += 1
|
||||
unlet item " avoid E706
|
||||
endwhile
|
||||
endfor
|
||||
|
||||
return [line, col]
|
||||
return col
|
||||
endfunction
|
||||
|
||||
function! s:add_mirror(stops, id, line, col, item) abort
|
||||
let stops = a:stops
|
||||
let item = a:item
|
||||
let stops[a:id].mirrors = get(stops[a:id], 'mirrors', [])
|
||||
let mirror = get(a:item, 1, {})
|
||||
let mirror.line = a:line
|
||||
let mirror.col = a:col
|
||||
call add(stops[a:id].mirrors, mirror)
|
||||
if len(item) == 1
|
||||
call add(item, mirror)
|
||||
endif
|
||||
function! s:add_update_objects(object, targets) abort
|
||||
let targets = a:targets
|
||||
|
||||
for item in targets
|
||||
let item.update_objects = get(item, 'update_objects', [])
|
||||
call add(item.update_objects, a:object)
|
||||
endfor
|
||||
|
||||
call add(targets, a:object)
|
||||
endfunction
|
||||
|
||||
" reads a .snippets file
|
||||
|
@ -113,7 +113,7 @@ function! s:state_update_changes() dict abort
|
||||
return self.remove()
|
||||
endif
|
||||
|
||||
call self.update(self.cur_stop, change_len)
|
||||
call self.update(self.cur_stop, change_len, change_len)
|
||||
if !empty(self.mirrors)
|
||||
call self.update_mirrors(change_len)
|
||||
endif
|
||||
@ -141,14 +141,37 @@ function! s:state_update_mirrors(change) dict abort
|
||||
endif
|
||||
endfor
|
||||
|
||||
call self.update(mirror, changeLen)
|
||||
if has_key(mirror, 'oldSize')
|
||||
" recover the old size deduce the endline
|
||||
let oldSize = mirror.oldSize
|
||||
else
|
||||
" first time, we use the intitial size
|
||||
let oldSize = strlen(newWord)
|
||||
endif
|
||||
|
||||
" Split the line into three parts: the mirror, what's before it, and
|
||||
" what's after it. Then combine them using the new mirror string.
|
||||
" Subtract one to go from column index to byte index
|
||||
|
||||
let theline = getline(mirror.line)
|
||||
let update = strpart(theline, 0, mirror.col - 1)
|
||||
let update .= substitute(newWord, get(mirror, 'pat', ''), get(mirror, 'sub', ''), get(mirror, 'flags', ''))
|
||||
let update .= strpart(theline, mirror.col + self.end_col - self.start_col - a:change - 1)
|
||||
|
||||
" part before the current mirror
|
||||
let beginline = strpart(theline, 0, mirror.col - 1)
|
||||
|
||||
" current mirror transformation, and save size
|
||||
let wordMirror= substitute(newWord, get(mirror, 'pat', ''), get(mirror, 'sub', ''), get(mirror, 'flags', ''))
|
||||
let mirror.oldSize = strlen(wordMirror)
|
||||
|
||||
" end of the line, use the oldSize because with the transformation,
|
||||
" the size of the mirror can be different from those of the snippet
|
||||
let endline = strpart(theline, mirror.col + oldSize -1)
|
||||
|
||||
" Update other object on the line
|
||||
call self.update(mirror, changeLen, mirror.oldSize - oldSize)
|
||||
|
||||
" reconstruct the line
|
||||
let update = beginline.wordMirror.endline
|
||||
|
||||
call setline(mirror.line, update)
|
||||
endfor
|
||||
|
||||
@ -179,17 +202,17 @@ function! s:state_find_update_objects(item) dict abort
|
||||
return item.update_objects
|
||||
endfunction
|
||||
|
||||
function! s:state_update(item, change_len) dict abort
|
||||
function! s:state_update(item, change_len, mirror_change) dict abort
|
||||
let item = a:item
|
||||
if exists('item.update_objects')
|
||||
let to_update = item.update_objects
|
||||
else
|
||||
let to_update = self.find_update_objects(a:item)
|
||||
let item.update_objects = to_update
|
||||
if !exists('item.update_objects')
|
||||
let item.update_objects = self.find_update_objects(a:item)
|
||||
endif
|
||||
let to_update = item.update_objects
|
||||
|
||||
for obj in to_update
|
||||
let obj.col += a:change_len
|
||||
" object does not necessarly have the same decalage
|
||||
" than mirrors if mirrors use regexp
|
||||
let obj.col += a:mirror_change
|
||||
if obj is self.cur_stop
|
||||
let self.start_col += a:change_len
|
||||
let self.end_col += a:change_len
|
||||
|
@ -12,8 +12,7 @@ function! snipmate#legacy#process_snippet(snip) abort
|
||||
else
|
||||
let visual = ''
|
||||
endif
|
||||
let snippet = substitute(snippet, '\n\(\t\+\).\{-\}\zs{VISUAL}',
|
||||
\ substitute(escape(visual, '%\'), "\n", "\n\\\\1", 'g'), 'g')
|
||||
let snippet = s:substitute_visual(snippet, visual)
|
||||
|
||||
" Evaluate eval (`...`) expressions.
|
||||
" Backquotes prefixed with a backslash "\" are ignored.
|
||||
@ -118,6 +117,16 @@ function! snipmate#legacy#build_stops(snip, lnum, col, indent) abort
|
||||
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
|
||||
|
@ -5,6 +5,7 @@ function! s:sfile() abort
|
||||
endfunction
|
||||
|
||||
let s:parser_proto = {}
|
||||
let s:special_chars = "$`\n"
|
||||
|
||||
function! s:new_parser(text) abort
|
||||
let ret = copy(s:parser_proto)
|
||||
@ -14,6 +15,7 @@ function! s:new_parser(text) abort
|
||||
let ret.indent = 0
|
||||
let ret.value = []
|
||||
let ret.vars = {}
|
||||
let ret.stored_lines = []
|
||||
call ret.advance()
|
||||
return ret
|
||||
endfunction
|
||||
@ -82,35 +84,56 @@ function! s:parser_varend() dict abort
|
||||
endfunction
|
||||
|
||||
function! s:parser_placeholder() dict abort
|
||||
return self.parse('}')
|
||||
let ret = self.text('}')
|
||||
return empty(ret) ? [''] : ret
|
||||
endfunction
|
||||
|
||||
function! s:parser_subst() dict abort
|
||||
let ret = {}
|
||||
let ret.pat = join(self.text('/', 1))
|
||||
let ret.pat = self.pat()
|
||||
if self.same('/')
|
||||
let ret.sub = join(self.text('/}'))
|
||||
let ret.sub = self.pat(1)
|
||||
endif
|
||||
if self.same('/')
|
||||
let ret.flags = join(self.text('}', 1))
|
||||
let ret.flags = self.pat(1)
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:parser_pat(...) dict abort
|
||||
let val = ''
|
||||
|
||||
while self.pos < self.len
|
||||
if self.same('\')
|
||||
if self.next == '/'
|
||||
let val .= '/'
|
||||
call self.advance()
|
||||
elseif a:0 && self.next == '}'
|
||||
let val .= '}'
|
||||
call self.advance()
|
||||
else
|
||||
let val .= '\'
|
||||
endif
|
||||
elseif self.next == '/' || a:0 && self.next == '}'
|
||||
break
|
||||
else
|
||||
let val .= self.next
|
||||
call self.advance()
|
||||
endif
|
||||
endwhile
|
||||
|
||||
return val
|
||||
endfunction
|
||||
|
||||
function! s:parser_expr() dict abort
|
||||
let str = join(self.text('`', 1))
|
||||
let str = self.string('`')
|
||||
call self.same('`')
|
||||
return snipmate#util#eval(str)
|
||||
endfunction
|
||||
|
||||
function! s:parser_text(...) dict abort
|
||||
let res = []
|
||||
function! s:parser_string(till, ...) dict abort
|
||||
let val = ''
|
||||
if a:0 == 2 && a:2
|
||||
let till = '\V' . escape(a:1, '\')
|
||||
else
|
||||
let till = '[`$' . (a:0 ? a:1 : '') . ']'
|
||||
endif
|
||||
let till = '\V\[' . escape(a:till, '\') . ']'
|
||||
|
||||
while self.pos < self.len
|
||||
if self.same('\')
|
||||
@ -120,11 +143,6 @@ function! s:parser_text(...) dict abort
|
||||
call self.advance()
|
||||
elseif self.next =~# till
|
||||
break
|
||||
elseif self.next == "\n"
|
||||
call add(res, val)
|
||||
let val = ''
|
||||
let self.indent = 0
|
||||
call self.advance()
|
||||
elseif self.next == "\t"
|
||||
let self.indent += 1
|
||||
let val .= s:indent(1)
|
||||
@ -135,55 +153,77 @@ function! s:parser_text(...) dict abort
|
||||
endif
|
||||
endwhile
|
||||
|
||||
call add(res, val)
|
||||
return res
|
||||
return val
|
||||
endfunction
|
||||
|
||||
function! s:parser_parse(...) dict abort
|
||||
let ret = a:0 ? [] : self.value
|
||||
function! s:join_consecutive_strings(list) abort
|
||||
let list = a:list
|
||||
let pos = 0
|
||||
while pos + 1 < len(list)
|
||||
if type(list[pos]) == type('') && type(list[pos+1]) == type('')
|
||||
let list[pos] .= list[pos+1]
|
||||
call remove(list, pos + 1)
|
||||
else
|
||||
let pos += 1
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:parser_text(till) dict abort
|
||||
let ret = []
|
||||
|
||||
while self.pos < self.len
|
||||
let lines = []
|
||||
|
||||
if self.same('$')
|
||||
let var = self.var()
|
||||
if !empty(var)
|
||||
if var[0] is# 'VISUAL'
|
||||
let add_to = s:visual_placeholder(var, self.indent)
|
||||
if !empty(ret) && type(ret[-1]) == type('')
|
||||
let ret[-1] .= add_to[0]
|
||||
else
|
||||
call add(ret, add_to[0])
|
||||
endif
|
||||
call extend(ret, add_to[1:-1])
|
||||
let lines = s:visual_placeholder(var, self.indent)
|
||||
elseif var[0] >= 0
|
||||
call add(ret, var)
|
||||
call self.add_var(var)
|
||||
endif
|
||||
endif
|
||||
elseif self.same('`')
|
||||
let add_to = self.expr()
|
||||
if !empty(ret) && type(ret[-1]) == type('')
|
||||
let ret[-1] .= add_to
|
||||
else
|
||||
call add(ret, add_to)
|
||||
endif
|
||||
let lines = split(self.expr(), "\n", 1)
|
||||
else
|
||||
let text = a:0 ? self.text(a:1) : self.text()
|
||||
if exists('add_to')
|
||||
let ret[-1] .= text[0]
|
||||
call remove(text, 0)
|
||||
unlet add_to
|
||||
endif
|
||||
call extend(ret, text)
|
||||
let lines = [self.string(a:till . s:special_chars)]
|
||||
endif
|
||||
if a:0 && self.next == a:1
|
||||
|
||||
if !empty(lines)
|
||||
call add(ret, lines[0])
|
||||
call extend(self.stored_lines, lines[1:])
|
||||
endif
|
||||
|
||||
" Empty lines are ignored if this is tested at the start of an iteration
|
||||
if self.next ==# a:till
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
|
||||
call s:join_consecutive_strings(ret)
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
call extend(s:parser_proto, snipmate#util#add_methods(s:sfile(), 'parser',
|
||||
\ [ 'advance', 'same', 'id', 'add_var', 'var', 'varend',
|
||||
\ 'placeholder', 'subst', 'expr', 'text', 'parse' ]), 'error')
|
||||
function! s:parser_line() dict abort
|
||||
let ret = []
|
||||
if !empty(self.stored_lines)
|
||||
call add(ret, remove(self.stored_lines, 0))
|
||||
else
|
||||
call extend(ret, self.text("\n"))
|
||||
call self.same("\n")
|
||||
endif
|
||||
let self.indent = 0
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:parser_parse() dict abort
|
||||
while self.pos < self.len || !empty(self.stored_lines)
|
||||
let line = self.line()
|
||||
call add(self.value, line)
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:indent(count) abort
|
||||
if &expandtab
|
||||
@ -211,9 +251,59 @@ function! s:visual_placeholder(var, indent) abort
|
||||
return content
|
||||
endfunction
|
||||
|
||||
function! snipmate#parse#snippet(text) abort
|
||||
function! s:parser_create_stubs() dict abort
|
||||
|
||||
for [id, dict] in items(self.vars)
|
||||
for i in dict.instances
|
||||
if len(i) > 1 && type(i[1]) != type({})
|
||||
if !has_key(dict, 'placeholder')
|
||||
let dict.placeholder = i[1:]
|
||||
call add(i, dict)
|
||||
else
|
||||
unlet i[1:]
|
||||
call s:create_mirror_stub(i, dict)
|
||||
endif
|
||||
else
|
||||
call s:create_mirror_stub(i, dict)
|
||||
endif
|
||||
endfor
|
||||
if !has_key(dict, 'placeholder')
|
||||
let dict.placeholder = []
|
||||
let j = 0
|
||||
while len(dict.instances[j]) > 2
|
||||
let j += 1
|
||||
endwhile
|
||||
let oldstub = remove(dict.instances[j], 1, -1)[-1]
|
||||
call add(dict.instances[j], '')
|
||||
call add(dict.instances[j], dict)
|
||||
call filter(dict.mirrors, 'v:val isnot oldstub')
|
||||
endif
|
||||
unlet dict.instances
|
||||
endfor
|
||||
|
||||
endfunction
|
||||
|
||||
function! s:create_mirror_stub(mirror, dict)
|
||||
let mirror = a:mirror
|
||||
let dict = a:dict
|
||||
let stub = get(mirror, 1, {})
|
||||
call add(mirror, stub)
|
||||
let dict.mirrors = get(dict, 'mirrors', [])
|
||||
call add(dict.mirrors, stub)
|
||||
endfunction
|
||||
|
||||
function! snipmate#parse#snippet(text, ...) abort
|
||||
let parser = s:new_parser(a:text)
|
||||
call parser.parse()
|
||||
if !(a:0 && a:1)
|
||||
call parser.create_stubs()
|
||||
endif
|
||||
unlet! b:snipmate_visual
|
||||
return [parser.value, parser.vars]
|
||||
endfunction
|
||||
|
||||
call extend(s:parser_proto, snipmate#util#add_methods(s:sfile(), 'parser',
|
||||
\ [ 'advance', 'same', 'id', 'add_var', 'var', 'varend',
|
||||
\ 'line', 'string', 'create_stubs', 'pat',
|
||||
\ 'placeholder', 'subst', 'expr', 'text', 'parse',
|
||||
\ ]), 'error')
|
||||
|
@ -1,7 +1,6 @@
|
||||
*SnipMate.txt* Plugin for using TextMate-style snippets in Vim.
|
||||
|
||||
SnipMate *snippet* *snippets* *SnipMate*
|
||||
Last Change: December 27, 2009
|
||||
|
||||
1. Description |SnipMate-description|
|
||||
2. Usage |SnipMate-usage|
|
||||
@ -504,6 +503,15 @@ Perhaps some of these features will be added in a later release.
|
||||
==============================================================================
|
||||
CHANGELOG *SnipMate-changelog*
|
||||
|
||||
0.89 - 2016-05-29
|
||||
-----------------
|
||||
|
||||
* Various regex updates to legacy parser Addition of double bang syntax to
|
||||
* completely remove a snippet from lookup Group various SnipMate autocommands
|
||||
* Support setting 'shiftwidth' to 0 Parser now operates linewise, adding some
|
||||
* flexibility Mirror substitutions are more literal Mirror length is
|
||||
* calculated correctly when substitutions occur
|
||||
|
||||
0.88 - 2015-04-04
|
||||
-----------------
|
||||
|
||||
|
@ -2,27 +2,27 @@ describe 'snippet parser'
|
||||
|
||||
before
|
||||
function! Parse(snippet, ...)
|
||||
let [snip, stops] = snipmate#parse#snippet(a:snippet)
|
||||
return a:0 ? [snip, stops] : snip
|
||||
let [snip, stops] = snipmate#parse#snippet(a:snippet, (a:0 ? a:1 : 1))
|
||||
return (a:0 > 1 && a:2) ? [snip, stops] : snip
|
||||
endfunction
|
||||
let b:snipmate_visual = 'testvisual'
|
||||
end
|
||||
|
||||
it 'parses numeric $id and ${id} vars as [id] lists'
|
||||
let expect = [[1234567890]]
|
||||
let expect = [[[1234567890]]]
|
||||
Expect Parse('$1234567890') == expect
|
||||
Expect Parse('${1234567890}') == expect
|
||||
end
|
||||
|
||||
it 'disregards $ or ${ followed by a non-id'
|
||||
Expect Parse('$x1') == ['x1']
|
||||
Expect Parse('${x}1') == ['x}1']
|
||||
Expect Parse('$VISUA1') == ['VISUA1']
|
||||
Expect Parse('${VISUA}1') == ['VISUA}1']
|
||||
Expect Parse('$x1') == [['x1']]
|
||||
Expect Parse('${x}1') == [['x}1']]
|
||||
Expect Parse('$VISUA1') == [['VISUA1']]
|
||||
Expect Parse('${VISUA}1') == [['VISUA}1']]
|
||||
end
|
||||
|
||||
it 'gathers references to each instance of each stop id'
|
||||
let [snip, b:stops] = Parse('x$1x${2:x$1x}x$1x${1/a/b}x$VISUALx', 1)
|
||||
let [snip, b:stops] = Parse('x$1x${2:x$1x}x$1x${1/a/b}x$VISUALx', 1, 1)
|
||||
function! InstanceFound(list)
|
||||
return !empty(filter(copy(b:stops[a:list[0]].instances),
|
||||
\ 'v:val is a:list'))
|
||||
@ -36,87 +36,107 @@ describe 'snippet parser'
|
||||
unlet item " E732
|
||||
endfor
|
||||
endfunction
|
||||
call CheckList(snip)
|
||||
call CheckList(snip[0])
|
||||
end
|
||||
|
||||
it 'parses mirror substitutions ${n/pat/sub} as [n, {...}]'
|
||||
let expect = [[1, { 'pat' : 'abc', 'sub' : 'def' }]]
|
||||
let expect = [[[1, { 'pat' : 'abc', 'sub' : 'def' }]]]
|
||||
Expect Parse('${1/abc/def}') == expect
|
||||
let expect[0][1].flags = ''
|
||||
let expect[0][0][1].flags = ''
|
||||
Expect Parse('${1/abc/def/}') == expect
|
||||
let expect[0][1].flags = 'g'
|
||||
let expect[0][0][1].flags = 'g'
|
||||
Expect Parse('${1/abc/def/g}') == expect
|
||||
end
|
||||
|
||||
it 'reads patterns literally except for "\/"'
|
||||
Expect Parse('${1/\a\/b/\c\/d\}}') == [[[1, { 'pat' : '\a/b', 'sub' : '\c/d}' }]]]
|
||||
end
|
||||
|
||||
it 'parses vars with placeholders as [id, placeholder] lists'
|
||||
Expect Parse('${1:abc}') == [[1, 'abc']]
|
||||
Expect Parse('${1:abc}') == [[[1, 'abc']]]
|
||||
end
|
||||
|
||||
it 'evaluates backtick expressions'
|
||||
Expect Parse('`fnamemodify("x.y", ":r")`') == ['x']
|
||||
Expect Parse('`fnamemodify("x.y", ":r")`') == [['x']]
|
||||
end
|
||||
|
||||
it 'parses placeholders for vars and other specials'
|
||||
let text = 'a `fnamemodify("x.y", ":r")` ${2:(${3/a/b})}'
|
||||
let expect = ['a x ', [2, '(', [3, { 'pat' : 'a', 'sub' : 'b' }], ')']]
|
||||
Expect Parse(text) == expect
|
||||
Expect Parse(printf('${1:%s}', text)) == [[1] + expect]
|
||||
Expect Parse(text) == [expect]
|
||||
Expect Parse(printf('${1:%s}', text)) == [[[1] + expect]]
|
||||
end
|
||||
|
||||
it 'converts tabs according to &et, &sts, &sw, &ts'
|
||||
" &noet -> leave tabs alone
|
||||
setl noet
|
||||
Expect Parse("abc\tdef\n\t\tghi") == ["abc\tdef", "\t\tghi"]
|
||||
Expect Parse("abc\tdef\n\t\tghi") == [["abc\tdef"], ["\t\tghi"]]
|
||||
|
||||
" &et -> &sts or &sw
|
||||
setl et sts=2 sw=3
|
||||
Expect Parse("abc\tdef\n\t\tghi") == ["abc def", " ghi"]
|
||||
Expect Parse("abc\tdef\n\t\tghi") == [["abc def"], [" ghi"]]
|
||||
|
||||
setl et sts=0 sw=3
|
||||
Expect Parse("abc\tdef\n\t\tghi") == ["abc def", " ghi"]
|
||||
Expect Parse("abc\tdef\n\t\tghi") == [["abc def"], [" ghi"]]
|
||||
|
||||
setl et sts=-1 sw=3
|
||||
Expect Parse("abc\tdef\n\t\tghi") == ["abc def", " ghi"]
|
||||
Expect Parse("abc\tdef\n\t\tghi") == [["abc def"], [" ghi"]]
|
||||
|
||||
" See #227
|
||||
if exists('*shiftwidth')
|
||||
setl et sts=0 sw=0 ts=3
|
||||
Expect Parse("abc\tdef\n\t\tghi") == ["abc def", " ghi"]
|
||||
Expect Parse("abc\tdef\n\t\tghi") == [["abc def"], [" ghi"]]
|
||||
endif
|
||||
end
|
||||
|
||||
it 'parses backslashes as escaping the next character or joining lines'
|
||||
Expect Parse('x\x') == ['xx']
|
||||
Expect Parse('x\\x') == ['x\x']
|
||||
Expect Parse("x\\\nx") == ['xx']
|
||||
Expect Parse('x\$1') == ['x$1']
|
||||
Expect Parse('${1:\}}') == [[1, '}']]
|
||||
Expect Parse('${1/\//\}}') == [[1, { 'pat' : '/', 'sub' : '}' }]]
|
||||
Expect Parse('`fnamemodify("\`.x", ":r")`') == ['`']
|
||||
Expect Parse('\`x\`') == ['`x`']
|
||||
Expect Parse('x\x') == [['xx']]
|
||||
Expect Parse('x\\x') == [['x\x']]
|
||||
Expect Parse("x\\\nx") == [['xx']]
|
||||
Expect Parse('x\$1') == [['x$1']]
|
||||
Expect Parse('${1:\}}') == [[[1, '}']]]
|
||||
Expect Parse('`fnamemodify("\`.x", ":r")`') == [['`']]
|
||||
Expect Parse('\`x\`') == [['`x`']]
|
||||
end
|
||||
|
||||
it 'splits text at newlines'
|
||||
Expect Parse("x\nx") == ['x', 'x']
|
||||
Expect Parse("x\nx") == [['x'], ['x']]
|
||||
end
|
||||
|
||||
it 'joins evaluated expressions to surrounding text on the same line'
|
||||
let g:foo = 'bar'
|
||||
Expect Parse("x`g:foo`x") == ['xbarx']
|
||||
Expect Parse("x`g:foo`\nx") == ['xbar', 'x']
|
||||
Expect Parse("x\n`g:foo`x") == ['x', 'barx']
|
||||
end
|
||||
|
||||
it 'adds empty strings before/after vars if at the start/end of a line'
|
||||
Expect Parse("x$1\nx") == ['x', [1], '', 'x']
|
||||
Expect Parse("x\n$1x") == ['x', '', [1], 'x']
|
||||
Expect Parse("x`g:foo`x") == [['xbarx']]
|
||||
Expect Parse("x`g:foo`\nx") == [['xbar'], ['x']]
|
||||
Expect Parse("x\n`g:foo`x") == [['x'], ['barx']]
|
||||
end
|
||||
|
||||
it 'expands $VISUAL placeholders with any indents'
|
||||
Expect Parse("x$VISUALx") == ['xtestvisualx']
|
||||
Expect Parse("x$VISUALx") == [['xtestvisualx']]
|
||||
let b:snipmate_visual = " foo\nbar\n baz"
|
||||
setl noet
|
||||
Expect Parse("\tx\n\t$VISUAL\nx") == ["\tx", "\t foo", "\tbar", "\t baz", "x"]
|
||||
Expect Parse("\tx\n\t$VISUAL\nx") == [["\tx"], ["\t foo"], ["\tbar"],
|
||||
\ ["\t baz"], ["x"]]
|
||||
end
|
||||
|
||||
it 'determines which var with an id is the stop'
|
||||
let [snip, stops] = Parse("$1$1$1", 0, 1)
|
||||
Expect snip == [[[1, "", stops[1]], [1, {}], [1, {}]]]
|
||||
|
||||
let [snip, stops] = Parse("$1${1}$1", 0, 1)
|
||||
Expect snip == [[[1, "", stops[1]], [1, {}], [1, {}]]]
|
||||
|
||||
let [snip, stops] = Parse("$1${1:}$1", 0, 1)
|
||||
Expect snip == [[[1, {}], [1, "", stops[1]], [1, {}]]]
|
||||
|
||||
end
|
||||
|
||||
it 'picks the first of many possible stops'
|
||||
let [snip, stops] = Parse("$1${1:foo}${1:bar}", 0, 1)
|
||||
Expect snip == [[[1, {}], [1, "foo", stops[1]], [1, {}]]]
|
||||
end
|
||||
|
||||
it 'represents empty lines as an empty string'
|
||||
Expect Parse("foo\n\nbar") == [['foo'], [''], ['bar']]
|
||||
end
|
||||
|
||||
end
|
||||
|
Reference in New Issue
Block a user