1
0
Fork 0
mirror of synced 2024-11-22 08:45:34 -05:00

Updated plugins

This commit is contained in:
amix 2015-02-04 10:43:54 +00:00
parent e7a01094b6
commit a4b4587019
71 changed files with 2076 additions and 1112 deletions

View file

@ -0,0 +1,383 @@
" Copyright (c) 2015 Junegunn Choi
"
" MIT License
"
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the
" "Software"), to deal in the Software without restriction, including
" without limitation the rights to use, copy, modify, merge, publish,
" distribute, sublicense, and/or sell copies of the Software, and to
" permit persons to whom the Software is furnished to do so, subject to
" the following conditions:
"
" The above copyright notice and this permission notice shall be
" included in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let s:cpo_save = &cpo
set cpo&vim
function! s:get_color(group, attr)
return synIDattr(synIDtrans(hlID(a:group)), a:attr)
endfunction
function! s:set_color(group, attr, color)
let gui = has('gui_running')
execute printf("hi %s %s%s=%s", a:group, gui ? 'gui' : 'cterm', a:attr, a:color)
endfunction
function! s:blank(repel)
if bufwinnr(t:goyo_pads.r) <= bufwinnr(t:goyo_pads.l) + 1
\ || bufwinnr(t:goyo_pads.b) <= bufwinnr(t:goyo_pads.t) + 3
call s:goyo_off()
endif
execute 'wincmd' a:repel
endfunction
function! s:init_pad(command)
execute a:command
setlocal buftype=nofile bufhidden=wipe nomodifiable nobuflisted noswapfile
\ nonu nocursorline nocursorcolumn winfixwidth winfixheight statusline=\
if exists('&rnu')
setlocal nornu
endif
if exists('&colorcolumn')
setlocal colorcolumn=
endif
let bufnr = winbufnr(0)
execute winnr('#') . 'wincmd w'
return bufnr
endfunction
function! s:setup_pad(bufnr, vert, size, repel)
let win = bufwinnr(a:bufnr)
execute win . 'wincmd w'
execute (a:vert ? 'vertical ' : '') . 'resize ' . max([0, a:size])
augroup goyop
execute 'autocmd WinEnter,CursorMoved <buffer> nested call s:blank("'.a:repel.'")'
autocmd WinLeave <buffer> call s:hide_statusline()
augroup END
" To hide scrollbars of pad windows in GVim
let diff = winheight(0) - line('$') - (has('gui_running') ? 2 : 0)
if diff > 0
setlocal modifiable
call append(0, map(range(1, diff), '""'))
normal! gg
setlocal nomodifiable
endif
execute winnr('#') . 'wincmd w'
endfunction
function! s:hmargin()
let nwidth = max([len(string(line('$'))) + 1, &numberwidth])
let width = t:goyo_width + (&number ? nwidth : 0)
return (&columns - width)
endfunction
function! s:resize_pads()
let t:goyo_width = max([2, t:goyo_width])
let t:goyo_margin_top = min([max([2, t:goyo_margin_top]), &lines / 2 - 1])
let t:goyo_margin_bottom = min([max([2, t:goyo_margin_bottom]), &lines / 2 - 1])
let hmargin = s:hmargin()
augroup goyop
autocmd!
augroup END
call s:setup_pad(t:goyo_pads.t, 0, t:goyo_margin_top - 1, 'j')
call s:setup_pad(t:goyo_pads.b, 0, t:goyo_margin_bottom - 2, 'k')
call s:setup_pad(t:goyo_pads.l, 1, hmargin / 2 - 1, 'l')
call s:setup_pad(t:goyo_pads.r, 1, hmargin / 2 - 1, 'h')
let t:goyo_width = winwidth(0)
endfunction
function! s:tranquilize()
let bg = s:get_color('Normal', 'bg')
for grp in ['NonText', 'FoldColumn', 'ColorColumn', 'VertSplit',
\ 'StatusLine', 'StatusLineNC', 'SignColumn']
" -1 on Vim / '' on GVim
if bg == -1 || empty(bg)
call s:set_color(grp, 'fg', get(g:, 'goyo_bg', 'black'))
call s:set_color(grp, 'bg', 'NONE')
else
call s:set_color(grp, 'fg', bg)
call s:set_color(grp, 'bg', bg)
endif
call s:set_color(grp, '', 'NONE')
endfor
endfunction
function! s:hide_statusline()
let &l:statusline = repeat(' ', winwidth(0))
endfunction
function! s:hide_linenr()
if !get(g:, 'goyo_linenr', 0)
setlocal nonu
if exists('&rnu')
setlocal nornu
endif
endif
if exists('&colorcolumn')
setlocal colorcolumn=
endif
endfunction
function! s:maps_nop()
let mapped = filter(['R', 'H', 'J', 'K', 'L', '|', '_'],
\ "empty(maparg(\"\<c-w>\".v:val, 'n'))")
for c in mapped
execute 'nnoremap <c-w>'.escape(c, '|').' <nop>'
endfor
return mapped
endfunction
function! s:maps_resize()
let commands = {
\ '=': ':<c-u>let [t:goyo_width, t:goyo_margin_top, t:goyo_margin_bottom] = t:goyo_initial_dim <bar> call <sid>resize_pads()<cr>',
\ '>': ':<c-u>let t:goyo_width = winwidth(0) + 2 * v:count1 <bar> call <sid>resize_pads()<cr>',
\ '<': ':<c-u>let t:goyo_width = winwidth(0) - 2 * v:count1 <bar> call <sid>resize_pads()<cr>',
\ '+': ':<c-u>let t:goyo_margin_top -= v:count1 <bar> let t:goyo_margin_bottom -= v:count1 <bar> call <sid>resize_pads()<cr>',
\ '-': ':<c-u>let t:goyo_margin_top += v:count1 <bar> let t:goyo_margin_bottom += v:count1 <bar> call <sid>resize_pads()<cr>'
\ }
let mapped = filter(keys(commands), "empty(maparg(\"\<c-w>\".v:val, 'n'))")
for c in mapped
execute 'nnoremap <silent> <c-w>'.c.' '.commands[c]
endfor
return mapped
endfunction
function! s:goyo_on(width)
let s:orig_tab = tabpagenr()
" New tab
tab split
let t:goyo_master = winbufnr(0)
let t:goyo_width = a:width
let t:goyo_margin_top = get(g:, 'goyo_margin_top', 4)
let t:goyo_margin_bottom = get(g:, 'goyo_margin_bottom', 4)
let t:goyo_initial_dim = [t:goyo_width, t:goyo_margin_top, t:goyo_margin_bottom]
let t:goyo_pads = {}
let t:goyo_revert =
\ { 'laststatus': &laststatus,
\ 'showtabline': &showtabline,
\ 'fillchars': &fillchars,
\ 'winminwidth': &winminwidth,
\ 'winwidth': &winwidth,
\ 'winminheight': &winminheight,
\ 'winheight': &winheight,
\ 'ruler': &ruler,
\ 'sidescroll': &sidescroll,
\ 'sidescrolloff': &sidescrolloff
\ }
let t:goyo_maps = extend(s:maps_nop(), s:maps_resize())
if has('gui_running')
let t:goyo_revert.guioptions = &guioptions
endif
" vim-gitgutter
let t:goyo_disabled_gitgutter = get(g:, 'gitgutter_enabled', 0)
if t:goyo_disabled_gitgutter
silent! GitGutterDisable
endif
" vim-signify
let t:goyo_disabled_signify = exists('b:sy') && b:sy.active
if t:goyo_disabled_signify
SignifyToggle
endif
" vim-airline
let t:goyo_disabled_airline = exists("#airline")
if t:goyo_disabled_airline
AirlineToggle
endif
" vim-powerline
let t:goyo_disabled_powerline = exists("#PowerlineMain")
if t:goyo_disabled_powerline
augroup PowerlineMain
autocmd!
augroup END
augroup! PowerlineMain
endif
" lightline.vim
let t:goyo_disabled_lightline = exists('#LightLine')
if t:goyo_disabled_lightline
silent! call lightline#disable()
endif
call s:hide_linenr()
" Global options
let &winheight = max([&winminheight, 1])
set winminheight=1
set winheight=1
set winminwidth=1 winwidth=1
set laststatus=0
set showtabline=0
set noruler
set fillchars+=vert:\
set fillchars+=stl:.
set fillchars+=stlnc:\
set sidescroll=1
set sidescrolloff=0
" Hide left-hand scrollbars
if has('gui_running')
set guioptions-=l
set guioptions-=L
endif
let t:goyo_pads.l = s:init_pad('vertical topleft new')
let t:goyo_pads.r = s:init_pad('vertical botright new')
let t:goyo_pads.t = s:init_pad('topleft new')
let t:goyo_pads.b = s:init_pad('botright new')
call s:resize_pads()
call s:tranquilize()
augroup goyo
autocmd!
autocmd TabLeave * call s:goyo_off()
autocmd VimResized * call s:resize_pads()
autocmd ColorScheme * call s:tranquilize()
autocmd BufWinEnter * call s:hide_linenr() | call s:hide_statusline()
autocmd WinEnter,WinLeave * call s:hide_statusline()
augroup END
call s:hide_statusline()
if exists('g:goyo_callbacks[0]')
call g:goyo_callbacks[0]()
endif
silent! doautocmd User GoyoEnter
endfunction
function! s:goyo_off()
if !exists('#goyo')
return
endif
" Oops, not this tab
if !exists('t:goyo_revert')
return
endif
" Clear auto commands
augroup goyo
autocmd!
augroup END
augroup! goyo
augroup goyop
autocmd!
augroup END
augroup! goyop
for c in t:goyo_maps
execute 'nunmap <c-w>'.escape(c, '|')
endfor
let goyo_revert = t:goyo_revert
let goyo_disabled_gitgutter = t:goyo_disabled_gitgutter
let goyo_disabled_signify = t:goyo_disabled_signify
let goyo_disabled_airline = t:goyo_disabled_airline
let goyo_disabled_powerline = t:goyo_disabled_powerline
let goyo_disabled_lightline = t:goyo_disabled_lightline
let goyo_orig_buffer = t:goyo_master
let [line, col] = [line('.'), col('.')]
if tabpagenr() == 1
tabnew
normal! gt
bd
endif
tabclose
execute 'normal! '.s:orig_tab.'gt'
if winbufnr(0) == goyo_orig_buffer
" Doesn't work if window closed with `q`
execute printf('normal! %dG%d|', line, col)
endif
let wmw = remove(goyo_revert, 'winminwidth')
let ww = remove(goyo_revert, 'winwidth')
let &winwidth = ww
let &winminwidth = wmw
let wmh = remove(goyo_revert, 'winminheight')
let wh = remove(goyo_revert, 'winheight')
let &winheight = max([wmh, 1])
let &winminheight = wmh
let &winheight = wh
for [k, v] in items(goyo_revert)
execute printf("let &%s = %s", k, string(v))
endfor
execute 'colo '. get(g:, 'colors_name', 'default')
if goyo_disabled_gitgutter
silent! GitGutterEnable
endif
if goyo_disabled_signify
silent! if !b:sy.active
SignifyToggle
endif
endif
if goyo_disabled_airline && !exists("#airline")
AirlineToggle
silent! AirlineRefresh
endif
if goyo_disabled_powerline && !exists("#PowerlineMain")
doautocmd PowerlineStartup VimEnter
silent! PowerlineReloadColorscheme
endif
if goyo_disabled_lightline
silent! call lightline#enable()
endif
if exists('#Powerline')
doautocmd Powerline ColorScheme
endif
if exists('g:goyo_callbacks[1]')
call g:goyo_callbacks[1]()
endif
silent! doautocmd User GoyoLeave
endfunction
function! goyo#execute(bang, ...)
let width = a:0 > 0 ? a:1 : get(g:, 'goyo_width', 80)
if a:bang
if exists('#goyo')
call s:goyo_off()
endif
else
if exists('#goyo') == 0
call s:goyo_on(width)
elseif a:0 > 0
let t:goyo_width = width
call s:resize_pads()
else
call s:goyo_off()
end
end
endfunction
let &cpo = s:cpo_save
unlet s:cpo_save

View file

@ -1,4 +1,4 @@
" Copyright (c) 2014 Junegunn Choi " Copyright (c) 2015 Junegunn Choi
" "
" MIT License " MIT License
" "
@ -21,363 +21,4 @@
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let s:cpo_save = &cpo command! -nargs=? -bar -bang Goyo call goyo#execute(<bang>0, <args>)
set cpo&vim
function! s:get_color(group, attr)
return synIDattr(synIDtrans(hlID(a:group)), a:attr)
endfunction
function! s:set_color(group, attr, color)
let gui = has('gui_running')
execute printf("hi %s %s%s=%s", a:group, gui ? 'gui' : 'cterm', a:attr, a:color)
endfunction
function! s:blank(repel)
if bufwinnr(t:goyo_pads.r) <= bufwinnr(t:goyo_pads.l) + 1
\ || bufwinnr(t:goyo_pads.b) <= bufwinnr(t:goyo_pads.t) + 3
call s:goyo_off()
endif
execute 'wincmd' a:repel
endfunction
function! s:init_pad(command)
execute a:command
setlocal buftype=nofile bufhidden=wipe nomodifiable nobuflisted noswapfile
\ nonu nocursorline nocursorcolumn winfixwidth winfixheight statusline=\
if exists('&rnu')
setlocal nornu
endif
if exists('&colorcolumn')
setlocal colorcolumn=
endif
let bufnr = winbufnr(0)
execute winnr('#') . 'wincmd w'
return bufnr
endfunction
function! s:setup_pad(bufnr, vert, size, repel)
let win = bufwinnr(a:bufnr)
execute win . 'wincmd w'
execute (a:vert ? 'vertical ' : '') . 'resize ' . max([0, a:size])
augroup goyop
execute 'autocmd WinEnter,CursorMoved <buffer> nested call s:blank("'.a:repel.'")'
autocmd WinLeave <buffer> call s:hide_statusline()
augroup END
" To hide scrollbars of pad windows in GVim
let diff = winheight(0) - line('$') - (has('gui_running') ? 2 : 0)
if diff > 0
setlocal modifiable
call append(0, map(range(1, diff), '""'))
normal! gg
setlocal nomodifiable
endif
execute winnr('#') . 'wincmd w'
endfunction
function! s:hmargin()
let nwidth = max([len(string(line('$'))) + 1, &numberwidth])
let width = t:goyo_width + (&number ? nwidth : 0)
return (&columns - width)
endfunction
function! s:resize_pads()
let t:goyo_width = max([2, t:goyo_width])
let t:goyo_margin_top = min([max([2, t:goyo_margin_top]), &lines / 2 - 1])
let t:goyo_margin_bottom = min([max([2, t:goyo_margin_bottom]), &lines / 2 - 1])
let hmargin = s:hmargin()
augroup goyop
autocmd!
augroup END
call s:setup_pad(t:goyo_pads.t, 0, t:goyo_margin_top - 1, 'j')
call s:setup_pad(t:goyo_pads.b, 0, t:goyo_margin_bottom - 2, 'k')
call s:setup_pad(t:goyo_pads.l, 1, hmargin / 2 - 1, 'l')
call s:setup_pad(t:goyo_pads.r, 1, hmargin / 2 - 1, 'h')
let t:goyo_width = winwidth(0)
endfunction
function! s:tranquilize()
let bg = s:get_color('Normal', 'bg')
for grp in ['NonText', 'FoldColumn', 'ColorColumn', 'VertSplit',
\ 'StatusLine', 'StatusLineNC', 'SignColumn']
" -1 on Vim / '' on GVim
if bg == -1 || empty(bg)
call s:set_color(grp, 'fg', get(g:, 'goyo_bg', 'black'))
call s:set_color(grp, 'bg', 'NONE')
else
call s:set_color(grp, 'fg', bg)
call s:set_color(grp, 'bg', bg)
endif
call s:set_color(grp, '', 'NONE')
endfor
endfunction
function! s:hide_statusline()
let &l:statusline = repeat(' ', winwidth(0))
endfunction
function! s:hide_linenr()
if !get(g:, 'goyo_linenr', 0)
setlocal nonu
if exists('&rnu')
setlocal nornu
endif
endif
if exists('&colorcolumn')
setlocal colorcolumn=
endif
endfunction
function! s:maps_nop()
let mapped = filter(['R', 'H', 'J', 'K', 'L', '|', '_', '='],
\ "empty(maparg(\"\<c-w>\".v:val, 'n'))")
for c in mapped
execute 'nnoremap <c-w>'.escape(c, '|').' <nop>'
endfor
return mapped
endfunction
function! s:maps_resize()
let commands = {
\ '>': ':<c-u>let t:goyo_width = winwidth(0) + 2 * v:count1 <bar> call <sid>resize_pads()<cr>',
\ '<': ':<c-u>let t:goyo_width = winwidth(0) - 2 * v:count1 <bar> call <sid>resize_pads()<cr>',
\ '+': ':<c-u>let t:goyo_margin_top -= v:count1 <bar> let t:goyo_margin_bottom -= v:count1 <bar> call <sid>resize_pads()<cr>',
\ '-': ':<c-u>let t:goyo_margin_top += v:count1 <bar> let t:goyo_margin_bottom += v:count1 <bar> call <sid>resize_pads()<cr>'
\ }
let mapped = filter(keys(commands), "empty(maparg(\"\<c-w>\".v:val, 'n'))")
for c in mapped
execute 'nnoremap <silent> <c-w>'.c.' '.commands[c]
endfor
return mapped
endfunction
function! s:goyo_on(width)
let s:orig_tab = tabpagenr()
" New tab
tab split
let t:goyo_master = winbufnr(0)
let t:goyo_width = a:width
let t:goyo_margin_top = get(g:, 'goyo_margin_top', 4)
let t:goyo_margin_bottom = get(g:, 'goyo_margin_bottom', 4)
let t:goyo_pads = {}
let t:goyo_revert =
\ { 'laststatus': &laststatus,
\ 'showtabline': &showtabline,
\ 'fillchars': &fillchars,
\ 'winminwidth': &winminwidth,
\ 'winwidth': &winwidth,
\ 'winminheight': &winminheight,
\ 'winheight': &winheight,
\ 'ruler': &ruler,
\ 'sidescroll': &sidescroll,
\ 'sidescrolloff': &sidescrolloff
\ }
let t:goyo_maps = extend(s:maps_nop(), s:maps_resize())
if has('gui_running')
let t:goyo_revert.guioptions = &guioptions
endif
" vim-gitgutter
let t:goyo_disabled_gitgutter = get(g:, 'gitgutter_enabled', 0)
if t:goyo_disabled_gitgutter
silent! GitGutterDisable
endif
" vim-signify
let t:goyo_disabled_signify = exists('b:sy') && b:sy.active
if t:goyo_disabled_signify
SignifyToggle
endif
" vim-airline
let t:goyo_disabled_airline = exists("#airline")
if t:goyo_disabled_airline
AirlineToggle
endif
" vim-powerline
let t:goyo_disabled_powerline = exists("#PowerlineMain")
if t:goyo_disabled_powerline
augroup PowerlineMain
autocmd!
augroup END
augroup! PowerlineMain
endif
" lightline.vim
let t:goyo_disabled_lightline = exists('#LightLine')
if t:goyo_disabled_lightline
silent! call lightline#disable()
endif
call s:hide_linenr()
" Global options
let &winheight = max([&winminheight, 1])
set winminheight=1
set winheight=1
set winminwidth=1 winwidth=1
set laststatus=0
set showtabline=0
set noruler
set fillchars+=vert:\
set fillchars+=stl:.
set fillchars+=stlnc:\
set sidescroll=1
set sidescrolloff=0
" Hide left-hand scrollbars
if has('gui_running')
set guioptions-=l
set guioptions-=L
endif
let t:goyo_pads.l = s:init_pad('vertical topleft new')
let t:goyo_pads.r = s:init_pad('vertical botright new')
let t:goyo_pads.t = s:init_pad('topleft new')
let t:goyo_pads.b = s:init_pad('botright new')
call s:resize_pads()
call s:tranquilize()
augroup goyo
autocmd!
autocmd TabLeave * call s:goyo_off()
autocmd VimResized * call s:resize_pads()
autocmd ColorScheme * call s:tranquilize()
autocmd BufWinEnter * call s:hide_linenr() | call s:hide_statusline()
autocmd WinEnter,WinLeave * call s:hide_statusline()
augroup END
call s:hide_statusline()
if exists('g:goyo_callbacks[0]')
call g:goyo_callbacks[0]()
endif
silent! doautocmd User GoyoEnter
endfunction
function! s:goyo_off()
if !exists('#goyo')
return
endif
" Oops, not this tab
if !exists('t:goyo_revert')
return
endif
" Clear auto commands
augroup goyo
autocmd!
augroup END
augroup! goyo
augroup goyop
autocmd!
augroup END
augroup! goyop
for c in t:goyo_maps
execute 'nunmap <c-w>'.escape(c, '|')
endfor
let goyo_revert = t:goyo_revert
let goyo_disabled_gitgutter = t:goyo_disabled_gitgutter
let goyo_disabled_signify = t:goyo_disabled_signify
let goyo_disabled_airline = t:goyo_disabled_airline
let goyo_disabled_powerline = t:goyo_disabled_powerline
let goyo_disabled_lightline = t:goyo_disabled_lightline
let goyo_orig_buffer = t:goyo_master
let [line, col] = [line('.'), col('.')]
if tabpagenr() == 1
tabnew
normal! gt
bd
endif
tabclose
execute 'normal! '.s:orig_tab.'gt'
if winbufnr(0) == goyo_orig_buffer
" Doesn't work if window closed with `q`
execute printf('normal! %dG%d|', line, col)
endif
let wmw = remove(goyo_revert, 'winminwidth')
let ww = remove(goyo_revert, 'winwidth')
let &winwidth = ww
let &winminwidth = wmw
let wmh = remove(goyo_revert, 'winminheight')
let wh = remove(goyo_revert, 'winheight')
let &winheight = max([wmh, 1])
let &winminheight = wmh
let &winheight = wh
for [k, v] in items(goyo_revert)
execute printf("let &%s = %s", k, string(v))
endfor
execute 'colo '. get(g:, 'colors_name', 'default')
if goyo_disabled_gitgutter
silent! GitGutterEnable
endif
if goyo_disabled_signify
silent! if !b:sy.active
SignifyToggle
endif
endif
if goyo_disabled_airline && !exists("#airline")
AirlineToggle
silent! AirlineRefresh
endif
if goyo_disabled_powerline && !exists("#PowerlineMain")
doautocmd PowerlineStartup VimEnter
silent! PowerlineReloadColorscheme
endif
if goyo_disabled_lightline
silent! call lightline#enable()
endif
if exists('#Powerline')
doautocmd Powerline ColorScheme
endif
if exists('g:goyo_callbacks[1]')
call g:goyo_callbacks[1]()
endif
silent! doautocmd User GoyoLeave
endfunction
function! s:goyo(bang, ...)
let width = a:0 > 0 ? a:1 : get(g:, 'goyo_width', 80)
if a:bang
if exists('#goyo')
call s:goyo_off()
endif
else
if exists('#goyo') == 0
call s:goyo_on(width)
elseif a:0 > 0
let t:goyo_width = width
call s:resize_pads()
else
call s:goyo_off()
end
end
endfunction
command! -nargs=? -bar -bang Goyo call s:goyo('<bang>' == '!', <args>)
let &cpo = s:cpo_save
unlet s:cpo_save

View file

@ -12,7 +12,20 @@ function! GotoFile(w)
let pos = "" let pos = ""
let fname = curword let fname = curword
endif endif
" Open new window if requested
" check exists file.
if filereadable(fname)
let fullname = fname
else
" try find file with prefix by working directory
let fullname = getcwd() . '/' . fname
if ! filereadable(fullname)
" the last try, using current directory based on file opened.
let fullname = expand('%:h') . '/' . fname
endif
endif
" Open new window if requested
if a:w == "new" if a:w == "new"
new new
endif endif

View file

@ -59,10 +59,10 @@ Haxe, Handlebars, HSS, HTML, Java, JavaScript, JSON, JSX, LESS, Lex, Limbo,
LISP, LLVM intermediate language, Lua, Markdown, MATLAB, NASM, Objective-C, LISP, LLVM intermediate language, Lua, Markdown, MATLAB, NASM, Objective-C,
Objective-C++, OCaml, Perl, Perl POD, PHP, gettext Portable Object, OS X and Objective-C++, OCaml, Perl, Perl POD, PHP, gettext Portable Object, OS X and
iOS property lists, Puppet, Python, R, Racket, Relax NG, reStructuredText, RPM iOS property lists, Puppet, Python, R, Racket, Relax NG, reStructuredText, RPM
spec, Ruby, SASS/SCSS, Scala, Slim, Tcl, TeX, Texinfo, Twig, TypeScript, Vala, spec, Ruby, SASS/SCSS, Scala, Slim, Swift, Tcl, TeX, Texinfo, Twig, TypeScript,
Verilog, VHDL, VimL, xHtml, XML, XSLT, YACC, YAML, z80, Zope page templates, Vala, Verilog, VHDL, VimL, xHtml, XML, XSLT, YACC, YAML, z80, Zope page
and zsh. See the [wiki][3] for details about the corresponding supported templates, and zsh. See the [wiki][3] for details about the corresponding
checkers. supported checkers.
Below is a screenshot showing the methods that Syntastic uses to display syntax Below is a screenshot showing the methods that Syntastic uses to display syntax
errors. Note that, in practise, you will only have a subset of these methods errors. Note that, in practise, you will only have a subset of these methods

View file

@ -121,12 +121,6 @@ function! syntastic#util#parseVersion(version) " {{{2
return map(split(matchstr( a:version, '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.'), 'str2nr(v:val)') return map(split(matchstr( a:version, '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.'), 'str2nr(v:val)')
endfunction " }}}2 endfunction " }}}2
" Run 'command' in a shell and parse output as a version string.
" Returns an array of version components.
function! syntastic#util#getVersion(command) " {{{2
return syntastic#util#parseVersion(system(a:command))
endfunction " }}}2
" Verify that the 'installed' version is at least the 'required' version. " Verify that the 'installed' version is at least the 'required' version.
" "
" 'installed' and 'required' must be arrays. If they have different lengths, " 'installed' and 'required' must be arrays. If they have different lengths,

View file

@ -19,7 +19,7 @@ if has('reltime')
lockvar! g:_SYNTASTIC_START lockvar! g:_SYNTASTIC_START
endif endif
let g:_SYNTASTIC_VERSION = '3.5.0-148' let g:_SYNTASTIC_VERSION = '3.6.0-14'
lockvar g:_SYNTASTIC_VERSION lockvar g:_SYNTASTIC_VERSION
" Sanity checks {{{1 " Sanity checks {{{1

View file

@ -77,6 +77,27 @@ function! g:SyntasticChecker.getLocList() " {{{2
return g:SyntasticLoclist.New(self.getLocListRaw()) return g:SyntasticLoclist.New(self.getLocListRaw())
endfunction " }}}2 endfunction " }}}2
function! g:SyntasticChecker.getVersion(...) " {{{2
if !exists('self._version')
let command = a:0 ? a:1 : self.getExecEscaped() . ' --version'
let version_output = system(command)
call self.log('getVersion: ' . string(command) . ': ' .
\ string(split(version_output, "\n", 1)) .
\ (v:shell_error ? ' (exit code ' . v:shell_error . ')' : '') )
call self.setVersion(syntastic#util#parseVersion(version_output))
endif
return get(self, '_version', [])
endfunction " }}}2
function! g:SyntasticChecker.setVersion(version) " {{{2
if len(a:version)
let self._version = copy(a:version)
call self.log(self.getExec() . ' version =', a:version)
else
call syntastic#log#error("checker " . self._filetype . "/" . self._name . ": can't parse version string (abnormal termination?)")
endif
endfunction " }}}2
function! g:SyntasticChecker.log(msg, ...) " {{{2 function! g:SyntasticChecker.log(msg, ...) " {{{2
let leader = self._filetype . '/' . self._name . ': ' let leader = self._filetype . '/' . self._name . ': '
if a:0 > 0 if a:0 > 0

View file

@ -74,6 +74,7 @@ let s:_DEFAULT_CHECKERS = {
\ 'sh': ['sh', 'shellcheck'], \ 'sh': ['sh', 'shellcheck'],
\ 'slim': ['slimrb'], \ 'slim': ['slimrb'],
\ 'spec': ['rpmlint'], \ 'spec': ['rpmlint'],
\ 'swift': ['xcrun'],
\ 'tcl': ['nagelfar'], \ 'tcl': ['nagelfar'],
\ 'tex': ['lacheck', 'chktex'], \ 'tex': ['lacheck', 'chktex'],
\ 'texinfo': ['makeinfo'], \ 'texinfo': ['makeinfo'],

View file

@ -71,13 +71,13 @@ function! g:SyntasticSignsNotifier._setup() " {{{2
endif endif
" define the signs used to display syntax and style errors/warns " define the signs used to display syntax and style errors/warns
exe 'sign define SyntasticError text=' . g:syntastic_error_symbol . execute 'sign define SyntasticError text=' . g:syntastic_error_symbol .
\ ' texthl=SyntasticErrorSign linehl=SyntasticErrorLine' \ ' texthl=SyntasticErrorSign linehl=SyntasticErrorLine'
exe 'sign define SyntasticWarning text=' . g:syntastic_warning_symbol . execute 'sign define SyntasticWarning text=' . g:syntastic_warning_symbol .
\ ' texthl=SyntasticWarningSign linehl=SyntasticWarningLine' \ ' texthl=SyntasticWarningSign linehl=SyntasticWarningLine'
exe 'sign define SyntasticStyleError text=' . g:syntastic_style_error_symbol . execute 'sign define SyntasticStyleError text=' . g:syntastic_style_error_symbol .
\ ' texthl=SyntasticStyleErrorSign linehl=SyntasticStyleErrorLine' \ ' texthl=SyntasticStyleErrorSign linehl=SyntasticStyleErrorLine'
exe 'sign define SyntasticStyleWarning text=' . g:syntastic_style_warning_symbol . execute 'sign define SyntasticStyleWarning text=' . g:syntastic_style_warning_symbol .
\ ' texthl=SyntasticStyleWarningSign linehl=SyntasticStyleWarningLine' \ ' texthl=SyntasticStyleWarningSign linehl=SyntasticStyleWarningLine'
endif endif
endfunction " }}}2 endfunction " }}}2

View file

@ -25,10 +25,7 @@ function! SyntaxCheckers_coffee_coffee_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
let ver = self.getVersion(self.getExecEscaped() . ' --version 2>' . syntastic#util#DevNull())
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version 2>' . syntastic#util#DevNull())
call self.log(self.getExec() . ' version = ', ver)
return syntastic#util#versionIsAtLeast(ver, [1, 6, 2]) return syntastic#util#versionIsAtLeast(ver, [1, 6, 2])
endfunction endfunction

View file

@ -20,9 +20,7 @@ set cpo&vim
function! SyntaxCheckers_coffee_coffeelint_GetLocList() dict function! SyntaxCheckers_coffee_coffeelint_GetLocList() dict
if !exists('s:coffeelint_new') if !exists('s:coffeelint_new')
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version') let s:coffeelint_new = syntastic#util#versionIsAtLeast(self.getVersion(), [1, 4])
call self.log(self.getExec() . ' version =', ver)
let s:coffeelint_new = syntastic#util#versionIsAtLeast(ver, [1, 4])
endif endif
let makeprg = self.makeprgBuild({ 'args_after': (s:coffeelint_new ? '--reporter csv' : '--csv') }) let makeprg = self.makeprgBuild({ 'args_after': (s:coffeelint_new ? '--reporter csv' : '--csv') })

View file

@ -27,10 +27,14 @@ function! SyntaxCheckers_eruby_ruby_IsAvailable() dict
endfunction endfunction
function! SyntaxCheckers_eruby_ruby_GetLocList() dict function! SyntaxCheckers_eruby_ruby_GetLocList() dict
if !exists('s:ruby_new')
let s:ruby_new = syntastic#util#versionIsAtLeast(self.getVersion(), [1, 9])
endif
let fname = "'" . escape(expand('%', 1), "\\'") . "'" let fname = "'" . escape(expand('%', 1), "\\'") . "'"
" TODO: encodings became useful in ruby 1.9 :) " TODO: encodings became useful in ruby 1.9 :)
if syntastic#util#versionIsAtLeast(syntastic#util#getVersion(self.getExecEscaped(). ' --version'), [1, 9]) if s:ruby_new
let enc = &fileencoding != '' ? &fileencoding : &encoding let enc = &fileencoding != '' ? &fileencoding : &encoding
let encoding_spec = ', :encoding => "' . (enc ==? 'utf-8' ? 'UTF-8' : 'BINARY') . '"' let encoding_spec = ', :encoding => "' . (enc ==? 'utf-8' ? 'UTF-8' : 'BINARY') . '"'
else else

View file

@ -41,7 +41,7 @@ function! SyntaxCheckers_haskell_ghc_mod_IsAvailable() dict
" need either a Vim that can handle NULs in system() output, or a " need either a Vim that can handle NULs in system() output, or a
" ghc-mod that has the "--boundary" option. " ghc-mod that has the "--boundary" option.
let parsed_ver = syntastic#util#parseVersion(ver[0]) let parsed_ver = syntastic#util#parseVersion(ver[0])
call self.log(self.getExec() . ' version =', parsed_ver) call self.setVersion(parsed_ver)
let s:ghc_mod_new = syntastic#util#versionIsAtLeast(parsed_ver, [2, 1, 2]) let s:ghc_mod_new = syntastic#util#versionIsAtLeast(parsed_ver, [2, 1, 2])
else else
call syntastic#log#error("checker haskell/ghc_mod: can't parse version string (abnormal termination?)") call syntastic#log#error("checker haskell/ghc_mod: can't parse version string (abnormal termination?)")

View file

@ -22,11 +22,7 @@ function! SyntaxCheckers_html_jshint_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
return syntastic#util#versionIsAtLeast(self.getVersion(), [2, 4])
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version')
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [2, 4])
endfunction endfunction
function! SyntaxCheckers_html_jshint_GetLocList() dict function! SyntaxCheckers_html_jshint_GetLocList() dict

View file

@ -204,7 +204,7 @@ endfunction " }}}2
function! s:LoadConfigFile() " {{{2 function! s:LoadConfigFile() " {{{2
if filereadable(expand(g:syntastic_java_javac_config_file, 1)) if filereadable(expand(g:syntastic_java_javac_config_file, 1))
exe 'source ' . fnameescape(expand(g:syntastic_java_javac_config_file, 1)) execute 'source ' . fnameescape(expand(g:syntastic_java_javac_config_file, 1))
endif endif
endfunction " }}}2 endfunction " }}}2

View file

@ -25,11 +25,7 @@ function! SyntaxCheckers_javascript_eslint_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
return syntastic#util#versionIsAtLeast(self.getVersion(), [0, 1])
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version')
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [0, 1])
endfunction endfunction
function! SyntaxCheckers_javascript_eslint_GetLocList() dict function! SyntaxCheckers_javascript_eslint_GetLocList() dict

View file

@ -27,20 +27,16 @@ function! SyntaxCheckers_javascript_jshint_IsAvailable() dict
return 0 return 0
endif endif
let s:jshint_version = syntastic#util#getVersion(self.getExecEscaped() . ' --version') let ver = self.getVersion()
call self.log(self.getExec() . ' version =', s:jshint_version) let s:jshint_new = syntastic#util#versionIsAtLeast(ver, [1, 1])
return syntastic#util#versionIsAtLeast(s:jshint_version, [1]) return syntastic#util#versionIsAtLeast(ver, [1])
endfunction endfunction
function! SyntaxCheckers_javascript_jshint_GetLocList() dict function! SyntaxCheckers_javascript_jshint_GetLocList() dict
call syntastic#log#deprecationWarn('javascript_jshint_conf', 'javascript_jshint_args', call syntastic#log#deprecationWarn('javascript_jshint_conf', 'javascript_jshint_args',
\ "'--config ' . syntastic#util#shexpand(OLD_VAR)") \ "'--config ' . syntastic#util#shexpand(OLD_VAR)")
if !exists('s:jshint_new')
let s:jshint_new = syntastic#util#versionIsAtLeast(s:jshint_version, [1, 1])
endif
let makeprg = self.makeprgBuild({ 'args_after': (s:jshint_new ? '--verbose ' : '') }) let makeprg = self.makeprgBuild({ 'args_after': (s:jshint_new ? '--verbose ' : '') })
let errorformat = s:jshint_new ? let errorformat = s:jshint_new ?

View file

@ -24,7 +24,7 @@ function! SyntaxCheckers_javascript_jsxhint_IsAvailable() dict
endif endif
let ver = syntastic#util#parseVersion(jsxhint_version) let ver = syntastic#util#parseVersion(jsxhint_version)
call self.log(self.getExec() . ' version =', ver) call self.setVersion(ver)
return syntastic#util#versionIsAtLeast(ver, [0, 4, 1]) return syntastic#util#versionIsAtLeast(ver, [0, 4, 1])
endfunction endfunction

View file

@ -19,18 +19,12 @@ let s:save_cpo = &cpo
set cpo&vim set cpo&vim
function! SyntaxCheckers_puppet_puppet_GetLocList() dict function! SyntaxCheckers_puppet_puppet_GetLocList() dict
if !exists('s:puppet_version') if !exists('s:puppet_new')
let s:puppet_version = syntastic#util#getVersion(self.getExecEscaped() . ' --version 2>' . syntastic#util#DevNull()) let s:puppet_new = syntastic#util#versionIsAtLeast(self.getVersion(), [2, 7, 0])
call self.log(self.getExec() . ' version =', s:puppet_version)
endif endif
if syntastic#util#versionIsAtLeast(s:puppet_version, [2,7,0]) let makeprg = self.makeprgBuild({
let args = 'parser validate --color=false' \ 'args_before': (s:puppet_new ? 'parser validate --color=false' : '--color=false --parseonly') })
else
let args = '--color=false --parseonly'
endif
let makeprg = self.makeprgBuild({ 'args_before': args })
let errorformat = let errorformat =
\ '%-Gerr: Try ''puppet help parser validate'' for usage,' . \ '%-Gerr: Try ''puppet help parser validate'' for usage,' .

View file

@ -24,10 +24,7 @@ function! SyntaxCheckers_puppet_puppetlint_IsAvailable() dict
if !executable('puppet') || !executable(self.getExec()) if !executable('puppet') || !executable(self.getExec())
return 0 return 0
endif endif
let ver = self.getVersion(self.getExecEscaped() . ' --version 2>' . syntastic#util#DevNull())
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version 2>' . syntastic#util#DevNull())
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [0, 1, 10]) return syntastic#util#versionIsAtLeast(ver, [0, 1, 10])
endfunction endfunction

View file

@ -13,9 +13,7 @@ set cpo&vim
function! SyntaxCheckers_python_pep257_GetLocList() dict function! SyntaxCheckers_python_pep257_GetLocList() dict
if !exists('s:pep257_new') if !exists('s:pep257_new')
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version') let s:pep257_new = syntastic#util#versionIsAtLeast(self.getVersion(), [0, 3])
call self.log(self.getExec() . ' version =', ver)
let s:pep257_new = syntastic#util#versionIsAtLeast(ver, [0, 3])
endif endif
let makeprg = self.makeprgBuild({}) let makeprg = self.makeprgBuild({})

View file

@ -26,11 +26,7 @@ function! SyntaxCheckers_python_prospector_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
return syntastic#util#versionIsAtLeast(self.getVersion(), [0, 7])
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version')
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [0, 7])
endfunction endfunction
function! SyntaxCheckers_python_prospector_GetLocList() dict function! SyntaxCheckers_python_prospector_GetLocList() dict

View file

@ -35,8 +35,7 @@ function! SyntaxCheckers_python_pylint_IsAvailable() dict
let pylint_version = filter( split(system(self.getExecEscaped() . ' --version'), '\m, \=\|\n'), let pylint_version = filter( split(system(self.getExecEscaped() . ' --version'), '\m, \=\|\n'),
\ 'v:val =~# ''\m^\(python[-0-9]*-\|\.\)\=pylint[-0-9]*\>''' )[0] \ 'v:val =~# ''\m^\(python[-0-9]*-\|\.\)\=pylint[-0-9]*\>''' )[0]
let ver = syntastic#util#parseVersion(substitute(pylint_version, '\v^\S+\s+', '', '')) let ver = syntastic#util#parseVersion(substitute(pylint_version, '\v^\S+\s+', '', ''))
call self.setVersion(ver)
call self.log(self.getExec() . ' version =', ver)
let s:pylint_new = syntastic#util#versionIsAtLeast(ver, [1]) let s:pylint_new = syntastic#util#versionIsAtLeast(ver, [1])
catch /\m^Vim\%((\a\+)\)\=:E684/ catch /\m^Vim\%((\a\+)\)\=:E684/

View file

@ -28,11 +28,7 @@ function! SyntaxCheckers_python_python_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
return syntastic#util#versionIsAtLeast(self.getVersion(), [2, 6])
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version')
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [2, 6])
endfunction endfunction
function! SyntaxCheckers_python_python_GetLocList() dict function! SyntaxCheckers_python_python_GetLocList() dict

View file

@ -22,11 +22,7 @@ function! SyntaxCheckers_ruby_reek_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
return syntastic#util#versionIsAtLeast(self.getVersion(), [1, 3, 0])
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version')
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [1, 3, 0])
endfunction endfunction
function! SyntaxCheckers_ruby_reek_GetLocList() dict function! SyntaxCheckers_ruby_reek_GetLocList() dict

View file

@ -22,11 +22,7 @@ function! SyntaxCheckers_ruby_rubocop_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
return syntastic#util#versionIsAtLeast(self.getVersion(), [0, 12, 0])
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version')
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [0, 12, 0])
endfunction endfunction
function! SyntaxCheckers_ruby_rubocop_GetLocList() dict function! SyntaxCheckers_ruby_rubocop_GetLocList() dict

View file

@ -21,9 +21,7 @@ set cpo&vim
function! SyntaxCheckers_ruby_rubylint_GetLocList() dict function! SyntaxCheckers_ruby_rubylint_GetLocList() dict
if !exists('s:rubylint_new') if !exists('s:rubylint_new')
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version') let s:rubylint_new = syntastic#util#versionIsAtLeast(self.getVersion(), [2])
call self.log(self.getExec() . ' version =', ver)
let s:rubylint_new = syntastic#util#versionIsAtLeast(ver, [2])
endif endif
let makeprg = self.makeprgBuild({ 'args': (s:rubylint_new ? '' : 'analyze ') . '--presenter=syntastic' }) let makeprg = self.makeprgBuild({ 'args': (s:rubylint_new ? '' : 'analyze ') . '--presenter=syntastic' })

View file

@ -21,11 +21,7 @@ function! SyntaxCheckers_scss_scss_lint_IsAvailable() dict
if !executable(self.getExec()) if !executable(self.getExec())
return 0 return 0
endif endif
return syntastic#util#versionIsAtLeast(self.getVersion(), [0, 12])
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version')
call self.log(self.getExec() . ' version =', ver)
return syntastic#util#versionIsAtLeast(ver, [0, 12])
endfunction endfunction
function! SyntaxCheckers_scss_scss_lint_GetLocList() dict function! SyntaxCheckers_scss_scss_lint_GetLocList() dict

View file

@ -20,8 +20,7 @@ set cpo&vim
function! SyntaxCheckers_slim_slimrb_GetLocList() dict function! SyntaxCheckers_slim_slimrb_GetLocList() dict
if !exists('s:slimrb_new') if !exists('s:slimrb_new')
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version 2>'. syntastic#util#DevNull()) let ver = self.getVersion(self.getExecEscaped() . ' --version 2>'. syntastic#util#DevNull())
call self.log(self.getExec() . ' version =', ver)
let s:slimrb_new = syntastic#util#versionIsAtLeast(ver, [1, 3, 1]) let s:slimrb_new = syntastic#util#versionIsAtLeast(ver, [1, 3, 1])
endif endif

View file

@ -0,0 +1,48 @@
"============================================================================
"File: xcrun.vim
"Description: swift syntax checker - using xcrun
"Maintainer: Tom Fogg <tom@canobe.com>
"License: This program is free software. It comes without any warranty,
" to the extent permitted by applicable law. You can redistribute
" it and/or modify it under the terms of the Do What The Fuck You
" Want To Public License, Version 2, as published by Sam Hocevar.
" See http://sam.zoy.org/wtfpl/COPYING for more details.
"============================================================================
if exists("g:loaded_syntastic_swift_xcrun_checker")
finish
endif
let g:loaded_syntastic_xcrun_checker = 1
let s:save_cpo = &cpo
set cpo&vim
function! SyntaxCheckers_swift_xcrun_GetLocList() dict
let makeprg = self.makeprgBuild({ 'args_after': 'swift' })
let errorformat=
\ '%f:%l:%c:{%*[^}]}: %trror: %m,'.
\ '%f:%l:%c:{%*[^}]}: fatal %trror: %m,'.
\ '%f:%l:%c:{%*[^}]}: %tarning: %m,'.
\ '%f:%l:%c: %trror: %m,'.
\ '%f:%l:%c: fatal %trror: %m,'.
\ '%f:%l:%c: %tarning: %m,'.
\ '%f:%l: %trror: %m,'.
\ '%f:%l: fatal %trror: %m,'.
\ '%f:%l: %tarning: %m,' .
\ '%-G%.%#'
return SyntasticMake({
\ 'makeprg': makeprg,
\ 'errorformat': errorformat })
endfunction
call g:SyntasticRegistry.CreateAndRegisterChecker({
\ 'filetype': 'swift',
\ 'name': 'xcrun'})
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: set sw=4 sts=4 et fdm=marker:

View file

@ -20,9 +20,7 @@ set cpo&vim
function! SyntaxCheckers_yaml_jsyaml_GetLocList() dict function! SyntaxCheckers_yaml_jsyaml_GetLocList() dict
if !exists('s:js_yaml_new') if !exists('s:js_yaml_new')
let ver = syntastic#util#getVersion(self.getExecEscaped() . ' --version') let s:js_yaml_new = syntastic#util#versionIsAtLeast(self.getVersion(), [2])
call self.log(self.getExec() . ' version =', ver)
let s:js_yaml_new = syntastic#util#versionIsAtLeast(ver, [2])
endif endif
let makeprg = self.makeprgBuild({ 'args_after': (s:js_yaml_new ? '' : '--compact') }) let makeprg = self.makeprgBuild({ 'args_after': (s:js_yaml_new ? '' : '--compact') })

View file

@ -89,6 +89,9 @@ endfunction
function! airline#update_statusline() function! airline#update_statusline()
for nr in filter(range(1, winnr('$')), 'v:val != winnr()') for nr in filter(range(1, winnr('$')), 'v:val != winnr()')
if airline#util#getwinvar(nr, 'airline_disabled', 0)
continue
endif
call setwinvar(nr, 'airline_active', 0) call setwinvar(nr, 'airline_active', 0)
let context = { 'winnr': nr, 'active': 0, 'bufnr': winbufnr(nr) } let context = { 'winnr': nr, 'active': 0, 'bufnr': winbufnr(nr) }
call s:invoke_funcrefs(context, s:inactive_funcrefs) call s:invoke_funcrefs(context, s:inactive_funcrefs)

View file

@ -105,7 +105,7 @@ function! airline#init#sections()
let g:airline_section_y = airline#section#create_right(['ffenc']) let g:airline_section_y = airline#section#create_right(['ffenc'])
endif endif
if !exists('g:airline_section_z') if !exists('g:airline_section_z')
let g:airline_section_z = airline#section#create(['windowswap', '%3p%%'.spc, 'linenr', ':%3c ']) let g:airline_section_z = airline#section#create(['windowswap', '%3p%%'.spc, 'linenr', ':%3v '])
endif endif
if !exists('g:airline_section_warning') if !exists('g:airline_section_warning')
let g:airline_section_warning = airline#section#create(['syntastic', 'eclim', 'whitespace']) let g:airline_section_warning = airline#section#create(['syntastic', 'eclim', 'whitespace'])

View file

@ -126,6 +126,11 @@ values):
heavily) > heavily) >
let g:airline_exclude_preview = 0 let g:airline_exclude_preview = 0
< <
* disable the Airline customization for selective windows (this is a
window-local variable so you can disable it for only some windows) >
let w:airline_disabled = 1
<
============================================================================== ==============================================================================
COMMANDS *airline-commands* COMMANDS *airline-commands*

View file

@ -44,7 +44,7 @@ describe 'init sections'
it 'section z should be line numbers' it 'section z should be line numbers'
Expect g:airline_section_z =~ '%3p%%' Expect g:airline_section_z =~ '%3p%%'
Expect g:airline_section_z =~ '%4l' Expect g:airline_section_z =~ '%4l'
Expect g:airline_section_z =~ '%3c' Expect g:airline_section_z =~ '%3v'
end end
it 'should not redefine sections already defined' it 'should not redefine sections already defined'

View file

@ -1,6 +1,6 @@
" fugitive.vim - A Git wrapper so awesome, it should be illegal " fugitive.vim - A Git wrapper so awesome, it should be illegal
" Maintainer: Tim Pope <http://tpo.pe/> " Maintainer: Tim Pope <http://tpo.pe/>
" Version: 2.1 " Version: 2.2
" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim " GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim
if exists('g:loaded_fugitive') || &cp if exists('g:loaded_fugitive') || &cp
@ -1759,7 +1759,7 @@ function! s:Diff(vert,...) abort
let winnr = winnr() let winnr = winnr()
if getwinvar('#', '&diff') if getwinvar('#', '&diff')
wincmd p wincmd p
call feedkeys("\<C-W>p", 'n') call feedkeys(winnr."\<C-W>w", 'n')
endif endif
return '' return ''
catch /^fugitive:/ catch /^fugitive:/

View file

@ -189,6 +189,22 @@ let g:go_highlight_structs = 1
## Troubleshooting ## Troubleshooting
### Command not found
If trying to use `:GoDef`, `:GoInfo` and get a `command not found`, check that you have the binaries installed by using: `:GoInstallBinaries`
Before opening vim, check your current `$PATH`:
echo $PATH
after opening vim, run `:echo $PATH`, the output must be your current `$PATH` + `$PATH/bin` (the location where `:GoInstallBinaries` installed the binaries
If problem persists and you are using maybe 'csh' or other shell, try adding this to your .vimrc:
set shell=/bin/sh
### I'm using Fish shell but have some problems using Vim-go ### I'm using Fish shell but have some problems using Vim-go
First environment variables in Fish are applied differently, it should be like: First environment variables in Fish are applied differently, it should be like:
@ -202,13 +218,12 @@ too). To overcome this problem change the default shell by adding the following
into your .vimrc (on the top of the file): into your .vimrc (on the top of the file):
if $SHELL =~ 'fish' if $SHELL =~ 'fish'
set shell='/bin/bash' set shell='/bin/sh'
endif endif
or or
set shell='/bin/bash' set shell='/bin/sh'
## Why another plugin? ## Why another plugin?
@ -221,6 +236,12 @@ months under heavy go development environment.
Give it a try. I hope you like it. Feel free to contribute to the project. Give it a try. I hope you like it. Feel free to contribute to the project.
## Donations
Vim-go is an open source project and I'm working on it on my free times. I'm spending a lot of time and thoughts to make it stable, fixing bugs, adding new features, etc... If you like vim-go and find it helpful, you might give me a gift from some of the books (kindle) I have in my wish list:
[Amazon.com Fatih's Wish List](http://amzn.com/w/3RUTKZC0U30P6). Thanks!
## Credits ## Credits
* Go Authors for official vim plugins * Go Authors for official vim plugins

View file

@ -19,7 +19,12 @@ fu! s:gocodeCurrentBuffer()
return file return file
endf endf
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
if go#vimproc#has_vimproc()
let s:vim_system = get(g:, 'gocomplete#system_function', 'vimproc#system2')
else
let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
endif
fu! s:system(str, ...) fu! s:system(str, ...)
return call(s:vim_system, [a:str] + a:000) return call(s:vim_system, [a:str] + a:000)

View file

@ -5,6 +5,10 @@ endif
function! go#errcheck#Run(...) abort function! go#errcheck#Run(...) abort
if a:0 == 0 if a:0 == 0
let package = go#package#ImportPath(expand('%:p:h')) let package = go#package#ImportPath(expand('%:p:h'))
if package == -1
echohl Error | echomsg "vim-go: package is not inside GOPATH src" | echohl None
return
endif
else else
let package = a:1 let package = a:1
end end
@ -14,6 +18,7 @@ function! go#errcheck#Run(...) abort
return return
endif endif
echon "vim-go: " | echohl Identifier | echon "errcheck analysing ..." | echohl None
let out = system(bin_path . ' ' . package) let out = system(bin_path . ' ' . package)
if v:shell_error if v:shell_error
let errors = [] let errors = []
@ -28,15 +33,21 @@ function! go#errcheck#Run(...) abort
\"text": tokens[4]}) \"text": tokens[4]})
endif endif
endfor endfor
if empty(errors) if empty(errors)
% | " Couldn't detect error format, output errors echohl Error | echomsg "GoErrCheck returned error" | echohl None
echo out
endif endif
if !empty(errors) if !empty(errors)
redraw | echo
call setqflist(errors, 'r') call setqflist(errors, 'r')
endif endif
echohl Error | echomsg "GoErrCheck returned error" | echohl None
else else
call setqflist([]) call setqflist([])
endif endif
cwindow cwindow
endfunction endfunction
" vim:ts=4:sw=4:et

View file

@ -74,8 +74,15 @@ function! go#fmt#Format(withGoimport)
" get the command first so we can test it " get the command first so we can test it
let fmt_command = g:go_fmt_command let fmt_command = g:go_fmt_command
if a:withGoimport == 1 if a:withGoimport == 1
let fmt_command = g:go_goimports_bin
endif
" if it's something else than gofmt, we need to check the existing of that
" binary. For example if it's goimports, let us check if it's installed,
" if not the user get's a warning via go#tool#BinPath()
if fmt_command != "gofmt"
" check if the user has installed goimports " check if the user has installed goimports
let bin_path = go#tool#BinPath(g:go_goimports_bin) let bin_path = go#tool#BinPath(fmt_command)
if empty(bin_path) if empty(bin_path)
return return
endif endif

View file

@ -32,7 +32,8 @@ function! go#tool#Imports()
endif endif
for package_path in split(out, '\n') for package_path in split(out, '\n')
let package_name = fnamemodify(package_path, ":t:r") let cmd = "go list -f {{.Name}} " . package_path
let package_name = substitute(go#tool#ExecuteInDir(cmd), '\n$', '', '')
let imports[package_name] = package_path let imports[package_name] = package_path
endfor endfor

View file

@ -0,0 +1,21 @@
"Check if has vimproc
function! go#vimproc#has_vimproc()
if !exists('g:go#use_vimproc')
if IsWin()
try
call vimproc#version()
let exists_vimproc = 1
catch
let exists_vimproc = 0
endtry
else
let exists_vimproc = 0
endif
let g:go#use_vimproc = exists_vimproc
endif
return g:go#use_vimproc
endfunction
" vim:ts=4:sw=4:et

View file

@ -558,6 +558,12 @@ Highlights method names. By default it's disabled. >
Highlights struct names. By default it's disabled. > Highlights struct names. By default it's disabled. >
let g:go_highlight_structs = 0 let g:go_highlight_structs = 0
<
*'g:go_highlight_build_constraints'*
Highlights build constraints. By default it's disabled. >
let g:go_highlight_build_constraints = 0
< <
*'g:go_textobj_enabled'* *'g:go_textobj_enabled'*

View file

@ -10,8 +10,9 @@ endsnippet
# anonymous function # anonymous function
snippet anon "fn := func() { ... }" snippet anon "fn := func() { ... }"
${1:fn} := func() { ${1:fn} := func() {
${0} ${2:${VISUAL}}
} }
${0}
endsnippet endsnippet
# append # append
@ -192,7 +193,7 @@ endsnippet
# Fmt Printf debug # Fmt Printf debug
snippet ff "fmt.Printf(...)" snippet ff "fmt.Printf(...)"
fmt.Printf("${1} = %+v\n", $1) fmt.Printf("${1:${VISUAL}} = %+v\n", $1)
endsnippet endsnippet
# Fmt Println debug # Fmt Println debug
@ -294,8 +295,9 @@ endsnippet
# goroutine anonymous function # goroutine anonymous function
snippet gof "go func() { ... }()" snippet gof "go func() { ... }()"
go func() { go func() {
${1} ${1:${VISUAL}}
}() }()
${0}
endsnippet endsnippet
# test function # test function

View file

@ -9,7 +9,7 @@ let g:go_loaded_install = 1
let s:packages = [ let s:packages = [
\ "github.com/nsf/gocode", \ "github.com/nsf/gocode",
\ "golang.org/x/tools/cmd/goimports", \ "golang.org/x/tools/cmd/goimports",
\ "code.google.com/p/rog-go/exp/cmd/godef", \ "github.com/rogpeppe/godef",
\ "golang.org/x/tools/cmd/oracle", \ "golang.org/x/tools/cmd/oracle",
\ "golang.org/x/tools/cmd/gorename", \ "golang.org/x/tools/cmd/gorename",
\ "github.com/golang/lint/golint", \ "github.com/golang/lint/golint",
@ -166,11 +166,6 @@ function! s:CheckBinaries()
echohl Error | echomsg "vim-go: git executable not found." | echohl None echohl Error | echomsg "vim-go: git executable not found." | echohl None
return -1 return -1
endif endif
if !executable('hg')
echohl Error | echomsg "vim.go: hg (mercurial) executable not found." | echohl None
return -1
endif
endfunction endfunction
" Autocommands " Autocommands

View file

@ -67,6 +67,10 @@ if !exists("g:go_highlight_structs")
let g:go_highlight_structs = 0 let g:go_highlight_structs = 0
endif endif
if !exists("g:go_highlight_build_constraints")
let g:go_highlight_build_constraints = 0
endif
syn case match syn case match
syn keyword goDirective package import syn keyword goDirective package import
@ -270,6 +274,21 @@ endif
hi def link goStruct Function hi def link goStruct Function
hi def link goStructDef Function hi def link goStructDef Function
" Build Constraints
if g:go_highlight_build_constraints != 0
syn keyword goBuildOs contained ignore cgo android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows
syn keyword goBuildArch contained 386 amd64 amd64p32 arm
syn match goBuildDirective display contained "+build"
syn region goBuildComment start="//\s*+build" end="$" contains=goBuildDirective,goBuildOs,goBuildArch
syn region goBuildComment start="/\*\s*+build" end="\*/" contains=goBuildDirective,goBuildOs,goBuildArch
endif
hi def link goBuildComment Comment
hi def link goBuildOs Type
hi def link goBuildArch Type
hi def link goBuildDirective PreProc
" Search backwards for a global declaration to start processing the syntax. " Search backwards for a global declaration to start processing the syntax.
"syn sync match goSync grouphere NONE /^\(const\|var\|type\|func\)\>/ "syn sync match goSync grouphere NONE /^\(const\|var\|type\|func\)\>/

View file

@ -69,7 +69,7 @@ By default, the 'next' key is also used to enter multicursor mode. If you want t
let g:multi_cursor_start_key='<F6>' let g:multi_cursor_start_key='<F6>'
``` ```
Note that when multicursor mode is started, it selects current word without boundaries, i.e. it behavies like `g*`. If you want to use word boundaries in Normal mode (as `*` does) but still have old behaviour up your sleeve, you can do the following: Note that when multicursor mode is started, it selects current word without boundaries, i.e. it behaves like `g*`. If you want to use word boundaries in Normal mode (as `*` does) but still have old behaviour up your sleeve, you can do the following:
``` ```
let g:multi_cursor_start_key='g<C-n>' let g:multi_cursor_start_key='g<C-n>'
let g:multi_cursor_start_word_key='<C-n>' let g:multi_cursor_start_word_key='<C-n>'

View file

@ -236,6 +236,14 @@ function! multiple_cursors#find(start, end, pattern)
return return
else else
echohl Normal | echo 'Added '.s:cm.size().' cursor'.(s:cm.size()>1?'s':'') | echohl None echohl Normal | echo 'Added '.s:cm.size().' cursor'.(s:cm.size()>1?'s':'') | echohl None
" If we've created any cursors, we need to call the before function, end
" function will be called via normal routes
if exists('*Multiple_cursors_before') && !s:before_function_called
exe "call Multiple_cursors_before()"
let s:before_function_called = 1
endif
call s:wait_for_user_input('v') call s:wait_for_user_input('v')
endif endif
endfunction endfunction
@ -458,8 +466,8 @@ function! s:CursorManager.update_current() dict
call cur.update_visual_selection(s:get_visual_region(s:pos('.'))) call cur.update_visual_selection(s:get_visual_region(s:pos('.')))
elseif s:from_mode ==# 'v' || s:from_mode ==# 'V' elseif s:from_mode ==# 'v' || s:from_mode ==# 'V'
call cur.remove_visual_selection() call cur.remove_visual_selection()
elseif s:from_mode ==# 'i' && s:to_mode ==# 'n' && self.current_index == self.size() - 1 elseif s:from_mode ==# 'i' && s:to_mode ==# 'n' && self.current_index != self.size() - 1
normal! `^ normal! h
endif endif
let vdelta = line('$') - s:saved_linecount let vdelta = line('$') - s:saved_linecount
" If the total number of lines changed in the buffer, we need to potentially " If the total number of lines changed in the buffer, we need to potentially
@ -985,7 +993,9 @@ endfunction
let s:retry_keys = "" let s:retry_keys = ""
function! s:display_error() function! s:display_error()
if s:bad_input == s:cm.size() && has_key(g:multi_cursor_normal_maps, s:char[0]) if s:bad_input == s:cm.size()
\ && s:from_mode ==# 'n'
\ && has_key(g:multi_cursor_normal_maps, s:char[0])
" we couldn't replay it anywhere but we're told it's the beginning of a " we couldn't replay it anywhere but we're told it's the beginning of a
" multi-character map like the `d` in `dw` " multi-character map like the `d` in `dw`
let s:retry_keys = s:char let s:retry_keys = s:char
@ -1037,14 +1047,14 @@ function! s:last_char()
endfunction endfunction
function! s:wait_for_user_input(mode) function! s:wait_for_user_input(mode)
call s:display_error()
let s:from_mode = a:mode let s:from_mode = a:mode
if empty(a:mode) if empty(a:mode)
let s:from_mode = s:to_mode let s:from_mode = s:to_mode
endif endif
let s:to_mode = '' let s:to_mode = ''
call s:display_error()
" Right before redraw, apply the highlighting bug fix " Right before redraw, apply the highlighting bug fix
call s:apply_highlight_fix() call s:apply_highlight_fix()

View file

@ -110,7 +110,7 @@ mode than for selecting the next location, do like the following: >
*g:multi_cursor_start_word_key* *g:multi_cursor_start_word_key*
When multicursor mode is started, it selects current word without When multicursor mode is started, it selects current word without
boundaries, i.e. it behavies like `g*`. If you want to use word boundaries in boundaries, i.e. it behaves like `g*`. If you want to use word boundaries in
Normal mode (as `*` does) but still have old behaviour up your sleeve, you can Normal mode (as `*` does) but still have old behaviour up your sleeve, you can
do the following: > do the following: >

View file

@ -89,10 +89,18 @@ function! repeat#run(count)
let c = g:repeat_count let c = g:repeat_count
let s = g:repeat_sequence let s = g:repeat_sequence
let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : '')) let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : ''))
call feedkeys(r . cnt, 'n') if ((v:version == 703 && has('patch100')) || (v:version == 704 && !has('patch601')))
call feedkeys(s) exe 'norm ' . r . cnt . s
else
call feedkeys(r . cnt, 'ni')
call feedkeys(s, 'i')
endif
else else
call feedkeys((a:count ? a:count : '') . '.', 'n') if ((v:version == 703 && has('patch100')) || (v:version == 704 && !has('patch601')))
exe 'norm! '.(a:count ? a:count : '') . '.'
else
call feedkeys((a:count ? a:count : '') . '.', 'ni')
endif
endif endif
endfunction endfunction

View file

@ -81,6 +81,23 @@ does `:SnipMateLoadScope rails` when editing a Rails project for example.
* Fix the use of the visual map at the end of a line * Fix the use of the visual map at the end of a line
* Add `:SnipMateLoadScope` command and buffer-local scope aliases * Add `:SnipMateLoadScope` command and buffer-local scope aliases
* Load `<scope>_*.snippets` files * Load `<scope>_*.snippets` files
* Indent visual placeholder expansions and remove extraneous lines ([#177][177]
and [#178][178])
* The nested branch has been merged
* A new snippet parser has been added. The g:snipmate.version as well as
version lines in snippet files determines which is used
* The new parser supports tab stops placed within placeholders,
substitutions, non-consecutive stop numbers, and fewer ambiguities
* The stop jumping code has been updated
* Tests have been added for the jumping code and the new parser
* The override branch has been merged
* The g:snipMate.override option is added. When enabled, if two snippets
share the same name, the later-loaded one is kept and the other discarded
* Override behavior can be enabled on a per-snippet basis with a bang (!) in
the snippet file
* Otherwise, SnipMate tries to preserve all snippets loaded
### 0.87 - 2014-01-04 ### ### 0.87 - 2014-01-04 ###
@ -106,3 +123,5 @@ does `:SnipMateLoadScope rails` when editing a Rails project for example.
[vundle]: https://github.com/gmarik/vundle [vundle]: https://github.com/gmarik/vundle
[143]: https://github.com/garbas/vim-snipmate/issues/143 [143]: https://github.com/garbas/vim-snipmate/issues/143
[177]: https://github.com/garbas/vim-snipmate/issues/177
[178]: https://github.com/garbas/vim-snipmate/issues/178

View file

@ -9,35 +9,39 @@ catch /.*/
echoe "you're missing tlib. See install instructions at ".expand('<sfile>:h:h').'/README.md' echoe "you're missing tlib. See install instructions at ".expand('<sfile>:h:h').'/README.md'
endtry endtry
" match $ which doesn't follow a \
let s:d = nr2char(31)
fun! Filename(...) fun! Filename(...)
let filename = expand('%:t:r') let filename = expand('%:t:r')
if filename == '' | return a:0 == 2 ? a:2 : '' | endif if filename == '' | return a:0 == 2 ? a:2 : '' | endif
return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g') return !a:0 || a:1 == '' ? filename : substitute(a:1, '$1', filename, 'g')
endf endf
let s:state_proto = {}
let s:cache = {} let s:cache = {}
fun! s:state_proto.remove() function! snipMate#expandSnip(snip, version, col)
unlet! b:snip_state let lnum = line('.')
" Remove all buffer-local autocommands in the snipmate_changes group let col = a:col
au! snipmate_changes * <buffer>
endf
fun! snipMate#expandSnip(snip, col)
let lnum = line('.') | let col = a:col
let snippet = s:ProcessSnippet(a:snip)
" Avoid error if eval evaluates to nothing
if snippet == '' | return '' | endif
" Expand snippet onto current position with the tab stops removed
let snipLines = split(substitute(snippet, ''.s:d .'\d\+\|'.s:d .'{\d\+.\{-}}', '', 'g'), "\n", 1)
let line = getline(lnum) let line = getline(lnum)
let indent = match(line, '\S\|$') + 1
let b:snip_state = snipmate#jumping#state()
if a:version == 1
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)
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)
let snipLines = split(substitute(snippet, printf('%s\d\+\|%s{\d\+.\{-}}',
\ g:snipmate#legacy#sigil, g:snipmate#legacy#sigil), '', 'g'), "\n", 1)
endif
" Abort if the snippet is empty
if empty(snippet)
return ''
endif
" Expand snippet onto current position
let afterCursor = strpart(line, col - 1) let afterCursor = strpart(line, col - 1)
" Keep text after the cursor " Keep text after the cursor
if afterCursor != "\t" && afterCursor != ' ' if afterCursor != "\t" && afterCursor != ' '
@ -52,336 +56,143 @@ fun! snipMate#expandSnip(snip, col)
endif endif
" Insert snippet with proper indentation " Insert snippet with proper indentation
let indent = match(line, '\S\|$') + 1
call setline(lnum, line . snipLines[0]) call setline(lnum, line . snipLines[0])
call append(lnum, map(snipLines[1:], "empty(v:val) ? v:val : '" . strpart(line, 0, indent - 1) . "' . v:val")) call append(lnum, map(snipLines[1:], "empty(v:val) ? v:val : '" . strpart(line, 0, indent - 1) . "' . v:val"))
" Open any folds snippet expands into " Open any folds snippet expands into
if &fen | sil! exe lnum.','.(lnum + len(snipLines) - 1).'foldopen' | endif if &foldenable
silent! exec lnum . ',' . (lnum + len(snipLines) - 1) . 'foldopen'
let b:snip_state = copy(s:state_proto)
let [b:snip_state.stops, b:snip_state.stop_count] = s:BuildTabStops(snippet, lnum, col - indent, indent)
if b:snip_state.stop_count
aug snipmate_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()
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
let newlines = len(snipLines) - 1
call cursor(lnum + newlines, indent + len(snipLines[-1]) - len(afterCursor)
\ + (newlines ? 0: col - 1))
endif endif
return ''
endf
" Update state information to correspond to the given tab stop aug snipmate_changes
function! s:state_proto.set_stop(stop) au CursorMoved,CursorMovedI <buffer> if exists('b:snip_state') |
let self.stop_no = a:stop \ call b:snip_state.update_changes() |
let self.cur_stop = self.stops[self.stop_no] \ else |
let self.end_col = self.cur_stop[1] + self.cur_stop[2] \ silent! au! snipmate_changes * <buffer> |
let self.start_col = self.cur_stop[1] \ endif
call cursor(self.cur_stop[0], self.cur_stop[1]) aug END
let self.prev_len = col('$')
let self.has_vars = exists('self.cur_stop[3]') let b:snip_state.stop_no = 0
let self.old_vars = self.has_vars ? deepcopy(self.cur_stop[3]) : [] return b:snip_state.set_stop(0)
endfunction endfunction
" Prepare snippet to be processed by s:BuildTabStops function! snipMate#placeholder_str(num, stops)
fun! s:ProcessSnippet(snip) return snipMate#sniplist_str(a:stops[a:num].placeholder, a:stops)[0]
let snippet = a:snip endfunction
let esc_bslash = '\%(\\\@<!\%(\\\\\)*\)\@<='
if exists('b:snipmate_content_visual') function! snipMate#sniplist_str(snippet, stops)
let visual = substitute(b:snipmate_content_visual, "\n$", '', '') let lines = ['']
unlet b:snipmate_content_visual let pos = 0
else let add_to = 1
let visual = '' let seen_stops = []
endif
let snippet = substitute(snippet, '\n\(\t\+\).\{-\}\zs{VISUAL}',
\ substitute(escape(visual, '%\'), "\n", "\n\\\\1", 'g'), 'g')
" Evaluate eval (`...`) expressions. while pos < len(a:snippet)
" Backquotes prefixed with a backslash "\" are ignored. let item = a:snippet[pos]
" And backslash can be escaped by doubling it.
" Using a loop here instead of a regex fixes a bug with nested "\=". if type(item) == type('')
if stridx(snippet, '`') != -1 if add_to
let new = [] let lines[-1] .= item
let snip = split(snippet, esc_bslash . '`', 1)
let isexp = 0
for i in snip
if isexp
call add(new, substitute(eval(i), "\n\\%$", '', ''))
else else
call add(new, i) call add(lines, item)
endif endif
let isexp = !isexp let add_to = 0
endfor elseif type(item) == type([])
let snippet = join(new, '') let lines[-1] .= snipMate#placeholder_str(item[0], a:stops)
let snippet = substitute(snippet, "\r", "\n", 'g') let add_to = 1
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: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 ${#}.
" (e.g. "${1:foo}" turns all "$1"'s into "foo")
let i = 1
while snippet =~ s:d.'{'.i
let s = matchstr(snippet, s:d.'{'.i.':\zs.\{-}\ze}')
if s != ''
let snippet = substitute(snippet, s:d.i, s.'&', 'g')
endif endif
let i += 1
endw
" Add ${0} tab stop if found let pos += 1
if snippet =~ s:d . '{0' unlet item " avoid E706
let snippet = substitute(snippet, s:d.'{0', s:d . '{' . i, '') endwhile
let s = matchstr(snippet, s:d.'{'.i.':\zs.\{-}\ze}')
if s != ''
let snippet = substitute(snippet, s:d.'0', s:d . i, 'g')
let snippet = substitute(snippet, s:d.i, s.'&', 'g')
endif
else
let snippet .= s:d . '{'.i.'}'
endif
if &et " Expand tabs to spaces if 'expandtab' is set. return lines
return substitute(snippet, '\t', repeat(' ', (&sts > 0) ? &sts : &sw), 'g')
endif
return snippet
endf
" Counts occurences of haystack in needle
fun! s:Count(haystack, needle)
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
endf
" 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.
fun! s:BuildTabStops(snip, lnum, col, indent)
let snipPos = []
let i = 1
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')
let j = i - 1
call add(snipPos, [0, 0, 0])
let snipPos[j][0] = a:lnum + s:Count(beforeTabStop, "\n")
let snipPos[j][1] = a:indent + len(matchstr(withoutOthers, '.*\(\n\|^\)\zs.*\ze'.s:d .'{'.i.'\D'))
if snipPos[j][0] == a:lnum | let snipPos[j][1] += a:col | endif
" Get all $# matches in another list, if ${#:name} is given
if withoutVars =~ ''.s:d .'{'.i.':'
let snipPos[j][2] = len(matchstr(withoutVars, ''.s:d .'{'.i.':\zs.\{-}\ze}'))
let dots = repeat('.', snipPos[j][2])
call add(snipPos[j], [])
let withoutOthers = substitute(a:snip, ''.s:d .'{\d\+.\{-}}\|'.s:d .''.i.'\@!\d\+', '', 'g')
while match(withoutOthers, ''.s:d .''.i.'\(\D\|$\)') != -1
let beforeMark = matchstr(withoutOthers, '^.\{-}\ze'.dots.''.s:d .''.i.'\(\D\|$\)')
call add(snipPos[j][3], [0, 0])
let snipPos[j][3][-1][0] = a:lnum + s:Count(beforeMark, "\n")
let snipPos[j][3][-1][1] = a:indent + (snipPos[j][3][-1][0] > a:lnum
\ ? len(matchstr(beforeMark, '.*\n\zs.*'))
\ : a:col + len(beforeMark))
let withoutOthers = substitute(withoutOthers, ''.s:d .''.i.'\ze\(\D\|$\)', '', '')
endw
endif
let i += 1
endw
return [snipPos, i - 1]
endf
function! s:state_proto.jump_stop(backwards)
" Update changes just in case
" This seems to be only needed because insert completion does not trigger
" the CursorMovedI event
call self.update_changes()
" Update stop and var locations
call self.update_stops()
" Store the changed col/length of the current stop
let self.cur_stop[1] = self.start_col
let self.cur_stop[2] = self.end_col - self.start_col
let self.stop_no += a:backwards ? -1 : 1
" Loop over the snippet when going backwards from the beginning
if self.stop_no < 0 | let self.stop_no = self.stop_count - 1 | endif
call self.set_stop(self.stop_no)
let ret = self.select_word()
if self.stop_no == self.stop_count - 1
call self.remove()
endif
return ret
endfunction endfunction
" Updates tab stops/vars function! s:build_stops(snippet, stops, lnum, col, indent)
function! s:state_proto.update_stops() let stops = a:stops
let changeLen = self.end_col - self.cur_stop[2] - self.start_col let line = a:lnum
" Update tab stops in snippet if text has been added via "$#" let col = a:col
" (e.g., in "${1:foo}bar$1${2}").
if changeLen != 0
let curLine = line('.')
for pos in self.stops for [id, dict] in items(stops)
if pos == self.cur_stop | continue | endif for i in dict.instances
let changed = pos[0] == curLine && pos[1] > self.cur_stop[1] if len(i) > 1 && type(i[1]) != type({})
let changedVars = 0 if !has_key(dict, 'placeholder')
let endPlaceholder = pos[2] - 1 + pos[1] let dict.placeholder = i[1:]
" Subtract changeLen from each tab stop that was after any of else
" the current tab stop's placeholders. unlet i[1:]
for [lnum, col] in self.old_vars
if lnum > pos[0] | break | endif
if pos[0] == lnum
if pos[1] > col || (pos[2] == -1 && pos[1] == col)
let changed += 1
elseif col < endPlaceholder
let changedVars += 1
endif
endif endif
endfor
let pos[1] += changeLen * changed
" Parse variables within placeholders, e.g., "${1:foo} ${2:$1bar}"
let pos[2] += changeLen * changedVars
" Do the same to any placeholders in the other tab stops.
if exists('pos[3]')
for nPos in pos[3]
let changed = nPos[0] == curLine && nPos[1] > self.start_col
if changed && nPos[1] < self.start_col + self.cur_stop[2]
call remove(pos, index(pos, nPos))
continue
endif
for [lnum, col] in self.old_vars
if lnum > nPos[0] | break | endif
if nPos[0] == lnum && nPos[1] > col
let changed += 1
endif
endfor
let nPos[1] += changeLen * changed
endfor
endif endif
endfor endfor
endif if !has_key(dict, 'placeholder')
endfunction let dict.placeholder = []
let j = 0
" Select the placeholder for the current tab stop while len(dict.instances[j]) > 1
function! s:state_proto.select_word() let j += 1
let len = self.cur_stop[2] endwhile
if !len | return '' | endif call add(dict.instances[j], '')
let l = col('.') != 1 ? 'l' : ''
if &sel == 'exclusive'
return "\<esc>".l.'v'.len."l\<c-g>"
endif
return len == 1 ? "\<esc>".l.'gh' : "\<esc>".l.'v'.(len - 1)."l\<c-g>"
endfunction
" Update the snippet as text is typed. The self.update_vars() function does
" the actual work.
" If the cursor moves outside of a placeholder, call self.remove()
function! s:state_proto.update_changes()
let change_len = col('$') - self.prev_len
let self.end_col += change_len
let col = col('.')
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
endif unlet dict.instances
let self.prev_len = col('$')
endfunction
" Actually update the vars for any changed text
function! s:state_proto.update_vars(change)
let newWordLen = self.end_col - self.start_col
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
for [lnum, col] in self.cur_stop[3]
if updateTabStops
let start = self.start_col
if lnum == curLine && col <= start
let self.start_col += changeLen
let self.end_col += changeLen
endif
for nPos in self.cur_stop[3][(i):]
" This list is in ascending order, so quit if we've gone too far.
if nPos[0] > lnum | break | endif
if nPos[0] == lnum && nPos[1] > col
let nPos[1] += changeLen
endif
endfor
if lnum == curLine && col > start
let col += changeLen
let self.cur_stop[3][i][1] = col
endif
let i += 1
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(lnum)
let update = strpart(theline, 0, col - 1)
let update .= newWord
let update .= strpart(theline, col + self.end_col - self.start_col - a:change - 1)
call setline(lnum, update)
endfor endfor
" Reposition the cursor in case a var updates on the same line but before let [line, col] = s:build_loc_info(a:snippet, stops, line, col, a:indent)
" the current tabstop
if oldStartSnip != self.start_col || mode() == 'i' " add zero tabstop if it doesn't exist and then link it to the highest stop
call cursor(0, curCol + self.start_col - oldStartSnip) " number
let stops[0] = get(stops, 0,
\ { 'placeholder' : [], 'line' : line, '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)
let stops = a:stops
let line = a:line
let col = a:col
let pos = 0
let in_text = 0
while pos < len(a:snippet)
let item = a:snippet[pos]
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)
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
return [line, col]
endfunction
function! s:add_mirror(stops, id, line, col, item)
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 endif
endfunction endfunction
@ -396,6 +207,7 @@ fun! snipMate#ReadSnippetsFile(file)
if !filereadable(a:file) | return [result, new_scopes] | endif if !filereadable(a:file) | return [result, new_scopes] | endif
let inSnip = 0 let inSnip = 0
let line_no = 0 let line_no = 0
let snipversion = get(g:snipMate, 'snippet_version', 0)
for line in readfile(a:file) + ["\n"] for line in readfile(a:file) + ["\n"]
let line_no += 1 let line_no += 1
@ -403,13 +215,15 @@ fun! snipMate#ReadSnippetsFile(file)
let content .= strpart(line, 1)."\n" let content .= strpart(line, 1)."\n"
continue continue
elseif inSnip elseif inSnip
call add(result, [trigger, name == '' ? 'default' : name, content[:-2]]) call add(result, [trigger, name,
\ content[:-2], bang, snipversion])
let inSnip = 0 let inSnip = 0
endif endif
if line[:6] == 'snippet' if line[:6] == 'snippet'
let inSnip = 1 let inSnip = 1
let trigger = strpart(line, 8) let bang = (line[7] == '!')
let trigger = strpart(line, 8 + bang)
let name = '' let name = ''
let space = stridx(trigger, ' ') + 1 let space = stridx(trigger, ' ') + 1
if space " Process multi snip if space " Process multi snip
@ -424,6 +238,8 @@ fun! snipMate#ReadSnippetsFile(file)
elseif line[:6] == 'extends' elseif line[:6] == 'extends'
call extend(new_scopes, map(split(strpart(line, 8)), call extend(new_scopes, map(split(strpart(line, 8)),
\ "substitute(v:val, ',*$', '', '')")) \ "substitute(v:val, ',*$', '', '')"))
elseif line[:6] == 'version'
let snipversion = +strpart(line, 8)
endif endif
endfor endfor
return [result, new_scopes] return [result, new_scopes]
@ -464,80 +280,40 @@ fun! s:AddScopeAliases(list)
return keys(did) return keys(did)
endf endf
if v:version < 704 || has('win32') au SourceCmd *.snippet,*.snippets call s:source_snippet()
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 function! s:info_from_filename(file)
" { path: { 'type': one of 'snippet' 'snippets', let parts = split(fnamemodify(a:file, ':r'), '/')
" 'exists': 1 or 0 let snipidx = len(parts) - index(reverse(copy(parts)), 'snippets') - 1
" " for single snippet files: let rtp_prefix = join(parts[(snipidx -
" 'name': name of snippet \ (parts[snipidx - 1] == 'after' ? 3 : 2)):snipidx - 1], '/')
" 'trigger': trigger of snippet let trigger = get(parts, snipidx + 2, '')
" } let desc = get(parts, snipidx + 3, get(g:snipMate, 'override', 0) ?
" } \ '' : fnamemodify(a:file, ':t'))
" use mustExist = 1 to return existing files only return [rtp_prefix, trigger, desc]
"
" mustExist = 0 is used by OpenSnippetFiles
function! snipMate#GetSnippetFiles(mustExist, scopes, trigger)
let paths = join(funcref#Call(g:snipMate.snippet_dirs), ',')
let result = {}
let scopes = s:AddScopeAliases(a:scopes)
let trigger = escape(a:trigger, "*[]?{}`'$")
" collect existing files
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
" 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': fnamemodify(f, ':t:r'), 'name_prefix' : scope }
endfor
for f in s:Glob(paths, 'snippets/' . scope . '/' . trigger . '*/*.snippet')
let result[f] = {'exists': 1, 'type': 'snippet', 'name' : fnamemodify(f, ':t:r'),
\ 'trigger': fnamemodify(f, ':h:t'), 'name_prefix' : scope }
endfor
if !a:mustExist
for p in split(paths, ',')
let p .= '/snippets/' . scope . '.snippets'
let result[p] = get(result, p, {'exists': 0, 'type': 'snippets'})
endfor
endif
endfor
return result
endfunction endfunction
" should be moved to utils or such? function! s:source_snippet()
function! snipMate#SetByPath(dict, trigger, path, snippet) abort let file = expand('<afile>:p')
let d = a:dict let [rtp_prefix, trigger, desc] = s:info_from_filename(file)
if !has_key(d, a:trigger) let new_snips = []
let d[a:trigger] = {} if fnamemodify(file, ':e') == 'snippet'
call add(new_snips, [trigger, desc, join(readfile(file), "\n"), 0,
\ get(g:snipMate, 'snippet_version', 0)])
else
let [snippets, extends] = s:CachedSnips(file)
let new_snips = deepcopy(snippets)
call extend(s:lookup_state.extends, extends)
endif endif
let d[a:trigger][a:path] = a:snippet for snip in new_snips
if get(g:snipMate, 'override', 0)
let snip[1] = join([s:lookup_state.scope, snip[1]])
else
let snip[1] = join([s:lookup_state.scope, rtp_prefix,
\ empty(snip[1]) ? desc : snip[1]])
endif
endfor
call extend(s:lookup_state.snips, new_snips)
endfunction endfunction
function! s:CachedSnips(file) function! s:CachedSnips(file)
@ -551,31 +327,50 @@ function! s:CachedSnips(file)
return s:cache[a:file].contents return s:cache[a:file].contents
endfunction endfunction
function! s:snippet_filenames(scope, trigger)
let mid = ['', '_*', '/*']
return join(map(extend(mid, map(filter(copy(mid), 'v:key != 1'),
\ "'/' . a:trigger . '*' . v:val")),
\ "'snippets/' . a:scope . v:val . '.snippet'"
\ . ". (v:key < 3 ? 's' : '')"))
endfunction
function! snipMate#SetByPath(dict, trigger, path, snippet, bang, snipversion)
let d = a:dict
if !has_key(d, a:trigger) || a:bang
let d[a:trigger] = {}
endif
let d[a:trigger][a:path] = [a:snippet, a:snipversion]
endfunction
" default triggers based on paths " default triggers based on paths
function! snipMate#DefaultPool(scopes, trigger, result) function! snipMate#DefaultPool(scopes, trigger, result)
let extra_scopes = [] let scopes = s:AddScopeAliases(a:scopes)
for [f,opts] in items(snipMate#GetSnippetFiles(1, a:scopes, a:trigger)) let scopes_done = []
let opts.name_prefix = matchstr(f, '\v/\zs.{-}\ze/snippets') . ' ' . opts.name_prefix let rtp_save = &rtp
if opts.type == 'snippets' let &rtp = join(g:snipMate.snippet_dirs, ',')
let [snippets, new_scopes] = s:CachedSnips(f) let s:lookup_state = {}
call extend(extra_scopes, new_scopes) let s:lookup_state.snips = []
for [trigger, name, contents] in snippets
if trigger =~ '\V\^' . escape(a:trigger, '\') while !empty(scopes)
call snipMate#SetByPath(a:result, trigger, let scope = remove(scopes, 0)
\ opts.name_prefix . ' ' . name, contents) let s:lookup_state.scope = scope
endif let s:lookup_state.extends = []
endfor
elseif opts.type == 'snippet' exec 'runtime!' s:snippet_filenames(scope, escape(a:trigger, "*[]?{}`'$|#%"))
call snipMate#SetByPath(a:result, opts.trigger,
\ opts.name_prefix . ' ' . opts.name, readfile(f)) call add(scopes_done, scope)
else call extend(scopes, s:lookup_state.extends)
throw "unexpected" call filter(scopes, 'index(scopes_done, v:val) == -1')
endwhile
for [trigger, desc, contents, bang, snipversion] in s:lookup_state.snips
if trigger =~ '\V\^' . escape(a:trigger, '\')
call snipMate#SetByPath(a:result, trigger, desc, contents, bang, snipversion)
endif endif
endfor endfor
if !empty(extra_scopes) let &rtp = rtp_save
call snipMate#DefaultPool(extra_scopes, a:trigger, a:result)
endif
endfunction endfunction
" return a dict of snippets found in runtimepath matching trigger " return a dict of snippets found in runtimepath matching trigger
@ -659,8 +454,15 @@ endf
fun! snipMate#GetSnippetsForWordBelowCursor(word, exact) fun! snipMate#GetSnippetsForWordBelowCursor(word, exact)
" Setup lookups: '1.2.3' becomes [1.2.3] + [3, 2.3] " Setup lookups: '1.2.3' becomes [1.2.3] + [3, 2.3]
let parts = split(a:word, '\W\zs') let parts = split(a:word, '\W\zs')
if len(parts) > 2 " Since '\W\zs' results in splitting *after* a non-keyword character, the
let parts = parts[-2:] " max 2 additional items, this might become a setting " first \W stays connected to whatever's before it, so split it off
if len(parts) > 1 && len(parts[0]) > 1
let parts = [ parts[0][:-2], strpart(parts[0], len(parts[0]) - 1) ]
\ + parts[1:]
endif
" Only look at the last few possibilities. Too many can be slow.
if len(parts) > 5
let parts = parts[-5:]
endif endif
let lookups = [a:word] let lookups = [a:word]
let lookup = '' let lookup = ''
@ -671,11 +473,6 @@ fun! snipMate#GetSnippetsForWordBelowCursor(word, exact)
endif endif
endfor endfor
" allow matching '.'
if a:word =~ '\.$'
call add(lookups, '.')
endif
" Remove empty lookup entries, but only if there are other nonempty lookups " Remove empty lookup entries, but only if there are other nonempty lookups
if len(lookups) > 1 if len(lookups) > 1
call filter(lookups, 'v:val != ""') call filter(lookups, 'v:val != ""')
@ -795,19 +592,12 @@ function! snipMate#TriggerSnippet(...)
let snippet = '' let snippet = ''
else else
let [trigger, snippetD] = list[0] let [trigger, snippetD] = list[0]
let snippet = s:ChooseSnippet(snippetD)
let s = s:ChooseSnippet(snippetD)
if type(s) == type([])
let snippet = join(s, "\n")
else
let snippet = s
end
" Before expanding snippet, create new undo point |i_CTRL-G| " Before expanding snippet, create new undo point |i_CTRL-G|
let &undolevels = &undolevels let &undolevels = &undolevels
let col = col('.') - len(trigger) let col = col('.') - len(trigger)
sil exe 's/\V'.escape(trigger, '/\.').'\%#//' sil exe 's/\V'.escape(trigger, '/\.').'\%#//'
return snipMate#expandSnip(snippet, col) return snipMate#expandSnip(snippet[0], snippet[1], col)
endif endif
" should allow other plugins to register hooks instead (duplicate code) " should allow other plugins to register hooks instead (duplicate code)

View file

@ -0,0 +1,205 @@
function! s:sfile()
return expand('<sfile>')
endfunction
let s:state_proto = {}
function! snipmate#jumping#state()
return copy(s:state_proto)
endfunction
function! s:listize_mirror(mirrors)
return map(copy(a:mirrors), '[v:val.line, v:val.col]')
endfunction
" Removes snippet state info
function! s:state_remove() dict
" Remove all autocmds in group snipmate_changes in the current buffer
unlet! b:snip_state
silent! au! snipmate_changes * <buffer>
endfunction
function! s:state_find_next_stop(backwards) dict
let self.stop_no += a:backwards? -1 : 1
while !has_key(self.stops, self.stop_no)
if self.stop_no == self.stop_count
let self.stop_no = 0
endif
if self.stop_no <= 0 && a:backwards
let self.stop_no = self.stop_count - 1
endif
let self.stop_no += a:backwards? -1 : 1
endwhile
endfunction
" Update state information to correspond to the given tab stop
function! s:state_set_stop(backwards) dict
call self.find_next_stop(a:backwards)
let self.cur_stop = self.stops[self.stop_no]
let self.stop_len = (type(self.cur_stop.placeholder) == type(0))
\ ? self.cur_stop.placeholder
\ : len(snipMate#placeholder_str(self.stop_no, self.stops))
let self.start_col = self.cur_stop.col
let self.end_col = self.start_col + self.stop_len
let self.mirrors = get(self.cur_stop, 'mirrors', [])
let self.old_mirrors = deepcopy(self.mirrors)
call cursor(self.cur_stop.line, self.cur_stop.col)
let self.prev_len = col('$')
let self.changed = 0
let ret = self.select_word()
if (self.stop_no == 0 || self.stop_no == self.stop_count - 1) && !a:backwards
call self.remove()
endif
return ret
endfunction
" Jump to the next/previous tab stop
function! s:state_jump_stop(backwards) dict
" Update changes just in case
" This seems to be only needed because insert completion does not trigger
" the CursorMovedI event
call self.update_changes()
" Store placeholder/location changes
let self.cur_stop.col = self.start_col
if self.changed
call self.remove_nested()
unlet! self.cur_stop.placeholder " avoid type error for old parsing version
let self.cur_stop.placeholder = [strpart(getline('.'),
\ self.start_col - 1, self.end_col - self.start_col)]
endif
return self.set_stop(a:backwards)
endfunction
function! s:state_remove_nested(...) dict
let id = a:0 ? a:1 : self.stop_no
if type(self.stops[id].placeholder) == type([])
for i in self.stops[id].placeholder
if type(i) == type([])
if type(i[1]) != type({})
call self.remove_nested(i[0])
call remove(self.stops, i[0])
else
call filter(self.stops[i[0]].mirrors, 'v:val isnot i[1]')
endif
endif
unlet i " Avoid E706
endfor
endif
endfunction
" Select the placeholder for the current tab stop
function! s:state_select_word() dict
let len = self.stop_len
if !len | return '' | endif
let l = col('.') != 1 ? 'l' : ''
if &sel == 'exclusive'
return "\<esc>".l.'v'.len."l\<c-g>"
endif
return len == 1 ? "\<esc>".l.'gh' : "\<esc>".l.'v'.(len - 1)."l\<c-g>"
endfunction
" Update the snippet as text is typed. The self.update_mirrors() function does
" the actual work.
" If the cursor moves outside of a placeholder, call self.remove()
function! s:state_update_changes() dict
let change_len = col('$') - self.prev_len
let self.changed = self.changed || change_len != 0
let self.end_col += change_len
let col = col('.')
if line('.') != self.cur_stop.line || col < self.start_col || col > self.end_col
return self.remove()
endif
call self.update(self.cur_stop, change_len)
if !empty(self.mirrors)
call self.update_mirrors(change_len)
endif
let self.prev_len = col('$')
endfunction
" Actually update the mirrors for any changed text
function! s:state_update_mirrors(change) dict
let newWordLen = self.end_col - self.start_col
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 i = 0
for mirror in self.mirrors
for stop in values(filter(copy(self.stops), 'v:key != 0'))
if type(stop.placeholder) == type(0)
if mirror.line == stop.line && mirror.col > stop.col
\ && mirror.col < stop.col + stop.placeholder
let stop.placeholder += changeLen
endif
endif
endfor
call self.update(mirror, changeLen)
" 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)
call setline(mirror.line, update)
endfor
" 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, curCol + self.start_col - oldStartSnip)
endif
endfunction
function! s:state_find_update_objects(item) dict
let item = a:item
let item.update_objects = []
" Filter the zeroth stop because it's duplicated as the last
for stop in values(filter(copy(self.stops), 'v:key != 0'))
if stop.line == item.line && stop.col > item.col
call add(item.update_objects, stop)
endif
for mirror in get(stop, 'mirrors', [])
if mirror.line == item.line && mirror.col > item.col
call add(item.update_objects, mirror)
endif
endfor
endfor
return item.update_objects
endfunction
function! s:state_update(item, change_len) dict
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
endif
for obj in to_update
let obj.col += a:change_len
if obj is self.cur_stop
let self.start_col += a:change_len
let self.end_col += a:change_len
endif
endfor
endfunction
call extend(s:state_proto, snipmate#util#add_methods(s:sfile(), 'state',
\ [ 'remove', 'set_stop', 'jump_stop', 'remove_nested',
\ 'select_word', 'update_changes', 'update_mirrors',
\ 'find_next_stop', 'find_update_objects', 'update' ]), 'error')
" vim:noet:sw=4:ts=4:ft=vim

View file

@ -0,0 +1,129 @@
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)
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 = substitute(snippet, '\n\(\t\+\).\{-\}\zs{VISUAL}',
\ substitute(escape(visual, '%\'), "\n", "\n\\\\1", 'g'), 'g')
" 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(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(' ', (&sts > 0) ? &sts : &sw), '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)
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\|^\)\zs.*\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
" Counts occurences of haystack in needle
function! s:count(haystack, needle)
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

View file

@ -0,0 +1,220 @@
" Snippet definition parsing code
function! s:sfile()
return expand('<sfile>')
endfunction
let s:parser_proto = {}
function! s:new_parser(text)
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 = {}
call ret.advance()
return ret
endfunction
function! s:parser_advance(...) dict
let self.pos += a:0 ? a:1 : 1
let self.next = self.input[self.pos]
endfunction
function! s:parser_same(tok) dict
if self.next == a:tok
call self.advance()
return 1
else
return 0
endif
endfunction
function! s:parser_id() dict
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
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
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
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
return self.parse('}')
endfunction
function! s:parser_subst() dict
let ret = {}
let ret.pat = join(self.text('/', 1))
if self.same('/')
let ret.sub = join(self.text('/}'))
endif
if self.same('/')
let ret.flags = join(self.text('}', 1))
endif
return ret
endfunction
function! s:parser_expr() dict
let str = join(self.text('`', 1))
let ret = eval(str)
call self.same('`')
return type(ret) == type('') ? ret : string(ret)
endfunction
function! s:parser_text(...) dict
let res = []
let val = ''
if a:0 == 2 && a:2
let till = '\V' . escape(a:1, '\')
else
let till = '[`$' . (a:0 ? a:1 : '') . ']'
endif
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 == "\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)
call self.advance()
else
let val .= self.next
call self.advance()
endif
endwhile
call add(res, val)
return res
endfunction
function! s:parser_parse(...) dict
let ret = a:0 ? [] : self.value
while self.pos < self.len
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])
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
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)
endif
if a:0 && self.next == a:1
break
endif
endwhile
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:indent(count)
if &expandtab
let shift = repeat(' ', (&sts > 0) ? &sts : &sw)
else
let shift = "\t"
endif
return repeat(shift, a:count)
endfunction
function! s:visual_placeholder(var, indent)
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! snipmate#parse#snippet(text)
let parser = s:new_parser(a:text)
call parser.parse()
unlet! b:snipmate_visual
return [parser.value, parser.vars]
endfunction

View file

@ -0,0 +1,10 @@
" The next function was based on s:function and s:add_methods in fugitive
" <https://github.com/tpope/vim-fugitive/blob/master/plugin/fugitive.vim>
function! snipmate#util#add_methods(sfile, namespace, methods)
let dict = {}
for name in a:methods
let dict[name] = function(join([matchstr(a:sfile, '<SNR>\d\+'),
\ a:namespace, name], '_'))
endfor
return dict
endfunction

View file

@ -6,7 +6,9 @@ Last Change: December 27, 2009
1. Description |SnipMate-description| 1. Description |SnipMate-description|
2. Usage |SnipMate-usage| 2. Usage |SnipMate-usage|
3. Interface and Settings |SnipMate-interface| |SnipMate-settings| 3. Interface and Settings |SnipMate-interface| |SnipMate-settings|
4. Snippet syntax |SnipMate-syntax| 4. Snippets |SnipMate-snippets|
- Snippet files |SnipMate-snippet-files|
- Snippet syntax |SnipMate-syntax|
5. Snippet sources |SnipMate-snippet-sources| 5. Snippet sources |SnipMate-snippet-sources|
6. Disadvantages to TextMate |SnipMate-disadvantages| 6. Disadvantages to TextMate |SnipMate-disadvantages|
7. Contact |SnipMate-contact| 7. Contact |SnipMate-contact|
@ -140,6 +142,24 @@ g:snipMate.no_default_aliases
the user or someone else will still be in the user or someone else will still be in
effect. effect.
g:snipMate.snippet_version
The snippet parser version to use. The
possible values are:
0 Use the older parser
1 Use the newer parser
If unset, SnipMate defaults to version 0. The
value of this option is also used for all
.snippet files.
g:snipMate.override
As detailed below, when two snippets with the
same name and description are loaded, both are
kept and differentiated by the location of the
file they were in. When this option is enabled
(set to 1), the snippet originating in the
last loaded file is kept, similar to how Vim
maps and other settings work.
g:snipMate['no_match_completion_feedkeys_chars'] g:snipMate['no_match_completion_feedkeys_chars']
A string inserted when no match for a trigger A string inserted when no match for a trigger
is found. By default a tab is inserted is found. By default a tab is inserted
@ -152,7 +172,7 @@ Mappings~
The mappings SnipMate uses can be customized with the |:map| commands. For The mappings SnipMate uses can be customized with the |:map| commands. For
example, to change the key that triggers snippets and moves to the next example, to change the key that triggers snippets and moves to the next
tabstop, > tab stop, >
:imap <C-J> <Plug>snipMateNextOrTrigger :imap <C-J> <Plug>snipMateNextOrTrigger
:smap <C-J> <Plug>snipMateNextOrTrigger :smap <C-J> <Plug>snipMateNextOrTrigger
@ -186,12 +206,17 @@ Additionally, <CR> is mapped in visual mode in .snippets files for retabbing
snippets. snippets.
============================================================================== ==============================================================================
SYNTAX *snippet-syntax* *SnipMate-syntax* SNIPPETS *SnipMate-snippets*
*SnipMate-snippet-files*
Snippet Files ~
Note: SnipMate does not ship with any snippets.
SnipMate looks inside of each entry of 'rtp' (or |SnipMate-snippet-sources|) SnipMate looks inside of each entry of 'rtp' (or |SnipMate-snippet-sources|)
for a directory named /snippets/. Based on the 'filetype' and 'syntax' for a directory named /snippets/. Based on the 'filetype' and 'syntax'
settings (taking into account the dotted syntax), the following files are read settings (dotted filetypes are parsed), the following files are read for
for snippets: > snippets: >
.../snippets/<scope>.snippets .../snippets/<scope>.snippets
.../snippets/<scope>_<name>.snippets .../snippets/<scope>_<name>.snippets
@ -199,7 +224,7 @@ for snippets: >
.../snippets/<scope>/<trigger>.snippet .../snippets/<scope>/<trigger>.snippet
.../snippets/<scope>/<trigger>/<description>.snippet .../snippets/<scope>/<trigger>/<description>.snippet
where <scope> is an entry in 'filetype' or 'syntax', <name> is an arbitrary where <scope> is a scope or 'filetype' or 'syntax', <name> is an arbitrary
name, <trigger> is the trigger for a snippet, and <description> is name, <trigger> is the trigger for a snippet, and <description> is
a description used for |SnipMate-multisnip|. a description used for |SnipMate-multisnip|.
@ -215,14 +240,25 @@ looks something like: >
more expanded text more expanded text
< *SnipMate-multisnip* < *SnipMate-multisnip*
The description is optional. If it is left out and a second snippet inside the The description is optional. If it is left out, the description "default" is
same .snippets file uses the same trigger, the second one will overwrite the used. When two snippets in the same scope have the same name and the same
first. Otherwise multisnip is used. description, SnipMate will try to preserve both. The g:snipMate.override
option disables this, in favor of keeping the last-loaded snippet. This can be
overridden on a per-snippet basis by defining the snippet with a bang (!): >
snippet! trigger optional description
expanded text
more expanded text
Note: Hard tabs in the expansion text are required. When the snippet is Note: Hard tabs in the expansion text are required. When the snippet is
expanded in the text and 'expandtab' is set, each tab will be replaced with expanded in the text and 'expandtab' is set, each tab will be replaced with
spaces based on 'softtabstop' if nonzero or 'shiftwidth' otherwise. spaces based on 'softtabstop' if nonzero or 'shiftwidth' otherwise.
Which version parser the snippets in a file should be used with can be
specified with a version line, e.g.: >
version 1
Comments can be made in .snippets files by starting a line with a # character. Comments can be made in .snippets files by starting a line with a # character.
However these can't be used inside of snippet definitions: > However these can't be used inside of snippet definitions: >
@ -243,74 +279,100 @@ directive, for example: >
will tell SnipMate to also read html, javascript, and css snippets. will tell SnipMate to also read html, javascript, and css snippets.
SNIPPET SYNTAX *snippet-syntax* *SnipMate-syntax*
Anywhere in a snippet, a backslash escapes the character following it,
regardless of whether that character is special or not. That is, '\a' will
always result in an 'a' in the output. A single backslash can be output by
using '\\'.
*SnipMate-tabstops* *SnipMate-tabstops*
Tab stops~ Tab stops~
A tab stop, specified by ${#} where # is a number, tells SnipMate where to When triggering a snippet, SnipMate will by default jump to the very end of
position the cursor next. The special tab stop ${0} denotes the last cursor the snippet text. This can be changed through the use of tab stops: $1, $2,
position; in its absence, the cursor is placed at the end of the snippet. and so on. After expansion, SnipMate will jump to the first tab stop. From
then on, the <Plug>snipMateNextOrTrigger map will jump to the next higher
numbered tabs top.
For example, to place the cursor first on the id of a <div> tag, allow However, SnipMate will always stop at the zero tab stop $0. Once it jumps to
the user to press <tab> to go to the middle of it, and finally end after the zero tab stop, snippet expansion is finished. If the zero tab stop is not
</div>: > present in a definition, it will be put at the end.
In the case of an ambiguity, for example if a stop occurs just before a literal
number, braces may be placed around the stop number to resolve it: ${3}79 is
the third tab stop followed by the string "79".
Note: In the version 0 snippet parser, the braces are mandatory.
For example, to place the cursor first on the id of a <div> tag, then on
its class, and finally end editing its contents: >
snippet div snippet div
<div id="${1}"> <div id="$1" class="$2">
${2} $0
</div> </div>
< *SnipMate-placeholders* *SnipMate-mirrors* < *SnipMate-placeholders*
Placeholders and Mirrors~ In addition to being simply a location, each tab stop contains a placeholder,
or some default text. The placeholder can be specified for every tab stop
(including the zero tab stop) with a colon after the stop ID, as in
${1:default text}. The braces are required only when specifying a placeholder.
Once a tab stop with a placeholder is reached, the placeholder will be
selected in |Select-mode|. For example, >
Placeholder text can be supplied using "${#:text}", where # is the number of snippet div
the tab stop. This text then can be copied throughout the snippet using "$#", <div id="${1:id}" class="${2:class}">
given # is the same number as used before. So, to make a C for loop: > $0
</div>
Finally, placeholders can contain mirrors and evaluations (detailed below) and
even entire other tab stops. If the placeholder is edited, then these nested
tab stops are removed and skipped entirely. For example, >
snippet div
<div${1: id="${2:id}"}${3: class="${4:class}"}>
$0
</div>
When expanded, this snippet selects the entirety of the id attribute. If this
stop is edited, then the second tab stop is removed and the third tab stop
becomes the next one. If the first tab stop is left unedited, then SnipMate
jumps to the second tab stop. This allows the user to use a single div snippet
that can be used for instances where the id or class attributes are desired
and those where they are not.
*SnipMate-mirrors*
Mirrors~
A mirror is simply a copy of a tab stop's text, updated as the tab stop is
edited. These look like a tab stop without a placeholder; $1 for example. In
the event that no placeholder is specified for a certain tab stop--say $1--the
first instance becomes the tab stop and the rest become mirrors.
Additionally substitutions similar to |:substitute| can be performed. For
instance ${1/foo/bar/g} will replace all instances of "foo" in the $1 mirror
with "bar". This uses |substitute()| behind the scenes.
Note: Just like with tab stops, braces can be used to avoid ambiguities: ${1}2
is a mirror of the first tab stop followed by a 2. Version 0 of the snippet
parser offers no way to resolve such ambiguities.
As an example, >
snippet for snippet for
for (${2:i}=0; $2 < ${1:count}; $2++) { for ($1 = ${2:start}; ${1:i} < ${3:end}; $1${4:++}) {
${4} ${0:/* code */}
} }
This will cause "count" to first be selected and change if the user starts < *SnipMate-eval*
typing. When <tab> is pressed, the "i" in ${2}'s position will be selected; Expression Evaluation~
all $2 variables will default to "i" and automatically be updated if the user
starts typing.
NOTE: "$#" syntax is used only for mirrors, not for tab stops as in TextMate. Snippets can contain Vim script expressions that are evaluated as the snippet
is expanded. Expressions are specified inside backticks: >
Mirrors can also be used inside of placeholders. For instance: >
snippet opt
<option value="${1:option}">${2:$1}</option>
Will, as usual, cause "option" to first be selected and update all the $1
variables if the user starts typing. Since one of these variables is inside of
${2}, this text will then be used as a placeholder for the next tab stop,
allowing the user to change it if he wishes.
To copy a value throughout a snippet without supplying default text, simply
use the "${#:}" construct without the text, e.g.: >
snippet foo
${1:}bar$1
< *SnipMate-visual*
There is a special placeholder called {VISUAL}. If you visually select text,
then press <Tab> Vim switches to insert mode. The next snippet you'll expand
will replace {VISUAL} by the text which was selected previously.
*SnipMate-eval*
Interpolated Vim Script~
Snippets can also contain Vim script commands that are executed (via |eval()|)
when the snippet is inserted. Commands are given inside backticks (`...`); for
TextMates's functionality, use the |system()| function. E.g.: >
snippet date snippet date
`system("date +%Y-%m-%d")` `strftime("%Y-%m-%d")`
will insert the current date, assuming you are on a Unix system. Note that you
can also (and should) use |strftime()| for this example.
Filename([{expr}] [, {defaultText}]) *SnipMate-Filename()* Filename([{expr}] [, {defaultText}]) *SnipMate-Filename()*
@ -336,6 +398,26 @@ empty string if it hasn't. The second returns the filename if it's been named,
and "name" if it hasn't. The third returns the filename followed by "_foo" if and "name" if it hasn't. The third returns the filename followed by "_foo" if
it has been named, and an empty string if it hasn't. it has been named, and an empty string if it hasn't.
*SnipMate-visual*
The VISUAL Stop~
While tab stops have numeric IDs, a special one exists with the ID 'VISUAL'.
When a snippet is expanded, if any text had been grabbed with the
snipMateVisual mapping (see |SnipMate-mappings|), all instances of the VISUAL
stop will be replaced with it. Both transformations as well as a default
placeholder can be used with the VISUAL stop.
Note: Both $VISUAL and ${VISUAL} are valid in version 1 of the snippet parser.
In version 0, only {VISUAL} is valid (without the $), and neither
transformations nor a default placeholder can be used.
Example: >
snippet div
<div>
${0:${VISUAL:<!-- content -->}}
</div>
============================================================================== ==============================================================================
SNIPPET SOURCES *SnipMate-snippet-sources* SNIPPET SOURCES *SnipMate-snippet-sources*
@ -398,19 +480,13 @@ See |SnipMate-syntax| for more details about all possible relative locations
to 'rtp' can be found in. to 'rtp' can be found in.
============================================================================== ==============================================================================
DISADVANTAGES *SnipMate-disadvantages* KNOWN ISSUES *SnipMate-known-issues*
SnipMate.vim currently has the following disadvantages to TextMate's snippets: SnipMate.vim currently has the following disadvantages to TextMate's snippets:
- Nested placeholders are not currently possible. E.g.: >
'<div${1: id="${2:some_id}}">${3}</div>'
< In TextMate this would first highlight ' id="some_id"', and if
you hit delete it would automatically skip ${2} and go to ${3}
on the next <tab>, but if you didn't delete it it would highlight
"some_id" first. You cannot do this in SnipMate.vim.
- Regex cannot be performed on variables, such as "${1/.*/\U&}"
- Placeholders cannot span multiple lines. - Placeholders cannot span multiple lines.
- Activating snippets in different scopes of the same file is - Activating snippets in different scopes of the same file is
not possible. not possible.
- Vim formatting with fo=t or fo=a can mess up SnipMate.
Perhaps some of these features will be added in a later release. Perhaps some of these features will be added in a later release.

View file

@ -91,9 +91,11 @@ let g:snipMate['get_snippets'] = get(g:snipMate, 'get_snippets', funcref#Functio
" List of paths where snippets/ dirs are located, or a function returning such " List of paths where snippets/ dirs are located, or a function returning such
" a list " a list
let g:snipMate['snippet_dirs'] = get(g:snipMate, 'snippet_dirs', funcref#Function('return split(&runtimepath,",")')) let g:snipMate['snippet_dirs'] = get(g:snipMate, 'snippet_dirs', split(&rtp, ','))
if type(g:snipMate['snippet_dirs']) == type([]) if type(g:snipMate['snippet_dirs']) != type([])
call map(g:snipMate['snippet_dirs'], 'expand(v:val)') echohl WarningMsg
echom "g:snipMate['snippet_dirs'] must be a List"
echohl None
endif endif
" _ is default scope added always " _ is default scope added always
@ -107,7 +109,7 @@ function! s:grab_visual()
let a_save = @a let a_save = @a
try try
normal! gv"ay normal! gv"ay
let b:snipmate_content_visual = @a let b:snipmate_visual = @a
finally finally
let @a = a_save let @a = a_save
endtry endtry

View file

@ -0,0 +1,175 @@
function! Setup(snip)
return snipMate#expandSnip(join(a:snip, "\n"), 1)
endfunction
function! s:to_be_file(expected)
return a:expected == getline(1,'$')
endfunction
function! s:to_be_in(item, list)
return !empty(filter(copy(a:list), 'v:val is a:item'))
endfunction
call vspec#customize_matcher('to_be_file', function('s:to_be_file'))
call vspec#customize_matcher('to_be_in', function('s:to_be_in'))
describe 'snippet state'
before
enew
let b:snip_state = snipmate#jumping#state()
end
after
bwipeout!
end
describe '.remove()'
it 'removes the state object'
Expect exists('b:snip_state') to_be_true
call b:snip_state.remove()
Expect exists('b:snip_state') to_be_false
end
it 'removes snippet related autocommands'
function! ReadAutocmds()
redir => autocmds
0verbose au snipmate_changes * <buffer>
redir END
return split(autocmds, "\n")
endfunction
aug snipmate_changes
au CursorMoved,CursorMovedI <buffer> echo 'event'
aug END
Expect len(ReadAutocmds()) > 1
call b:snip_state.remove()
Expect len(ReadAutocmds()) == 1
end
end
describe '.find_next_stop()'
it 'increments/decrements the stop_no'
let b:snip_state.stops = { 1 : {}, 2 : {} }
let b:snip_state.stop_no = 1
let b:snip_state.stop_count = 4
call b:snip_state.find_next_stop(0)
Expect b:snip_state.stop_no == 2
call b:snip_state.find_next_stop(1)
Expect b:snip_state.stop_no == 1
end
it 'continues iterating if the next/previous stop does not exist'
let b:snip_state.stops = { 3 : {} }
let b:snip_state.stop_count = 6
let b:snip_state.stop_no = 1
call b:snip_state.find_next_stop(0)
Expect b:snip_state.stop_no == 3
let b:snip_state.stop_no = 5
call b:snip_state.find_next_stop(1)
Expect b:snip_state.stop_no == 3
end
it 'does something at the ends'
"
end
end
describe '.remove_nested()'
it 'removes nested mirrors and only nested mirrors'
let mirror = { 'line' : 0 }
let b:snip_state.stops = { 1 : { 'placeholder' : [[2, mirror]] },
\ 2 : { 'mirrors' : [mirror, {}] } }
call b:snip_state.remove_nested(1)
Expect len(b:snip_state.stops[2].mirrors) == 1
Expect b:snip_state.stops[2].mirrors[0] isnot mirror
end
it 'removes nested stops'
let stop = [2, 'abc']
let b:snip_state.stops = { 1 : { 'placeholder' : [stop] },
\ 2 : { 'placeholder' : stop[1:1] } }
call b:snip_state.remove_nested(1)
Expect len(b:snip_state.stops) == 1
Expect keys(b:snip_state.stops) == ['1']
end
end
describe '.find_update_objects()'
it 'finds mirrors/stops on the same line and after cur_stop'
let b:snip_state.stops = {
\ 1 : { 'line' : 1, 'col' : 5,
\ 'placeholder' : ['x'] },
\ 2 : { 'line' : 1, 'col' : 7,
\ 'mirrors' : [{ 'line' : 1, 'col' : 7 }] }
\ }
let stop = b:snip_state.stops[1]
call b:snip_state.find_update_objects(stop)
for obj in stop.update_objects
Expect obj to_be_in [ b:snip_state.stops[2],
\ b:snip_state.stops[2].mirrors[0] ]
endfor
end
it 'finds mirrors/stops on the same line and after cur_stop mirrors'
let b:snip_state.stops = {
\ 1 : { 'line' : 1, 'col' : 5,
\ 'mirrors' : [{ 'line' : 2, 'col' : 5 }],
\ 'placeholder' : ['x'] },
\ 2 : { 'line' : 2, 'col' : 7,
\ 'mirrors' : [{ 'line' : 2, 'col' : 7 }] }
\ }
let stop = b:snip_state.stops[1]
call b:snip_state.find_update_objects(stop)
for obj in stop.update_objects
Expect obj to_be_in [ b:snip_state.stops[2],
\ b:snip_state.stops[2].mirrors[0] ]
endfor
end
it 'ignores mirrors/stops on other lines'
let b:snip_state.stops = {
\ 1 : { 'line' : 2, 'col' : 5,
\ 'placeholder' : ['x'] },
\ 2 : { 'line' : 1, 'col' : 7,
\ 'mirrors' : [{ 'line' : 1, 'col' : 7 }] },
\ 3 : { 'line' : 3, 'col' : 7,
\ 'mirrors' : [{ 'line' : 3, 'col' : 7 }] }
\ }
let stop = b:snip_state.stops[1]
call b:snip_state.find_update_objects(stop)
Expect empty(stop.update_objects) to_be_true
end
it 'ignores mirrors/stops on the same line but before cur_stop/mirrors'
let b:snip_state.stops = {
\ 1 : { 'line' : 1, 'col' : 5,
\ 'mirrors' : [{ 'line' : 2, 'col' : 5 }],
\ 'placeholder' : ['x'] },
\ 2 : { 'line' : 1, 'col' : 1,
\ 'mirrors' : [{ 'line' : 2, 'col' : 1 }] },
\ 3 : { 'line' : 2, 'col' : 3,
\ 'mirrors' : [{ 'line' : 1, 'col' : 3 }] },
\ }
let stop = b:snip_state.stops[1]
call b:snip_state.find_update_objects(stop)
Expect empty(stop.update_objects) to_be_true
end
end
end

View file

@ -0,0 +1,116 @@
describe 'snippet parser'
before
function! Parse(snippet, ...)
let [snip, stops] = snipmate#parse#snippet(a:snippet)
return a:0 ? [snip, stops] : snip
endfunction
let b:snipmate_visual = 'testvisual'
end
it 'parses numeric $id and ${id} vars as [id] lists'
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']
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)
function! InstanceFound(list)
return !empty(filter(copy(b:stops[a:list[0]].instances),
\ 'v:val is a:list'))
endfunction
function! CheckList(list)
for item in a:list
if type(item) == type([])
Expect InstanceFound(item) to_be_true
call CheckList(item)
endif
unlet item " E732
endfor
endfunction
call CheckList(snip)
end
it 'parses mirror substitutions ${n/pat/sub} as [n, {...}]'
let expect = [[1, { 'pat' : 'abc', 'sub' : 'def' }]]
Expect Parse('${1/abc/def}') == expect
let expect[0][1].flags = ''
Expect Parse('${1/abc/def/}') == expect
let expect[0][1].flags = 'g'
Expect Parse('${1/abc/def/g}') == expect
end
it 'parses vars with placeholders as [id, placeholder] lists'
Expect Parse('${1:abc}') == [[1, 'abc']]
end
it 'evaluates backtick expressions'
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]
end
it 'converts tabs according to &et, &sts, &sw'
" &noet -> leave tabs alone
setl noet
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"]
setl et sts=0 sw=3
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"]
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`']
end
it 'splits text at newlines'
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']
end
it 'expands $VISUAL placeholders with any indents'
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"]
end
end

View file

@ -0,0 +1,20 @@
#!/bin/sh
tmp="$(mktemp || tmpfile)"
vim -Es $tmp <<- EOF
source ~/.vimrc
%delete _
call append(0, split(&rtp, ','))
delete _
wq
EOF
rtp="$(grep -iE 'vspec|snipmate|tlib|mw-utils' < $tmp | grep -v after)"
vspec="$(grep -iE 'vspec' < $tmp | grep -v after)"
test_files="${*:-parser jumping}"
for test in $test_files; do
$vspec/bin/vspec $rtp ${test%%.vim}.vim
done
rm $tmp

View file

@ -5,12 +5,12 @@
priority -50 priority -50
snippet pat "Case:Receive:Try Clause" snippet pat "Case:Receive:Try Clause"
${1:pattern}${2: when ${3:guard}} ->; ${1:pattern}${2: when ${3:guard}} ->
${4:body} ${4:body}
endsnippet endsnippet
snippet beh "Behaviour Directive" snippet beh "Behaviour Directive" b
-behaviour (${1:behaviour}). -behaviour(${1:behaviour}).
endsnippet endsnippet
snippet case "Case Expression" snippet case "Case Expression"
@ -20,12 +20,12 @@ case ${1:expression} of
end end
endsnippet endsnippet
snippet def "Define Directive" snippet def "Define Directive" b
-define (${1:macro}${2: (${3:param})}, ${4:body}). -define(${1:macro}${2: (${3:param})}, ${4:body}).
endsnippet endsnippet
snippet exp "Export Directive" snippet exp "Export Directive" b
-export ([${1:function}/${2:arity}]). -export([${1:function}/${2:arity}]).
endsnippet endsnippet
snippet fun "Fun Expression" snippet fun "Fun Expression"
@ -36,7 +36,7 @@ end
endsnippet endsnippet
snippet fu "Function" snippet fu "Function"
${1:function} (${2:param})${3: when ${4:guard}} -> ${1:function}(${2:param})${3: when ${4:guard}} ->
${5:body} ${5:body}
endsnippet endsnippet
@ -47,24 +47,24 @@ if
end end
endsnippet endsnippet
snippet ifdef "Ifdef Directive" snippet ifdef "Ifdef Directive" b
-ifdef (${1:macro}). -ifdef(${1:macro}).
endsnippet endsnippet
snippet ifndef "Ifndef Directive" snippet ifndef "Ifndef Directive" b
-ifndef (${1:macro}). -ifndef(${1:macro}).
endsnippet endsnippet
snippet imp "Import Directive" snippet imp "Import Directive" b
-import (${1:module}, [${2:function}/${3:arity}]). -import(${1:module}, [${2:function}/${3:arity}]).
endsnippet endsnippet
snippet inc "Include Directive" snippet inc "Include Directive" b
-include ("${1:file}"). -include("${1:file}").
endsnippet endsnippet
snippet mod "Module Directive" snippet mod "Module Directive" b
-module (${1:`!p snip.rv = snip.basename or "module"`}). -module(${1:`!p snip.rv = snip.basename or "module"`}).
endsnippet endsnippet
snippet rcv "Receive Expression" snippet rcv "Receive Expression"
@ -77,8 +77,8 @@ ${6:after
end end
endsnippet endsnippet
snippet rec "Record Directive" snippet rec "Record Directive" b
-record (${1:record}, {${2:field}${3: = ${4:value}}}). -record(${1:record}, {${2:field}${3: = ${4:value}}}).
endsnippet endsnippet
snippet try "Try Expression" snippet try "Try Expression"
@ -93,8 +93,16 @@ ${13:after
end end
endsnippet endsnippet
snippet undef "Undef Directive" snippet undef "Undef Directive" b
-undef (${1:macro}). -undef(${1:macro}).
endsnippet
snippet || "List Comprehension"
[${1:X} || ${2:X} <- ${3:List}${4:, gen}]
endsnippet
snippet gen "Generator Expression"
${1:X} <- ${2:List}${3:, gen}
endsnippet endsnippet
# vim:ft=snippets: # vim:ft=snippets:

View file

@ -17,7 +17,7 @@ snippet label_and_input
endsnippet endsnippet
snippet input snippet input
<input type="${1:text}" value="${2}" name="${3}"${4: id="${5:$3}}/>${7} <input type="${1:text}" value="${2}" name="${3}"${4: id="${5:$3}"}/>${7}
endsnippet endsnippet
snippet submit snippet submit

View file

@ -102,44 +102,54 @@ var_export(${1});${2}
endsnippet endsnippet
snippet getter "PHP Class Getter" b snippet getter "PHP Class Getter" b
/* /**
* Getter for $1 * Getter for $1
*
* ${2:return string}
*/ */
public function get${1/\w+\s*/\u$0/}() public function get${1/\w+\s*/\u$0/}()
{ {
return $this->$1;$2 return $this->$1;$3
} }
$4 $0
endsnippet endsnippet
snippet setter "PHP Class Setter" b snippet setter "PHP Class Setter" b
/* /**
* Setter for $1 * Setter for $1
*
* @param ${2:string} $$1
* @return ${3:`!p snip.rv=snip.basename`}
*/ */
public function set${1/\w+\s*/\u$0/}($$1) public function set${1/\w+\s*/\u$0/}(${4:${2/(void|string|int|integer|double|float|object|boolear|null|mixed|number|resource)|(.*)/(?1::$2 )/}}$$1)
{ {
$this->$1 = $$1;$3 $this->$1 = $$1;$5
${4:return $this;} ${6:return $this;}
} }
$0 $0
endsnippet endsnippet
snippet gs "PHP Class Getter Setter" b snippet gs "PHP Class Getter Setter" b
/* /**
* Getter for $1 * Getter for $1
*
* return ${2:string}
*/ */
public function get${1/\w+\s*/\u$0/}() public function get${1/\w+\s*/\u$0/}()
{ {
return $this->$1;$2 return $this->$1;$3
} }
/* /**
* Setter for $1 * Setter for $1
*
* @param $2 $$1
* @return ${4:`!p snip.rv=snip.basename`}
*/ */
public function set${1/\w+\s*/\u$0/}($$1) public function set${1/\w+\s*/\u$0/}(${5:${2/(void|string|int|integer|double|float|object|boolear|null|mixed|number|resource)|(.*)/(?1::$2 )/}}$$1)
{ {
$this->$1 = $$1;$3 $this->$1 = $$1;$6
${4:return $this;} ${7:return $this;}
} }
$0 $0
endsnippet endsnippet

View file

@ -7,33 +7,30 @@ snippet l_rsc "Laravel resource controller" b
* \date `!v strftime('%d-%m-%y')` * \date `!v strftime('%d-%m-%y')`
*/ */
class $1 { class $1 extends ${3: BaseController} {
public function index() { function __construct() {
${3}
}
public function create() {
${4} ${4}
} }
public function index() {
}
public function create() {
}
public function store($id) { public function store($id) {
${5}
} }
public function show($id) { public function show($id) {
${6}
} }
public function edit($id) { public function edit($id) {
${7}
} }
public function update($id) { public function update($id) {
${8}
} }
public function destroy($id) { public function destroy($id) {
${9}
} }
} }
endsnippet endsnippet
@ -117,7 +114,7 @@ namespace $1;
class $2 extends \Eloquent { class $2 extends \Eloquent {
protected $table = '${4:`!p snip.rv = t[2].lower()`}'; protected $table = '${4:`!p snip.rv = t[2].lower()`}';
public $timestamps = '${5:false}'; public $timestamps = ${5:false};
protected $hidden = array(${6}); protected $hidden = array(${6});
@ -196,7 +193,7 @@ snippet l_r "Laravel Repository" b
/*! /*!
* \namespace ${1:Repositories\\${2}} * \namespace ${1:Repositories\\${2}}
* \class ${3:`!v expand('%:t:r')`} * \class ${3:`!v expand('%:t:r')`}
* \implements ${4:BaseRepositoryInterface} * \implements ${4:$3RepositoryInterface}
* *
* \author ${5:`!v g:snips_author`} * \author ${5:`!v g:snips_author`}
* \date `!v strftime('%d-%m-%y')` * \date `!v strftime('%d-%m-%y')`
@ -204,8 +201,8 @@ snippet l_r "Laravel Repository" b
namespace $1; namespace $1;
class $3 extends \\$1 implements $4 { class $3 extends \\${6} implements $4 {
${6} ${7}
} }
endsnippet endsnippet

View file

@ -29,7 +29,6 @@ snippet GPL2
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>. along with this program; if not, see <http://www.gnu.org/licenses/>.
${0} ${0}
snippet LGPL2 snippet LGPL2
${1:One line to give the program's name and a brief description.} ${1:One line to give the program's name and a brief description.}
@ -47,7 +46,6 @@ snippet LGPL2
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this library; if not, see <http://www.gnu.org/licenses/>. along with this library; if not, see <http://www.gnu.org/licenses/>.
${0} ${0}
snippet GPL3 snippet GPL3
${1:one line to give the program's name and a brief description.} ${1:one line to give the program's name and a brief description.}
@ -65,7 +63,6 @@ snippet GPL3
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
${0} ${0}
snippet LGPL3 snippet LGPL3
${1:One line to give the program's name and a brief description.} ${1:One line to give the program's name and a brief description.}
@ -83,7 +80,6 @@ snippet LGPL3
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this library; if not, see <http://www.gnu.org/licenses/>. along with this library; if not, see <http://www.gnu.org/licenses/>.
${0} ${0}
snippet AGPL3 snippet AGPL3
${1:one line to give the program's name and a brief description.} ${1:one line to give the program's name and a brief description.}
@ -101,7 +97,6 @@ snippet AGPL3
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
${0} ${0}
snippet GMGPL linking exception snippet GMGPL linking exception
As a special exception, if other files instantiate generics from As a special exception, if other files instantiate generics from
@ -140,7 +135,6 @@ snippet BSD2
The views and conclusions contained in the software and documentation The views and conclusions contained in the software and documentation
are those of the authors and should not be interpreted as representing are those of the authors and should not be interpreted as representing
official policies, either expressedor implied, of $2. official policies, either expressedor implied, of $2.
${0} ${0}
snippet BSD3 snippet BSD3
${1:one line to give the program's name and a brief description} ${1:one line to give the program's name and a brief description}
@ -168,7 +162,6 @@ snippet BSD3
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
${0} ${0}
snippet BSD4 snippet BSD4
${1:one line to give the program's name and a brief description} ${1:one line to give the program's name and a brief description}
@ -199,7 +192,6 @@ snippet BSD4
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
${0} ${0}
snippet MIT snippet MIT
${1:one line to give the program's name and a brief description} ${1:one line to give the program's name and a brief description}
@ -222,7 +214,6 @@ snippet MIT
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
${0} ${0}
snippet APACHE snippet APACHE
${1:one line to give the program's name and a brief description} ${1:one line to give the program's name and a brief description}
@ -239,7 +230,6 @@ snippet APACHE
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
${0} ${0}
snippet BEERWARE snippet BEERWARE
${1:one line to give the program's name and a brief description} ${1:one line to give the program's name and a brief description}
@ -249,7 +239,6 @@ snippet BEERWARE
$2 wrote this file. As long as you retain this notice you $2 wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy me a beer or coffee in return this stuff is worth it, you can buy me a beer or coffee in return
${0} ${0}
snippet WTFPL snippet WTFPL
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
@ -271,5 +260,4 @@ snippet MPL2
This Source Code Form is subject to the terms of the Mozilla Public This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. file, You can obtain one at http://mozilla.org/MPL/2.0/.
${0} ${0}

View file

@ -75,6 +75,8 @@ snippet ===
`repeat('=', strlen(getline(line(".") - 1)) - strlen(getline('.')))` `repeat('=', strlen(getline(line(".") - 1)) - strlen(getline('.')))`
${0} ${0}
snippet -
- ${0}
snippet --- snippet ---
`repeat('-', strlen(getline(line(".") - 1)) - strlen(getline('.')))` `repeat('-', strlen(getline(line(".") - 1)) - strlen(getline('.')))`

View file

@ -90,7 +90,7 @@ snippet class
${0} ${0}
} }
snippet node snippet node
node '${1:`vim_snippets#Filename('', 'fqdn')`}' { node "${1:`vim_snippets#Filename('', 'fqdn')`}" {
${0} ${0}
} }
snippet case snippet case
@ -107,13 +107,21 @@ snippet if
if $${1:variable} { if $${1:variable} {
${0} ${0}
} }
snippet ifd
if defined(${1:Resource}["${2:name}"]) {
${0}
}
snippet ifnd
if !defined(${1:Resource}["${2:name}"]) {
${0}
}
snippet el snippet el
else { else {
${0} ${0}
} }
snippet ? snippet ?
? { ? {
'${1}' => ${0} "${1}" => ${0}
} }
# #
# blocks etc and general syntax sugar # blocks etc and general syntax sugar
@ -122,98 +130,98 @@ snippet [
snippet > snippet >
${1} => ${0} ${1} => ${0}
snippet p: snippet p:
'puppet://puppet/${1:module name}/${0:file name}' "puppet://puppet/${1:module name}/${0:file name}"
# #
# Functions # Functions
snippet alert snippet alert
alert('${1:message}') alert("${1:message}")
snippet crit snippet crit
crit('${1:message}') crit("${1:message}")
snippet debug snippet debug
debug('${1:message}') debug("${1:message}")
snippet defined snippet defined
defined(${1:Resource}['${2:name}']) defined(${1:Resource}["${2:name}"])
snippet emerg snippet emerg
emerg('${1:message}') emerg("${1:message}")
snippet extlookup Simple extlookup snippet extlookup Simple extlookup
extlookup('${1:variable}') extlookup("${1:variable}")
snippet extlookup Extlookup with defaults snippet extlookup Extlookup with defaults
extlookup('${1:variable}', '${2:default}') extlookup("${1:variable}", "${2:default}")
snippet extlookup Extlookup with defaults and custom data file snippet extlookup Extlookup with defaults and custom data file
extlookup('${1:variable}', '${2:default}', '${3:data source}') extlookup("${1:variable}", "${2:default}", "${3:data source}")
snippet fail snippet fail
fail('${1:message}') fail("${1:message}")
snippet info snippet info
info('${1:message}') info("${1:message}")
snippet inline_template snippet inline_template
inline_template('<%= ${1} %>') inline_template("<%= ${1} %>")
snippet notice snippet notice
notice('${1:message}') notice("${1:message}")
snippet realize snippet realize
realize(${1:Resource}[${2:name}]) realize(${1:Resource}[${2:name}])
snippet regsubst snippet regsubst
regsubst(${1:hay stack}, ${2:needle}, '${3:replacement}') regsubst(${1:hay stack}, ${2:needle}, "${3:replacement}")
snippet inc snippet inc
include ${1:classname} include ${1:classname}
snippet split snippet split
split(${1:hay stack}, '${2:patten}') split(${1:hay stack}, "${2:patten}")
snippet versioncmp snippet versioncmp
versioncmp('${1:version}', '${2:version}') versioncmp("${1:version}", "${2:version}")
snippet warning snippet warning
warning('${1:message}') warning("${1:message}")
# #
# Types # Types
snippet cron snippet cron
cron { '${1:name}': cron { "${1:name}":
command => '${2}', command => "${2}",
user => '${3:root}', user => "${3:root}",
${4} => ${0}, ${4} => ${0},
} }
snippet exec snippet exec
exec { '${1:name}': exec { "${1:name}":
command => '${2:$1}', command => "${2:$1}",
user => '${3:root}', user => "${3:root}",
${4} => ${0}, ${4} => ${0},
} }
snippet user snippet user
user { '${1:user}': user { "${1:user}":
ensure => present, ensure => present,
comment => '${2:$1}', comment => "${2:$1}",
managehome => true, managehome => true,
home => '${0:/home/$1}', home => "${0:/home/$1}",
} }
snippet group snippet group
group { '${1:group}': group { "${1:group}":
ensure => ${0:present}, ensure => ${0:present},
} }
snippet host snippet host
host { '${1:hostname}': host { "${1:hostname}":
ip => ${0:127.0.0.1}, ip => ${0:127.0.0.1},
} }
snippet mailalias snippet mailalias
mailalias { '${1:localpart}': mailalias { "${1:localpart}":
recipient => '${0:recipient}', recipient => "${0:recipient}",
} }
snippet mount snippet mount
mount { '${1:destination path}': mount { "${1:destination path}":
ensure => ${2:mounted}, ensure => ${2:mounted},
device => '${0:device name or path}', device => "${0:device name or path}",
} }
snippet package snippet package
package { '${1:package name}': package { "${1:package name}":
ensure => ${0:present}, ensure => ${0:present},
} }
snippet yumrepo snippet yumrepo
yumrepo { '${1:repo name}': yumrepo { "${1:repo name}":
Descr => '${2:$1}', Descr => "${2:$1}",
enabled => ${0:1}, enabled => ${0:1},
} }
@ -223,22 +231,39 @@ snippet define
} }
snippet service snippet service
service { '${1:service}' : service { "${1:service}" :
ensure => running, ensure => running,
enable => true, enable => true,
require => [ Package['${2:package}'], File['${3:file}'], ], require => [ Package["${2:package}"], File["${3:file}"], ],
subscribe => [ File['${4:configfile1}'], File['${5:configfile2}'], Package['${6:package}'], ], subscribe => [ File["${4:configfile1}"], File["${5:configfile2}"], Package["${6:package}"], ],
} }
snippet file snippet file
file { '${1:filename}' : file { "${1:filename}" :
ensure => ${2:present}, ensure => ${2:present},
owner => '${3:root}', owner => "${3:root}",
group => '${4:root}', group => "${4:root}",
mode => '${5:0644}', mode => "${5:0644}",
source => 'puppet:///modules/${6:module}/${7:source}', source => "puppet:///modules/${6:module}/${7:source}",
content => template('/etc/puppet/templates/${8:template}'), content => template("${8:module}/${9:template}"),
alias => '${9:alias}', alias => "${10:alias}",
require => [ Package['${10:package}'], File['${11:file}'], ], require => [ Package["${11:package}"], File["${12:file}"], ],
}
snippet archive
archive { "${1:filename}" :
ensure => ${2:present},
url => "http://${3:url}",
extension => "${4:tgz}",
target => "${5:target}",
checksum => ${6:false},
src_target => "${7:/tmp}",
}
snippet firewall
firewall { "${1:comment}" :
proto => ${2:tcp},
action => ${3:accept},
port => ${4},
} }

View file

@ -135,6 +135,9 @@ snippet iem
# ipython debugger (pdbbb) # ipython debugger (pdbbb)
snippet pdbbb snippet pdbbb
import pdbpp; pdbpp.set_trace() import pdbpp; pdbpp.set_trace()
# remote python debugger (rpdb)
snippet rpdb
import rpdb; rpdb.set_trace()
# python_prompt_toolkit # python_prompt_toolkit
snippet ppt snippet ppt
from prompt_toolkit.contrib.repl import embed from prompt_toolkit.contrib.repl import embed

View file

@ -39,8 +39,9 @@ easiest to understand with some examples:
<div>Yo!*</div> dst Yo! <div>Yo!*</div> dst Yo!
Change surroundings is *cs* . It takes two arguments, a target like with Change surroundings is *cs* . It takes two arguments, a target like with
|ds|, and a replacement. Details about the second argument can be found |ds|, and a replacement. *cS* changes surroundings, placing the surrounded
below in |surround-replacements|. Once again, examples are in order. text on its own line(s) like |yS|. Details about the second argument can be
found below in |surround-replacements|. Once again, examples are in order.
Old text Command New text ~ Old text Command New text ~
"Hello *world!" cs"' 'Hello world!' "Hello *world!" cs"' 'Hello world!'

View file

@ -441,7 +441,8 @@ function! s:dosurround(...) " {{{1
endif endif
call setreg('"',keeper,regtype) call setreg('"',keeper,regtype)
if newchar != "" if newchar != ""
call s:wrapreg('"',newchar) let special = a:0 > 2 ? a:3 : 0
call s:wrapreg('"',newchar, special)
endif endif
silent exe 'norm! ""'.pcmd.'`[' silent exe 'norm! ""'.pcmd.'`['
if removed =~ '\n' || okeeper =~ '\n' || getreg('"') =~ '\n' if removed =~ '\n' || okeeper =~ '\n' || getreg('"') =~ '\n'
@ -456,11 +457,11 @@ function! s:dosurround(...) " {{{1
if newchar == "" if newchar == ""
silent! call repeat#set("\<Plug>Dsurround".char,scount) silent! call repeat#set("\<Plug>Dsurround".char,scount)
else else
silent! call repeat#set("\<Plug>Csurround".char.newchar.s:input,scount) silent! call repeat#set("\<Plug>C".(a:0 > 2 && a:3 ? "S" : "s")."urround".char.newchar.s:inpur,scount)
endif endif
endfunction " }}}1 endfunction " }}}1
function! s:changesurround() " {{{1 function! s:changesurround(...) " {{{1
let a = s:inputtarget() let a = s:inputtarget()
if a == "" if a == ""
return s:beep() return s:beep()
@ -469,7 +470,7 @@ function! s:changesurround() " {{{1
if b == "" if b == ""
return s:beep() return s:beep()
endif endif
call s:dosurround(a,b) call s:dosurround(a,b,a:0 && a:1)
endfunction " }}}1 endfunction " }}}1
function! s:opfunc(type,...) " {{{1 function! s:opfunc(type,...) " {{{1
@ -558,6 +559,7 @@ endfunction " }}}1
nnoremap <silent> <Plug>SurroundRepeat . nnoremap <silent> <Plug>SurroundRepeat .
nnoremap <silent> <Plug>Dsurround :<C-U>call <SID>dosurround(<SID>inputtarget())<CR> nnoremap <silent> <Plug>Dsurround :<C-U>call <SID>dosurround(<SID>inputtarget())<CR>
nnoremap <silent> <Plug>Csurround :<C-U>call <SID>changesurround()<CR> nnoremap <silent> <Plug>Csurround :<C-U>call <SID>changesurround()<CR>
nnoremap <silent> <Plug>CSurround :<C-U>call <SID>changesurround(1)<CR>
nnoremap <silent> <Plug>Yssurround :<C-U>call <SID>opfunc(v:count1)<CR> nnoremap <silent> <Plug>Yssurround :<C-U>call <SID>opfunc(v:count1)<CR>
nnoremap <silent> <Plug>YSsurround :<C-U>call <SID>opfunc2(v:count1)<CR> nnoremap <silent> <Plug>YSsurround :<C-U>call <SID>opfunc2(v:count1)<CR>
" <C-U> discards the numerical argument but there's not much we can do with it " <C-U> discards the numerical argument but there's not much we can do with it
@ -571,6 +573,7 @@ inoremap <silent> <Plug>ISurround <C-R>=<SID>insert(1)<CR>
if !exists("g:surround_no_mappings") || ! g:surround_no_mappings if !exists("g:surround_no_mappings") || ! g:surround_no_mappings
nmap ds <Plug>Dsurround nmap ds <Plug>Dsurround
nmap cs <Plug>Csurround nmap cs <Plug>Csurround
nmap cS <Plug>CSurround
nmap ys <Plug>Ysurround nmap ys <Plug>Ysurround
nmap yS <Plug>YSurround nmap yS <Plug>YSurround
nmap yss <Plug>Yssurround nmap yss <Plug>Yssurround