Merged global snippets branch from Ryan

This commit is contained in:
Holger Rapp 2010-08-17 13:30:59 +02:00
commit 564c2af59c
8 changed files with 184 additions and 115 deletions

View File

@ -4,41 +4,40 @@
############## ##############
# NICE BOXES # # NICE BOXES #
############## ##############
global !p
def cs(snip):
c = '#'
cs = snip.opt("&commentstring")
if len(cs) == 3:
c = cs[0]
return c
endglobal
snippet box "A nice box with the current comment symbol" b snippet box "A nice box with the current comment symbol" b
`!p `!p
c = '#' c = cs(snip)
cs = vim.eval("&commentstring")
if len(cs) == 3:
c = cs[0]
snip.locals["c"] = c
snip.rv = (len(t[1])+4)*c snip.rv = (len(t[1])+4)*c
snip.locals["bar"] = snip.rv bar = snip.rv
snip += c + ' '`${1:content}`!p snip += c + ' '`${1:content}`!p
c = snip.locals["c"]
snip.rv = ' ' + c snip.rv = ' ' + c
snip += snip.locals["bar"]` snip += bar`
$0 $0
endsnippet endsnippet
snippet bbox "A nice box over the full width" b snippet bbox "A nice box over the full width" b
`!p `!p
c = '#' c = cs(snip)
cs = vim.eval("&commentstring") bar = 75*c
if len(cs) == 3:
c = cs[0]
snip.locals["c"] = c
snip.locals["bar"] = 75*c
snip.rv = snip.locals["bar"] snip.rv = bar
snip += c + " " + (71-len(t[1]))/2*' ' snip += c + " " + (71-len(t[1]))/2*' '
`${1:content}`!p `${1:content}`!p
c = snip.locals["c"]
a = 71-len(t[1]) a = 71-len(t[1])
snip.rv = (a/2 + a%2) * " " + " " + c snip.rv = (a/2 + a%2) * " " + " " + c
snip += snip.locals["bar"]` snip += bar`
$0 $0
endsnippet endsnippet

View File

@ -1,35 +1,28 @@
# Snippets for VIM Help Files # Snippets for VIM Help Files
global !p
def sec_title(snip, t):
file_start = snip.fn.split('.')[0]
sec_name = t[1].strip("1234567890. ").lower().replace(' ', '-')
return ("*%s-%s*" % (file_start, sec_name)).rjust(77-len(t[1]))
endglobal
snippet sec "Section marker" b snippet sec "Section marker" b
============================================================================= =============================================================================
${1:SECTION}`!p ${1:SECTION}`!p snip.rv = sec_title(snip, t)`
file_start = snip.fn.split('.')[0]
sec_name = t[1].strip("1234567890. ").lower().replace(' ', '-')
snip.rv = ("*%s-%s*" % (file_start, sec_name)).rjust(77-len(t[1]))`
$0 $0
endsnippet endsnippet
snippet ssec "Sub section marker" b snippet ssec "Sub section marker" b
${1:Subsection}`!p ${1:Subsection}`!p snip.rv = sec_title(snip, t)
file_start = snip.fn.split('.')[0]
sec_name = t[1].strip("1234567890. ").lower().replace(' ', '-')
sec_title = ("*%s-%s*" % (file_start, sec_name)).rjust(77-len(t[1]))
snip.rv = sec_title
snip += "-"*len(t[1])` snip += "-"*len(t[1])`
$0 $0
endsnippet endsnippet
snippet sssec "Subsub Section marker" b snippet sssec "Subsub Section marker" b
${1:SubSubsection}:`!p ${1:SubSubsection}:`!p snip.rv = sec_title(snip, t)`
file_start = fn.split('.')[0]
sec_name = t[1].strip("1234567890. ").lower().replace(' ', '-')
sec_title = ("*%s-%s*" % (file_start, sec_name)).rjust(77-len(t[1]))
snip.rv = sec_title`
$0 $0
endsnippet endsnippet

View File

@ -2,6 +2,14 @@
# TextMate Snippets # # TextMate Snippets #
########################################################################### ###########################################################################
global !p
def x(snip):
if snip.ft.startswith("x"):
snip.rv = '/'
else:
snip.rv = ""
endglobal
############ ############
# Doctypes # # Doctypes #
############ ############
@ -112,12 +120,12 @@ endsnippet
# HTML TAGS # # HTML TAGS #
############# #############
snippet input "Input with Label" snippet input "Input with Label"
<label for="${2:${1/[[:alpha:]]+|( )/(?1:_:\L$0)/g}}">$1</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="$5"${6: id="${7:$2}"}`!p if snip.ft.startswith("x"): snip.rv = '/'`> <label for="${2:${1/[[:alpha:]]+|( )/(?1:_:\L$0)/g}}">$1</label><input type="${3:text/submit/hidden/button}" name="${4:$2}" value="$5"${6: id="${7:$2}"}`!p x(snip)`>
endsnippet endsnippet
snippet input "XHTML <input>" snippet input "XHTML <input>"
<input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="$3"${4: id="${5:$2}"}`!p if snip.ft.startswith("x"): snip.rv = '/'`> <input type="${1:text/submit/hidden/button}" name="${2:some_name}" value="$3"${4: id="${5:$2}"}`!p x(snip)`>
endsnippet endsnippet
@ -143,7 +151,7 @@ snippet mailto "XHTML <a mailto: >"
endsnippet endsnippet
snippet base "XHTML <base>" snippet base "XHTML <base>"
<base href="$1"${2: target="$3"}`!p if snip.ft.startswith("x"): snip.rv = '/'`> <base href="$1"${2: target="$3"}`!p x(snip)`>
endsnippet endsnippet
snippet body "XHTML <body>" snippet body "XHTML <body>"
@ -166,7 +174,7 @@ snip.rv = (snip.basename or 'unnamed') + '_submit'
`}" method="${2:get}" accept-charset="utf-8"> `}" method="${2:get}" accept-charset="utf-8">
$0 $0
<p><input type="submit" value="Continue →"`!p if snip.ft.startswith("x"): snip.rv = '/'`></p> <p><input type="submit" value="Continue →"`!p x(snip)`></p>
</form> </form>
endsnippet endsnippet
@ -176,18 +184,18 @@ endsnippet
snippet head "XHTML <head>" snippet head "XHTML <head>"
<head> <head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"`!p if snip.ft.startswith("x"): snip.rv = '/'`> <meta http-equiv="Content-type" content="text/html; charset=utf-8"`!p x(snip)`>
<title>${1:`!p snip.rv = snip.basename or "Page Title"`}</title> <title>${1:`!p snip.rv = snip.basename or "Page Title"`}</title>
$0 $0
</head> </head>
endsnippet endsnippet
snippet link "XHTML <link>" snippet link "XHTML <link>"
<link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" title="${4:no title}" charset="${5:utf-8}"`!p if snip.ft.startswith("x"): snip.rv = '/'`> <link rel="${1:stylesheet}" href="${2:/css/master.css}" type="text/css" media="${3:screen}" title="${4:no title}" charset="${5:utf-8}"`!p x(snip)`>
endsnippet endsnippet
snippet meta "XHTML <meta>" snippet meta "XHTML <meta>"
<meta name="${1:name}" content="${2:content}"`!p if snip.ft.startswith("x"): snip.rv = '/'`> <meta name="${1:name}" content="${2:content}"`!p x(snip)`>
endsnippet endsnippet
snippet scriptsrc "XHTML <script src...>" snippet scriptsrc "XHTML <script src...>"
@ -227,15 +235,15 @@ endsnippet
snippet movie "Embed QT movie (movie)" b snippet movie "Embed QT movie (movie)" b
<object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab"> <object width="$2" height="$3" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab">
<param name="src" value="$1"`!p snip.locals['xhtml'] = snip.ft.startswith("x") and "/" or ""; snip.rv = snip.locals['xhtml']`> <param name="src" value="$1"`!p x(snip)`>
<param name="controller" value="$4"`!p snip.rv = snip.locals['xhtml']`> <param name="controller" value="$4"`!p x(snip)`>
<param name="autoplay" value="$5"`!p snip.rv = snip.locals['xhtml']`> <param name="autoplay" value="$5"`!p x(snip)`>
<embed src="${1:movie.mov}" <embed src="${1:movie.mov}"
width="${2:320}" height="${3:240}" width="${2:320}" height="${3:240}"
controller="${4:true}" autoplay="${5:true}" controller="${4:true}" autoplay="${5:true}"
scale="tofit" cache="true" scale="tofit" cache="true"
pluginspage="http://www.apple.com/quicktime/download/" pluginspage="http://www.apple.com/quicktime/download/"
`!p snip.rv = snip.locals['xhtml']`> `!p x(snip)`>
</object> </object>
endsnippet endsnippet

View File

@ -23,26 +23,33 @@ endsnippet
# "g:ultisnips_python_style" which, if set to "doxygen" will use doxygen # "g:ultisnips_python_style" which, if set to "doxygen" will use doxygen
# style comments in docstrings. # style comments in docstrings.
global !p
def get_args(arglist, snip):
args = [arg.split('=')[0].strip() for arg in arglist.split(',') if arg]
args = [arg for arg in args if arg and arg != "self"]
if args:
snip += ""
for arg in args:
style = snip.opt("g:ultisnips_python_style", "normal")
if style == "doxygen":
snip += "@param %s TODO" % arg
else:
snip += ":%s: TODO" % arg
return args
endglobal
snippet class "smart class" b snippet class "smart class" b
class ${1:MyClass}(${2:object}): class ${1:MyClass}(${2:object}):
""" ${3:Docstring for $1 }""" """ ${3:Docstring for $1 }"""
def __init__(self$4): def __init__(self$4):
""" ${5:TODO: Fill me in}`!p """ ${5:TODO: Fill me in}`!p
snip.rv = ""
snip >> 2 snip >> 2
args = [arg.split('=')[0].strip() for arg in t[4].split(',') if arg] args = get_args(t[4], snip)
args = [arg for arg in args if arg and arg != "self"]
if args:
snip += ""
for arg in args:
style = snip.opt("g:ultisnips_python_style", "normal")
if style == "doxygen":
snip += "@param %s TODO" % arg
else:
snip += ":%s: TODO" % arg
if args: if args:
snip += '"""' snip += '"""'
@ -65,24 +72,14 @@ def ${1:function}(${2:self}):
snip.rv = "" # Force update snip.rv = "" # Force update
snip >> 1 snip >> 1
args = [arg.split('=')[0].strip() for arg in t[2].split(',') if arg] args = get_args(t[2], snip)
args = [arg for arg in args if arg and arg != "self"]
if args:
snip += ""
snip.locals["style"] = style = snip.opt("g:ultisnips_python_style", "normal")
for arg in args:
if style == "doxygen":
snip += "@param %s TODO" % arg
else:
snip += ":%s: TODO" % arg
`${4: `${4:
`!p `!p
snip.rv = "" # Force update snip.rv = "" # Force update
style = snip.locals["style"] style = snip.opt("g:ultisnips_python_style", "normal")
if style == "doxygen": if style == "doxygen":
snip.rv = "@return" snip.rv = "@return"
else: else:

View File

@ -15,6 +15,7 @@ UltiSnips *snippet* *snippets* *UltiSnips*
4.3.1 Shellcode |UltiSnips-shellcode| 4.3.1 Shellcode |UltiSnips-shellcode|
4.3.2 VimScript |UltiSnips-vimscript| 4.3.2 VimScript |UltiSnips-vimscript|
4.3.3 Python |UltiSnips-python| 4.3.3 Python |UltiSnips-python|
4.3.4 Global Snippets |UltiSnips-globals|
4.4 Tab Stops and Placeholders |UltiSnips-tabstops| 4.4 Tab Stops and Placeholders |UltiSnips-tabstops|
4.6 Mirrors |UltiSnips-mirrors| 4.6 Mirrors |UltiSnips-mirrors|
4.7 Transformations |UltiSnips-transformations| 4.7 Transformations |UltiSnips-transformations|
@ -202,7 +203,7 @@ snippet on. The options currently supported are >
match. The regular expression MUST be surrounded like a multi-word match. The regular expression MUST be surrounded like a multi-word
trigger (see above) even if it doesn't have any spaces. The resulting trigger (see above) even if it doesn't have any spaces. The resulting
match is also passed to any python code blocks in your snippet match is also passed to any python code blocks in your snippet
definition in the as "snips.local['match']". definition as the local variable "match".
4.2 Plaintext snippets *UltiSnips-plaintext-snippets* 4.2 Plaintext snippets *UltiSnips-plaintext-snippets*
---------------------- ----------------------
@ -281,7 +282,7 @@ which can be used: >
fn - The current filename fn - The current filename
path - The complete path to the current file path - The complete path to the current file
t - The values of the placeholders, t[1] -> current text of ${1} and so on t - The values of the placeholders, t[1] -> current text of ${1} and so on
snip - Provides easy indentation handling, and snippet-local variables. snip - Provides easy indentation handling.
The snip object provides the following methods: > The snip object provides the following methods: >
@ -307,10 +308,6 @@ The snip object provides the following methods: >
The snip object provides some properties as well: > The snip object provides some properties as well: >
snip.locals:
Is a dictionary which is available to any python block inside the
snippet.
snip.rv: snip.rv:
the text that will fill this python block's position, it always starts the text that will fill this python block's position, it always starts
out as an empty string. This deprecates the "res" variable. out as an empty string. This deprecates the "res" variable.
@ -339,6 +336,7 @@ easier: >
snip += line: snip += line:
is equivalent to "snip.rv += '\n' + snip.mkline(line)" is equivalent to "snip.rv += '\n' + snip.mkline(line)"
Any variables set in a python block can be used in any following blocks.
Also, the vim, re, os, string and random modules are already imported inside Also, the vim, re, os, string and random modules are already imported inside
the snippet code. This allows for very flexible snippets. For example, the the snippet code. This allows for very flexible snippets. For example, the
following snippet mirrors the first Tab Stops value on the same line in following snippet mirrors the first Tab Stops value on the same line in
@ -352,6 +350,29 @@ endsnippet
wow<tab>Hello World -> wow<tab>Hello World ->
Hello World HELLO WORLD Hello World HELLO WORLD
4.3.4 Global Snippets: *UltiSnips-globals*
Global snippets provide a way to take common code out of snippets. Currently,
only python code is supported. The result of executing the contents of the
snippet is put into the globals of each python block in the snippet file. To
create a global snippet, you use the keyword "global" in place of "snippet",
and for python code, you use "!p" for the trigger, for example, the following
is identical to the previous example, except that "upper_right" can be reused:
------------------- SNIP -------------------
global !p
def upper_right(inp):
return (75 - 2 * len(inp))*' ' + inp.upper()
endglobal
snippet wow
${1:Text}`!p snip.rv = upper_right(t[1])`
endsnippet
------------------- SNAP -------------------
wow<tab>Hello World ->
Hello World HELLO WORLD
4.4 Tab Stops and Placeholders *UltiSnips-tabstops* *UltiSnips-placeholders* 4.4 Tab Stops and Placeholders *UltiSnips-tabstops* *UltiSnips-placeholders*
------------------------------ ------------------------------

View File

@ -705,17 +705,10 @@ class _Tabs(object):
return ts.current_text return ts.current_text
class SnippetUtil(object): class SnippetUtil(object):
""" Provides easy access to indentation, and """ Provides easy access to indentation, etc.
snippet-local variables, which can be accessed by
any PythonCode object in the snippet.
""" """
def __init__(self, initial_indent, cur="", snippet=None): def __init__(self, initial_indent, cur=""):
if snippet:
self._locals = snippet.locals
else:
self._locals = {}
self._sw = int(vim.eval("&sw")) self._sw = int(vim.eval("&sw"))
self._sts = int(vim.eval("&sts")) self._sts = int(vim.eval("&sts"))
self._et = (vim.eval("&expandtab") == "1") self._et = (vim.eval("&expandtab") == "1")
@ -842,11 +835,6 @@ class SnippetUtil(object):
""" """
return self._c return self._c
@property
def locals(self):
""" Provides snippet local variables. """
return self._locals
def opt(self, option, default=None): def opt(self, option, default=None):
""" Gets a vim variable. """ """ Gets a vim variable. """
if vim.eval("exists('%s')" % option) == "1": if vim.eval("exists('%s')" % option) == "1":
@ -884,7 +872,12 @@ class PythonCode(TextObject):
snippet = snippet._parent snippet = snippet._parent
except AttributeError: except AttributeError:
snippet = None snippet = None
self._snip = SnippetUtil(indent, snippet=snippet) self._snip = SnippetUtil(indent)
self._locals = snippet.locals
self._globals = {}
globals = snippet.globals.get("!p", [])
exec "\n".join(globals) in self._globals
# Add Some convenience to the code # Add Some convenience to the code
self._code = "import re, os, vim, string, random\n" + code self._code = "import re, os, vim, string, random\n" + code
@ -900,21 +893,23 @@ class PythonCode(TextObject):
ct = self.current_text ct = self.current_text
self._snip._reset(ct) self._snip._reset(ct)
d = { local_d = self._locals
local_d.update({
't': _Tabs(self), 't': _Tabs(self),
'fn': fn, 'fn': fn,
'path': path, 'path': path,
'cur': ct, 'cur': ct,
'res': ct, 'res': ct,
'snip' : self._snip, 'snip' : self._snip,
} })
exec self._code in d exec self._code in self._globals, local_d
if self._snip._rv_changed: if self._snip._rv_changed:
self.current_text = self._snip.rv self.current_text = self._snip.rv
else: else:
self.current_text = str(d["res"]) self.current_text = str(local_d["res"])
def __repr__(self): def __repr__(self):
return "PythonCode(%s -> %s)" % (self._start, self._end) return "PythonCode(%s -> %s)" % (self._start, self._end)
@ -945,13 +940,14 @@ class SnippetInstance(TextObject):
""" """
# TODO: for beauty sake, start and end should come before initial text # TODO: for beauty sake, start and end should come before initial text
def __init__(self, parent, indent, initial_text, start = None, end = None, last_re = None): def __init__(self, parent, indent, initial_text, start = None, end = None, last_re = None, globals = None):
if start is None: if start is None:
start = Position(0,0) start = Position(0,0)
if end is None: if end is None:
end = Position(0,0) end = Position(0,0)
self.locals = {"match" : last_re} self.locals = {"match" : last_re}
self.globals = globals
TextObject.__init__(self, parent, start, end, initial_text) TextObject.__init__(self, parent, start, end, initial_text)

View File

@ -63,6 +63,7 @@ class _SnippetsFileParser(object):
self._sm = snip_manager self._sm = snip_manager
self._ft = ft self._ft = ft
self._fn = fn self._fn = fn
self._globals = {}
if file_data is None: if file_data is None:
self._lines = open(fn).readlines() self._lines = open(fn).readlines()
else: else:
@ -96,17 +97,17 @@ class _SnippetsFileParser(object):
self._idx += 1 self._idx += 1
return self._line() return self._line()
def _parse_snippet(self): def _parse_first(self, line):
line = self._line() """ Parses the first line of the snippet definition. Returns the
snippet type, trigger, description, and options in a tuple in that
order.
"""
cdescr = "" cdescr = ""
coptions = "" coptions = ""
cs = "" cs = ""
# Ensure this is a snippet # Ensure this is a snippet
snip = line.split()[0] snip = line.split()[0]
if snip != "snippet":
self._error("Expecting 'snippet' not: %s" % snip)
# Get and strip options if they exist # Get and strip options if they exist
remain = line[len(snip):].lstrip() remain = line[len(snip):].lstrip()
@ -133,17 +134,37 @@ class _SnippetsFileParser(object):
else: else:
cs = cs[1:-1] cs = cs[1:-1]
return (snip, cs, cdescr, coptions)
def _parse_snippet(self):
line = self._line()
(snip, trig, desc, opts) = self._parse_first(line)
end = "end" + snip
cv = "" cv = ""
while self._goto_next_line(): while self._goto_next_line():
line = self._line() line = self._line()
if line.rstrip() == "endsnippet": if line.rstrip() == end:
cv = cv[:-1] # Chop the last newline cv = cv[:-1] # Chop the last newline
if cs:
self._sm.add_snippet(cs, cv, cdescr, coptions, self._ft)
break break
cv += line cv += line
else: else:
self._error("Missing 'endsnippet' for %r" % cs) self._error("Missing 'endsnippet' for %r" % trig)
return None
if not trig:
# there was an error
return None
elif snip == "global":
# add snippet contents to file globals
if trig not in self._globals:
self._globals[trig] = []
self._globals[trig].append(cv)
elif snip == "snippet":
self._sm.add_snippet(trig, cv, desc, opts, self._ft, self._globals)
else:
self._error("Invalid snippet type: '%s'" % snip)
def parse(self): def parse(self):
while self._line(): while self._line():
@ -154,7 +175,7 @@ class _SnippetsFileParser(object):
[ p.strip() for p in tail.split(',') ]) [ p.strip() for p in tail.split(',') ])
else: else:
self._error("'extends' without file types") self._error("'extends' without file types")
elif head == "snippet": elif head in ("snippet", "global"):
self._parse_snippet() self._parse_snippet()
elif head == "clearsnippets": elif head == "clearsnippets":
self._sm.clear_snippets(tail.split(), self._ft) self._sm.clear_snippets(tail.split(), self._ft)
@ -168,13 +189,14 @@ class _SnippetsFileParser(object):
class Snippet(object): class Snippet(object):
_INDENT = re.compile(r"^[ \t]*") _INDENT = re.compile(r"^[ \t]*")
def __init__(self, trigger, value, descr, options): def __init__(self, trigger, value, descr, options, globals):
self._t = trigger self._t = trigger
self._v = value self._v = value
self._d = descr self._d = descr
self._opts = options self._opts = options
self._matched = "" self._matched = ""
self._last_re = None self._last_re = None
self._globals = globals
def __repr__(self): def __repr__(self):
return "Snippet(%s,%s,%s)" % (self._t,self._d,self._opts) return "Snippet(%s,%s,%s)" % (self._t,self._d,self._opts)
@ -337,10 +359,10 @@ class Snippet(object):
if parent is None: if parent is None:
return SnippetInstance(StartMarker(start), indent, return SnippetInstance(StartMarker(start), indent,
v, last_re = self._last_re) v, last_re = self._last_re, globals = self._globals)
else: else:
return SnippetInstance(parent, indent, v, start, return SnippetInstance(parent, indent, v, start,
end, last_re = self._last_re) end, last_re = self._last_re, globals = self._globals)
class VimState(object): class VimState(object):
def __init__(self): def __init__(self):
@ -504,11 +526,11 @@ class SnippetManager(object):
if not rv: if not rv:
self._handle_failure(self.expand_trigger) self._handle_failure(self.expand_trigger)
def add_snippet(self, trigger, value, descr, options, ft = "all"): def add_snippet(self, trigger, value, descr, options, ft = "all", globals = None):
if ft not in self._snippets: if ft not in self._snippets:
self._snippets[ft] = _SnippetDictionary() self._snippets[ft] = _SnippetDictionary()
l = self._snippets[ft].add_snippet( l = self._snippets[ft].add_snippet(
Snippet(trigger, value, descr, options) Snippet(trigger, value, descr, options, globals or {})
) )
def clear_snippets(self, triggers = [], ft = "all"): def clear_snippets(self, triggers = [], ft = "all"):

41
test.py
View File

@ -739,8 +739,8 @@ class PythonCode_OptNoExists(_VimTest):
# locals # locals
class PythonCode_Locals(_VimTest): class PythonCode_Locals(_VimTest):
snippets = ("test", r"""hi `!p snip.locals["a"] = "test" snippets = ("test", r"""hi `!p a = "test"
snip.rv = "nothing"` `!p snip.rv = snip.locals["a"] snip.rv = "nothing"` `!p snip.rv = a
` End""") ` End""")
keys = """test""" + EX keys = """test""" + EX
wanted = """hi nothing test End""" wanted = """hi nothing test End"""
@ -1468,14 +1468,14 @@ class SnippetOptions_Regex_Self_TextBefore(_Regex_Self):
wanted = "a." + EX wanted = "a." + EX
class SnippetOptions_Regex_PythonBlockMatch(_VimTest): class SnippetOptions_Regex_PythonBlockMatch(_VimTest):
snippets = (r"([abc]+)([def]+)", r"""`!p m = snip.locals["match"] snippets = (r"([abc]+)([def]+)", r"""`!p m = match
snip.rv += m.group(2) snip.rv += m.group(2)
snip.rv += m.group(1) snip.rv += m.group(1)
`""", "", "r") `""", "", "r")
keys = "test cabfed" + EX keys = "test cabfed" + EX
wanted = "test fedcab" wanted = "test fedcab"
class SnippetOptions_Regex_PythonBlockNoMatch(_VimTest): class SnippetOptions_Regex_PythonBlockNoMatch(_VimTest):
snippets = (r"cabfed", r"""`!p snip.rv = snip.locals["match"] or "No match"`""") snippets = (r"cabfed", r"""`!p snip.rv = match or "No match"`""")
keys = "test cabfed" + EX keys = "test cabfed" + EX
wanted = "test No match" wanted = "test No match"
@ -1805,6 +1805,39 @@ class ParseSnippets_MultiWord_UnmatchedContainer(_VimTest):
UltiSnips: Invalid multiword trigger: '!inv snip/' in test_file(2) UltiSnips: Invalid multiword trigger: '!inv snip/' in test_file(2)
""").strip() """).strip()
class ParseSnippets_Global_Python(_VimTest):
snippets_test_file = ("all", "test_file", r"""
global !p
def tex(ins):
return "a " + ins + " b"
endglobal
snippet ab
x `!p snip.rv = tex("bob")` y
endsnippet
snippet ac
x `!p snip.rv = tex("jon")` y
endsnippet
""")
keys = "ab" + EX + "\nac" + EX
wanted = "x a bob b y\nx a jon b y"
class ParseSnippets_Global_Local_Python(_VimTest):
snippets_test_file = ("all", "test_file", r"""
global !p
def tex(ins):
return "a " + ins + " b"
endglobal
snippet ab
x `!p first = tex("bob")
snip.rv = "first"` `!p snip.rv = first` y
endsnippet
""")
keys = "ab" + EX
wanted = "x first a bob b y"
########################################################################### ###########################################################################
# END OF TEST # # END OF TEST #