2009-07-21 04:21:05 -04:00
|
|
|
" File: UltiSnips.vim
|
|
|
|
" Author: Holger Rapp <SirVer@gmx.de>
|
|
|
|
" Description: The Ultimate Snippets solution for Vim
|
|
|
|
" Last Modified: July 21, 2009
|
|
|
|
"
|
|
|
|
" Testing Info: {{{
|
A "clearsnippets" feature
=========================
It's difficult for the user to control which of the default
bundled snippets are active in his environment. The
'runtimepath' variable must be set to the root of the ultisnips
installation, which brings in all of the bundled snippets.
Though the user may individually override the definition of the
bundled snippets using the "!" flag, the method has a couple of
problems:
- There's no way to remove a snippet, only to override it (and
each snippet must be overridden individually).
- The "!" flag currently doesn't remove the overridden snippets
from the "list snippets" command.
It might be considered a feature that "!" doesn't actually
remove the snippets from the "list snippets" command, though
perhaps that's an unintended effect. In any case, it would be
more convenient to allow the user to selectively remove the
bundled snippets from his environment.
A patch is provided in the following branch to address these problems:
http://code.launchpad.net/~drmikehenry/ultisnips/clearsnippets
The branch's primary purpose is the addition of a
"clearsnippets" command that may be placed in a user's
~/.vim/UltiSnips/ft.snippets file. The user may clear all
lower-priority snippet for that file type with the line:
clearsnippets
Alternatively, he may clear individual snippets by listing their
triggers:
clearsnippets trigger1 trigger2
A few changes were made to the testing system as part of the
incorporation of this new feature. These changes include:
- The "extends" directive is now supported on multiple lines
throughout file.
- A completely empty .snippets file is now possible.
- The test.py scripts now handles most of the vim setup,
simplifying the running of the tests. The invocation of Vim
now reduces to:
vim -u NONE
Instructions for running the tests are included at top of
test.py, where they should be more visible to interested
users; UltiSnips.vim now just points to test.py's
instructions.
- A new function vim_quote() encodes an arbitrary string into a
singly-quoted Vim string, with embedded quotes escaped.
- SnippetsFileParser() now allows file_data to be passed
directly for unit testing, avoiding the need to create files
in the filesystem for test purposes.
- A new _error() function reports errors to the user. At
runtime, this function uses :echo_err in general, but also can
append error text to current buffer to check for expected
errors during unit tests.
- Added error checks to snippets file parsing, along with unit
tests for the parsing.
- Increased retries from 2 to 4 (on my system, occasionally the
timing still causes tests to fail).
2009-09-08 20:15:10 -04:00
|
|
|
" See directions at the top of the test.py script located one
|
|
|
|
" directory above this file.
|
2009-07-21 04:21:05 -04:00
|
|
|
" }}}
|
2009-07-04 10:08:14 -04:00
|
|
|
|
2009-07-26 11:42:40 -04:00
|
|
|
if exists('did_UltiSnips_vim') || &cp || version < 700 || !has("python")
|
A "clearsnippets" feature
=========================
It's difficult for the user to control which of the default
bundled snippets are active in his environment. The
'runtimepath' variable must be set to the root of the ultisnips
installation, which brings in all of the bundled snippets.
Though the user may individually override the definition of the
bundled snippets using the "!" flag, the method has a couple of
problems:
- There's no way to remove a snippet, only to override it (and
each snippet must be overridden individually).
- The "!" flag currently doesn't remove the overridden snippets
from the "list snippets" command.
It might be considered a feature that "!" doesn't actually
remove the snippets from the "list snippets" command, though
perhaps that's an unintended effect. In any case, it would be
more convenient to allow the user to selectively remove the
bundled snippets from his environment.
A patch is provided in the following branch to address these problems:
http://code.launchpad.net/~drmikehenry/ultisnips/clearsnippets
The branch's primary purpose is the addition of a
"clearsnippets" command that may be placed in a user's
~/.vim/UltiSnips/ft.snippets file. The user may clear all
lower-priority snippet for that file type with the line:
clearsnippets
Alternatively, he may clear individual snippets by listing their
triggers:
clearsnippets trigger1 trigger2
A few changes were made to the testing system as part of the
incorporation of this new feature. These changes include:
- The "extends" directive is now supported on multiple lines
throughout file.
- A completely empty .snippets file is now possible.
- The test.py scripts now handles most of the vim setup,
simplifying the running of the tests. The invocation of Vim
now reduces to:
vim -u NONE
Instructions for running the tests are included at top of
test.py, where they should be more visible to interested
users; UltiSnips.vim now just points to test.py's
instructions.
- A new function vim_quote() encodes an arbitrary string into a
singly-quoted Vim string, with embedded quotes escaped.
- SnippetsFileParser() now allows file_data to be passed
directly for unit testing, avoiding the need to create files
in the filesystem for test purposes.
- A new _error() function reports errors to the user. At
runtime, this function uses :echo_err in general, but also can
append error text to current buffer to check for expected
errors during unit tests.
- Added error checks to snippets file parsing, along with unit
tests for the parsing.
- Increased retries from 2 to 4 (on my system, occasionally the
timing still causes tests to fail).
2009-09-08 20:15:10 -04:00
|
|
|
finish
|
2009-07-21 04:21:05 -04:00
|
|
|
endif
|
2009-07-04 10:08:14 -04:00
|
|
|
|
2009-07-21 04:21:05 -04:00
|
|
|
" Global Variables {{{
|
|
|
|
|
|
|
|
" The trigger used to expand a snippet.
|
|
|
|
" NOTE: expansion and forward jumping can, but needn't be the same trigger
|
|
|
|
if !exists("g:UltiSnipsExpandTrigger")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsExpandTrigger = "<tab>"
|
2009-07-04 10:08:14 -04:00
|
|
|
endif
|
2009-07-21 04:21:05 -04:00
|
|
|
|
2009-08-16 12:50:14 -04:00
|
|
|
" The trigger used to display all triggers that could possible
|
|
|
|
" match in the current position.
|
|
|
|
if !exists("g:UltiSnipsListSnippets")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsListSnippets = "<c-tab>"
|
2009-08-16 12:50:14 -04:00
|
|
|
endif
|
|
|
|
|
2009-07-21 04:21:05 -04:00
|
|
|
" The trigger used to jump forward to the next placeholder.
|
|
|
|
" NOTE: expansion and forward jumping can, but needn't be the same trigger
|
|
|
|
if !exists("g:UltiSnipsJumpForwardTrigger")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsJumpForwardTrigger = "<c-j>"
|
2009-07-21 04:21:05 -04:00
|
|
|
endif
|
|
|
|
|
|
|
|
" The trigger to jump backward inside a snippet
|
|
|
|
if !exists("g:UltiSnipsJumpBackwardTrigger")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsJumpBackwardTrigger = "<c-k>"
|
2009-07-21 04:21:05 -04:00
|
|
|
endif
|
|
|
|
|
2010-08-20 03:32:12 -04:00
|
|
|
" Should UltiSnips unmap select mode mappings automagically?
|
|
|
|
if !exists("g:UltiSnipsRemoveSelectModeMappings")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsRemoveSelectModeMappings = 1
|
2010-08-20 03:32:12 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
" If UltiSnips should remove Mappings, which should be ignored
|
|
|
|
if !exists("g:UltiSnipsMappingsToIgnore")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsMappingsToIgnore = []
|
2010-08-20 03:32:12 -04:00
|
|
|
endif
|
|
|
|
|
2010-09-22 07:01:04 -04:00
|
|
|
" UltiSnipsEdit will use this variable to decide if a new window
|
|
|
|
" is opened when editing. default is "normal", allowed are also
|
|
|
|
" "vertical", "horizontal"
|
|
|
|
if !exists("g:UltiSnipsEditSplit")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsEditSplit = 'normal'
|
2010-09-22 07:01:04 -04:00
|
|
|
endif
|
|
|
|
|
2011-03-31 01:40:56 -04:00
|
|
|
" A list of directory names that are searched for snippets.
|
|
|
|
if !exists("g:UltiSnipsSnippetDirectories")
|
2011-04-27 11:37:07 -04:00
|
|
|
let g:UltiSnipsSnippetDirectories = [ "UltiSnips" ]
|
2011-03-31 01:40:56 -04:00
|
|
|
endif
|
2009-07-21 04:21:05 -04:00
|
|
|
" }}}
|
|
|
|
|
2010-09-22 07:01:04 -04:00
|
|
|
"" Global Commands {{{
|
|
|
|
|
|
|
|
" reset/reload snippets
|
|
|
|
command! -nargs=0 UltiSnipsReset :py UltiSnips_Manager.reset()
|
|
|
|
|
|
|
|
function! UltiSnipsEdit(...)
|
2011-04-27 11:37:07 -04:00
|
|
|
if a:0 == 1 && a:1 != ''
|
|
|
|
let type = a:1
|
|
|
|
elseif &filetype != ''
|
|
|
|
let type = split(&filetype, '\.')[0]
|
|
|
|
else
|
|
|
|
let type = 'all'
|
|
|
|
endif
|
|
|
|
|
|
|
|
if exists('g:UltiSnipsSnippetsDir')
|
|
|
|
let mode = 'e'
|
|
|
|
if exists('g:UltiSnipsEditSplit')
|
|
|
|
if g:UltiSnipsEditSplit == 'vertical'
|
|
|
|
let mode = 'vs'
|
|
|
|
elseif g:UltiSnipsEditSplit == 'horizontal'
|
|
|
|
let mode = 'sp'
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
exe ':'.mode.' '.g:UltiSnipsSnippetsDir.'/'.type.'.snippets'
|
|
|
|
else
|
|
|
|
for dir in g:UltiSnipsSnippetDirectories
|
|
|
|
for p in reverse(split(&runtimepath, ','))
|
|
|
|
if isdirectory(p.'/'.dir)
|
|
|
|
let g:UltiSnipsSnippetsDir = p.'/'.dir
|
|
|
|
call UltiSnipsEdit(type)
|
|
|
|
break
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
endfor
|
|
|
|
endif
|
2010-09-22 07:01:04 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
" edit snippets, default of current file type or the specified type
|
|
|
|
command! -nargs=? UltiSnipsEdit :call UltiSnipsEdit(<q-args>)
|
|
|
|
|
|
|
|
"" }}}
|
|
|
|
|
2009-07-21 04:21:05 -04:00
|
|
|
"" FUNCTIONS {{{
|
2010-07-12 08:52:12 -04:00
|
|
|
function! CompensateForPUM()
|
2011-04-27 11:37:07 -04:00
|
|
|
""" The CursorMovedI event is not triggered while the popup-menu is visible,
|
|
|
|
""" and it's by this event that UltiSnips updates its vim-state. The fix is
|
|
|
|
""" to explicitly check for the presence of the popup menu, and update
|
|
|
|
""" the vim-state accordingly.
|
|
|
|
if pumvisible()
|
|
|
|
py UltiSnips_Manager.cursor_moved()
|
|
|
|
endif
|
2010-07-12 08:52:12 -04:00
|
|
|
endfunction
|
|
|
|
|
2009-07-21 04:21:05 -04:00
|
|
|
function! UltiSnips_ExpandSnippet()
|
2011-04-27 11:37:07 -04:00
|
|
|
py UltiSnips_Manager.expand()
|
|
|
|
return ""
|
2009-07-21 04:21:05 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! UltiSnips_ExpandSnippetOrJump()
|
2011-04-27 11:37:07 -04:00
|
|
|
call CompensateForPUM()
|
|
|
|
py UltiSnips_Manager.expand_or_jump()
|
|
|
|
return ""
|
2009-07-04 06:15:12 -04:00
|
|
|
endfunction
|
|
|
|
|
2009-08-16 12:50:14 -04:00
|
|
|
function! UltiSnips_ListSnippets()
|
2011-04-27 11:37:07 -04:00
|
|
|
py UltiSnips_Manager.list_snippets()
|
|
|
|
return ""
|
2009-08-16 12:50:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2009-07-10 06:47:54 -04:00
|
|
|
function! UltiSnips_JumpBackwards()
|
2011-04-27 11:37:07 -04:00
|
|
|
call CompensateForPUM()
|
|
|
|
py UltiSnips_Manager.jump_backwards()
|
|
|
|
return ""
|
2009-07-09 09:30:23 -04:00
|
|
|
endfunction
|
|
|
|
|
2009-07-10 06:47:54 -04:00
|
|
|
function! UltiSnips_JumpForwards()
|
2011-04-27 11:37:07 -04:00
|
|
|
call CompensateForPUM()
|
|
|
|
py UltiSnips_Manager.jump_forwards()
|
|
|
|
return ""
|
2009-07-04 06:15:12 -04:00
|
|
|
endfunction
|
2010-12-18 12:07:46 -05:00
|
|
|
|
|
|
|
function! UltiSnips_AddSnippet(trigger, value, descr, options, ...)
|
2011-04-27 11:37:07 -04:00
|
|
|
" Takes the same arguments as SnippetManager.add_snippet:
|
|
|
|
" (trigger, value, descr, options, ft = "all", globals = None)
|
2010-12-18 12:07:46 -05:00
|
|
|
py << EOB
|
|
|
|
args = vim.eval("a:000")
|
|
|
|
trigger = vim.eval("a:trigger")
|
|
|
|
value = vim.eval("a:value")
|
|
|
|
descr = vim.eval("a:descr")
|
|
|
|
options = vim.eval("a:options")
|
|
|
|
|
|
|
|
UltiSnips_Manager.add_snippet(trigger, value, descr, options, *args)
|
|
|
|
EOB
|
2011-04-27 11:37:07 -04:00
|
|
|
return ""
|
2010-12-18 12:07:46 -05:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! UltiSnips_Anon(value, ...)
|
2011-04-27 11:37:07 -04:00
|
|
|
" Takes the same arguments as SnippetManager.expand_anon:
|
|
|
|
" (value, trigger="", descr="", options="", globals = None)
|
2010-12-18 12:07:46 -05:00
|
|
|
py << EOB
|
|
|
|
args = vim.eval("a:000")
|
|
|
|
value = vim.eval("a:value")
|
|
|
|
UltiSnips_Manager.expand_anon(value, *args)
|
|
|
|
EOB
|
2011-04-27 11:37:07 -04:00
|
|
|
return ""
|
2010-12-18 12:07:46 -05:00
|
|
|
endfunction
|
2009-07-04 06:15:12 -04:00
|
|
|
|
2009-07-27 03:51:09 -04:00
|
|
|
function! UltiSnips_MapKeys()
|
2011-04-27 11:37:07 -04:00
|
|
|
" Map the keys correctly
|
|
|
|
if g:UltiSnipsExpandTrigger == g:UltiSnipsJumpForwardTrigger
|
|
|
|
exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=UltiSnips_ExpandSnippetOrJump()<cr>"
|
|
|
|
exec "snoremap <silent> " . g:UltiSnipsExpandTrigger . " <Esc>:call UltiSnips_ExpandSnippetOrJump()<cr>"
|
|
|
|
else
|
|
|
|
exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=UltiSnips_ExpandSnippet()<cr>"
|
|
|
|
exec "snoremap <silent> " . g:UltiSnipsExpandTrigger . " <Esc>:call UltiSnips_ExpandSnippet()<cr>"
|
|
|
|
exec "inoremap <silent> " . g:UltiSnipsJumpForwardTrigger . " <C-R>=UltiSnips_JumpForwards()<cr>"
|
|
|
|
exec "snoremap <silent> " . g:UltiSnipsJumpForwardTrigger . " <Esc>:call UltiSnips_JumpForwards()<cr>"
|
|
|
|
endif
|
|
|
|
exec "inoremap <silent> " . g:UltiSnipsJumpBackwardTrigger . " <C-R>=UltiSnips_JumpBackwards()<cr>"
|
|
|
|
exec "snoremap <silent> " . g:UltiSnipsJumpBackwardTrigger . " <Esc>:call UltiSnips_JumpBackwards()<cr>"
|
|
|
|
exec "inoremap <silent> " . g:UltiSnipsListSnippets . " <C-R>=UltiSnips_ListSnippets()<cr>"
|
|
|
|
exec "snoremap <silent> " . g:UltiSnipsListSnippets . " <Esc>:call UltiSnips_ListSnippets()<cr>"
|
|
|
|
|
|
|
|
" Do not remap this.
|
|
|
|
snoremap <silent> <BS> <Esc>:py UltiSnips_Manager.backspace_while_selected()<cr>
|
2009-07-27 03:51:09 -04:00
|
|
|
endf
|
2009-07-21 04:21:05 -04:00
|
|
|
" }}}
|
2009-07-04 06:15:12 -04:00
|
|
|
|
2009-07-21 04:21:05 -04:00
|
|
|
"" STARTUP CODE {{{
|
2009-07-04 10:08:14 -04:00
|
|
|
|
2009-07-04 06:15:12 -04:00
|
|
|
" Expand our path
|
2009-07-04 10:08:14 -04:00
|
|
|
python << EOF
|
|
|
|
import vim, os, sys
|
|
|
|
|
2011-02-04 19:02:30 -05:00
|
|
|
new_path = vim.eval('expand("<sfile>:h")')
|
|
|
|
sys.path.append(new_path)
|
2009-07-04 10:08:14 -04:00
|
|
|
|
2009-07-10 06:47:54 -04:00
|
|
|
from UltiSnips import UltiSnips_Manager
|
2009-07-21 04:21:05 -04:00
|
|
|
UltiSnips_Manager.expand_trigger = vim.eval("g:UltiSnipsExpandTrigger")
|
|
|
|
UltiSnips_Manager.forward_trigger = vim.eval("g:UltiSnipsJumpForwardTrigger")
|
|
|
|
UltiSnips_Manager.backward_trigger = vim.eval("g:UltiSnipsJumpBackwardTrigger")
|
2009-07-04 10:08:14 -04:00
|
|
|
EOF
|
2009-07-04 06:15:12 -04:00
|
|
|
|
2009-07-10 06:47:54 -04:00
|
|
|
au CursorMovedI * py UltiSnips_Manager.cursor_moved()
|
|
|
|
au InsertEnter * py UltiSnips_Manager.entered_insert_mode()
|
2009-07-27 03:51:09 -04:00
|
|
|
|
|
|
|
call UltiSnips_MapKeys()
|
2011-04-27 11:37:07 -04:00
|
|
|
|
2009-07-21 04:21:05 -04:00
|
|
|
let did_UltiSnips_vim=1
|
|
|
|
|
|
|
|
" }}}
|
2011-04-27 11:37:07 -04:00
|
|
|
" vim: ts=8 sts=4 sw=4
|