1
0
mirror of https://github.com/amix/vimrc synced 2025-07-13 14:55:01 +08:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Mirosław Pragłowski
2014-10-13 21:54:40 +02:00
266 changed files with 11284 additions and 3954 deletions

View File

@ -2,7 +2,6 @@
if !exists('g:snipMate')
let g:snipMate = {}
endif
let s:c = g:snipMate
try
call tlib#input#List('mi', '', [])
@ -11,27 +10,7 @@ catch /.*/
endtry
" match $ which doesn't follow a \
let s:d = '\%([\\]\@<!\$\)'
" if filetype is objc, cpp, cs or cu also append snippets from scope 'c'
" you can add multiple by separating scopes by ',', see s:AddScopeAliases
let s:c.scope_aliases = get(s:c, 'scope_aliases', {})
if !exists('g:snipMate_no_default_aliases') || !g:snipMate_no_default_aliases
let s:c.scope_aliases.objc = get(s:c.scope_aliases, 'objc', 'c')
let s:c.scope_aliases.cpp = get(s:c.scope_aliases, 'cpp', 'c')
let s:c.scope_aliases.cu = get(s:c.scope_aliases, 'cu', 'c')
let s:c.scope_aliases.xhtml = get(s:c.scope_aliases, 'xhtml', 'html')
let s:c.scope_aliases.html = get(s:c.scope_aliases, 'html', 'javascript')
let s:c.scope_aliases.php = get(s:c.scope_aliases, 'php', 'php,html,javascript')
let s:c.scope_aliases.ur = get(s:c.scope_aliases, 'ur', 'html,javascript')
let s:c.scope_aliases.mxml = get(s:c.scope_aliases, 'mxml', 'actionscript')
let s:c.scope_aliases.eruby = get(s:c.scope_aliases, 'eruby', 'eruby-rails,html')
endif
" set this to "\<tab>" to make snipmate not swallow tab (make sure to not have
" expandtab set). Remember that you can always enter tabs by <c-v> <tab> then
" you don't need this
let s:c['no_match_completion_feedkeys_chars'] = get(s:c, 'no_match_completion_feedkeys_chars', "\t")
let s:d = nr2char(31)
fun! Filename(...)
let filename = expand('%:t:r')
@ -85,11 +64,20 @@ fun! snipMate#expandSnip(snip, col)
if b:snip_state.stop_count
aug snipmate_changes
au CursorMoved,CursorMovedI <buffer> call b:snip_state.update_changes()
au CursorMoved,CursorMovedI <buffer> if exists('b:snip_state') |
\ call b:snip_state.update_changes() |
\ else |
\ silent! au! snipmate_changes * <buffer> |
\ endif
aug END
call b:snip_state.set_stop(0)
let ret = b:snip_state.select_word()
return b:snip_state.select_word()
if b:snip_state.stop_count == 1
call b:snip_state.remove()
endif
return ret
else
unlet b:snip_state
" Place cursor at end of snippet if no tab stop is given
@ -115,6 +103,7 @@ endfunction
" Prepare snippet to be processed by s:BuildTabStops
fun! s:ProcessSnippet(snip)
let snippet = a:snip
let esc_bslash = '\%(\\\@<!\%(\\\\\)*\)\@<='
if exists('b:snipmate_content_visual')
let visual = b:snipmate_content_visual
@ -130,7 +119,7 @@ fun! s:ProcessSnippet(snip)
" Using a loop here instead of a regex fixes a bug with nested "\=".
if stridx(snippet, '`') != -1
let new = []
let snip = split(snippet, '\%(\\\@<!\%(\\\\\)*\)\@<=`', 1)
let snip = split(snippet, esc_bslash . '`', 1)
let isexp = 0
for i in snip
if isexp
@ -143,13 +132,15 @@ fun! s:ProcessSnippet(snip)
let snippet = join(new, '')
let snippet = substitute(snippet, "\r", "\n", 'g')
let snippet = substitute(snippet, '\\`', "`", '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, s:d.'{\d\+:\(.\{-}\)}', '&\1', 'g')
let snippet = substitute(snippet, esc_bslash . '\$\({\d\+:\(.\{-}\)}\|{\d\+}\)', s:d . '\1\2', 'g')
let snippet = substitute(snippet, esc_bslash . '\$\(\d\+\)', s:d . '\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 ${#}.
@ -165,14 +156,14 @@ fun! s:ProcessSnippet(snip)
" Add ${0} tab stop if found
if snippet =~ s:d . '{0'
let snippet = substitute(snippet, s:d.'{0', '${'.i, '')
let snippet = substitute(snippet, s:d.'{0', s:d . '{' . i, '')
let s = matchstr(snippet, s:d.'{'.i.':\zs.\{-}\ze}')
if s != ''
let snippet = substitute(snippet, s:d.'0', '$'.i, 'g')
let snippet = substitute(snippet, s:d.'0', s:d . i, 'g')
let snippet = substitute(snippet, s:d.i, s.'&', 'g')
endif
else
let snippet .= '${'.i.'}'
let snippet .= s:d . '{'.i.'}'
endif
if &et " Expand tabs to spaces if 'expandtab' is set.
@ -206,7 +197,7 @@ endf
fun! s:BuildTabStops(snip, lnum, col, indent)
let snipPos = []
let i = 1
let withoutVars = substitute(a:snip, '$\d\+', '', 'g')
let withoutVars = substitute(a:snip, s:d . '\d\+', '', 'g')
while a:snip =~ s:d.'{'.i
let beforeTabStop = matchstr(withoutVars, '^.*\ze'.s:d .'{'.i.'\D')
let withoutOthers = substitute(withoutVars, ''.s:d .'{\('.i.'\D\)\@!\d\+.\{-}}', '', 'g')
@ -255,13 +246,12 @@ function! s:state_proto.jump_stop(backwards)
" Loop over the snippet when going backwards from the beginning
if self.stop_no < 0 | let self.stop_no = self.stop_count - 1 | endif
if self.stop_no == self.stop_count
call self.remove()
return ''
endif
call self.set_stop(self.stop_no)
return self.select_word()
let ret = self.select_word()
if self.stop_no == self.stop_count - 1
call self.remove()
endif
return ret
endfunction
" Updates tab stops/vars
@ -274,7 +264,7 @@ function! s:state_proto.update_stops()
for pos in self.stops
if pos == self.cur_stop | continue | endif
let changed = pos[0] == curLine && pos[1] > self.start_col
let changed = pos[0] == curLine && pos[1] > self.cur_stop[1]
let changedVars = 0
let endPlaceholder = pos[2] - 1 + pos[1]
" Subtract changeLen from each tab stop that was after any of
@ -333,10 +323,13 @@ function! s:state_proto.update_changes()
let self.end_col += change_len
let col = col('.')
if line('.') != self.cur_stop[0] || col < self.start_col || col > self.end_col
call self.remove()
elseif self.has_vars
call self.update_vars(change_len)
if mode() == 'i'
if line('.') != self.cur_stop[0]
\ || col < self.start_col || col > self.end_col
call self.remove()
elseif self.has_vars
call self.update_vars(change_len)
endif
endif
let self.prev_len = col('$')
@ -348,6 +341,7 @@ function! s:state_proto.update_vars(change)
let newWord = strpart(getline('.'), self.start_col - 1, newWordLen)
let changeLen = a:change
let curLine = line('.')
let curCol = col('.')
let oldStartSnip = self.start_col
let updateTabStops = changeLen != 0
let i = 0
@ -386,7 +380,7 @@ function! s:state_proto.update_vars(change)
" Reposition the cursor in case a var updates on the same line but before
" the current tabstop
if oldStartSnip != self.start_col || mode() == 'i'
call cursor(0, col('.') + self.start_col - oldStartSnip)
call cursor(0, curCol + self.start_col - oldStartSnip)
endif
endfunction
@ -394,12 +388,16 @@ endfunction
" returns list of
" ['triggername', 'name', 'contents']
" if triggername is not set 'default' is assumed
" TODO: better error checking
fun! snipMate#ReadSnippetsFile(file)
let result = []
let new_scopes = []
if !filereadable(a:file) | return [result, new_scopes] | endif
let inSnip = 0
let line_no = 0
for line in readfile(a:file) + ["\n"]
let line_no += 1
if inSnip && (line[0] == "\t" || line == '')
let content .= strpart(line, 1)."\n"
continue
@ -418,6 +416,10 @@ fun! snipMate#ReadSnippetsFile(file)
let trigger = strpart(trigger, 0, space - 1)
endif
let content = ''
if trigger =~ '^\s*$' " discard snippets with empty triggers
echom 'Invalid snippet in' a:file 'near line' line_no
let inSnip = 0
endif
elseif line[:6] == 'extends'
call extend(new_scopes, map(split(strpart(line, 8)),
\ "substitute(v:val, ',*$', '', '')"))
@ -426,12 +428,26 @@ fun! snipMate#ReadSnippetsFile(file)
return [result, new_scopes]
endf
function! s:GetScopes()
let ret = exists('b:snipMate.scope_aliases') ? copy(b:snipMate.scope_aliases) : {}
let global = get(g:snipMate, 'scope_aliases', {})
for alias in keys(global)
if has_key(ret, alias)
let ret[alias] = join(split(ret[alias], ',')
\ + split(global[alias], ','), ',')
else
let ret[alias] = global[alias]
endif
endfor
return ret
endfunction
" adds scope aliases to list.
" returns new list
" the aliases of aliases are added recursively
fun! s:AddScopeAliases(list)
let did = {}
let scope_aliases = get(s:c,'scope_aliases', {})
let scope_aliases = s:GetScopes()
let new = a:list
let new2 = []
while !empty(new)
@ -447,16 +463,22 @@ fun! s:AddScopeAliases(list)
return keys(did)
endf
function! s:Glob(path, expr)
let res = []
for p in split(a:path, ',')
let h = fnamemodify(a:expr, ':h')
if isdirectory(p . '/' . h)
call extend(res, split(glob(p . '/' . a:expr), "\n"))
endif
endfor
return filter(res, 'filereadable(v:val)')
endfunction
if v:version < 704 || has('win32')
function! s:Glob(path, expr)
let res = []
for p in split(a:path, ',')
let h = split(fnamemodify(a:expr, ':h'), '/')[0]
if isdirectory(p . '/' . h)
call extend(res, split(glob(p . '/' . a:expr), "\n"))
endif
endfor
return filter(res, 'filereadable(v:val)')
endfunction
else
function! s:Glob(path, expr)
return split(globpath(a:path, a:expr), "\n")
endfunction
endif
" returns dict of
" { path: { 'type': one of 'snippet' 'snippets',
@ -466,12 +488,11 @@ endfunction
" 'trigger': trigger of snippet
" }
" }
" use trigger = '*' to match all snippet files
" use mustExist = 1 to return existing files only
"
" mustExist = 0 is used by OpenSnippetFiles
function! snipMate#GetSnippetFiles(mustExist, scopes, trigger)
let paths = join(funcref#Call(s:c.snippet_dirs), ',')
let paths = join(funcref#Call(g:snipMate.snippet_dirs), ',')
let result = {}
let scopes = s:AddScopeAliases(a:scopes)
let trigger = escape(a:trigger, "*[]?{}`'$")
@ -480,19 +501,22 @@ function! snipMate#GetSnippetFiles(mustExist, scopes, trigger)
for scope in scopes
for f in s:Glob(paths, 'snippets/' . scope . '.snippets') +
\ s:Glob(paths, 'snippets/' . scope . '_*.snippets') +
\ s:Glob(paths, 'snippets/' . scope . '/*.snippets')
let result[f] = { 'exists' : 1, 'type' : 'snippets',
\ 'name_prefix' : fnamemodify(f, ':t:r') }
endfor
for f in s:Glob(paths, 'snippets/'.scope.'/'.trigger.'.snippet')
" We check for trigger* in the next two loops. In the case of an exact
" match, that'll be handled in snipMate#GetSnippetsForWordBelowCursor.
for f in s:Glob(paths, 'snippets/' . scope . '/' . trigger . '*.snippet')
let result[f] = {'exists': 1, 'type': 'snippet', 'name': 'default',
\ 'trigger': a:trigger, 'name_prefix' : scope }
\ 'trigger': fnamemodify(f, ':t:r'), 'name_prefix' : scope }
endfor
for f in s:Glob(paths, 'snippets/'.scope.'/'.trigger.'/*.snippet')
for f in s:Glob(paths, 'snippets/' . scope . '/' . trigger . '*/*.snippet')
let result[f] = {'exists': 1, 'type': 'snippet', 'name' : fnamemodify(f, ':t:r'),
\ 'trigger': a:trigger, 'name_prefix' : scope }
\ 'trigger': fnamemodify(f, ':h:t'), 'name_prefix' : scope }
endfor
if !a:mustExist
@ -507,21 +531,12 @@ function! snipMate#GetSnippetFiles(mustExist, scopes, trigger)
endfunction
" should be moved to utils or such?
function! snipMate#SetByPath(dict, path, value)
function! snipMate#SetByPath(dict, trigger, path, snippet) abort
let d = a:dict
for p in a:path[:-2]
if !has_key(d,p) | let d[p] = {} | endif
let d = d[p]
endfor
let d[a:path[-1]] = a:value
endfunction
function! s:ReadFile(file)
if a:file =~ '\.snippet$'
return [['', '', readfile(a:file), '1']]
else
return snipMate#ReadSnippetsFile(a:file)
if !has_key(d, a:trigger)
let d[a:trigger] = {}
endif
let d[a:trigger][a:path] = a:snippet
endfunction
function! s:CachedSnips(file)
@ -545,13 +560,13 @@ function! snipMate#DefaultPool(scopes, trigger, result)
call extend(extra_scopes, new_scopes)
for [trigger, name, contents] in snippets
if trigger =~ '\V\^' . escape(a:trigger, '\')
call snipMate#SetByPath(a:result,
\ [trigger, opts.name_prefix . ' ' . name],
\ contents)
call snipMate#SetByPath(a:result, trigger,
\ opts.name_prefix . ' ' . name, contents)
endif
endfor
elseif opts.type == 'snippet'
call snipMate#SetByPath(a:result, [opts.trigger, opts.name_prefix.' '.opts.name], readfile(f))
call snipMate#SetByPath(a:result, opts.trigger,
\ opts.name_prefix . ' ' . opts.name, readfile(f))
else
throw "unexpected"
endif
@ -636,7 +651,7 @@ endf
fun! snipMate#ScopesByFile()
" duplicates are removed in AddScopeAliases
return filter(funcref#Call(s:c.get_scopes), "v:val != ''")
return filter(funcref#Call(g:snipMate.get_scopes), "v:val != ''")
endf
" used by both: completion and insert snippet
@ -669,8 +684,8 @@ fun! snipMate#GetSnippetsForWordBelowCursor(word, exact)
let snippet = ''
" prefer longest word
for word in lookups
let s:c.word = word
for [k,snippetD] in items(funcref#Call(s:c['get_snippets'], [snipMate#ScopesByFile(), word]))
let g:snipMate.word = word
for [k,snippetD] in items(funcref#Call(g:snipMate['get_snippets'], [snipMate#ScopesByFile(), word]))
" hack: require exact match
if a:exact && k !=# word
continue
@ -730,7 +745,7 @@ fun! snipMate#ShowAvailableSnips()
" Pretty hacky, but really can't have the tab swallowed!
if len(matches) == 0
call feedkeys(s:c['no_match_completion_feedkeys_chars'], 'n')
call feedkeys(g:snipMate['no_match_completion_feedkeys_chars'], 'n')
return ""
endif