Merge lp:~ryan.wooden/ultisnips/ultisnips-fixes into lp:~sirver/ultisnips/trunk

Proposed by Ryan Wooden
Status: Merged
Merged at revision: 288
Proposed branch: lp:~ryan.wooden/ultisnips/ultisnips-fixes
Merge into: lp:~sirver/ultisnips/trunk
Diff against target: 174 lines (+71/-15)
3 files modified
plugin/UltiSnips/Util.py (+15/-0)
plugin/UltiSnips/__init__.py (+18/-14)
test.py (+38/-1)
To merge this branch: bzr merge lp:~ryan.wooden/ultisnips/ultisnips-fixes
Reviewer Review Type Date Requested Status
SirVer Pending
Review via email: mp+59684@code.launchpad.net

Description of the change

Applied patch from allait with a fix for bug #774911, but reordered the snippets before returning them so that they arrive in the order expected in the tests.

Added tests and my own fix for bug #774917. I added a function I used in one of my own little plugins to safely convert Python dicts, lists, and strings to be returned to vim. I replaced the _vim_quote() function with mine, and quoted the list returned in _ask_snippets().

All tests currently pass.

To post a comment you must log in.
293. By Ryan Wooden

Added tests and a fix for bug #774923.

Revision history for this message
Ryan Wooden (ryan.wooden) wrote :

I added tests and fix for bug #774923. The problem was caused by the fact that the mapping for <BS> takes vim out of SELECT mode, but the method being called tries to press <BS> anyway. To solve it, the method instead presses "gvc" to reselect the region and replace it, which simulates what would happen normally when pressing BS in select mode.

Revision history for this message
SirVer (sirver) wrote :

Great work! Merged in r 288.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugin/UltiSnips/Util.py'
2--- plugin/UltiSnips/Util.py 2010-11-18 18:00:36 +0000
3+++ plugin/UltiSnips/Util.py 2011-05-02 19:24:32 +0000
4@@ -4,6 +4,21 @@
5 import vim
6 import os
7
8+def vim_string(inp):
9+ """ Creates a vim-friendly string from a group of
10+ dicts, lists and strings.
11+ """
12+ def conv(obj):
13+ if isinstance(obj, list):
14+ return u'[' + u",".join([conv(o) for o in obj]) + u']'
15+ elif isinstance(obj, dict):
16+ return u'{' + u','.join([
17+ u"%s:%s" % (conv(key), conv(value))
18+ for key, value in obj.iteritems()]) + u'}'
19+ else:
20+ return u'"%s"' % str(obj).replace(u'"', u'\\"')
21+ return conv(inp)
22+
23 class IndentUtil(object):
24 """ Utility class for dealing properly with indentation. """
25
26
27=== modified file 'plugin/UltiSnips/__init__.py'
28--- plugin/UltiSnips/__init__.py 2011-04-28 06:23:01 +0000
29+++ plugin/UltiSnips/__init__.py 2011-05-02 19:24:32 +0000
30@@ -14,7 +14,7 @@
31 from UltiSnips.Geometry import Position
32 from UltiSnips.TextObjects import *
33 from UltiSnips.Buffer import VimBuffer
34-from UltiSnips.Util import IndentUtil
35+from UltiSnips.Util import IndentUtil, vim_string
36 from UltiSnips.Langmap import LangMapTranslator
37
38 # The following lines silence DeprecationWarnings. They are raised
39@@ -51,17 +51,13 @@
40 _to_scratch_buffer(s)
41 return wrapper
42
43-def _vim_quote(s):
44- """Quote string s as Vim literal string."""
45- return "'" + s.replace("'", "''") + "'"
46-
47 def feedkeys(s, mode='n'):
48 """Wrapper around vim's feedkeys function. Mainly for convenience."""
49 vim.command(r'call feedkeys("%s", "%s")' % (s, mode))
50
51 def echom(mes, *args):
52 mes = mes % args
53- vim.command('echom "%s"' % mes.replace('"', '\\"'))
54+ vim.command('echom %s' % vim_string(mes))
55
56 class _SnippetDictionary(object):
57 def __init__(self, *args, **kwargs):
58@@ -151,7 +147,7 @@
59 self._idx = 0
60
61 def _error(self, msg):
62- fn = vim.eval("""fnamemodify(%s, ":~:.")""" % _vim_quote(self._fn))
63+ fn = vim.eval("""fnamemodify(%s, ":~:.")""" % vim_string(self._fn))
64 self._sm._error("%s in %s(%d)" % (msg, fn, self._idx + 1))
65
66 def _line(self):
67@@ -755,7 +751,9 @@
68 feedkeys(r"i")
69 self._chars_entered('')
70 else:
71- feedkeys(r"\<BS>")
72+ # We can't just pass <BS> through, because we took vim
73+ # out of SELECT mode, so instead we reselect and replace
74+ feedkeys(r"gvc")
75
76 @err_to_scratch_buffer
77 def cursor_moved(self):
78@@ -831,7 +829,7 @@
79 # Private/Protect Functions Below #
80 ###################################
81 def _error(self, msg):
82- msg = _vim_quote("UltiSnips: " + msg)
83+ msg = vim_string("UltiSnips: " + msg)
84 if self._test_error:
85 msg = msg.replace('"', r'\"')
86 msg = msg.replace('|', r'\|')
87@@ -945,11 +943,17 @@
88 found_snippets += self._find_snippets(ft, before, possible)
89
90 # Search if any of the snippets overwrites the previous
91- snippets = []
92+ # Dictionary allows O(1) access for easy overwrites
93+ snippets = {}
94 for s in found_snippets:
95- if s.overwrites_previous:
96- snippets = []
97- snippets.append(s)
98+ if (s.trigger not in snippets) or s.overwrites_previous:
99+ snippets[s.trigger] = []
100+ snippets[s.trigger].append(s)
101+
102+ # Transform dictionary into flat list of snippets
103+ selected_snippets = set([item for sublist in snippets.values() for item in sublist])
104+ # Return snippets to their original order
105+ snippets = [snip for snip in found_snippets if snip in selected_snippets]
106
107 return snippets
108
109@@ -964,7 +968,7 @@
110 )
111
112 try:
113- rv = vim.eval("inputlist(%s)" % display)
114+ rv = vim.eval("inputlist([%s])" % vim_string(display))
115 if rv is None or rv == '0':
116 return None
117 rv = int(rv)
118
119=== modified file 'test.py'
120--- test.py 2011-04-28 02:41:30 +0000
121+++ test.py 2011-05-02 19:24:32 +0000
122@@ -1786,7 +1786,6 @@
123 keys = "abc test test" + EX
124 wanted = "abc test Expand me!"
125
126-
127 #######################
128 # MULTI-WORD SNIPPETS #
129 #######################
130@@ -1856,6 +1855,44 @@
131 keys = "a-test it" + EX
132 wanted = "a-Expand me!"
133
134+# Test for Bug #774917
135+def _snip_quote(qt):
136+ return (
137+ ("te" + qt + "st", "Expand me" + qt + "!", "test: "+qt),
138+ ("te", "Bad", ""),
139+ )
140+
141+class Snippet_With_SingleQuote(_VimTest):
142+ snippets = _snip_quote("'")
143+ keys = "te'st" + EX
144+ wanted = "Expand me'!"
145+
146+class Snippet_With_SingleQuote_List(_VimTest):
147+ snippets = _snip_quote("'")
148+ keys = "te" + LS + "1\n"
149+ wanted = "Expand me'!"
150+
151+class Snippet_With_DoubleQuote(_VimTest):
152+ snippets = _snip_quote('"')
153+ keys = 'te"st' + EX
154+ wanted = "Expand me\"!"
155+
156+class Snippet_With_DoubleQuote_List(_VimTest):
157+ snippets = _snip_quote('"')
158+ keys = "te" + LS + "1\n"
159+ wanted = "Expand me\"!"
160+
161+# Test for Bug #774917
162+class Backspace_TabStop_Zero(_VimTest):
163+ snippets = ("test", "A${1:C} ${0:DDD}", "This is Case 1")
164+ keys = "test" + EX + "A" + JF + BS + "BBB"
165+ wanted = "AA BBB"
166+
167+class Backspace_TabStop_NotZero(_VimTest):
168+ snippets = ("test", "A${1:C} ${2:DDD}", "This is Case 1")
169+ keys = "test" + EX + "A" + JF + BS + "BBB"
170+ wanted = "AA BBB"
171+
172 ######################
173 # SELECTING MULTIPLE #
174 ######################

Subscribers

People subscribed via source and target branches