aboutsummaryrefslogtreecommitdiff
path: root/vim/bundle/vim-snipmate/autoload/snipmate/parse.vim
diff options
context:
space:
mode:
Diffstat (limited to 'vim/bundle/vim-snipmate/autoload/snipmate/parse.vim')
-rw-r--r--vim/bundle/vim-snipmate/autoload/snipmate/parse.vim309
1 files changed, 309 insertions, 0 deletions
diff --git a/vim/bundle/vim-snipmate/autoload/snipmate/parse.vim b/vim/bundle/vim-snipmate/autoload/snipmate/parse.vim
new file mode 100644
index 0000000..dd495e9
--- /dev/null
+++ b/vim/bundle/vim-snipmate/autoload/snipmate/parse.vim
@@ -0,0 +1,309 @@
+" Snippet definition parsing code
+
+function! s:sfile() abort
+ return expand('<sfile>')
+endfunction
+
+let s:parser_proto = {}
+let s:special_chars = "$`\n"
+
+function! s:new_parser(text) abort
+ let ret = copy(s:parser_proto)
+ let ret.input = a:text
+ let ret.len = strlen(ret.input)
+ let ret.pos = -1
+ let ret.indent = 0
+ let ret.value = []
+ let ret.vars = {}
+ let ret.stored_lines = []
+ call ret.advance()
+ return ret
+endfunction
+
+function! s:parser_advance(...) dict abort
+ let self.pos += a:0 ? a:1 : 1
+ let self.next = self.input[self.pos]
+endfunction
+
+function! s:parser_same(tok) dict abort
+ if self.next == a:tok
+ call self.advance()
+ return 1
+ else
+ return 0
+ endif
+endfunction
+
+function! s:parser_id() dict abort
+ if self.input[(self.pos):(self.pos+5)] == 'VISUAL'
+ call self.advance(6)
+ return 'VISUAL'
+ elseif self.next =~ '\d'
+ let end = matchend(self.input, '\d\+', self.pos)
+ let res = strpart(self.input, self.pos, end - self.pos)
+ call self.advance(end - self.pos)
+ return +res " force conversion to Number
+ endif
+ return -1
+endfunction
+
+function! s:parser_add_var(var) dict abort
+ let id = a:var[0]
+ if !has_key(self.vars, id)
+ let self.vars[id] = { 'instances' : [] }
+ endif
+ call add(self.vars[id].instances, a:var)
+endfunction
+
+function! s:parser_var() dict abort
+ let ret = []
+ if self.same('{')
+ let id = self.id()
+ if id >= 0
+ call add(ret, id)
+ call extend(ret, self.varend())
+ endif
+ else
+ let id = self.id()
+ if id >= 0
+ call add(ret, id)
+ endif
+ endif
+ return ret
+endfunction
+
+function! s:parser_varend() dict abort
+ let ret = []
+ if self.same(':')
+ call extend(ret, self.placeholder())
+ elseif self.same('/')
+ call add(ret, self.subst())
+ endif
+ call self.same('}')
+ return ret
+endfunction
+
+function! s:parser_placeholder() dict abort
+ let ret = self.text('}')
+ return empty(ret) ? [''] : ret
+endfunction
+
+function! s:parser_subst() dict abort
+ let ret = {}
+ let ret.pat = self.pat()
+ if self.same('/')
+ let ret.sub = self.pat(1)
+ endif
+ if self.same('/')
+ 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 = self.string('`')
+ call self.same('`')
+ return snipmate#util#eval(str)
+endfunction
+
+function! s:parser_string(till, ...) dict abort
+ let val = ''
+ let till = '\V\[' . escape(a:till, '\') . ']'
+
+ while self.pos < self.len
+ if self.same('\')
+ if self.next != "\n"
+ let val .= self.next
+ endif
+ call self.advance()
+ elseif self.next =~# till
+ break
+ elseif self.next == "\t"
+ let self.indent += 1
+ let val .= s:indent(1)
+ call self.advance()
+ else
+ let val .= self.next
+ call self.advance()
+ endif
+ endwhile
+
+ return val
+endfunction
+
+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 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 lines = split(self.expr(), "\n", 1)
+ else
+ let lines = [self.string(a:till . s:special_chars)]
+ endif
+
+ 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
+
+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
+ let shift = repeat(' ', snipmate#util#tabwidth())
+ else
+ let shift = "\t"
+ endif
+ return repeat(shift, a:count)
+endfunction
+
+function! s:visual_placeholder(var, indent) abort
+ let arg = get(a:var, 1, {})
+ if type(arg) == type({})
+ let pat = get(arg, 'pat', '')
+ let sub = get(arg, 'sub', '')
+ let flags = get(arg, 'flags', '')
+ let content = split(substitute(get(b:, 'snipmate_visual', ''), pat, sub, flags), "\n", 1)
+ else
+ let content = split(get(b:, 'snipmate_visual', arg), "\n", 1)
+ endif
+
+ let indent = s:indent(a:indent)
+ call map(content, '(v:key != 0) ? indent . v:val : v:val')
+
+ return content
+endfunction
+
+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')