Support $n tabstops for snipMate snippets.

Before, only ${n} tabstops were supported. Apparently snipMate changed
this behavior though, so now we support that too.

Fixes #533.
This commit is contained in:
Holger Rapp 2015-07-20 15:01:49 +02:00
parent e058d1d400
commit 300156642c
4 changed files with 37 additions and 25 deletions

View File

@ -7,6 +7,23 @@ from UltiSnips.position import Position
from UltiSnips.snippet.parsing._lexer import tokenize, TabStopToken from UltiSnips.snippet.parsing._lexer import tokenize, TabStopToken
from UltiSnips.text_objects import TabStop from UltiSnips.text_objects import TabStop
from UltiSnips.text_objects import Mirror
from UltiSnips.snippet.parsing._lexer import MirrorToken
def resolve_ambiguity(all_tokens, seen_ts):
"""$1 could be a Mirror or a TabStop.
This figures this out.
"""
for parent, token in all_tokens:
if isinstance(token, MirrorToken):
if token.number not in seen_ts:
seen_ts[token.number] = TabStop(parent, token)
else:
Mirror(parent, seen_ts[token.number], token)
def tokenize_snippet_text(snippet_instance, text, indent, def tokenize_snippet_text(snippet_instance, text, indent,
allowed_tokens_in_text, allowed_tokens_in_tabstops, allowed_tokens_in_text, allowed_tokens_in_tabstops,

View File

@ -3,7 +3,7 @@
"""Parses a snipMate snippet definition and launches it into Vim.""" """Parses a snipMate snippet definition and launches it into Vim."""
from UltiSnips.snippet.parsing._base import tokenize_snippet_text, finalize from UltiSnips.snippet.parsing._base import tokenize_snippet_text, finalize, resolve_ambiguity
from UltiSnips.snippet.parsing._lexer import EscapeCharToken, \ from UltiSnips.snippet.parsing._lexer import EscapeCharToken, \
VisualToken, TabStopToken, MirrorToken, ShellCodeToken VisualToken, TabStopToken, MirrorToken, ShellCodeToken
from UltiSnips.text_objects import EscapedChar, Mirror, VimLCode, Visual from UltiSnips.text_objects import EscapedChar, Mirror, VimLCode, Visual
@ -23,13 +23,6 @@ __ALLOWED_TOKENS_IN_TABSTOPS = [
] ]
def _create_mirrors(all_tokens, seen_ts):
"""Now that all tabstops are known, we can create mirrors."""
for parent, token in all_tokens:
if isinstance(token, MirrorToken):
Mirror(parent, seen_ts[token.number], token)
def parse_and_instantiate(parent_to, text, indent): def parse_and_instantiate(parent_to, text, indent):
"""Parses a snippet definition in snipMate format from 'text' assuming the """Parses a snippet definition in snipMate format from 'text' assuming the
current 'indent'. current 'indent'.
@ -41,5 +34,5 @@ def parse_and_instantiate(parent_to, text, indent):
all_tokens, seen_ts = tokenize_snippet_text(parent_to, text, indent, all_tokens, seen_ts = tokenize_snippet_text(parent_to, text, indent,
__ALLOWED_TOKENS, __ALLOWED_TOKENS_IN_TABSTOPS, __ALLOWED_TOKENS, __ALLOWED_TOKENS_IN_TABSTOPS,
_TOKEN_TO_TEXTOBJECT) _TOKEN_TO_TEXTOBJECT)
_create_mirrors(all_tokens, seen_ts) resolve_ambiguity(all_tokens, seen_ts)
finalize(all_tokens, seen_ts, parent_to) finalize(all_tokens, seen_ts, parent_to)

View File

@ -3,7 +3,7 @@
"""Parses a UltiSnips snippet definition and launches it into Vim.""" """Parses a UltiSnips snippet definition and launches it into Vim."""
from UltiSnips.snippet.parsing._base import tokenize_snippet_text, finalize from UltiSnips.snippet.parsing._base import tokenize_snippet_text, finalize, resolve_ambiguity
from UltiSnips.snippet.parsing._lexer import EscapeCharToken, \ from UltiSnips.snippet.parsing._lexer import EscapeCharToken, \
VisualToken, TransformationToken, TabStopToken, MirrorToken, \ VisualToken, TransformationToken, TabStopToken, MirrorToken, \
PythonCodeToken, VimLCodeToken, ShellCodeToken PythonCodeToken, VimLCodeToken, ShellCodeToken
@ -24,20 +24,6 @@ __ALLOWED_TOKENS = [
] ]
def _resolve_ambiguity(all_tokens, seen_ts):
"""$1 could be a Mirror or a TabStop.
This figures this out.
"""
for parent, token in all_tokens:
if isinstance(token, MirrorToken):
if token.number not in seen_ts:
seen_ts[token.number] = TabStop(parent, token)
else:
Mirror(parent, seen_ts[token.number], token)
def _create_transformations(all_tokens, seen_ts): def _create_transformations(all_tokens, seen_ts):
"""Create the objects that need to know about tabstops.""" """Create the objects that need to know about tabstops."""
for parent, token in all_tokens: for parent, token in all_tokens:
@ -59,6 +45,6 @@ def parse_and_instantiate(parent_to, text, indent):
""" """
all_tokens, seen_ts = tokenize_snippet_text(parent_to, text, indent, all_tokens, seen_ts = tokenize_snippet_text(parent_to, text, indent,
__ALLOWED_TOKENS, __ALLOWED_TOKENS, _TOKEN_TO_TEXTOBJECT) __ALLOWED_TOKENS, __ALLOWED_TOKENS, _TOKEN_TO_TEXTOBJECT)
_resolve_ambiguity(all_tokens, seen_ts) resolve_ambiguity(all_tokens, seen_ts)
_create_transformations(all_tokens, seen_ts) _create_transformations(all_tokens, seen_ts)
finalize(all_tokens, seen_ts, parent_to) finalize(all_tokens, seen_ts, parent_to)

View File

@ -87,6 +87,22 @@ snippet for
wanted = 'for (j; j < blub; blub++) {\n\thi\n}' wanted = 'for (j; j < blub; blub++) {\n\thi\n}'
class snipMate_TestNoBraceTabstops(_VimTest):
files = { 'snippets/_.snippets': """
snippet test
\t$1 is $2"""}
keys = 'test' + EX + 'blub' + JF + 'blah'
wanted = 'blub is blah'
class snipMate_TestNoBraceTabstopsAndMirrors(_VimTest):
files = { 'snippets/_.snippets': """
snippet test
\t$1 is $1, $2 is ${2}"""}
keys = 'test' + EX + 'blub' + JF + 'blah'
wanted = 'blub is blub, blah is blah'
class snipMate_TestMirrorsInPlaceholders(_VimTest): class snipMate_TestMirrorsInPlaceholders(_VimTest):
files = { 'snippets/_.snippets': """ files = { 'snippets/_.snippets': """
snippet opt snippet opt