You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

434 lines
14 KiB
Python

Squashed 'vim/bundle/ultisnips/' changes from cecc7aad8..786145030 786145030 quick and dirty fix tests for vanilla vim ea8094c50 syntax: treat python in context/actions as string 61df32722 syntax highlighting: fix context highlighting 3a3e56a98 grant access to visual to context and actions 059c9a9da Merge pull request #679 from SirVer/overwrite-tabstops-from-py-interpolation 23a6ec87c Merge pull request #663 from kmarius/fix-transformation 8fdfde190 Fix escapes in conditional tabstob transformation 7536ac900 tabstops can be overwritten from interpolation a514585cd ignore .ropeproject ed40bebab Add test cases for conditional transformations 25882e95c add testcase for #658 0657e61e6 Merge pull request #643 from dNItro/master 4b27b7152 Testcase added! bdd9012eb Merge pull request #647 from alexlafroscia/master 6d38cad14 Allow Deoplete entries to show up with existing matches 203218297 More detailed documentation on multiline option 8a8e183b8 Documentation on multiline option b057f633e Add support to do transformation on multiple lines 3f2c591c3 Merge pull request #625 from chemzqm/location 0058e8664 doc: add link to options for #Anon() ec9b292ba fix typos in doc/UltiSnips.txt 52ade8fed doc for all param of SnippetsInCurrentScope 4e2e897de change g:current_ulti_dict_all to g:current_ulti_dict_info 319ccddcd Merge pull request #628 from kmarius/fix_syntax 9a73473e7 Fix highlighting for nested visual tabstob 6a69a4415 add all param to UltiSnips#SnippetsInCurrentScope dbd43ad27 Merge pull request #624 from chemzqm/patch-1 3a70765f4 syntax highlight for unite ultisnips 5a2dcc5cb disable tests in vanilla vim for #616 45e3775c1 fix #616: update state on edit w/o cursor move 1b481f312 Merge pull request #615 from SirVer/updated_changelog 60c47e8e9 Reworked README for change of maintenance. 2e9f12bfd Fixed doc/UltiSnips.txt for change of maintainer. 95d6e535e Updated ChangeLog for 3.1. c5a21c509 Merge pull request #611 from HerringtonDarkholme/deoplete 024374614 Add support for deoplete 9c73ce948 Fix a unicode bug in python3. 53bf0dbd7 Merge pull request #608 from JarrodCTaylor/master 53571bf4f Refactor: More descriptive method name 1d4d8b049 Enhancement: Align snippet names in unite source options ef72df8e7 Merge pull request #603 from seletskiy/do-not-break-last-jump-on-post-expand cba31b191 Use new path for neovims config directory. 6ea78e525 fix last jump $0 placeholder using post_expand c9699feed Fix docs: "'" has no special meaning in snippets. 0480b2243 Adapt to changed Neovim configuration directory. 1ce44ac9c Merge pull request #592 from seletskiy/show-backtrace-on-error 08b96cbdb print erroneous snippet location 698f2d491 print snippet information in backtrace (fix #551) d03b13a68 review: add comment about snippet_code 47a3d1862 review fixes: 3accb5cb4 mark line number in traceback 00e3a877d print executed code cc6ac3c06 Exit any snippets when entering a unite buffer. baa9c9709 Merge pull request #589 from seletskiy/autotrigger 6ad7472aa autotrigger: solve performance issues fde4a066c Disable Neovim tests, since they do not pass. 30ba8155a NEOVIM testing is just too flaky. Let's make it optional again. 69b7c501a Merge pull request #582 from seletskiy/autotrigger 76ebfec3c autotrigger: make snippets expand without <tab> e1e005a81 Merge pull request #575 from manishrjain/master c39ffb851 Fix link to Vimcasts ef2c0d6d8 Merge pull request #573 from ericdouglas/patch-1 e603117f6 Fix Tabstops and Placeholders index 036d0d9c2 Merge pull request #570 from dueyfinster/patch-1 74bbca2f9 Fixed URL e48d8a28e Rollback "Merge support for auto expand." 490430f91 Merge support for auto expand. 8c7ce8827 Allow neovim to fail for the moment. It is flaky on travis. c45867be5 add missing doc for autotrigger_only 9eb2de6c3 add test for vim<7.4.214 5a5de0734 neovim tests a994e3286 fix py3 tests 61e06bbc1 add note about version and fix tests 878f79ffd review fixes 8ff84758a fix tests cf2c473a8 Define UltiSnips#FileTypeChanged always b968bc3e9 Merge pull request #548 from blueyed/remove-bootstrap-again 5e2f58c35 Define UltiSnips#FileTypeChanged always 4a302149e Remove autoload/UltiSnips/bootstrap.vim again 29ad00ec0 Merge pull request #544 from wincent/fix-autocmd 3eabbe71a Use <nomodeline> when firing user autocmds b3cd0cae1 Merge pull request #541 from hanschen/master 44644f1fd Add field numbers to avoid errors in Python 2.6 ffb9b7948 Do not run autocommands when using --noplugin. 6c4fb6f3f fix b->b2<BS> case, fix merge 14ea90385 tests and docs 1356560f9 fix blumba test 5af229abc add error handling f80414fac prototype of autotrigger 7c74aa768 Merge pull request #537 from krisdages/master cc43d1251 Pipe-quoting helptag reference to UltiSnips-context-snippets c12867d1b Merge support for snippet-actions. 5638cdf4a review fix for == c3add0bef fix neovim tests 58a2094d4 review fixes 175e3ba52 fix doc 80 chars limit a39f3c241 revert access to UltiSnips_Manager bdecd9a8b fix not cleared context 3c4ac11af fix python3, finally b50c5c86c pass all args to snip.expand_anon 9649f15a9 fix buffer edits from jump action 5a663116f edge case: anon snip in pre-action 1e771de60 fix tests ba774c39c review fixes 8958b7134 add docs to the buffer proxy object bc29e2322 VimBufferHelper -> VimBufferProxy 972305725 fix expan_anon in pre-action, snip object, fixes 191ebd8e8 migrate to snip.* namespace 7ead6fa17 detect buffer changes via changedtick 760fd25e4 fix python3 compatibility 1ca82f76f pre/post-expand and post-jump actions 67fbdb2ad Handle $0 in a default text like any other tabstop. 5c211b0e7 Clear up pathogen installation instructions. 34679be7a Updated ChangeLog. 300156642 Support $n tabstops for snipMate snippets. e058d1d40 Added waffle.io badge. c68c9dd74 Add a webhook for gitter.im. 7f64510a7 Link to the Vimcasts about UltiSnips. cd0e60bc0 Remove no longer needed langmap translation. 290600c02 Pass the expected python version to the tests. 44db53b7b Even more leanient timings. 0be9d0f86 Even slower typing. eee82219b More lenient typing speed for Neovim. 306f0ace5 Add a testing interface that works for Neovim. 992e09463 Add a warning about changing the buffer in autocommands. c4ee3ecf1 Fire autocommands when setting up and tearing down inner state 29d7080d6 Do not set up inner state if it is already setup. 33db8b4ab Update pathogen installation instructions. 324a4f8ff Support regexp trigger ending in whitespace. 6b12b1141 Only set autocommands when there are snippets. 2ed217a05 Remove deprecated functions like a boss. becab789a Remove bootstrap.vim. Simplify startup. b13015d47 Remove sys.path manipulations. 5f75dde20 Remove snipMate compatibility script. 9822193e4 Make scripts actually executable. 4f65a7654 Fix testing and test against more scenarios. 5590f9b7b Merge pull request #522 from blueyed/use-vim-current-buffer 8c257e24e VimBuffer: use vim.current.buffer.number instead of vim.eval c3a0924b7 Require Vim 7.4 in preparation of removal of compatibility features. de70b1ed5 Exit snippets when entering/exiting command window. 3806a6987 Fix improper use of augroup in ftdetect. 2fb8820ff A backward compatible solution 00d50c3ae Remove augroup block 188e00f7b Merge pull request #493 from cwahbong/fold-fix ca1977231 Fix folding for snippet files. ab1cc1afa Remove documentation for using the same trigger for jump and expand. d6098193e Merge pull request #446 from seletskiy/context-snippets 50bb61cdc another test for error reporting 463e68a61 fix for correct error reporting 9587d9daa Merge pull request #486 from seletskiy/enhance-undo 2f355c233 another little fix in documentation 099d3bcfb Add more precise undo levels (expanding, jumping) 1b3ecf4a8 priority test, docs & fmt fixes 904fbdecf review fixes 4ab4c1df4 Do not use --interface anymore. 1bf07737b Make sure tmux is available before starting any test. 82ceb6288 Remove testing with GNU screen 2c15427b1 Merge pull request #482 from blueyed/check-python-support-for-UltiSnipsUsePythonVersion 87c3a7ba4 fix UltiSnipFunc test 709f8dc93 minor doc fix and new cursor variable 9861a6e6c typo fix in docs 66bc2e8f6 documentation, pull-requests fixes 0beefd4a1 fix context match on False value ed8cf4911 fix tests b3aec0705 proof of concept for context snips 800a54da1 bootstrap: use WarningMsg with python warning message ac42c83a7 bootstrap: verify that g:UltiSnipsUsePythonVersion is available 00848d7d6 Merge pull request #483 from cwahbong/master 3ccc14dca Try to work around transiently failing commands. aeb2e2420 Disabled unite test - it seems flaky. 4b39bf655 Priority must always be an integer. ee7e15558 Make install_vim.sh actually executable. 99eede1bf Started to test py2 and py3 on travis now. 01a17a1a4 Merge pull request #480 from KazuakiM/master bf20bc6f6 Update document for zero tabstop. 62a96bb05 Merge pull request #462 from kawing-chiu/fix-#457 71a8fdec5 Add contributor to doc. 42fc6c031 Merge branch 'improve_neocomplete' 3ae9b48cf Delete default setting in neocomplete/sources/ultisnips.vim f9a22111f Fix adjacent tabstop input issue. 1971030b5 Merge pull request #456 from spacewander/master 4d88df461 remove duplicate things in vim_test_case.py 56ac14840 Disable neocomplete test which fails right now. cf23624c0 A usable travis configuration. e11252655 More travis. ad2c6d35c Add travis badge and try running on python3 too. db00408a1 More travis. eb9adc50e More travis. f47ec08ef More travis. 348dd4346 More travis. c1aec63bd Typo in travis script. 35cdaba3a A travis script. 09876e008 Support for m (trim) snippet option. e04118766 Do not try to remap the keymaps if langnoremap is available and set. c1bde18cd Add support vim's langnoremap new option 8367587e4 Test fixes. 1a3d0ce4b tests: allow passing in PYTHON, and default to python2 6e787df80 tests: use return code from testrunner 936aac8da tests: add -x / --exitfirst option to fail fast 6602da89d tests: fix duplicate method name (test_SnippetPriorities) 125e6be78 tests: minor doc fixes 98fa887e5 tests: remove star imports, sort ed34607d3 Merge pull request #436 from waffle-iron/master 483dc4ab2 add waffle.io badge 81a628c6e Add option 'm' for trimming whitespaces in snippet d693259ab Add option to not traverse all of the rtp. 0ce8b2366 Less verbose pylint errors. b47e68652 do not walk &rtp if abs path to snips specified 6a787cdc7 Applied pyformat on entire codebase. e1436a8ae Accept numbers and text for disabling snipMate. d240aa24d Added Pyrohh to the list of contributors. 7df82bbe5 Merge pull request #415 from seletskiy/toggle-snipmate fc080b4fd add g:UltiSnipsEnableSnipMate 67630f4ae Merge pull request #414 from Pyrohh/master c050d68e5 Check if editor is Neovim when setting snippet_dir b26f2c97b Merge pull request #413 from lencioni/documentation bbb07646a Fix typo "endglobals" in documentation 6907b2444 Merge pull request #410 from tho/master 185f96c4d Fix list of trigger functions in documentation 6dd476750 Merge pull request #406 from jszakmeister/dont-rely-on-cwd e3159ce0d Merge pull request #407 from jszakmeister/update-documentation d85f0b0c2 Merge pull request #408 from tinypenguin/master d9691a912 Added a terminal emulator warning line for using c-tab combo with usnips eb82c6691 Add some documentation on running the test suite. 1f3f1ce64 Don't rely on having the tmux/screen cwd being in the project directory. e502c9ba8 Fix a couple of typos. 9028abd95 Fixes for Unicode issues by jszakmeister. 8b2115ec2 Fix #171: UltiSnips crashes in new file with text containing 0x80 char f4df1bd9e Teach _vim_enc to handle UnicodeDecodeErrors. 56aa817be Reset the unnamed register at the start of a test. cb8536d72 Merge pull request #394 from michamos/master f179fcf99 Map <c-r> in select mode 1ad970379 Support for sw=0 in newer Vim versions. 4e72a5d08 Merge pull request #388 from blueyed/doc-ref-triggers e3abd6678 Added test case for shiftwidth=0 and added myself to contributors list. 14e5b4638 doc: add tags for trigger vars 482650a00 Use shiftwidth() where available. This allows UltiSnips to work properly when shiftwidth is zero. Per ":help shiftwidth": 8aeb1a2e3 Merge pull request #377 from petobens/master 0775156de Don't escape backslashes in :UltiSnipsEdit 386b3a097 Merge pull request #360 from tafryn/master cae25e533 Change indent level to 3(?!) spaces. 9c632378a Add missing newline to ftdetect. f6e33387a Clean-up vimpager check. c681560b4 Add 'context' value to g:UltiSnipsEditSplit. c79cfd50f Merge pull request #370 from sakana/master 1129ca67d Fix UltiSnipsEdit for g:UltiSnipsSnippetsDir paths that include spaces 2c3c4a777 Add 'context' value to g:UltiSnipsEditSplit 59defbdd5 Merge pull request #357 from kballard/tweak_ftplugin a69764dff Tweak the ftplugin 1292b0fae Merge pull request #355 from kballard/fix_syntax_nested_tabstop a8c9caae8 Add check to prevent errors when using vimpager. 81f917313 Fix highlighting of nested tab stops 279d6e63c Updates the doc for the new clearsnippets behavior. Slight rewording by me. c3660128a Implements clearsnippets by priority. 57ed954cc Merge pull request #348 from cwahbong/select-cr-fix 0abfc3bec Some refinements. 63f65ea87 Add/modify test cases for priority-based clearsnippets. 4784a9e12 Refactor: snippet dictionary does not keep the extend info now. 20f3832ff Code cleanup. 5c87806d7 Implement priority-based clearsnippets. a9aa8c76a Update document for priority based clearsnippets. a053433e4 Variable rename and illustration. 97bad9906 Add test case for #341 (github). f6ce0f92d Merge pull request #349 from m42e/master 79705c3fc Ignore Errors E403 from included syntax files e05788cec Fix issue #341 (github). 4dcfca755 Test refactorings. 1cf3b928f Refactor: split test.py into several smaller files. 9521b942b Merge pull request #340 from cwahbong/test-fix 0872600b9 Ahbong is contributer now. 0dc6a8e4a Now test.py check the version or tmux. b11d5496a Add docstrings for TempFileManager. 15a0a17af Fix tmux interface. e97d52c68 Merge pull request #342 from chivalry/master 2d8ae2fcd Correct misspelling 3002b6852 Solves waiting problem in an elegant way. cc4dc3703 Code cleanup for test.py. 9a98039d2 Fix test.py. ccf79ba82 Merge pull request #331 from kballard/tagbar_snippets dee826520 Support TagBar for snippets files d1f6f7ed8 Better syntax file. b10b62ae6 Twiddle indentation settings 67c7422ae Set up basic highlighting for snipmate files 40145103b Stop embedding python/viml/sh if the `` includes { 010e2c4fa Remove the coloring for python commands ebd62751e Tweak snippet/global highlighting to always highlight the end 30ecd1d1b Rewrite parsing for tab stops 5fa39faa9 fixup! Clean up miscellaneous syntax items 4b73864b7 Fix the docstring for ShellCodeToken 0dba6503e Clean up miscellaneous syntax items acc79747c Syntax highlight the snippet trigger properly 5760eb403 Fix empty snippets/globals d239402b7 Rewrite syntax matching for `global` cb2905c17 Rewrite syntax matching for `snippet` 5937cea08 Mark up syntax items with 'display' as appropriate b82759b25 Rewrite extends/priority/clearsnippets 672117c47 Add hierarchy to syntax file 739e3d94a Fix coloring of shell/VimL/Python command substitutions 5b80ef187 Properly handle \` escapes in commands 636546beb Fix syntax name cab150995 Fix embedded VimL highlighting 1ad7d54d7 Fix highlighting of Python/VimL commands 7b8641e1f Back out fix for #323. Fixes #324. 7d65e2141 Merge pull request #323 from opennota/master 93be385d3 Don't complain about undefined function e59a60cbe Fixed docu for clearsnippets. ee1a2bb2b Escape '\\' in UltiSnipsEdit. f2d9e8b60 Support for selection=old. da5b124af add support for selection=old e4f2e34fc Remove tool that converts snipMate snippets. As support is now build into ultisnips, this is no longer needed. bca51cb40 Brought back snipMate compatibility file. We cannot rely on people tracking vim-snippets to have the renmamed version of this available there. 5c8e3ca48 Merge pull request #275 from skeept/patch-2 fb58034b1 Re-add > before code. 1e6928d0a Merge pull request #276 from meonkeys/patch-1 2042ad476 README: adapt to Vundle interface change 98289510c Update UltiSnips.txt 04ef0f8f5 Merged unite source by Skeept. 2f8489944 Remove snipMate compatibility file. If at all, this should now live in vim-snippets. c21016573 All mappings should be 'silent'. 77a9d8941 simple test for unite interface eff62c336 Be more correct about encoding/decoding strings under py3. Patch by aeruder. cae27fba5 Ensure that _vim_{dec,enc} always succeeds on py3 15f39c080 Do not barf more than once when python is not found. Patch by blueyed. 210304884 Define all/other dummy functions used in autocommands 7da9dbe2a Add UltiSnipsFileType augroup and unset it if UltiSnips is disabled 3208654c4 Do not map keys if 'g:_uspy' could not be set c57c717e3 Delete autocommands when Bootstrap failed 2ad6ad449 Fix E168: :finish used outside of a sourced file a3e654fc5 _vimfiles -> vimfiles. Patch b Oberon. 7bee824db use function to invoqe unite cc1514542 add unite source b6d545ecd Properly escape locations on windows. ae70ec895 Escape correctly file names in windows. 4b4ee4885 Overwrite all snippets with lower priority on expansion. 511600124 Documentation fixes. fee999a71 Docs: remove a reference to defunct ! snippet option 360f58dbf Show where snippets are defined in selection. 7c34a3400 Escape \ when asking for snippets. cd99bdd3b selection=old cannot work with UltiSnips. 69e0acd58 Change the way placeholders are selected. 5aaeae5e8 Do not delete child that is already gone. 1b21741a2 Update ChangeLog. f40c3ac5e Made UltiSnipsEdit! more consistent with multiple filetypes. 5ac043669 Retry unmapping when we switched buffers. b0a3266a6 More tweaking. 940f4d9f2 tweaked readme 5fe88fdc9 Use the demo in the README. 764fd65a7 Added a nice interactive demo. 001c2a967 Added realname of petobens. c6906d85b Fixed a bug in UltiSnipsEdit! 6398a598b Made UltiSnipsEdit more useful and consistent. f44640923 Mention neocomplete in the docs. ba2f30fdf Adapted neosnippets source. Examples by petobens. e6d335aa4 Make the cloning direcotory explicit on stdout. 96557f397 Added integration test for SuperTab. a800b51e0 Removed no longer planned TODOs 147df653a Snippet sources can now be registered. 1ce706e3a Adapted neocomplete integration. a23911f7f Add option to only clone and immediately exit the test runner. c017806b1 Added preliminary support for neocomplete. 1ec523801 Added version checking for other plugins. f4cda8802 Add integration tests with YouCompleteMe. b65efa5aa Added quickstart to readme. 7b51ec6f6 Removed snippet contributors from README. 35e57fad0 Removes snippets. Please track honza/vim-snippets. c4fa2c03b Barf when using "snipmate" for UltiSnips. c9681051c Small fixes to the documentation. 1ec2f187b Updated ChangeLog. c690a3610 Empty lines do not end a snippet for snipMate. 14fca8523 Ups. Forgot to add this. fe7cb4cf8 Makes UltiSnips a drop in replacement for snipMate. 6b8bb1b64 Launch and exit vim for each test. 2c28b51db Allow tests to write arbitrary files into the runtimepath, not just snippet files. 48dcaa02b Attempted fix at several startup problems. 2d18d5365 Change initialization to make session work. git-subtree-dir: vim/bundle/ultisnips git-subtree-split: 78614503098571ecdb09f79bc9543aacdb0e41c0
9 years ago
#!/usr/bin/env python
# encoding: utf-8
"""Snippet representation after parsing."""
import re
import vim
import textwrap
from UltiSnips import _vim
from UltiSnips.compatibility import as_unicode
from UltiSnips.indent_util import IndentUtil
from UltiSnips.position import Position
from UltiSnips.text import escape
from UltiSnips.text_objects import SnippetInstance
from UltiSnips.text_objects._python_code import SnippetUtilCursor, SnippetUtilForAction
__WHITESPACE_SPLIT = re.compile(r"\s")
def split_at_whitespace(string):
"""Like string.split(), but keeps empty words as empty words."""
return re.split(__WHITESPACE_SPLIT, string)
def _words_for_line(trigger, before, num_words=None):
"""Gets the final 'num_words' words from 'before'.
If num_words is None, then use the number of words in 'trigger'.
"""
if num_words is None:
num_words = len(split_at_whitespace(trigger))
word_list = split_at_whitespace(before)
if len(word_list) <= num_words:
return before.strip()
else:
before_words = before
for i in range(-1, -(num_words + 1), -1):
left = before_words.rfind(word_list[i])
before_words = before_words[:left]
return before[len(before_words):].strip()
class SnippetDefinition(object):
"""Represents a snippet as parsed from a file."""
_INDENT = re.compile(r"^[ \t]*")
_TABS = re.compile(r"^\t*")
def __init__(self, priority, trigger, value, description,
options, globals, location, context, actions):
self._priority = int(priority)
self._trigger = as_unicode(trigger)
self._value = as_unicode(value)
self._description = as_unicode(description)
self._opts = options
self._matched = ''
self._last_re = None
self._globals = globals
self._location = location
self._context_code = context
self._context = None
self._actions = actions
# Make sure that we actually match our trigger in case we are
# immediately expanded.
self.matches(self._trigger)
def __repr__(self):
return '_SnippetDefinition(%r,%s,%s,%s)' % (
self._priority, self._trigger, self._description, self._opts)
def _re_match(self, trigger):
"""Test if a the current regex trigger matches `trigger`.
If so, set _last_re and _matched.
"""
for match in re.finditer(self._trigger, trigger):
if match.end() != len(trigger):
continue
else:
self._matched = trigger[match.start():match.end()]
self._last_re = match
return match
return False
def _context_match(self, visual_content):
# skip on empty buffer
if len(vim.current.buffer) == 1 and vim.current.buffer[0] == "":
return
locals = {
'context': None,
'visual_mode': '',
'visual_text': '',
'last_placeholder': None
}
if visual_content:
locals['visual_mode'] = visual_content.mode
locals['visual_text'] = visual_content.text
locals['last_placeholder'] = visual_content.placeholder
return self._eval_code('snip.context = ' + self._context_code,
locals).context
def _eval_code(self, code, additional_locals={}):
code = "\n".join([
'import re, os, vim, string, random',
'\n'.join(self._globals.get('!p', [])).replace('\r\n', '\n'),
code
])
current = vim.current
locals = {
'window': current.window,
'buffer': current.buffer,
'line': current.window.cursor[0]-1,
'column': current.window.cursor[1]-1,
'cursor': SnippetUtilCursor(current.window.cursor),
}
locals.update(additional_locals)
snip = SnippetUtilForAction(locals)
try:
exec(code, {'snip': snip})
except Exception as e:
e.snippet_info = textwrap.dedent("""
Defined in: {}
Trigger: {}
Description: {}
Context: {}
Pre-expand: {}
Post-expand: {}
""").format(
self._location,
self._trigger,
self._description,
self._context_code if self._context_code else '<none>',
self._actions['pre_expand'] if 'pre_expand' in self._actions
else '<none>',
self._actions['post_expand'] if 'post_expand' in self._actions
else '<none>',
code,
)
e.snippet_code = code
raise
return snip
def _execute_action(
self,
action,
context,
additional_locals={}
):
mark_to_use = '`'
with _vim.save_mark(mark_to_use):
_vim.set_mark_from_pos(mark_to_use, _vim.get_cursor_pos())
cursor_line_before = _vim.buf.line_till_cursor
locals = {
'context': context,
}
locals.update(additional_locals)
snip = self._eval_code(action, locals)
if snip.cursor.is_set():
vim.current.window.cursor = snip.cursor.to_vim_cursor()
else:
new_mark_pos = _vim.get_mark_pos(mark_to_use)
cursor_invalid = False
if _vim._is_pos_zero(new_mark_pos):
cursor_invalid = True
else:
_vim.set_cursor_from_pos(new_mark_pos)
if cursor_line_before != _vim.buf.line_till_cursor:
cursor_invalid = True
if cursor_invalid:
raise RuntimeError(
'line under the cursor was modified, but ' +
'"snip.cursor" variable is not set; either set set ' +
'"snip.cursor" to new cursor position, or do not ' +
'modify cursor line'
)
return snip
def has_option(self, opt):
"""Check if the named option is set."""
return opt in self._opts
@property
def description(self):
"""Descriptive text for this snippet."""
return ('(%s) %s' % (self._trigger, self._description)).strip()
@property
def priority(self):
"""The snippets priority, which defines which snippet will be preferred
over others with the same trigger."""
return self._priority
@property
def trigger(self):
"""The trigger text for the snippet."""
return self._trigger
@property
def matched(self):
"""The last text that matched this snippet in match() or
could_match()."""
return self._matched
@property
def location(self):
"""Where this snippet was defined."""
return self._location
@property
def context(self):
"""The matched context."""
return self._context
def matches(self, before, visual_content=None):
"""Returns True if this snippet matches 'before'."""
# If user supplies both "w" and "i", it should perhaps be an
# error, but if permitted it seems that "w" should take precedence
# (since matching at word boundary and within a word == matching at word
# boundary).
self._matched = ''
words = _words_for_line(self._trigger, before)
if 'r' in self._opts:
match = self._re_match(before)
elif 'w' in self._opts:
words_len = len(self._trigger)
words_prefix = words[:-words_len]
words_suffix = words[-words_len:]
match = (words_suffix == self._trigger)
if match and words_prefix:
# Require a word boundary between prefix and suffix.
boundary_chars = escape(words_prefix[-1:] +
words_suffix[:1], r'\"')
match = _vim.eval(
'"%s" =~# "\\\\v.<."' %
boundary_chars) != '0'
elif 'i' in self._opts:
match = words.endswith(self._trigger)
else:
match = (words == self._trigger)
# By default, we match the whole trigger
if match and not self._matched:
self._matched = self._trigger
# Ensure the match was on a word boundry if needed
if 'b' in self._opts and match:
text_before = before.rstrip()[:-len(self._matched)]
if text_before.strip(' \t') != '':
self._matched = ''
return False
self._context = None
if match and self._context_code:
self._context = self._context_match(visual_content)
if not self.context:
match = False
return match
def could_match(self, before):
"""Return True if this snippet could match the (partial) 'before'."""
self._matched = ''
# List all on whitespace.
if before and before[-1] in (' ', '\t'):
before = ''
if before and before.rstrip() is not before:
return False
words = _words_for_line(self._trigger, before)
if 'r' in self._opts:
# Test for full match only
match = self._re_match(before)
elif 'w' in self._opts:
# Trim non-empty prefix up to word boundary, if present.
qwords = escape(words, r'\"')
words_suffix = _vim.eval(
'substitute("%s", "\\\\v^.+<(.+)", "\\\\1", "")' % qwords)
match = self._trigger.startswith(words_suffix)
self._matched = words_suffix
# TODO: list_snippets() function cannot handle partial-trigger
# matches yet, so for now fail if we trimmed the prefix.
if words_suffix != words:
match = False
elif 'i' in self._opts:
# TODO: It is hard to define when a inword snippet could match,
# therefore we check only for full-word trigger.
match = self._trigger.startswith(words)
else:
match = self._trigger.startswith(words)
# By default, we match the words from the trigger
if match and not self._matched:
self._matched = words
# Ensure the match was on a word boundry if needed
if 'b' in self._opts and match:
text_before = before.rstrip()[:-len(self._matched)]
if text_before.strip(' \t') != '':
self._matched = ''
return False
return match
def instantiate(self, snippet_instance, initial_text, indent):
"""Parses the content of this snippet and brings the corresponding text
objects alive inside of Vim."""
raise NotImplementedError()
def do_pre_expand(self, visual_content, snippets_stack):
if 'pre_expand' in self._actions:
locals = {'buffer': _vim.buf, 'visual_content': visual_content}
snip = self._execute_action(
self._actions['pre_expand'], self._context, locals
)
self._context = snip.context
return snip.cursor.is_set()
else:
return False
def do_post_expand(self, start, end, snippets_stack):
if 'post_expand' in self._actions:
locals = {
'snippet_start': start,
'snippet_end': end,
'buffer': _vim.buf
}
snip = self._execute_action(
self._actions['post_expand'], snippets_stack[-1].context, locals
)
snippets_stack[-1].context = snip.context
return snip.cursor.is_set()
else:
return False
def do_post_jump(
self, tabstop_number, jump_direction, snippets_stack, current_snippet
):
if 'post_jump' in self._actions:
start = current_snippet.start
end = current_snippet.end
locals = {
'tabstop': tabstop_number,
'jump_direction': jump_direction,
'tabstops': current_snippet.get_tabstops(),
'snippet_start': start,
'snippet_end': end,
'buffer': _vim.buf
}
snip = self._execute_action(
self._actions['post_jump'], current_snippet.context, locals
)
current_snippet.context = snip.context
return snip.cursor.is_set()
else:
return False
def launch(self, text_before, visual_content, parent, start, end):
"""Launch this snippet, overwriting the text 'start' to 'end' and
keeping the 'text_before' on the launch line.
'Parent' is the parent snippet instance if any.
"""
indent = self._INDENT.match(text_before).group(0)
lines = (self._value + '\n').splitlines()
ind_util = IndentUtil()
# Replace leading tabs in the snippet definition via proper indenting
initial_text = []
for line_num, line in enumerate(lines):
if 't' in self._opts:
tabs = 0
else:
tabs = len(self._TABS.match(line).group(0))
line_ind = ind_util.ntabs_to_proper_indent(tabs)
if line_num != 0:
line_ind = indent + line_ind
result_line = line_ind + line[tabs:]
if 'm' in self._opts:
result_line = result_line.rstrip()
initial_text.append(result_line)
initial_text = '\n'.join(initial_text)
snippet_instance = SnippetInstance(
self, parent, initial_text, start, end, visual_content,
last_re=self._last_re, globals=self._globals,
context=self._context)
self.instantiate(snippet_instance, initial_text, indent)
snippet_instance.update_textobjects()
return snippet_instance