From 2e62906c333a8ee12676200ce52888bc587495f2 Mon Sep 17 00:00:00 2001 From: Egor Kovetskiy Date: Wed, 13 Apr 2016 17:15:20 +0600 Subject: [PATCH] allow specify context using special header --- doc/UltiSnips.txt | 5 +++ .../UltiSnips/snippet/source/file/_common.py | 8 +++++ .../snippet/source/file/ultisnips.py | 16 ++++++--- syntax/snippets.vim | 9 +++++ test/test_ContextSnippets.py | 34 ++++++++++++++++++- 5 files changed, 66 insertions(+), 6 deletions(-) diff --git a/doc/UltiSnips.txt b/doc/UltiSnips.txt index 45c1fd5..1cd5063 100644 --- a/doc/UltiSnips.txt +++ b/doc/UltiSnips.txt @@ -1387,6 +1387,11 @@ In that case snippet should be defined using this syntax: > snippet tab_trigger "description" "expression" options +Context can be defined using special header using this syntax: > + + context "expression" + snippet tab_trigger "description" options + The 'expression' can be any python expression. If 'expression' evaluates to 'True', then this snippet will be chosen for expansion. The 'expression' must be wrapped with double-quotes. diff --git a/pythonx/UltiSnips/snippet/source/file/_common.py b/pythonx/UltiSnips/snippet/source/file/_common.py index ec4be60..d33281b 100644 --- a/pythonx/UltiSnips/snippet/source/file/_common.py +++ b/pythonx/UltiSnips/snippet/source/file/_common.py @@ -19,3 +19,11 @@ def handle_action(head, tail, line_index): else: return 'error', ("'{}' without specified action".format(head), line_index) + + +def handle_context(tail, line_index): + if tail: + return 'context', tail.strip('"').replace(r'\"', '"')\ + .replace(r'\\\\', r'\\') + else: + return 'error', ("'context' without body", line_index) diff --git a/pythonx/UltiSnips/snippet/source/file/ultisnips.py b/pythonx/UltiSnips/snippet/source/file/ultisnips.py index 2005ebd..fb66dab 100644 --- a/pythonx/UltiSnips/snippet/source/file/ultisnips.py +++ b/pythonx/UltiSnips/snippet/source/file/ultisnips.py @@ -11,7 +11,7 @@ from UltiSnips import _vim from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition from UltiSnips.snippet.source.file._base import SnippetFileSource from UltiSnips.snippet.source.file._common import handle_extends, \ - handle_action + handle_action, handle_context from UltiSnips.text import LineIterator, head_tail @@ -55,7 +55,7 @@ def find_all_snippet_files(ft): def _handle_snippet_or_global( - filename, line, lines, python_globals, priority, pre_expand + filename, line, lines, python_globals, priority, pre_expand, context ): """Parses the snippet that begins at the current line.""" start_line_index = lines.line_index @@ -75,8 +75,7 @@ def _handle_snippet_or_global( opts = words[-1] remain = remain[:-len(opts) - 1].rstrip() - context = None - if 'e' in opts: + if 'e' in opts and not context: left = remain[:-1].rfind('"') if left != -1 and left != 0: context, remain = remain[left:].strip('"'), remain[:left] @@ -134,6 +133,7 @@ def _parse_snippets_file(data, filename): lines = LineIterator(data) current_priority = 0 actions = {} + context = None for line in lines: if not line.strip(): continue @@ -144,16 +144,22 @@ def _parse_snippets_file(data, filename): filename, line, lines, python_globals, current_priority, - actions + actions, + context ) actions = {} + context = None if snippet is not None: yield snippet elif head == 'extends': yield handle_extends(tail, lines.line_index) elif head == 'clearsnippets': yield 'clearsnippets', (current_priority, tail.split()) + elif head == 'context': + head, context, = handle_context(tail, lines.line_index) + if head == 'error': + yield (head, tail) elif head == 'priority': try: current_priority = int(tail.split()[0]) diff --git a/syntax/snippets.vim b/syntax/snippets.vim index f7782fb..0e5306a 100644 --- a/syntax/snippets.vim +++ b/syntax/snippets.vim @@ -155,6 +155,12 @@ syn match snipPriority "^priority\%(\s.*\|$\)" contains=snipPriorityKeyword disp syn match snipPriorityKeyword "^priority" contained nextgroup=snipPriorityValue skipwhite display syn match snipPriorityValue "-\?\d\+" contained display +" context {{{3 + +syn match snipContext "^\context\%(\s.*\|$\)" contains=snipContextKeyword display +syn match snipContextKeyword "^context" contained nextgroup=snipContextValue skipwhite display +syn match snipContextValue '".*"' contained display + " Actions {{{3 syn match snipAction "^\%(pre_expand\|post_expand\|post_jump\).*$" contains=snipActionKeyword display skipwhite @@ -212,6 +218,9 @@ hi def link snipTransformationReplace String hi def link snipTransformationEscape snipEscape hi def link snipTransformationOptions Operator +hi def link snipContextKeyword Keyword +hi def link snipContextValue String + hi def link snipPriorityKeyword Keyword hi def link snipPriorityValue Number diff --git a/test/test_ContextSnippets.py b/test/test_ContextSnippets.py index 14e048a..452b02c 100644 --- a/test/test_ContextSnippets.py +++ b/test/test_ContextSnippets.py @@ -11,7 +11,6 @@ class ContextSnippets_SimpleSnippet(_VimTest): keys = 'a' + EX wanted = 'abc' - class ContextSnippets_ExpandOnTrue(_VimTest): files = { 'us/all.snippets': r""" global !p @@ -139,6 +138,7 @@ class ContextSnippets_CursorIsZeroBased(_VimTest): keys = "e" + EX wanted = "(2, 1)" + class ContextSnippets_ContextIsClearedBeforeExpand(_VimTest): files = { 'us/all.snippets': r""" pre_expand "snip.context = 1 if snip.context is None else 2" @@ -164,3 +164,35 @@ class ContextSnippets_ContextHasAccessToVisual(_VimTest): keys = "123" + ESC + "vhh" + EX + "test" + EX + " zzz" + ESC + \ "vhh" + EX + "test" + EX wanted = "Yes No" + + +class ContextSnippets_Header_ExpandOnTrue(_VimTest): + files = { 'us/all.snippets': r""" + global !p + def check_context(): + return True + endglobal + + context "check_context()" + snippet a "desc" e + abc + endsnippet + """} + keys = 'a' + EX + wanted = 'abc' + + +class ContextSnippets_Header_DoNotExpandOnFalse(_VimTest): + files = { 'us/all.snippets': r""" + global !p + def check_context(): + return False + endglobal + + context "check_context()" + snippet a "desc" e + abc + endsnippet + """} + keys = 'a' + EX + wanted = keys