documentation, pull-requests fixes

This commit is contained in:
Stanislav Seletskiy 2015-04-16 11:31:12 +06:00
parent 0beefd4a19
commit 66bc2e8f6e
4 changed files with 114 additions and 15 deletions

View File

@ -653,6 +653,11 @@ The options currently supported are: >
Without this option empty lines in snippets definition will have Without this option empty lines in snippets definition will have
indentation too. indentation too.
e Context snippets - With this option expansion of snippet can be
controlled not only by previous characters in line, but by any given python
expression. This option can be specified along with other options,
like 'b'. See |UltiSnips-context-snippets| for more info.
The end line is the 'endsnippet' keyword on a line by itself. > The end line is the 'endsnippet' keyword on a line by itself. >
endsnippet endsnippet
@ -818,6 +823,7 @@ The variables automatically defined in python code are: >
t - The values of the placeholders, t[1] is the text of ${1}, and so on t - The values of the placeholders, t[1] is the text of ${1}, and so on
snip - UltiSnips.TextObjects.SnippetUtil object instance. Has methods that snip - UltiSnips.TextObjects.SnippetUtil object instance. Has methods that
simplify indentation handling. simplify indentation handling.
context - Result of context condition. See |UltiSnips-context-snippets|.
The 'snip' object provides the following methods: > The 'snip' object provides the following methods: >
@ -1293,6 +1299,96 @@ clearsnippets trigger1 trigger2
------------------- SNAP ------------------- ------------------- SNAP -------------------
4.9 Context snippets *UltiSnips-context-snippets*
Context snippets can be enabled by using 'e' option in snippet definition.
In that case snippet should be defined using this syntax: >
snippet tab_trigger "description" "expression" options
'expression' can be any python expression. If 'expression' evaluates to
'True', then this snippet will be chosen for expansion. 'expression' must be
wrapped with double-quotes.
Following python modules are automatically imported: 're', 'os', 'vim',
'string', 'random'.
Also, variables are declared in local scope for use in expression: >
'window' - alias for 'vim.current.window'
'buffer' - alias for 'vim.current.window.buffer'
'line' and 'column' - aliases for cursor position
Keep in mind, that lines in vim numbered from 1, and lists in python starts
from 0, so to access current line you need to use 'line-1' expression.
------------------- SNIP -------------------
snippet r "return" "re.match('^\s+if err ', buffer[line-2])" be
return err
endsnippet
------------------- SNAP -------------------
That snippet will expand to 'return err' only if previous line is starting
from 'if err' prefix.
Note: context snippets prioritized over non-context ones. So, if there are
two snippets with the same trigger, and one of them is context snippet and
it's expression evaluates to 'True', then context snippet will be used for
expansion and first will be ignored.
------------------- SNIP -------------------
snippet i "if ..." b
if $1 {
$2
}
endsnippet
snippet i "if err != nil" "re.match('^\s+[^=]*err\s*:?=', buffer[line-2])" be
if err != nil {
$1
}
endsnippet
------------------- SNAP -------------------
That snippet will expand into 'if err != nil' if previous line will
match 'err :=' prefix, otherwise default 'if' snippet will be expanded.
It's good idea to move context conditions to separate library, so it can be
used with other UltiSnips user. In that case, library should be imported
using 'global' keyword, like this:
------------------- SNIP -------------------
global !p
import my_utils
endglobal
snippet , "return ..., nil/err" "my_utils.is_return_argument(buffer, line, column)" ie
, `!p if my_utils.is_in_err_condition():
snip.rv = "err"
else:
snip.rv = "nil"`
endsnippet
------------------- SNAP -------------------
That snippet will expand only if cursor is located in the return statement,
and then it will expand either to 'err' or to 'nil' depending in which 'if'
statement it's located. 'is_return_argument' and 'is_in_err_condition' are
part of custom python library which is called 'my_utils' in this example.
Context condition can return any value which python can use as
condition in it's 'if' statement, and if it's considired 'True', then snippet
will be expanded. Moreover, result of condition will be accessed in the
'context' variable:
------------------- SNIP -------------------
snippet + "var +=" "re.match('\s*(.*?)\s*:?=', buffer[line-2])" ie
`!p snip.rv = context.group(1)` += $1
endsnippet
------------------- SNAP -------------------
That snippet will expand to 'var1 +=' after line, which begins from 'var1 :='.
============================================================================== ==============================================================================
5. UltiSnips and Other Plugins *UltiSnips-other-plugins* 5. UltiSnips and Other Plugins *UltiSnips-other-plugins*

View File

@ -4,6 +4,7 @@
"""Snippet representation after parsing.""" """Snippet representation after parsing."""
import re import re
import vim import vim
from UltiSnips import _vim from UltiSnips import _vim
@ -44,7 +45,7 @@ class SnippetDefinition(object):
_TABS = re.compile(r"^\t*") _TABS = re.compile(r"^\t*")
def __init__(self, priority, trigger, value, description, def __init__(self, priority, trigger, value, description,
options, globals, location, context=None): options, globals, location, context):
self._priority = int(priority) self._priority = int(priority)
self._trigger = as_unicode(trigger) self._trigger = as_unicode(trigger)
self._value = as_unicode(value) self._value = as_unicode(value)
@ -90,17 +91,17 @@ class SnippetDefinition(object):
code = "\n".join([ code = "\n".join([
'import re, os, vim, string, random', 'import re, os, vim, string, random',
'\n'.join(self._globals.get('!p', [])).replace('\r\n', '\n'), '\n'.join(self._globals.get('!p', [])).replace('\r\n', '\n'),
'ctx["match"] = ' + self._context_code, 'context["match"] = ' + self._context_code,
'' ''
]) ])
context = {'match': False} context = {'match': False}
locals = { locals = {
'ctx': context, 'context': context,
'w': current.window, 'window': current.window,
'b': current.buffer, 'buffer': current.buffer,
'l': current.window.cursor[0], 'line': current.window.cursor[0],
'c': current.window.cursor[1], 'column': current.window.cursor[1],
} }
exec(code, locals) exec(code, locals)

View File

@ -15,7 +15,8 @@ class SnipMateSnippetDefinition(SnippetDefinition):
def __init__(self, trigger, value, description, location): def __init__(self, trigger, value, description, location):
SnippetDefinition.__init__(self, self.SNIPMATE_SNIPPET_PRIORITY, SnippetDefinition.__init__(self, self.SNIPMATE_SNIPPET_PRIORITY,
trigger, value, description, '', {}, location) trigger, value, description, '', {}, location,
None)
def instantiate(self, snippet_instance, initial_text, indent): def instantiate(self, snippet_instance, initial_text, indent):
parse_and_instantiate(snippet_instance, initial_text, indent) parse_and_instantiate(snippet_instance, initial_text, indent)

View File

@ -72,12 +72,11 @@ def _handle_snippet_or_global(filename, line, lines, python_globals, priority):
opts = words[-1] opts = words[-1]
remain = remain[:-len(opts) - 1].rstrip() remain = remain[:-len(opts) - 1].rstrip()
if 'x' in opts: context = None
if 'e' in opts:
left = remain[:-1].rfind('"') left = remain[:-1].rfind('"')
if left != -1 and left != 0: if left != -1 and left != 0:
context, remain = remain[left:].strip('"'), remain[:left] context, remain = remain[left:].strip('"'), remain[:left]
else:
context = None
# Get and strip description if it exists # Get and strip description if it exists
remain = remain.strip() remain = remain.strip()
@ -111,10 +110,12 @@ def _handle_snippet_or_global(filename, line, lines, python_globals, priority):
if snip == 'global': if snip == 'global':
python_globals[trig].append(content) python_globals[trig].append(content)
elif snip == 'snippet': elif snip == 'snippet':
return 'snippet', (UltiSnipsSnippetDefinition(priority, trig, content, definition = UltiSnipsSnippetDefinition(
priority, trig, content,
descr, opts, python_globals, descr, opts, python_globals,
'%s:%i' % (filename, start_line_index), '%s:%i' % (filename, start_line_index),
context),) context)
return 'snippet', (definition,)
else: else:
return 'error', ("Invalid snippet type: '%s'" % snip, lines.line_index) return 'error', ("Invalid snippet type: '%s'" % snip, lines.line_index)