1
0
mirror of https://github.com/gryf/snipmate.vim.git synced 2025-12-29 01:42:36 +01:00

fixed some bugs, and added support for nested snippets (!)

This commit is contained in:
Michael Sanders
2009-02-26 18:22:05 -05:00
parent 8db937bb3b
commit 2e5caabf53
2 changed files with 39 additions and 31 deletions

View File

@@ -1,23 +1,24 @@
" These are the mappings for snipMate.vim. Putting it here ensures that it " These are the mappings for snipMate.vim. Putting it here ensures that it
" will be mapped after other plugins such as supertab.vim. " will be mapped after other plugins such as supertab.vim.
if exists('s:did_snips_mappings') || &cp || version < 700 if exists('s:did_snips_mappings') || &cp || version < 700
fini finish
en endif
let s:did_snips_mappings = 1 let s:did_snips_mappings = 1
ino <tab> <c-r>=TriggerSnippet()<cr> ino <silent> <tab> <c-r>=TriggerSnippet()<cr>
snor <tab> <esc>i<right><c-r>=TriggerSnippet()<cr> snor <silent> <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
snor <bs> b<bs> snor <bs> b<bs>
snor ' b<bs>' snor ' b<bs>'
snor <right> <esc>a snor <right> <esc>a
snor <left> <esc>bi snor <left> <esc>bi
" By default load snippets in ~/.vim/snippets/<filetype> " By default load snippets in ~/.vim/snippets/<filetype>
" NOTE: I need to make sure this works on Windows
if isdirectory($HOME.'/.vim/snippets') if isdirectory($HOME.'/.vim/snippets')
if isdirectory($HOME.'/.vim/snippets/_') if isdirectory($HOME.'/.vim/snippets/_')
call ExtractSnips($HOME.'/.vim/snippets/_', '_') call ExtractSnips($HOME.'/.vim/snippets/_', '_')
endif endif
au FileType * if !exists('s:did_'.&ft) && au FileType * if !exists('s:did_'.&ft) &&
\ isdirectory($HOME.'/.vim/snippets/'.&ft) \ isdirectory($HOME.'/.vim/snippets/'.&ft)
\| cal ExtractSnips($HOME.'/.vim/snippets/'.&ft, &ft) | en \| cal ExtractSnips($HOME.'/.vim/snippets/'.&ft, &ft) | en
endif endif

View File

@@ -41,7 +41,7 @@ fun s:MakeSnippet(text, ft, multisnip)
let name = strpart(a:text, space, quote-space) let name = strpart(a:text, space, quote-space)
let space = stridx(a:text, ' ', quote) let space = stridx(a:text, ' ', quote)
let var = 's:multi_snips' let var = 's:multi_snips'
else " evaluating a regular snippet else
let var = 's:snippets' let var = 's:snippets'
endif endif
if !has_key({var}, a:ft) | let {var}[a:ft] = {} | endif if !has_key({var}, a:ft) | let {var}[a:ft] = {} | endif
@@ -64,11 +64,12 @@ fun! ExtractSnips(dir, ft)
for path in split(globpath(a:dir, '*'), '\n') for path in split(globpath(a:dir, '*'), '\n')
if isdirectory(path) if isdirectory(path)
for snipFile in split(globpath(path, '*.snippet'), '\n') for snipFile in split(globpath(path, '*.snippet'), '\n')
call s:ProcessFile(snipFile, a:ft, strpart(path, strridx(path, s:slash)+1)) call s:ProcessFile(snipFile, a:ft,
\ strpart(path, strridx(path, s:slash)+1))
endfor endfor
continue else
call s:ProcessFile(path, a:ft)
endif endif
call s:ProcessFile(path, a:ft)
endfor endfor
unl s:slash unl s:slash
let s:did_{a:ft} = 1 let s:did_{a:ft} = 1
@@ -114,24 +115,22 @@ fun! TriggerSnippet()
call feedkeys("\<esc>a", 'n') | call s:UpdateChangedSnip(0) call feedkeys("\<esc>a", 'n') | call s:UpdateChangedSnip(0)
endif endif
if exists('s:snipPos')
return s:JumpTabStop()
endif
if !exists('s:sid') && exists('g:SuperTabMappingForward') if !exists('s:sid') && exists('g:SuperTabMappingForward')
\ && g:SuperTabMappingForward == "<tab>" \ && g:SuperTabMappingForward == "<tab>"
call s:GetSuperTabSID() call s:GetSuperTabSID()
endif endif
let word = s:GetSnippet()
let word = s:GetSnippet()
" if word is a trigger for a snippet, delete the trigger & expand the snippet " if word is a trigger for a snippet, delete the trigger & expand the snippet
if exists('s:snippet') if exists('s:snippet')
if s:snippet == '' if s:snippet == '' " if user cancelled a multi snippet, quit
return unl s:snippet " if user cancelled multi snippet, quit return unl s:snippet
endif endif
let col = col('.')-len(word) let col = col('.')-len(word)
sil exe 's/'.escape(word, '/\*[]').'\%#//' sil exe 's/'.escape(word, '/\*[]').'\%#//'
return s:ExpandSnippet(col) return s:ExpandSnippet(col)
elseif exists('s:snipPos')
return s:JumpTabStop()
endif endif
return exists('s:sid') ? {s:sid}_SuperTab('n') : "\<tab>" return exists('s:sid') ? {s:sid}_SuperTab('n') : "\<tab>"
endf endf
@@ -195,18 +194,22 @@ fun s:ExpandSnippet(col)
unl s:snippet unl s:snippet
if snipLen if snipLen
let s:curPos = 0 if exists('s:snipLen')
let s:snipLen = snipLen let s:snipLen += snipLen-1 | let s:curPos += 1
let s:endSnip = s:snipPos[0][1] else
let s:snipLen = snipLen | let s:curPos = 0
endif
let s:endSnip = s:snipPos[s:curPos][1]
let s:endSnipLine = s:snipPos[s:curPos][0] let s:endSnipLine = s:snipPos[s:curPos][0]
call cursor(s:snipPos[0][0], s:snipPos[0][1]) call cursor(s:snipPos[s:curPos][0], s:snipPos[s:curPos][1])
let s:prevLen = [line('$'), col('$')] let s:prevLen = [line('$'), col('$')]
if s:snipPos[0][2] != -1 | return s:SelectWord() | endif if s:snipPos[s:curPos][2] != -1 | return s:SelectWord() | endif
else else
if !exists('s:snipLen') | unl s:snipPos | endif
" place cursor at end of snippet if no tab stop is given " place cursor at end of snippet if no tab stop is given
unl s:snipPos | let newlines = len(snip)-1 let newlines = len(snip)-1
call cursor(lnum + newlines, tab + len(snip[-1]) - len(afterCursor) call cursor(lnum + newlines, indent + len(snip[-1]) - len(afterCursor)
\ + (newlines ? 0: col)) \ + (newlines ? 0: col))
endif endif
return '' return ''
@@ -274,29 +277,28 @@ endf
" second is the position (column) of the "$#" tab stop on the line. " second is the position (column) of the "$#" tab stop on the line.
" If there are none of these tab stop, an empty list ([]) is returnrned " If there are none of these tab stop, an empty list ([]) is returnrned
fun s:BuildTabStops(lnum, col, indent) fun s:BuildTabStops(lnum, col, indent)
let s:snipPos = [] let snipPos = [] | let i = 1
let i = 1
" temporarily delete placeholders " temporarily delete placeholders
let cut_snip = substitute(s:snippet, '$\d', '', 'g') let cut_snip = substitute(s:snippet, '$\d', '', 'g')
wh stridx(s:snippet, '${'.i) != -1 wh stridx(s:snippet, '${'.i) != -1
let s:snipPos += [[a:lnum+s:Count(matchstr(cut_snip, '^.*\ze${'.i), "\n"), let snipPos += [[a:lnum+s:Count(matchstr(cut_snip, '^.*\ze${'.i), "\n"),
\ a:indent+len(matchstr(substitute(cut_snip, '${'.i.'\@!\d.\{-}}', '', 'g'), \ a:indent+len(matchstr(substitute(cut_snip, '${'.i.'\@!\d.\{-}}', '', 'g'),
\ "^.*\\(\n\\|^\\)\\zs.*\\ze${".i.'.\{-}}')), -1]] \ "^.*\\(\n\\|^\\)\\zs.*\\ze${".i.'.\{-}}')), -1]]
if s:snipPos[i-1][0] == a:lnum if snipPos[i-1][0] == a:lnum
let s:snipPos[i-1][1] += a:col let snipPos[i-1][1] += a:col
endif endif
" get all $# matches in another list, if ${#:name} is given " get all $# matches in another list, if ${#:name} is given
if stridx(cut_snip, '${'.i.':') != -1 if stridx(cut_snip, '${'.i.':') != -1
let j = i-1 let j = i-1
let s:snipPos[j][2] = len(matchstr(cut_snip, '${'.i.':\zs.\{-}\ze}')) let snipPos[j][2] = len(matchstr(cut_snip, '${'.i.':\zs.\{-}\ze}'))
let s:snipPos[j] += [[]] let snipPos[j] += [[]]
" temporarily delete all other tab stops/placeholders " temporarily delete all other tab stops/placeholders
let tempstr = substitute(s:snippet, '$'.i.'\@!\d\|${\d.\{-}}', '', 'g') let tempstr = substitute(s:snippet, '$'.i.'\@!\d\|${\d.\{-}}', '', 'g')
wh stridx(tempstr, '$'.i) != -1 wh stridx(tempstr, '$'.i) != -1
let beforeMark = matchstr(tempstr, '^.\{-}\ze$'.i) let beforeMark = matchstr(tempstr, '^.\{-}\ze$'.i)
let linecount = a:lnum+s:Count(beforeMark, "\n") let linecount = a:lnum+s:Count(beforeMark, "\n")
let s:snipPos[j][3] += [[linecount, let snipPos[j][3] += [[linecount,
\ a:indent+(linecount > a:lnum ? \ a:indent+(linecount > a:lnum ?
\ len(matchstr(beforeMark, "^.*\n\\zs.*")) \ len(matchstr(beforeMark, "^.*\n\\zs.*"))
\ : a:col+len(beforeMark))]] \ : a:col+len(beforeMark))]]
@@ -305,6 +307,11 @@ fun s:BuildTabStops(lnum, col, indent)
endif endif
let i += 1 let i += 1
endw endw
if exists('s:snipPos') " allow nested snippets
let s:snipPos = extend(s:snipPos, snipPos, s:curPos+1)
else
let s:snipPos = snipPos
endif
return i-1 return i-1
endf endf