Applied pyformat on entire codebase.

This commit is contained in:
Holger Rapp 2015-01-20 21:26:03 +01:00
parent e1436a8aeb
commit 6a787cdc7b
65 changed files with 3734 additions and 2457 deletions

View File

@ -10,39 +10,45 @@ import sys
from UltiSnips import _vim from UltiSnips import _vim
from UltiSnips.position import Position from UltiSnips.position import Position
def is_complete_edit(initial_line, original, wanted, cmds): def is_complete_edit(initial_line, original, wanted, cmds):
"""Returns true if 'original' is changed to 'wanted' with the edit commands """Returns true if 'original' is changed to 'wanted' with the edit commands
in 'cmds'. Initial line is to change the line numbers in 'cmds'.""" in 'cmds'.
Initial line is to change the line numbers in 'cmds'.
"""
buf = original[:] buf = original[:]
for cmd in cmds: for cmd in cmds:
ctype, line, col, char = cmd ctype, line, col, char = cmd
line -= initial_line line -= initial_line
if ctype == "D": if ctype == 'D':
if char != '\n': if char != '\n':
buf[line] = buf[line][:col] + buf[line][col+len(char):] buf[line] = buf[line][:col] + buf[line][col + len(char):]
else: else:
if line + 1 < len(buf): if line + 1 < len(buf):
buf[line] = buf[line] + buf[line+1] buf[line] = buf[line] + buf[line + 1]
del buf[line+1] del buf[line + 1]
else: else:
del buf[line] del buf[line]
elif ctype == "I": elif ctype == 'I':
buf[line] = buf[line][:col] + char + buf[line][col:] buf[line] = buf[line][:col] + char + buf[line][col:]
buf = '\n'.join(buf).split('\n') buf = '\n'.join(buf).split('\n')
return (len(buf) == len(wanted) and return (len(buf) == len(wanted) and
all(j == k for j, k in zip(buf, wanted))) all(j == k for j, k in zip(buf, wanted)))
def guess_edit(initial_line, last_text, current_text, vim_state): def guess_edit(initial_line, last_text, current_text, vim_state):
""" """Try to guess what the user might have done by heuristically looking at
Try to guess what the user might have done by heuristically looking at
cursor movement, number of changed lines and if they got longer or shorter. cursor movement, number of changed lines and if they got longer or shorter.
This will detect most simple movements like insertion, deletion of a line This will detect most simple movements like insertion, deletion of a line
or carriage return. 'initial_text' is the index of where the comparison or carriage return. 'initial_text' is the index of where the comparison
starts, 'last_text' is the last text of the snippet, 'current_text' is the starts, 'last_text' is the last text of the snippet, 'current_text' is the
current text of the snippet and 'vim_state' is the cached vim state. current text of the snippet and 'vim_state' is the cached vim state.
Returns (True, edit_cmds) when the edit could be guessed, (False, None) Returns (True, edit_cmds) when the edit could be guessed, (False,
otherwise. None) otherwise.
""" """
if not len(last_text) and not len(current_text): if not len(last_text) and not len(current_text):
return True, () return True, ()
@ -53,83 +59,84 @@ def guess_edit(initial_line, last_text, current_text, vim_state):
if (len(last_text) and if (len(last_text) and
(not current_text or (not current_text or
(len(current_text) == 1 and not current_text[0])) (len(current_text) == 1 and not current_text[0]))
): ):
es = [] es = []
if not current_text: if not current_text:
current_text = [''] current_text = ['']
for i in last_text: for i in last_text:
es.append(("D", initial_line, 0, i)) es.append(('D', initial_line, 0, i))
es.append(("D", initial_line, 0, "\n")) es.append(('D', initial_line, 0, '\n'))
es.pop() # Remove final \n because it is not really removed es.pop() # Remove final \n because it is not really removed
if is_complete_edit(initial_line, last_text, current_text, es): if is_complete_edit(initial_line, last_text, current_text, es):
return True, es return True, es
if ppos.mode == 'v': # Maybe selectmode? if ppos.mode == 'v': # Maybe selectmode?
sv = list(map(int, _vim.eval("""getpos("'<")"""))) sv = list(map(int, _vim.eval("""getpos("'<")""")))
sv = Position(sv[1]-1, sv[2]-1) sv = Position(sv[1] - 1, sv[2] - 1)
ev = list(map(int, _vim.eval("""getpos("'>")"""))) ev = list(map(int, _vim.eval("""getpos("'>")""")))
ev = Position(ev[1]-1, ev[2]-1) ev = Position(ev[1] - 1, ev[2] - 1)
if "exclusive" in _vim.eval("&selection"): if 'exclusive' in _vim.eval('&selection'):
ppos.col -= 1 # We want to be inclusive, sorry. ppos.col -= 1 # We want to be inclusive, sorry.
ev.col -= 1 ev.col -= 1
es = [] es = []
if sv.line == ev.line: if sv.line == ev.line:
es.append(("D", sv.line, sv.col, es.append(('D', sv.line, sv.col,
last_text[sv.line - initial_line][sv.col:ev.col+1])) last_text[sv.line - initial_line][sv.col:ev.col + 1]))
if sv != pos and sv.line == pos.line: if sv != pos and sv.line == pos.line:
es.append(("I", sv.line, sv.col, es.append(('I', sv.line, sv.col,
current_text[sv.line - initial_line][sv.col:pos.col+1])) current_text[sv.line - initial_line][sv.col:pos.col + 1]))
if is_complete_edit(initial_line, last_text, current_text, es): if is_complete_edit(initial_line, last_text, current_text, es):
return True, es return True, es
if pos.line == ppos.line: if pos.line == ppos.line:
if len(last_text) == len(current_text): # Movement only in one line if len(last_text) == len(current_text): # Movement only in one line
llen = len(last_text[ppos.line - initial_line]) llen = len(last_text[ppos.line - initial_line])
clen = len(current_text[pos.line - initial_line]) clen = len(current_text[pos.line - initial_line])
if ppos < pos and clen > llen: # maybe only chars have been added if ppos < pos and clen > llen: # maybe only chars have been added
es = ( es = (
("I", ppos.line, ppos.col, ('I', ppos.line, ppos.col,
current_text[ppos.line - initial_line] current_text[ppos.line - initial_line]
[ppos.col:pos.col]), [ppos.col:pos.col]),
) )
if is_complete_edit(initial_line, last_text, current_text, es): if is_complete_edit(initial_line, last_text, current_text, es):
return True, es return True, es
if clen < llen: if clen < llen:
if ppos == pos: # 'x' or DEL or dt or something if ppos == pos: # 'x' or DEL or dt or something
es = ( es = (
("D", pos.line, pos.col, ('D', pos.line, pos.col,
last_text[ppos.line - initial_line] last_text[ppos.line - initial_line]
[ppos.col:ppos.col + (llen - clen)]), [ppos.col:ppos.col + (llen - clen)]),
) )
if is_complete_edit(initial_line, last_text, if is_complete_edit(initial_line, last_text,
current_text, es): current_text, es):
return True, es return True, es
if pos < ppos: # Backspacing or dT dF? if pos < ppos: # Backspacing or dT dF?
es = ( es = (
("D", pos.line, pos.col, ('D', pos.line, pos.col,
last_text[pos.line - initial_line] last_text[pos.line - initial_line]
[pos.col:pos.col + llen - clen]), [pos.col:pos.col + llen - clen]),
) )
if is_complete_edit(initial_line, last_text, if is_complete_edit(initial_line, last_text,
current_text, es): current_text, es):
return True, es return True, es
elif len(current_text) < len(last_text): elif len(current_text) < len(last_text):
# where some lines deleted? (dd or so) # where some lines deleted? (dd or so)
es = [] es = []
for i in range(len(last_text)-len(current_text)): for i in range(len(last_text) - len(current_text)):
es.append(("D", pos.line, 0, es.append(('D', pos.line, 0,
last_text[pos.line - initial_line + i])) last_text[pos.line - initial_line + i]))
es.append(("D", pos.line, 0, '\n')) es.append(('D', pos.line, 0, '\n'))
if is_complete_edit(initial_line, last_text, if is_complete_edit(initial_line, last_text,
current_text, es): current_text, es):
return True, es return True, es
else: else:
# Movement in more than one line # Movement in more than one line
if ppos.line + 1 == pos.line and pos.col == 0: # Carriage return? if ppos.line + 1 == pos.line and pos.col == 0: # Carriage return?
es = (("I", ppos.line, ppos.col, "\n"),) es = (('I', ppos.line, ppos.col, '\n'),)
if is_complete_edit(initial_line, last_text, if is_complete_edit(initial_line, last_text,
current_text, es): current_text, es):
return True, es return True, es
return False, None return False, None
def diff(a, b, sline=0): def diff(a, b, sline=0):
""" """
Return a list of deletions and insertions that will turn 'a' into 'b'. This Return a list of deletions and insertions that will turn 'a' into 'b'. This
@ -154,8 +161,8 @@ def diff(a, b, sline=0):
d[0] = [(0, 0, sline, 0, ())] d[0] = [(0, 0, sline, 0, ())]
cost = 0 cost = 0
deletion_cost = len(a)+len(b) deletion_cost = len(a) + len(b)
insertion_cost = len(a)+len(b) insertion_cost = len(a) + len(b)
while True: while True:
while len(d[cost]): while len(d[cost]):
x, y, line, col, what = d[cost].pop() x, y, line, col, what = d[cost].pop()
@ -170,50 +177,50 @@ def diff(a, b, sline=0):
ncol = 0 ncol = 0
nline += 1 nline += 1
lcost = cost + 1 lcost = cost + 1
if (what and what[-1][0] == "D" and what[-1][1] == line and if (what and what[-1][0] == 'D' and what[-1][1] == line and
what[-1][2] == col and a[x] != '\n'): what[-1][2] == col and a[x] != '\n'):
# Matching directly after a deletion should be as costly as # Matching directly after a deletion should be as costly as
# DELETE + INSERT + a bit # DELETE + INSERT + a bit
lcost = (deletion_cost + insertion_cost)*1.5 lcost = (deletion_cost + insertion_cost) * 1.5
if seen[x+1, y+1] > lcost: if seen[x + 1, y + 1] > lcost:
d[lcost].append((x+1, y+1, nline, ncol, what)) d[lcost].append((x + 1, y + 1, nline, ncol, what))
seen[x+1, y+1] = lcost seen[x + 1, y + 1] = lcost
if y < len(b): # INSERT if y < len(b): # INSERT
ncol = col + 1 ncol = col + 1
nline = line nline = line
if b[y] == '\n': if b[y] == '\n':
ncol = 0 ncol = 0
nline += 1 nline += 1
if (what and what[-1][0] == "I" and what[-1][1] == nline and if (what and what[-1][0] == 'I' and what[-1][1] == nline and
what[-1][2]+len(what[-1][-1]) == col and b[y] != '\n' and what[-1][2] + len(what[-1][-1]) == col and b[y] != '\n' and
seen[x, y+1] > cost + (insertion_cost + ncol) // 2 seen[x, y + 1] > cost + (insertion_cost + ncol) // 2
): ):
seen[x, y+1] = cost + (insertion_cost + ncol) // 2 seen[x, y + 1] = cost + (insertion_cost + ncol) // 2
d[cost + (insertion_cost + ncol) // 2].append( d[cost + (insertion_cost + ncol) // 2].append(
(x, y+1, line, ncol, what[:-1] + ( (x, y + 1, line, ncol, what[:-1] + (
("I", what[-1][1], what[-1][2], ('I', what[-1][1], what[-1][2],
what[-1][-1] + b[y]),) what[-1][-1] + b[y]),)
) )
) )
elif seen[x, y+1] > cost + insertion_cost + ncol: elif seen[x, y + 1] > cost + insertion_cost + ncol:
seen[x, y+1] = cost + insertion_cost + ncol seen[x, y + 1] = cost + insertion_cost + ncol
d[cost + ncol + insertion_cost].append((x, y+1, nline, ncol, d[cost + ncol + insertion_cost].append((x, y + 1, nline, ncol,
what + (("I", line, col, b[y]),)) what + (('I', line, col, b[y]),))
) )
if x < len(a): # DELETE if x < len(a): # DELETE
if (what and what[-1][0] == "D" and what[-1][1] == line and if (what and what[-1][0] == 'D' and what[-1][1] == line and
what[-1][2] == col and a[x] != '\n' and what[-1][2] == col and a[x] != '\n' and
what[-1][-1] != '\n' and what[-1][-1] != '\n' and
seen[x+1, y] > cost + deletion_cost // 2 seen[x + 1, y] > cost + deletion_cost // 2
): ):
seen[x+1, y] = cost + deletion_cost // 2 seen[x + 1, y] = cost + deletion_cost // 2
d[cost + deletion_cost // 2].append( d[cost + deletion_cost // 2].append(
(x+1, y, line, col, what[:-1] + ( (x + 1, y, line, col, what[:-1] + (
("D", line, col, what[-1][-1] + a[x]),)) ('D', line, col, what[-1][-1] + a[x]),))
)
elif seen[x+1, y] > cost + deletion_cost:
seen[x+1, y] = cost + deletion_cost
d[cost + deletion_cost].append((x+1, y, line, col, what +
(("D", line, col, a[x]),))
) )
elif seen[x + 1, y] > cost + deletion_cost:
seen[x + 1, y] = cost + deletion_cost
d[cost + deletion_cost].append((x + 1, y, line, col, what +
(('D', line, col, a[x]),))
)
cost += 1 cost += 1

View File

@ -9,35 +9,37 @@ import vim # pylint:disable=import-error
from vim import error # pylint:disable=import-error,unused-import from vim import error # pylint:disable=import-error,unused-import
from UltiSnips.compatibility import col2byte, byte2col, \ from UltiSnips.compatibility import col2byte, byte2col, \
as_unicode, as_vimencoding as_unicode, as_vimencoding
from UltiSnips.position import Position from UltiSnips.position import Position
class VimBuffer(object): class VimBuffer(object):
"""Wrapper around the current Vim buffer.""" """Wrapper around the current Vim buffer."""
def __getitem__(self, idx): def __getitem__(self, idx):
if isinstance(idx, slice): # Py3 if isinstance(idx, slice): # Py3
return self.__getslice__(idx.start, idx.stop) return self.__getslice__(idx.start, idx.stop)
rv = vim.current.buffer[idx] rv = vim.current.buffer[idx]
return as_unicode(rv) return as_unicode(rv)
def __getslice__(self, i, j): # pylint:disable=no-self-use def __getslice__(self, i, j): # pylint:disable=no-self-use
rv = vim.current.buffer[i:j] rv = vim.current.buffer[i:j]
return [as_unicode(l) for l in rv] return [as_unicode(l) for l in rv]
def __setitem__(self, idx, text): def __setitem__(self, idx, text):
if isinstance(idx, slice): # Py3 if isinstance(idx, slice): # Py3
return self.__setslice__(idx.start, idx.stop, text) return self.__setslice__(idx.start, idx.stop, text)
vim.current.buffer[idx] = as_vimencoding(text) vim.current.buffer[idx] = as_vimencoding(text)
def __setslice__(self, i, j, text): # pylint:disable=no-self-use def __setslice__(self, i, j, text): # pylint:disable=no-self-use
vim.current.buffer[i:j] = [as_vimencoding(l) for l in text] vim.current.buffer[i:j] = [as_vimencoding(l) for l in text]
def __len__(self): def __len__(self):
return len(vim.current.buffer) return len(vim.current.buffer)
@property @property
def line_till_cursor(self): # pylint:disable=no-self-use def line_till_cursor(self): # pylint:disable=no-self-use
"""Returns the text before the cursor.""" """Returns the text before the cursor."""
# Note: we want byte position here # Note: we want byte position here
_, col = vim.current.window.cursor _, col = vim.current.window.cursor
@ -46,27 +48,30 @@ class VimBuffer(object):
return before return before
@property @property
def number(self): # pylint:disable=no-self-use def number(self): # pylint:disable=no-self-use
"""The bufnr() of this buffer.""" """The bufnr() of this buffer."""
return int(eval("bufnr('%')")) return int(eval("bufnr('%')"))
@property @property
def cursor(self): # pylint:disable=no-self-use def cursor(self): # pylint:disable=no-self-use
""" """The current windows cursor.
The current windows cursor. Note that this is 0 based in col and 0
based in line which is different from Vim's cursor. Note that this is 0 based in col and 0 based in line which is
different from Vim's cursor.
""" """
line, nbyte = vim.current.window.cursor line, nbyte = vim.current.window.cursor
col = byte2col(line, nbyte) col = byte2col(line, nbyte)
return Position(line - 1, col) return Position(line - 1, col)
@cursor.setter @cursor.setter
def cursor(self, pos): # pylint:disable=no-self-use def cursor(self, pos): # pylint:disable=no-self-use
"""See getter.""" """See getter."""
nbyte = col2byte(pos.line + 1, pos.col) nbyte = col2byte(pos.line + 1, pos.col)
vim.current.window.cursor = pos.line + 1, nbyte vim.current.window.cursor = pos.line + 1, nbyte
buf = VimBuffer() # pylint:disable=invalid-name buf = VimBuffer() # pylint:disable=invalid-name
def escape(inp): def escape(inp):
"""Creates a vim-friendly string from a group of """Creates a vim-friendly string from a group of
dicts, lists and strings.""" dicts, lists and strings."""
@ -76,17 +81,19 @@ def escape(inp):
rv = as_unicode('[' + ','.join(conv(o) for o in obj) + ']') rv = as_unicode('[' + ','.join(conv(o) for o in obj) + ']')
elif isinstance(obj, dict): elif isinstance(obj, dict):
rv = as_unicode('{' + ','.join([ rv = as_unicode('{' + ','.join([
"%s:%s" % (conv(key), conv(value)) '%s:%s' % (conv(key), conv(value))
for key, value in obj.iteritems()]) + '}') for key, value in obj.iteritems()]) + '}')
else: else:
rv = as_unicode('"%s"') % as_unicode(obj).replace('"', '\\"') rv = as_unicode('"%s"') % as_unicode(obj).replace('"', '\\"')
return rv return rv
return conv(inp) return conv(inp)
def command(cmd): def command(cmd):
"""Wraps vim.command.""" """Wraps vim.command."""
return as_unicode(vim.command(as_vimencoding(cmd))) return as_unicode(vim.command(as_vimencoding(cmd)))
def eval(text): def eval(text):
"""Wraps vim.eval.""" """Wraps vim.eval."""
rv = vim.eval(as_vimencoding(text)) rv = vim.eval(as_vimencoding(text))
@ -94,77 +101,88 @@ def eval(text):
return as_unicode(rv) return as_unicode(rv)
return rv return rv
def feedkeys(keys, mode='n'): def feedkeys(keys, mode='n'):
"""Wrapper around vim's feedkeys function. Mainly for convenience.""" """Wrapper around vim's feedkeys function.
Mainly for convenience.
"""
command(as_unicode(r'call feedkeys("%s", "%s")') % (keys, mode)) command(as_unicode(r'call feedkeys("%s", "%s")') % (keys, mode))
def new_scratch_buffer(text): def new_scratch_buffer(text):
"""Create a new scratch buffer with the text given""" """Create a new scratch buffer with the text given."""
vim.command("botright new") vim.command('botright new')
vim.command("set ft=") vim.command('set ft=')
vim.command("set buftype=nofile") vim.command('set buftype=nofile')
vim.current.buffer[:] = text.splitlines() vim.current.buffer[:] = text.splitlines()
feedkeys(r"\<Esc>") feedkeys(r"\<Esc>")
def virtual_position(line, col): def virtual_position(line, col):
"""Runs the position through virtcol() and returns the result.""" """Runs the position through virtcol() and returns the result."""
nbytes = col2byte(line, col) nbytes = col2byte(line, col)
return line, int(eval('virtcol([%d, %d])' % (line, nbytes))) return line, int(eval('virtcol([%d, %d])' % (line, nbytes)))
def select(start, end): def select(start, end):
"""Select the span in Select mode""" """Select the span in Select mode."""
_unmap_select_mode_mapping() _unmap_select_mode_mapping()
selection = eval("&selection") selection = eval('&selection')
col = col2byte(start.line + 1, start.col) col = col2byte(start.line + 1, start.col)
vim.current.window.cursor = start.line + 1, col vim.current.window.cursor = start.line + 1, col
move_cmd = "" move_cmd = ''
if eval("mode()") != 'n': if eval('mode()') != 'n':
move_cmd += r"\<Esc>" move_cmd += r"\<Esc>"
if start == end: if start == end:
# Zero Length Tabstops, use 'i' or 'a'. # Zero Length Tabstops, use 'i' or 'a'.
if col == 0 or eval("mode()") not in 'i' and \ if col == 0 or eval('mode()') not in 'i' and \
col < len(buf[start.line]): col < len(buf[start.line]):
move_cmd += "i" move_cmd += 'i'
else: else:
move_cmd += "a" move_cmd += 'a'
else: else:
# Non zero length, use Visual selection. # Non zero length, use Visual selection.
move_cmd += "v" move_cmd += 'v'
if "inclusive" in selection: if 'inclusive' in selection:
if end.col == 0: if end.col == 0:
move_cmd += "%iG$" % end.line move_cmd += '%iG$' % end.line
else: else:
move_cmd += "%iG%i|" % virtual_position(end.line + 1, end.col) move_cmd += '%iG%i|' % virtual_position(end.line + 1, end.col)
elif "old" in selection: elif 'old' in selection:
move_cmd += "%iG%i|" % virtual_position(end.line + 1, end.col) move_cmd += '%iG%i|' % virtual_position(end.line + 1, end.col)
else: else:
move_cmd += "%iG%i|" % virtual_position(end.line + 1, end.col + 1) move_cmd += '%iG%i|' % virtual_position(end.line + 1, end.col + 1)
move_cmd += "o%iG%i|o\\<c-g>" % virtual_position( move_cmd += 'o%iG%i|o\\<c-g>' % virtual_position(
start.line + 1, start.col + 1) start.line + 1, start.col + 1)
feedkeys(_LangMapTranslator().translate(move_cmd)) feedkeys(_LangMapTranslator().translate(move_cmd))
def _unmap_select_mode_mapping(): def _unmap_select_mode_mapping():
"""This function unmaps select mode mappings if so wished by the user. """This function unmaps select mode mappings if so wished by the user.
Removes select mode mappings that can actually be typed by the user Removes select mode mappings that can actually be typed by the user
(ie, ignores things like <Plug>). (ie, ignores things like <Plug>).
"""
if int(eval("g:UltiSnipsRemoveSelectModeMappings")):
ignores = eval("g:UltiSnipsMappingsToIgnore") + ['UltiSnips']
for option in ("<buffer>", ""): """
if int(eval('g:UltiSnipsRemoveSelectModeMappings')):
ignores = eval('g:UltiSnipsMappingsToIgnore') + ['UltiSnips']
for option in ('<buffer>', ''):
# Put all smaps into a var, and then read the var # Put all smaps into a var, and then read the var
command(r"redir => _tmp_smaps | silent smap %s " % option + command(r"redir => _tmp_smaps | silent smap %s " % option +
"| redir END") '| redir END')
# Check if any mappings where found # Check if any mappings where found
all_maps = list(filter(len, eval(r"_tmp_smaps").splitlines())) all_maps = list(filter(len, eval(r"_tmp_smaps").splitlines()))
if len(all_maps) == 1 and all_maps[0][0] not in " sv": if len(all_maps) == 1 and all_maps[0][0] not in ' sv':
# "No maps found". String could be localized. Hopefully # "No maps found". String could be localized. Hopefully
# it doesn't start with any of these letters in any # it doesn't start with any of these letters in any
# language # language
@ -172,37 +190,38 @@ def _unmap_select_mode_mapping():
# Only keep mappings that should not be ignored # Only keep mappings that should not be ignored
maps = [m for m in all_maps if maps = [m for m in all_maps if
not any(i in m for i in ignores) and len(m.strip())] not any(i in m for i in ignores) and len(m.strip())]
for map in maps: for map in maps:
# The first three chars are the modes, that might be listed. # The first three chars are the modes, that might be listed.
# We are not interested in them here. # We are not interested in them here.
trig = map[3:].split()[0] if len(map[3:].split()) != 0 else None trig = map[3:].split()[0] if len(
map[3:].split()) != 0 else None
if trig is None: if trig is None:
continue continue
# The bar separates commands # The bar separates commands
if trig[-1] == "|": if trig[-1] == '|':
trig = trig[:-1] + "<Bar>" trig = trig[:-1] + '<Bar>'
# Special ones # Special ones
if trig[0] == "<": if trig[0] == '<':
add = False add = False
# Only allow these # Only allow these
for valid in ["Tab", "NL", "CR", "C-Tab", "BS"]: for valid in ['Tab', 'NL', 'CR', 'C-Tab', 'BS']:
if trig == "<%s>" % valid: if trig == '<%s>' % valid:
add = True add = True
if not add: if not add:
continue continue
# UltiSnips remaps <BS>. Keep this around. # UltiSnips remaps <BS>. Keep this around.
if trig == "<BS>": if trig == '<BS>':
continue continue
# Actually unmap it # Actually unmap it
try: try:
command("silent! sunmap %s %s" % (option, trig)) command('silent! sunmap %s %s' % (option, trig))
except: # pylint:disable=bare-except except: # pylint:disable=bare-except
# Bug 908139: ignore unmaps that fail because of # Bug 908139: ignore unmaps that fail because of
# unprintable characters. This is not ideal because we # unprintable characters. This is not ideal because we
@ -214,16 +233,19 @@ def _unmap_select_mode_mapping():
# though. # though.
pass pass
class _RealLangMapTranslator(object): class _RealLangMapTranslator(object):
"""This cares for the Vim langmap option and basically reverses the """This cares for the Vim langmap option and basically reverses the
mappings. This was the only solution to get UltiSnips to work nicely with mappings. This was the only solution to get UltiSnips to work nicely with
langmap; other stuff I tried was using inoremap movement commands and langmap; other stuff I tried was using inoremap movement commands and
caching and restoring the langmap option. caching and restoring the langmap option.
Note that this will not work if the langmap overwrites a character Note that this will not work if the langmap overwrites a character
completely, for example if 'j' is remapped, but nothing is mapped back to completely, for example if 'j' is remapped, but nothing is mapped
'j', then moving one line down is no longer possible and UltiSnips will back to 'j', then moving one line down is no longer possible and
fail. UltiSnips will fail.
""" """
_maps = {} _maps = {}
_SEMICOLONS = re.compile(r"(?<!\\);") _SEMICOLONS = re.compile(r"(?<!\\);")
@ -231,12 +253,12 @@ class _RealLangMapTranslator(object):
def _create_translation(self, langmap): def _create_translation(self, langmap):
"""Create the reverse mapping from 'langmap'.""" """Create the reverse mapping from 'langmap'."""
from_chars, to_chars = "", "" from_chars, to_chars = '', ''
for char in self._COMMA.split(langmap): for char in self._COMMA.split(langmap):
char = char.replace("\\,", ",") char = char.replace('\\,', ',')
res = self._SEMICOLONS.split(char) res = self._SEMICOLONS.split(char)
if len(res) > 1: if len(res) > 1:
from_char, to_char = [a.replace("\\;", ";") for a in res] from_char, to_char = [a.replace('\\;', ';') for a in res]
from_chars += from_char from_chars += from_char
to_chars += to_char to_chars += to_char
else: else:
@ -246,8 +268,8 @@ class _RealLangMapTranslator(object):
def translate(self, text): def translate(self, text):
"""Inverse map 'text' through langmap.""" """Inverse map 'text' through langmap."""
langmap = eval("&langmap").strip() langmap = eval('&langmap').strip()
if langmap == "": if langmap == '':
return text return text
text = as_unicode(text) text = as_unicode(text)
if langmap not in self._maps: if langmap not in self._maps:
@ -256,9 +278,14 @@ class _RealLangMapTranslator(object):
text = text.replace(before, after) text = text.replace(before, after)
return text return text
class _DummyLangMapTranslator(object): class _DummyLangMapTranslator(object):
"""If vim hasn't got the langmap compiled in, we never have to do anything. """If vim hasn't got the langmap compiled in, we never have to do anything.
Then this class is used. """
Then this class is used.
"""
translate = lambda self, s: s translate = lambda self, s: s
_LangMapTranslator = _RealLangMapTranslator _LangMapTranslator = _RealLangMapTranslator

View File

@ -1,10 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
""" """This file contains compatibility code to stay compatible with as many python
This file contains compatibility code to stay compatible with versions as possible."""
as many python versions as possible.
"""
import sys import sys
@ -16,34 +14,30 @@ if sys.version_info >= (3, 0):
# We don't have the luxury here of failing, everything # We don't have the luxury here of failing, everything
# falls apart if we don't return a bytearray from the # falls apart if we don't return a bytearray from the
# passed in string # passed in string
return string.decode(vim.eval("&encoding"), "replace") return string.decode(vim.eval('&encoding'), 'replace')
def _vim_enc(bytearray): def _vim_enc(bytearray):
"""Encode 'string' using &encoding.""" """Encode 'string' using &encoding."""
# We don't have the luxury here of failing, everything # We don't have the luxury here of failing, everything
# falls apart if we don't return a string from the passed # falls apart if we don't return a string from the passed
# in bytearray # in bytearray
return bytearray.encode(vim.eval("&encoding"), "replace") return bytearray.encode(vim.eval('&encoding'), 'replace')
def open_ascii_file(filename, mode): def open_ascii_file(filename, mode):
"""Opens a file in "r" mode.""" """Opens a file in "r" mode."""
return open(filename, mode, encoding="utf-8") return open(filename, mode, encoding='utf-8')
def col2byte(line, col): def col2byte(line, col):
""" """Convert a valid column index into a byte index inside of vims
Convert a valid column index into a byte index inside buffer."""
of vims buffer.
"""
# We pad the line so that selecting the +1 st column still works. # We pad the line so that selecting the +1 st column still works.
pre_chars = (vim.current.buffer[line-1] + " ")[:col] pre_chars = (vim.current.buffer[line - 1] + ' ')[:col]
return len(_vim_enc(pre_chars)) return len(_vim_enc(pre_chars))
def byte2col(line, nbyte): def byte2col(line, nbyte):
""" """Convert a column into a byteidx suitable for a mark or cursor
Convert a column into a byteidx suitable for a mark or cursor position inside of vim."""
position inside of vim line = vim.current.buffer[line - 1]
"""
line = vim.current.buffer[line-1]
raw_bytes = _vim_enc(line)[:nbyte] raw_bytes = _vim_enc(line)[:nbyte]
return len(_vim_dec(raw_bytes)) return len(_vim_dec(raw_bytes))
@ -58,12 +52,12 @@ if sys.version_info >= (3, 0):
return string return string
else: else:
import warnings import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning) warnings.filterwarnings('ignore', category=DeprecationWarning)
def _vim_dec(string): def _vim_dec(string):
"""Decode 'string' using &encoding.""" """Decode 'string' using &encoding."""
try: try:
return string.decode(vim.eval("&encoding")) return string.decode(vim.eval('&encoding'))
except UnicodeDecodeError: except UnicodeDecodeError:
# At least we tried. There might be some problems down the road now # At least we tried. There might be some problems down the road now
return string return string
@ -71,7 +65,7 @@ else:
def _vim_enc(string): def _vim_enc(string):
"""Encode 'string' using &encoding.""" """Encode 'string' using &encoding."""
try: try:
return string.encode(vim.eval("&encoding")) return string.encode(vim.eval('&encoding'))
except UnicodeDecodeError: except UnicodeDecodeError:
return string return string
except UnicodeEncodeError: except UnicodeEncodeError:
@ -82,21 +76,17 @@ else:
return open(filename, mode) return open(filename, mode)
def col2byte(line, col): def col2byte(line, col):
""" """Convert a valid column index into a byte index inside of vims
Convert a valid column index into a byte index inside buffer."""
of vims buffer.
"""
# We pad the line so that selecting the +1 st column still works. # We pad the line so that selecting the +1 st column still works.
pre_chars = _vim_dec(vim.current.buffer[line-1] + " ")[:col] pre_chars = _vim_dec(vim.current.buffer[line - 1] + ' ')[:col]
return len(_vim_enc(pre_chars)) return len(_vim_enc(pre_chars))
def byte2col(line, nbyte): def byte2col(line, nbyte):
""" """Convert a column into a byteidx suitable for a mark or cursor
Convert a column into a byteidx suitable for a mark or cursor position inside of vim."""
position inside of vim line = vim.current.buffer[line - 1]
""" if nbyte >= len(line): # This is beyond end of line
line = vim.current.buffer[line-1]
if nbyte >= len(line): # This is beyond end of line
return nbyte return nbyte
return len(_vim_dec(line[:nbyte])) return len(_vim_dec(line[:nbyte]))

View File

@ -1,17 +1,21 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""Convenience methods that help with debugging. They should never be used in """Convenience methods that help with debugging.
production code."""
They should never be used in production code.
"""
import sys import sys
from UltiSnips.compatibility import as_unicode from UltiSnips.compatibility import as_unicode
DUMP_FILENAME = "/tmp/file.txt" if not sys.platform.lower().startswith("win") \ DUMP_FILENAME = '/tmp/file.txt' if not sys.platform.lower().startswith('win') \
else "C:/windows/temp/ultisnips.txt" else 'C:/windows/temp/ultisnips.txt'
with open(DUMP_FILENAME, "w"): with open(DUMP_FILENAME, 'w'):
pass # clears the file pass # clears the file
def echo_to_hierarchy(text_object): def echo_to_hierarchy(text_object):
"""Outputs the given 'text_object' and its children hierarchically.""" """Outputs the given 'text_object' and its children hierarchically."""
@ -20,24 +24,26 @@ def echo_to_hierarchy(text_object):
while parent._parent: while parent._parent:
parent = parent._parent parent = parent._parent
def _do_print(text_object, indent=""): def _do_print(text_object, indent=''):
"""prints recursively.""" """prints recursively."""
debug(indent + as_unicode(text_object)) debug(indent + as_unicode(text_object))
try: try:
for child in text_object._children: for child in text_object._children:
_do_print(child, indent=indent + " ") _do_print(child, indent=indent + ' ')
except AttributeError: except AttributeError:
pass pass
_do_print(parent) _do_print(parent)
def debug(msg): def debug(msg):
"""Dumb 'msg' into the debug file.""" """Dumb 'msg' into the debug file."""
msg = as_unicode(msg) msg = as_unicode(msg)
with open(DUMP_FILENAME, "ab") as dump_file: with open(DUMP_FILENAME, 'ab') as dump_file:
dump_file.write((msg + '\n').encode("utf-8")) dump_file.write((msg + '\n').encode('utf-8'))
def print_stack(): def print_stack():
"""Dump a stack trace into the debug file.""" """Dump a stack trace into the debug file."""
import traceback import traceback
with open(DUMP_FILENAME, "ab") as dump_file: with open(DUMP_FILENAME, 'ab') as dump_file:
traceback.print_stack(file=dump_file) traceback.print_stack(file=dump_file)

View File

@ -5,35 +5,38 @@
from UltiSnips import _vim from UltiSnips import _vim
class IndentUtil(object): class IndentUtil(object):
"""Utility class for dealing properly with indentation. """
"""Utility class for dealing properly with indentation."""
def __init__(self): def __init__(self):
self.reset() self.reset()
def reset(self): def reset(self):
""" Gets the spacing properties from Vim. """ """Gets the spacing properties from Vim."""
self.shiftwidth = int(_vim.eval("exists('*shiftwidth') ? shiftwidth() : &shiftwidth")) self.shiftwidth = int(
self._expandtab = (_vim.eval("&expandtab") == "1") _vim.eval("exists('*shiftwidth') ? shiftwidth() : &shiftwidth"))
self._tabstop = int(_vim.eval("&tabstop")) self._expandtab = (_vim.eval('&expandtab') == '1')
self._tabstop = int(_vim.eval('&tabstop'))
def ntabs_to_proper_indent(self, ntabs): def ntabs_to_proper_indent(self, ntabs):
"""Convert 'ntabs' number of tabs to the proper indent prefix.""" """Convert 'ntabs' number of tabs to the proper indent prefix."""
line_ind = ntabs * self.shiftwidth * " " line_ind = ntabs * self.shiftwidth * ' '
line_ind = self.indent_to_spaces(line_ind) line_ind = self.indent_to_spaces(line_ind)
line_ind = self.spaces_to_indent(line_ind) line_ind = self.spaces_to_indent(line_ind)
return line_ind return line_ind
def indent_to_spaces(self, indent): def indent_to_spaces(self, indent):
""" Converts indentation to spaces respecting Vim settings. """ """Converts indentation to spaces respecting Vim settings."""
indent = indent.expandtabs(self._tabstop) indent = indent.expandtabs(self._tabstop)
right = (len(indent) - len(indent.rstrip(" "))) * " " right = (len(indent) - len(indent.rstrip(' '))) * ' '
indent = indent.replace(" ", "") indent = indent.replace(' ', '')
indent = indent.replace('\t', " " * self._tabstop) indent = indent.replace('\t', ' ' * self._tabstop)
return indent + right return indent + right
def spaces_to_indent(self, indent): def spaces_to_indent(self, indent):
""" Converts spaces to proper indentation respecting Vim settings """ """Converts spaces to proper indentation respecting Vim settings."""
if not self._expandtab: if not self._expandtab:
indent = indent.replace(" " * self._tabstop, '\t') indent = indent.replace(' ' * self._tabstop, '\t')
return indent return indent

View File

@ -4,7 +4,9 @@
"""Represents a Position in a text file: (0 based line index, 0 based column """Represents a Position in a text file: (0 based line index, 0 based column
index) and provides methods for moving them around.""" index) and provides methods for moving them around."""
class Position(object): class Position(object):
"""See module docstring.""" """See module docstring."""
def __init__(self, line, col): def __init__(self, line, col):
@ -13,7 +15,7 @@ class Position(object):
def move(self, pivot, delta): def move(self, pivot, delta):
"""'pivot' is the position of the first changed character, 'delta' is """'pivot' is the position of the first changed character, 'delta' is
how text after it moved""" how text after it moved."""
if self < pivot: if self < pivot:
return return
if delta.line == 0: if delta.line == 0:
@ -62,4 +64,4 @@ class Position(object):
return (self.line, self.col) <= (other.line, other.col) return (self.line, self.col) <= (other.line, other.col)
def __repr__(self): def __repr__(self):
return "(%i,%i)" % (self.line, self.col) return '(%i,%i)' % (self.line, self.col)

View File

@ -11,10 +11,12 @@ from UltiSnips.indent_util import IndentUtil
from UltiSnips.text import escape from UltiSnips.text import escape
from UltiSnips.text_objects import SnippetInstance from UltiSnips.text_objects import SnippetInstance
def _words_for_line(trigger, before, num_words=None): def _words_for_line(trigger, before, num_words=None):
""" Gets the final 'num_words' words from 'before'. """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, then use the number of words in 'trigger'.
""" """
if not len(before): if not len(before):
return '' return ''
@ -32,20 +34,22 @@ def _words_for_line(trigger, before, num_words=None):
before_words = before_words[:left] before_words = before_words[:left]
return before[len(before_words):].strip() return before[len(before_words):].strip()
class SnippetDefinition(object): class SnippetDefinition(object):
"""Represents a snippet as parsed from a file.""" """Represents a snippet as parsed from a file."""
_INDENT = re.compile(r"^[ \t]*") _INDENT = re.compile(r"^[ \t]*")
_TABS = re.compile(r"^\t*") _TABS = re.compile(r"^\t*")
def __init__(self, priority, trigger, value, description, def __init__(self, priority, trigger, value, description,
options, globals, location): options, globals, location):
self._priority = priority self._priority = priority
self._trigger = as_unicode(trigger) self._trigger = as_unicode(trigger)
self._value = as_unicode(value) self._value = as_unicode(value)
self._description = as_unicode(description) self._description = as_unicode(description)
self._opts = options self._opts = options
self._matched = "" self._matched = ''
self._last_re = None self._last_re = None
self._globals = globals self._globals = globals
self._location = location self._location = location
@ -55,12 +59,14 @@ class SnippetDefinition(object):
self.matches(self._trigger) self.matches(self._trigger)
def __repr__(self): def __repr__(self):
return "_SnippetDefinition(%r,%s,%s,%s)" % ( return '_SnippetDefinition(%r,%s,%s,%s)' % (
self._priority, self._trigger, self._description, self._opts) self._priority, self._trigger, self._description, self._opts)
def _re_match(self, trigger): def _re_match(self, trigger):
""" Test if a the current regex trigger matches """Test if a the current regex trigger matches `trigger`.
`trigger`. If so, set _last_re and _matched.
If so, set _last_re and _matched.
""" """
for match in re.finditer(self._trigger, trigger): for match in re.finditer(self._trigger, trigger):
if match.end() != len(trigger): if match.end() != len(trigger):
@ -73,13 +79,13 @@ class SnippetDefinition(object):
return False return False
def has_option(self, opt): def has_option(self, opt):
""" Check if the named option is set """ """Check if the named option is set."""
return opt in self._opts return opt in self._opts
@property @property
def description(self): def description(self):
"""Descriptive text for this snippet.""" """Descriptive text for this snippet."""
return ("(%s) %s" % (self._trigger, self._description)).strip() return ('(%s) %s' % (self._trigger, self._description)).strip()
@property @property
def priority(self): def priority(self):
@ -109,7 +115,7 @@ class SnippetDefinition(object):
# error, but if permitted it seems that "w" should take precedence # error, but if permitted it seems that "w" should take precedence
# (since matching at word boundary and within a word == matching at word # (since matching at word boundary and within a word == matching at word
# boundary). # boundary).
self._matched = "" self._matched = ''
# Don't expand on whitespace # Don't expand on whitespace
if trigger and trigger.rstrip() != trigger: if trigger and trigger.rstrip() != trigger:
@ -117,19 +123,21 @@ class SnippetDefinition(object):
words = _words_for_line(self._trigger, trigger) words = _words_for_line(self._trigger, trigger)
if "r" in self._opts: if 'r' in self._opts:
match = self._re_match(trigger) match = self._re_match(trigger)
elif "w" in self._opts: elif 'w' in self._opts:
words_len = len(self._trigger) words_len = len(self._trigger)
words_prefix = words[:-words_len] words_prefix = words[:-words_len]
words_suffix = words[-words_len:] words_suffix = words[-words_len:]
match = (words_suffix == self._trigger) match = (words_suffix == self._trigger)
if match and words_prefix: if match and words_prefix:
# Require a word boundary between prefix and suffix. # Require a word boundary between prefix and suffix.
boundary_chars = escape(words_prefix[-1:] + \ boundary_chars = escape(words_prefix[-1:] +
words_suffix[:1], r'\"') words_suffix[:1], r'\"')
match = _vim.eval('"%s" =~# "\\\\v.<."' % boundary_chars) != '0' match = _vim.eval(
elif "i" in self._opts: '"%s" =~# "\\\\v.<."' %
boundary_chars) != '0'
elif 'i' in self._opts:
match = words.endswith(self._trigger) match = words.endswith(self._trigger)
else: else:
match = (words == self._trigger) match = (words == self._trigger)
@ -139,33 +147,33 @@ class SnippetDefinition(object):
self._matched = self._trigger self._matched = self._trigger
# Ensure the match was on a word boundry if needed # Ensure the match was on a word boundry if needed
if "b" in self._opts and match: if 'b' in self._opts and match:
text_before = trigger.rstrip()[:-len(self._matched)] text_before = trigger.rstrip()[:-len(self._matched)]
if text_before.strip(" \t") != '': if text_before.strip(' \t') != '':
self._matched = "" self._matched = ''
return False return False
return match return match
def could_match(self, trigger): def could_match(self, trigger):
"""Return True if this snippet could match the (partial) 'trigger'.""" """Return True if this snippet could match the (partial) 'trigger'."""
self._matched = "" self._matched = ''
# List all on whitespace. # List all on whitespace.
if trigger and trigger[-1] in (" ", "\t"): if trigger and trigger[-1] in (' ', '\t'):
trigger = "" trigger = ''
if trigger and trigger.rstrip() is not trigger: if trigger and trigger.rstrip() is not trigger:
return False return False
words = _words_for_line(self._trigger, trigger) words = _words_for_line(self._trigger, trigger)
if "r" in self._opts: if 'r' in self._opts:
# Test for full match only # Test for full match only
match = self._re_match(trigger) match = self._re_match(trigger)
elif "w" in self._opts: elif 'w' in self._opts:
# Trim non-empty prefix up to word boundary, if present. # Trim non-empty prefix up to word boundary, if present.
qwords = escape(words, r'\"') qwords = escape(words, r'\"')
words_suffix = _vim.eval( words_suffix = _vim.eval(
'substitute("%s", "\\\\v^.+<(.+)", "\\\\1", "")' % qwords) 'substitute("%s", "\\\\v^.+<(.+)", "\\\\1", "")' % qwords)
match = self._trigger.startswith(words_suffix) match = self._trigger.startswith(words_suffix)
self._matched = words_suffix self._matched = words_suffix
@ -173,7 +181,7 @@ class SnippetDefinition(object):
# matches yet, so for now fail if we trimmed the prefix. # matches yet, so for now fail if we trimmed the prefix.
if words_suffix != words: if words_suffix != words:
match = False match = False
elif "i" in self._opts: elif 'i' in self._opts:
# TODO: It is hard to define when a inword snippet could match, # TODO: It is hard to define when a inword snippet could match,
# therefore we check only for full-word trigger. # therefore we check only for full-word trigger.
match = self._trigger.startswith(words) match = self._trigger.startswith(words)
@ -185,10 +193,10 @@ class SnippetDefinition(object):
self._matched = words self._matched = words
# Ensure the match was on a word boundry if needed # Ensure the match was on a word boundry if needed
if "b" in self._opts and match: if 'b' in self._opts and match:
text_before = trigger.rstrip()[:-len(self._matched)] text_before = trigger.rstrip()[:-len(self._matched)]
if text_before.strip(" \t") != '': if text_before.strip(' \t') != '':
self._matched = "" self._matched = ''
return False return False
return match return match
@ -200,16 +208,19 @@ class SnippetDefinition(object):
def launch(self, text_before, visual_content, parent, start, end): def launch(self, text_before, visual_content, parent, start, end):
"""Launch this snippet, overwriting the text 'start' to 'end' and """Launch this snippet, overwriting the text 'start' to 'end' and
keeping the 'text_before' on the launch line. 'Parent' is the parent keeping the 'text_before' on the launch line.
snippet instance if any."""
'Parent' is the parent snippet instance if any.
"""
indent = self._INDENT.match(text_before).group(0) indent = self._INDENT.match(text_before).group(0)
lines = (self._value + "\n").splitlines() lines = (self._value + '\n').splitlines()
ind_util = IndentUtil() ind_util = IndentUtil()
# Replace leading tabs in the snippet definition via proper indenting # Replace leading tabs in the snippet definition via proper indenting
initial_text = [] initial_text = []
for line_num, line in enumerate(lines): for line_num, line in enumerate(lines):
if "t" in self._opts: if 't' in self._opts:
tabs = 0 tabs = 0
else: else:
tabs = len(self._TABS.match(line).group(0)) tabs = len(self._TABS.match(line).group(0))
@ -221,8 +232,8 @@ class SnippetDefinition(object):
initial_text = '\n'.join(initial_text) initial_text = '\n'.join(initial_text)
snippet_instance = SnippetInstance( snippet_instance = SnippetInstance(
self, parent, initial_text, start, end, visual_content, self, parent, initial_text, start, end, visual_content,
last_re=self._last_re, globals=self._globals) last_re=self._last_re, globals=self._globals)
self.instantiate(snippet_instance, initial_text, indent) self.instantiate(snippet_instance, initial_text, indent)
snippet_instance.update_textobjects() snippet_instance.update_textobjects()

View File

@ -6,14 +6,16 @@
from UltiSnips.snippet.definition._base import SnippetDefinition from UltiSnips.snippet.definition._base import SnippetDefinition
from UltiSnips.snippet.parsing.snipmate import parse_and_instantiate from UltiSnips.snippet.parsing.snipmate import parse_and_instantiate
class SnipMateSnippetDefinition(SnippetDefinition): class SnipMateSnippetDefinition(SnippetDefinition):
"""See module doc.""" """See module doc."""
SNIPMATE_SNIPPET_PRIORITY = -1000 SNIPMATE_SNIPPET_PRIORITY = -1000
def __init__(self, trigger, value, description, location): def __init__(self, trigger, value, description, location):
SnippetDefinition.__init__(self, self.SNIPMATE_SNIPPET_PRIORITY, SnippetDefinition.__init__(self, self.SNIPMATE_SNIPPET_PRIORITY,
trigger, value, description, "", {}, location) trigger, value, description, '', {}, location)
def instantiate(self, snippet_instance, initial_text, indent): def instantiate(self, snippet_instance, initial_text, indent):
parse_and_instantiate(snippet_instance, initial_text, indent) parse_and_instantiate(snippet_instance, initial_text, indent)

View File

@ -6,7 +6,9 @@
from UltiSnips.snippet.definition._base import SnippetDefinition from UltiSnips.snippet.definition._base import SnippetDefinition
from UltiSnips.snippet.parsing.ultisnips import parse_and_instantiate from UltiSnips.snippet.parsing.ultisnips import parse_and_instantiate
class UltiSnipsSnippetDefinition(SnippetDefinition): class UltiSnipsSnippetDefinition(SnippetDefinition):
"""See module doc.""" """See module doc."""
def instantiate(self, snippet_instance, initial_text, indent): def instantiate(self, snippet_instance, initial_text, indent):

View File

@ -7,14 +7,19 @@ 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
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,
token_to_textobject): token_to_textobject):
"""Turns 'text' into a stream of tokens and creates the text objects from """Turns 'text' into a stream of tokens and creates the text objects from
those tokens that are mentioned in 'token_to_textobject' assuming the those tokens that are mentioned in 'token_to_textobject' assuming the
current 'indent'. The 'allowed_tokens_in_text' define which tokens will be current 'indent'.
recognized in 'text' while 'allowed_tokens_in_tabstops' are the tokens that
will be recognized in TabStop placeholder text.""" The 'allowed_tokens_in_text' define which tokens will be recognized
in 'text' while 'allowed_tokens_in_tabstops' are the tokens that
will be recognized in TabStop placeholder text.
"""
seen_ts = {} seen_ts = {}
all_tokens = [] all_tokens = []
@ -27,7 +32,7 @@ def tokenize_snippet_text(snippet_instance, text, indent,
ts = TabStop(parent, token) ts = TabStop(parent, token)
seen_ts[token.number] = ts seen_ts[token.number] = ts
_do_parse(ts, token.initial_text, _do_parse(ts, token.initial_text,
allowed_tokens_in_tabstops) allowed_tokens_in_tabstops)
else: else:
klass = token_to_textobject.get(token.__class__, None) klass = token_to_textobject.get(token.__class__, None)
if klass is not None: if klass is not None:
@ -35,11 +40,12 @@ def tokenize_snippet_text(snippet_instance, text, indent,
_do_parse(snippet_instance, text, allowed_tokens_in_text) _do_parse(snippet_instance, text, allowed_tokens_in_text)
return all_tokens, seen_ts return all_tokens, seen_ts
def finalize(all_tokens, seen_ts, snippet_instance): def finalize(all_tokens, seen_ts, snippet_instance):
"""Adds a tabstop 0 if non is in 'seen_ts' and brings the text of the """Adds a tabstop 0 if non is in 'seen_ts' and brings the text of the
snippet instance into Vim.""" snippet instance into Vim."""
if 0 not in seen_ts: if 0 not in seen_ts:
mark = all_tokens[-1][1].end # Last token is always EndOfText mark = all_tokens[-1][1].end # Last token is always EndOfText
m1 = Position(mark.line, mark.col) m1 = Position(mark.line, mark.col)
TabStop(snippet_instance, 0, mark, m1) TabStop(snippet_instance, 0, mark, m1)
snippet_instance.replace_initial_text() snippet_instance.replace_initial_text()

View File

@ -1,10 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
""" """Not really a lexer in the classical sense, but code to convert snippet
Not really a lexer in the classical sense, but code to convert snippet definitions into logical units called Tokens."""
definitions into logical units called Tokens.
"""
import string import string
import re import re
@ -13,7 +11,9 @@ from UltiSnips.compatibility import as_unicode
from UltiSnips.position import Position from UltiSnips.position import Position
from UltiSnips.text import unescape from UltiSnips.text import unescape
class _TextIterator(object): class _TextIterator(object):
"""Helper class to make iterating over text easier.""" """Helper class to make iterating over text easier."""
def __init__(self, text, offset): def __init__(self, text, offset):
@ -44,7 +44,7 @@ class _TextIterator(object):
def peek(self, count=1): def peek(self, count=1):
"""Returns the next 'count' characters without advancing the stream.""" """Returns the next 'count' characters without advancing the stream."""
if count > 1: # This might return '' if nothing is found if count > 1: # This might return '' if nothing is found
return self._text[self._idx:self._idx + count] return self._text[self._idx:self._idx + count]
try: try:
return self._text[self._idx] return self._text[self._idx]
@ -56,17 +56,17 @@ class _TextIterator(object):
"""Current position in the text.""" """Current position in the text."""
return Position(self._line, self._col) return Position(self._line, self._col)
def _parse_number(stream): def _parse_number(stream):
""" """Expects the stream to contain a number next, returns the number without
Expects the stream to contain a number next, returns the number consuming any more bytes."""
without consuming any more bytes rv = ''
"""
rv = ""
while stream.peek() and stream.peek() in string.digits: while stream.peek() and stream.peek() in string.digits:
rv += next(stream) rv += next(stream)
return int(rv) return int(rv)
def _parse_till_closing_brace(stream): def _parse_till_closing_brace(stream):
""" """
Returns all chars till a non-escaped } is found. Other Returns all chars till a non-escaped } is found. Other
@ -74,7 +74,7 @@ def _parse_till_closing_brace(stream):
Will also consume the closing }, but not return it Will also consume the closing }, but not return it
""" """
rv = "" rv = ''
in_braces = 1 in_braces = 1
while True: while True:
if EscapeCharToken.starts_here(stream, '{}'): if EscapeCharToken.starts_here(stream, '{}'):
@ -90,6 +90,7 @@ def _parse_till_closing_brace(stream):
rv += char rv += char
return rv return rv
def _parse_till_unescaped_char(stream, chars): def _parse_till_unescaped_char(stream, chars):
""" """
Returns all chars till a non-escaped char is found. Returns all chars till a non-escaped char is found.
@ -97,7 +98,7 @@ def _parse_till_unescaped_char(stream, chars):
Will also consume the closing char, but and return it as second Will also consume the closing char, but and return it as second
return value return value
""" """
rv = "" rv = ''
while True: while True:
escaped = False escaped = False
for char in chars: for char in chars:
@ -111,20 +112,24 @@ def _parse_till_unescaped_char(stream, chars):
rv += char rv += char
return rv, char return rv, char
class Token(object): class Token(object):
"""Represents a Token as parsed from a snippet definition.""" """Represents a Token as parsed from a snippet definition."""
def __init__(self, gen, indent): def __init__(self, gen, indent):
self.initial_text = as_unicode("") self.initial_text = as_unicode('')
self.start = gen.pos self.start = gen.pos
self._parse(gen, indent) self._parse(gen, indent)
self.end = gen.pos self.end = gen.pos
def _parse(self, stream, indent): def _parse(self, stream, indent):
"""Parses the token from 'stream' with the current 'indent'.""" """Parses the token from 'stream' with the current 'indent'."""
pass # Does nothing pass # Does nothing
class TabStopToken(Token): class TabStopToken(Token):
"""${1:blub}""" """${1:blub}"""
CHECK = re.compile(r'^\${\d+[:}]') CHECK = re.compile(r'^\${\d+[:}]')
@ -135,21 +140,23 @@ class TabStopToken(Token):
return cls.CHECK.match(stream.peek(10)) is not None return cls.CHECK.match(stream.peek(10)) is not None
def _parse(self, stream, indent): def _parse(self, stream, indent):
next(stream) # $ next(stream) # $
next(stream) # { next(stream) # {
self.number = _parse_number(stream) self.number = _parse_number(stream)
if stream.peek() == ":": if stream.peek() == ':':
next(stream) next(stream)
self.initial_text = _parse_till_closing_brace(stream) self.initial_text = _parse_till_closing_brace(stream)
def __repr__(self): def __repr__(self):
return "TabStopToken(%r,%r,%r,%r)" % ( return 'TabStopToken(%r,%r,%r,%r)' % (
self.start, self.end, self.number, self.initial_text self.start, self.end, self.number, self.initial_text
) )
class VisualToken(Token): class VisualToken(Token):
"""${VISUAL}""" """${VISUAL}"""
CHECK = re.compile(r"^\${VISUAL[:}/]") CHECK = re.compile(r"^\${VISUAL[:}/]")
@ -160,15 +167,15 @@ class VisualToken(Token):
return cls.CHECK.match(stream.peek(10)) is not None return cls.CHECK.match(stream.peek(10)) is not None
def _parse(self, stream, indent): def _parse(self, stream, indent):
for _ in range(8): # ${VISUAL for _ in range(8): # ${VISUAL
next(stream) next(stream)
if stream.peek() == ":": if stream.peek() == ':':
next(stream) next(stream)
self.alternative_text, char = _parse_till_unescaped_char(stream, '/}') self.alternative_text, char = _parse_till_unescaped_char(stream, '/}')
self.alternative_text = unescape(self.alternative_text) self.alternative_text = unescape(self.alternative_text)
if char == '/': # Transformation going on if char == '/': # Transformation going on
try: try:
self.search = _parse_till_unescaped_char(stream, '/')[0] self.search = _parse_till_unescaped_char(stream, '/')[0]
self.replace = _parse_till_unescaped_char(stream, '/')[0] self.replace = _parse_till_unescaped_char(stream, '/')[0]
@ -182,11 +189,13 @@ class VisualToken(Token):
self.options = None self.options = None
def __repr__(self): def __repr__(self):
return "VisualToken(%r,%r)" % ( return 'VisualToken(%r,%r)' % (
self.start, self.end self.start, self.end
) )
class TransformationToken(Token): class TransformationToken(Token):
"""${1/match/replace/options}""" """${1/match/replace/options}"""
CHECK = re.compile(r'^\${\d+\/') CHECK = re.compile(r'^\${\d+\/')
@ -198,24 +207,26 @@ class TransformationToken(Token):
return cls.CHECK.match(stream.peek(10)) is not None return cls.CHECK.match(stream.peek(10)) is not None
def _parse(self, stream, indent): def _parse(self, stream, indent):
next(stream) # $ next(stream) # $
next(stream) # { next(stream) # {
self.number = _parse_number(stream) self.number = _parse_number(stream)
next(stream) # / next(stream) # /
self.search = _parse_till_unescaped_char(stream, '/')[0] self.search = _parse_till_unescaped_char(stream, '/')[0]
self.replace = _parse_till_unescaped_char(stream, '/')[0] self.replace = _parse_till_unescaped_char(stream, '/')[0]
self.options = _parse_till_closing_brace(stream) self.options = _parse_till_closing_brace(stream)
def __repr__(self): def __repr__(self):
return "TransformationToken(%r,%r,%r,%r,%r)" % ( return 'TransformationToken(%r,%r,%r,%r,%r)' % (
self.start, self.end, self.number, self.search, self.replace self.start, self.end, self.number, self.search, self.replace
) )
class MirrorToken(Token): class MirrorToken(Token):
"""$1"""
"""$1."""
CHECK = re.compile(r'^\$\d+') CHECK = re.compile(r'^\$\d+')
@classmethod @classmethod
@ -225,16 +236,18 @@ class MirrorToken(Token):
return cls.CHECK.match(stream.peek(10)) is not None return cls.CHECK.match(stream.peek(10)) is not None
def _parse(self, stream, indent): def _parse(self, stream, indent):
next(stream) # $ next(stream) # $
self.number = _parse_number(stream) self.number = _parse_number(stream)
def __repr__(self): def __repr__(self):
return "MirrorToken(%r,%r,%r)" % ( return 'MirrorToken(%r,%r,%r)' % (
self.start, self.end, self.number self.start, self.end, self.number
) )
class EscapeCharToken(Token): class EscapeCharToken(Token):
"""\\n"""
"""\\n."""
@classmethod @classmethod
def starts_here(cls, stream, chars=r'{}\$`'): def starts_here(cls, stream, chars=r'{}\$`'):
"""Returns true if this token starts at the current position in """Returns true if this token starts at the current position in
@ -244,15 +257,17 @@ class EscapeCharToken(Token):
return True return True
def _parse(self, stream, indent): def _parse(self, stream, indent):
next(stream) # \ next(stream) # \
self.initial_text = next(stream) self.initial_text = next(stream)
def __repr__(self): def __repr__(self):
return "EscapeCharToken(%r,%r,%r)" % ( return 'EscapeCharToken(%r,%r,%r)' % (
self.start, self.end, self.initial_text self.start, self.end, self.initial_text
) )
class ShellCodeToken(Token): class ShellCodeToken(Token):
"""`echo "hi"`""" """`echo "hi"`"""
@classmethod @classmethod
def starts_here(cls, stream): def starts_here(cls, stream):
@ -261,15 +276,17 @@ class ShellCodeToken(Token):
return stream.peek(1) == '`' return stream.peek(1) == '`'
def _parse(self, stream, indent): def _parse(self, stream, indent):
next(stream) # ` next(stream) # `
self.code = _parse_till_unescaped_char(stream, '`')[0] self.code = _parse_till_unescaped_char(stream, '`')[0]
def __repr__(self): def __repr__(self):
return "ShellCodeToken(%r,%r,%r)" % ( return 'ShellCodeToken(%r,%r,%r)' % (
self.start, self.end, self.code self.start, self.end, self.code
) )
class PythonCodeToken(Token): class PythonCodeToken(Token):
"""`!p snip.rv = "Hi"`""" """`!p snip.rv = "Hi"`"""
CHECK = re.compile(r'^`!p\s') CHECK = re.compile(r'^`!p\s')
@ -281,7 +298,7 @@ class PythonCodeToken(Token):
def _parse(self, stream, indent): def _parse(self, stream, indent):
for _ in range(3): for _ in range(3):
next(stream) # `!p next(stream) # `!p
if stream.peek() in '\t ': if stream.peek() in '\t ':
next(stream) next(stream)
@ -292,17 +309,19 @@ class PythonCodeToken(Token):
lines = code.splitlines() lines = code.splitlines()
self.code = lines[0] + '\n' self.code = lines[0] + '\n'
self.code += '\n'.join([l[len(indent):] self.code += '\n'.join([l[len(indent):]
for l in lines[1:]]) for l in lines[1:]])
else: else:
self.code = code self.code = code
self.indent = indent self.indent = indent
def __repr__(self): def __repr__(self):
return "PythonCodeToken(%r,%r,%r)" % ( return 'PythonCodeToken(%r,%r,%r)' % (
self.start, self.end, self.code self.start, self.end, self.code
) )
class VimLCodeToken(Token): class VimLCodeToken(Token):
"""`!v g:hi`""" """`!v g:hi`"""
CHECK = re.compile(r'^`!v\s') CHECK = re.compile(r'^`!v\s')
@ -314,18 +333,22 @@ class VimLCodeToken(Token):
def _parse(self, stream, indent): def _parse(self, stream, indent):
for _ in range(4): for _ in range(4):
next(stream) # `!v next(stream) # `!v
self.code = _parse_till_unescaped_char(stream, '`')[0] self.code = _parse_till_unescaped_char(stream, '`')[0]
def __repr__(self): def __repr__(self):
return "VimLCodeToken(%r,%r,%r)" % ( return 'VimLCodeToken(%r,%r,%r)' % (
self.start, self.end, self.code self.start, self.end, self.code
) )
class EndOfTextToken(Token): class EndOfTextToken(Token):
"""Appears at the end of the text.""" """Appears at the end of the text."""
def __repr__(self): def __repr__(self):
return "EndOfText(%r)" % self.end return 'EndOfText(%r)' % self.end
def tokenize(text, indent, offset, allowed_tokens): def tokenize(text, indent, offset, allowed_tokens):
"""Returns an iterator of tokens of 'text'['offset':] which is assumed to """Returns an iterator of tokens of 'text'['offset':] which is assumed to

View File

@ -22,18 +22,24 @@ __ALLOWED_TOKENS_IN_TABSTOPS = [
EscapeCharToken, VisualToken, MirrorToken, ShellCodeToken EscapeCharToken, VisualToken, MirrorToken, ShellCodeToken
] ]
def _create_mirrors(all_tokens, seen_ts): def _create_mirrors(all_tokens, seen_ts):
"""Now that all tabstops are known, we can create mirrors.""" """Now that all tabstops are known, we can create mirrors."""
for parent, token in all_tokens: for parent, token in all_tokens:
if isinstance(token, MirrorToken): if isinstance(token, MirrorToken):
Mirror(parent, seen_ts[token.number], token) 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'. Will instantiate all the objects and link them as current 'indent'.
children to parent_to. Will also put the initial text into Vim."""
Will instantiate all the objects and link them as children to
parent_to. Will also put the initial text into Vim.
"""
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) _create_mirrors(all_tokens, seen_ts)
finalize(all_tokens, seen_ts, parent_to) finalize(all_tokens, seen_ts, parent_to)

View File

@ -8,7 +8,7 @@ from UltiSnips.snippet.parsing._lexer import EscapeCharToken, \
VisualToken, TransformationToken, TabStopToken, MirrorToken, \ VisualToken, TransformationToken, TabStopToken, MirrorToken, \
PythonCodeToken, VimLCodeToken, ShellCodeToken PythonCodeToken, VimLCodeToken, ShellCodeToken
from UltiSnips.text_objects import EscapedChar, Mirror, PythonCode, \ from UltiSnips.text_objects import EscapedChar, Mirror, PythonCode, \
ShellCode, TabStop, Transformation, VimLCode, Visual ShellCode, TabStop, Transformation, VimLCode, Visual
_TOKEN_TO_TEXTOBJECT = { _TOKEN_TO_TEXTOBJECT = {
EscapeCharToken: EscapedChar, EscapeCharToken: EscapedChar,
@ -23,8 +23,13 @@ __ALLOWED_TOKENS = [
MirrorToken, PythonCodeToken, VimLCodeToken, ShellCodeToken MirrorToken, PythonCodeToken, VimLCodeToken, ShellCodeToken
] ]
def _resolve_ambiguity(all_tokens, seen_ts): def _resolve_ambiguity(all_tokens, seen_ts):
"""$1 could be a Mirror or a TabStop. This figures this out.""" """$1 could be a Mirror or a TabStop.
This figures this out.
"""
for parent, token in all_tokens: for parent, token in all_tokens:
if isinstance(token, MirrorToken): if isinstance(token, MirrorToken):
if token.number not in seen_ts: if token.number not in seen_ts:
@ -32,23 +37,28 @@ def _resolve_ambiguity(all_tokens, seen_ts):
else: else:
Mirror(parent, seen_ts[token.number], token) 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:
if isinstance(token, TransformationToken): if isinstance(token, TransformationToken):
if token.number not in seen_ts: if token.number not in seen_ts:
raise RuntimeError( raise RuntimeError(
"Tabstop %i is not known but is used by a Transformation" 'Tabstop %i is not known but is used by a Transformation'
% token.number) % token.number)
Transformation(parent, seen_ts[token.number], token) Transformation(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 UltiSnips format from 'text' assuming the """Parses a snippet definition in UltiSnips format from 'text' assuming the
current 'indent'. Will instantiate all the objects and link them as current 'indent'.
children to parent_to. Will also put the initial text into Vim."""
Will instantiate all the objects and link them as children to
parent_to. Will also put the initial text into Vim.
"""
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

@ -7,7 +7,9 @@ from collections import defaultdict
from UltiSnips.snippet.source._snippet_dictionary import SnippetDictionary from UltiSnips.snippet.source._snippet_dictionary import SnippetDictionary
class SnippetSource(object): class SnippetSource(object):
"""See module docstring.""" """See module docstring."""
def __init__(self): def __init__(self):
@ -15,25 +17,25 @@ class SnippetSource(object):
self._extends = defaultdict(set) self._extends = defaultdict(set)
def ensure(self, filetypes): def ensure(self, filetypes):
"""Update/reload the snippets in the source when needed. It makes sure """Update/reload the snippets in the source when needed.
that the snippets are not outdated.
It makes sure that the snippets are not outdated.
""" """
pass
def _get_existing_deep_extends(self, base_filetypes): def _get_existing_deep_extends(self, base_filetypes):
"""Helper for get all existing filetypes extended by base """Helper for get all existing filetypes extended by base filetypes."""
filetypes.
"""
deep_extends = self.get_deep_extends(base_filetypes) deep_extends = self.get_deep_extends(base_filetypes)
return [ft for ft in deep_extends if ft in self._snippets] return [ft for ft in deep_extends if ft in self._snippets]
def get_snippets(self, filetypes, before, possible): def get_snippets(self, filetypes, before, possible):
"""Returns the snippets for all 'filetypes' (in order) and their parents """Returns the snippets for all 'filetypes' (in order) and their
matching the text 'before'. If 'possible' is true, a partial match is parents matching the text 'before'. If 'possible' is true, a partial
enough. Base classes can override this method to provide means of match is enough. Base classes can override this method to provide means
creating snippets on the fly. of creating snippets on the fly.
Returns a list of SnippetDefinition s. Returns a list of SnippetDefinition s.
""" """
result = [] result = []
for ft in self._get_existing_deep_extends(filetypes): for ft in self._get_existing_deep_extends(filetypes):
@ -43,7 +45,10 @@ class SnippetSource(object):
def get_clear_priority(self, filetypes): def get_clear_priority(self, filetypes):
"""Get maximum clearsnippets priority without arguments for specified """Get maximum clearsnippets priority without arguments for specified
filetypes, if any. It returns None if there are no clearsnippets. filetypes, if any.
It returns None if there are no clearsnippets.
""" """
pri = None pri = None
for ft in self._get_existing_deep_extends(filetypes): for ft in self._get_existing_deep_extends(filetypes):
@ -54,8 +59,7 @@ class SnippetSource(object):
def get_cleared(self, filetypes): def get_cleared(self, filetypes):
"""Get a set of cleared snippets marked by clearsnippets with arguments """Get a set of cleared snippets marked by clearsnippets with arguments
for specified filetypes. for specified filetypes."""
"""
cleared = {} cleared = {}
for ft in self._get_existing_deep_extends(filetypes): for ft in self._get_existing_deep_extends(filetypes):
snippets = self._snippets[ft] snippets = self._snippets[ft]
@ -65,21 +69,23 @@ class SnippetSource(object):
return cleared return cleared
def update_extends(self, child_ft, parent_fts): def update_extends(self, child_ft, parent_fts):
"""Update the extending relation by given child filetype and """Update the extending relation by given child filetype and its parent
its parent filetypes. filetypes."""
"""
self._extends[child_ft].update(parent_fts) self._extends[child_ft].update(parent_fts)
def get_deep_extends(self, base_filetypes): def get_deep_extends(self, base_filetypes):
"""Get a list of filetypes that is either directed or indirected """Get a list of filetypes that is either directed or indirected
extended by given base filetypes. Note that the returned list extended by given base filetypes.
include the root filetype itself.
Note that the returned list include the root filetype itself.
""" """
seen = set(base_filetypes) seen = set(base_filetypes)
todo_fts = list(set(base_filetypes)) todo_fts = list(set(base_filetypes))
while todo_fts: while todo_fts:
todo_ft = todo_fts.pop() todo_ft = todo_fts.pop()
unseen_extends = set(ft for ft in self._extends[todo_ft] if ft not in seen) unseen_extends = set(
ft for ft in self._extends[todo_ft] if ft not in seen)
seen.update(unseen_extends) seen.update(unseen_extends)
todo_fts.extend(unseen_extends) todo_fts.extend(unseen_extends)
return seen return seen

View File

@ -3,7 +3,9 @@
"""Implements a container for parsed snippets.""" """Implements a container for parsed snippets."""
class SnippetDictionary(object): class SnippetDictionary(object):
"""See module docstring.""" """See module docstring."""
def __init__(self): def __init__(self):
@ -16,8 +18,11 @@ class SnippetDictionary(object):
self._snippets.append(snippet) self._snippets.append(snippet)
def get_matching_snippets(self, trigger, potentially): def get_matching_snippets(self, trigger, potentially):
"""Returns all snippets matching the given trigger. If 'potentially' is """Returns all snippets matching the given trigger.
true, returns all that could_match()."""
If 'potentially' is true, returns all that could_match().
"""
all_snippets = self._snippets all_snippets = self._snippets
if not potentially: if not potentially:
return [s for s in all_snippets if s.matches(trigger)] return [s for s in all_snippets if s.matches(trigger)]
@ -25,8 +30,12 @@ class SnippetDictionary(object):
return [s for s in all_snippets if s.could_match(trigger)] return [s for s in all_snippets if s.could_match(trigger)]
def clear_snippets(self, priority, triggers): def clear_snippets(self, priority, triggers):
"""Clear the snippets by mark them as cleared. If trigger is """Clear the snippets by mark them as cleared.
None, it updates the value of clear priority instead."""
If trigger is None, it updates the value of clear priority
instead.
"""
if not triggers: if not triggers:
if self._clear_priority is None or priority > self._clear_priority: if self._clear_priority is None or priority > self._clear_priority:
self._clear_priority = priority self._clear_priority = priority

View File

@ -5,7 +5,9 @@
from UltiSnips.snippet.source._base import SnippetSource from UltiSnips.snippet.source._base import SnippetSource
class AddedSnippetsSource(SnippetSource): class AddedSnippetsSource(SnippetSource):
"""See module docstring.""" """See module docstring."""
def add_snippet(self, ft, snippet): def add_snippet(self, ft, snippet):

View File

@ -11,19 +11,25 @@ from UltiSnips import _vim
from UltiSnips import compatibility from UltiSnips import compatibility
from UltiSnips.snippet.source._base import SnippetSource from UltiSnips.snippet.source._base import SnippetSource
def _hash_file(path): def _hash_file(path):
"""Returns a hashdigest of 'path'""" """Returns a hashdigest of 'path'."""
if not os.path.isfile(path): if not os.path.isfile(path):
return False return False
return hashlib.sha1(open(path, "rb").read()).hexdigest() return hashlib.sha1(open(path, 'rb').read()).hexdigest()
class SnippetSyntaxError(RuntimeError): class SnippetSyntaxError(RuntimeError):
"""Thrown when a syntax error is found in a file.""" """Thrown when a syntax error is found in a file."""
def __init__(self, filename, line_index, msg): def __init__(self, filename, line_index, msg):
RuntimeError.__init__(self, "%s in %s:%d" % ( RuntimeError.__init__(self, '%s in %s:%d' % (
msg, filename, line_index)) msg, filename, line_index))
class SnippetFileSource(SnippetSource): class SnippetFileSource(SnippetSource):
"""Base class that abstracts away 'extends' info and file hashes.""" """Base class that abstracts away 'extends' info and file hashes."""
def __init__(self): def __init__(self):
@ -74,23 +80,23 @@ class SnippetFileSource(SnippetSource):
"""Parse the 'filename' for the given 'ft' and watch it for changes in """Parse the 'filename' for the given 'ft' and watch it for changes in
the future.""" the future."""
self._file_hashes[filename] = _hash_file(filename) self._file_hashes[filename] = _hash_file(filename)
file_data = compatibility.open_ascii_file(filename, "r").read() file_data = compatibility.open_ascii_file(filename, 'r').read()
for event, data in self._parse_snippet_file(file_data, filename): for event, data in self._parse_snippet_file(file_data, filename):
if event == "error": if event == 'error':
msg, line_index = data msg, line_index = data
filename = _vim.eval("""fnamemodify(%s, ":~:.")""" % filename = _vim.eval("""fnamemodify(%s, ":~:.")""" %
_vim.escape(filename)) _vim.escape(filename))
raise SnippetSyntaxError(filename, line_index, msg) raise SnippetSyntaxError(filename, line_index, msg)
elif event == "clearsnippets": elif event == 'clearsnippets':
priority, triggers = data priority, triggers = data
self._snippets[ft].clear_snippets(priority, triggers) self._snippets[ft].clear_snippets(priority, triggers)
elif event == "extends": elif event == 'extends':
# TODO(sirver): extends information is more global # TODO(sirver): extends information is more global
# than one snippet source. # than one snippet source.
filetypes, = data filetypes, = data
self.update_extends(ft, filetypes) self.update_extends(ft, filetypes)
elif event == "snippet": elif event == 'snippet':
snippet, = data snippet, = data
self._snippets[ft].add_snippet(snippet) self._snippets[ft].add_snippet(snippet)
else: else:
assert False, "Unhandled %s: %r" % (event, data) assert False, 'Unhandled %s: %r' % (event, data)

View File

@ -3,9 +3,10 @@
"""Common code for snipMate and UltiSnips snippet files.""" """Common code for snipMate and UltiSnips snippet files."""
def handle_extends(tail, line_index): def handle_extends(tail, line_index):
"""Handles an extends line in a snippet.""" """Handles an extends line in a snippet."""
if tail: if tail:
return "extends", ([p.strip() for p in tail.split(',')],) return 'extends', ([p.strip() for p in tail.split(',')],)
else: else:
return "error", ("'extends' without file types", line_index) return 'error', ("'extends' without file types", line_index)

View File

@ -12,17 +12,18 @@ from UltiSnips.snippet.source.file._base import SnippetFileSource
from UltiSnips.snippet.source.file._common import handle_extends from UltiSnips.snippet.source.file._common import handle_extends
from UltiSnips.text import LineIterator, head_tail from UltiSnips.text import LineIterator, head_tail
def _splitall(path): def _splitall(path):
"""Split 'path' into all its components.""" """Split 'path' into all its components."""
# From http://my.safaribooksonline.com/book/programming/ # From http://my.safaribooksonline.com/book/programming/
# python/0596001673/files/pythoncook-chp-4-sect-16 # python/0596001673/files/pythoncook-chp-4-sect-16
allparts = [] allparts = []
while 1: while True:
parts = os.path.split(path) parts = os.path.split(path)
if parts[0] == path: # sentinel for absolute paths if parts[0] == path: # sentinel for absolute paths
allparts.insert(0, parts[0]) allparts.insert(0, parts[0])
break break
elif parts[1] == path: # sentinel for relative paths elif parts[1] == path: # sentinel for relative paths
allparts.insert(0, parts[1]) allparts.insert(0, parts[1])
break break
else: else:
@ -30,46 +31,49 @@ def _splitall(path):
allparts.insert(0, parts[1]) allparts.insert(0, parts[1])
return allparts return allparts
def snipmate_files_for(ft): def snipmate_files_for(ft):
"""Returns all snipMate files we need to look at for 'ft'.""" """Returns all snipMate files we need to look at for 'ft'."""
if ft == "all": if ft == 'all':
ft = "_" ft = '_'
patterns = [ patterns = [
"%s.snippets" % ft, '%s.snippets' % ft,
os.path.join(ft, "*.snippets"), os.path.join(ft, '*.snippets'),
os.path.join(ft, "*.snippet"), os.path.join(ft, '*.snippet'),
os.path.join(ft, "*/*.snippet"), os.path.join(ft, '*/*.snippet'),
] ]
ret = set() ret = set()
for rtp in _vim.eval("&runtimepath").split(','): for rtp in _vim.eval('&runtimepath').split(','):
path = os.path.realpath(os.path.expanduser( path = os.path.realpath(os.path.expanduser(
os.path.join(rtp, "snippets"))) os.path.join(rtp, 'snippets')))
for pattern in patterns: for pattern in patterns:
for fn in glob.glob(os.path.join(path, pattern)): for fn in glob.glob(os.path.join(path, pattern)):
ret.add(fn) ret.add(fn)
return ret return ret
def _parse_snippet_file(content, full_filename): def _parse_snippet_file(content, full_filename):
"""Parses 'content' assuming it is a .snippet file and yields events.""" """Parses 'content' assuming it is a .snippet file and yields events."""
filename = full_filename[:-len(".snippet")] # strip extension filename = full_filename[:-len('.snippet')] # strip extension
segments = _splitall(filename) segments = _splitall(filename)
segments = segments[segments.index("snippets")+1:] segments = segments[segments.index('snippets') + 1:]
assert len(segments) in (2, 3) assert len(segments) in (2, 3)
trigger = segments[1] trigger = segments[1]
description = segments[2] if 2 < len(segments) else "" description = segments[2] if 2 < len(segments) else ''
# Chomp \n if any. # Chomp \n if any.
if content and content.endswith(os.linesep): if content and content.endswith(os.linesep):
content = content[:-len(os.linesep)] content = content[:-len(os.linesep)]
yield "snippet", (SnipMateSnippetDefinition(trigger, content, yield 'snippet', (SnipMateSnippetDefinition(trigger, content,
description, full_filename),) description, full_filename),)
def _parse_snippet(line, lines, filename): def _parse_snippet(line, lines, filename):
"""Parse a snippet defintions.""" """Parse a snippet defintions."""
start_line_index = lines.line_index start_line_index = lines.line_index
trigger, description = head_tail(line[len("snippet"):].lstrip()) trigger, description = head_tail(line[len('snippet'):].lstrip())
content = "" content = ''
while True: while True:
next_line = lines.peek() next_line = lines.peek()
if next_line is None: if next_line is None:
@ -81,34 +85,41 @@ def _parse_snippet(line, lines, filename):
line = line[1:] line = line[1:]
content += line content += line
content = content[:-1] # Chomp the last newline content = content[:-1] # Chomp the last newline
return "snippet", (SnipMateSnippetDefinition( return 'snippet', (SnipMateSnippetDefinition(
trigger, content, description, "%s:%i" % (filename, start_line_index)),) trigger, content, description, '%s:%i' % (filename, start_line_index)),)
def _parse_snippets_file(data, filename): def _parse_snippets_file(data, filename):
"""Parse 'data' assuming it is a .snippets file. Yields events in the """Parse 'data' assuming it is a .snippets file.
file."""
Yields events in the file.
"""
lines = LineIterator(data) lines = LineIterator(data)
for line in lines: for line in lines:
if not line.strip(): if not line.strip():
continue continue
head, tail = head_tail(line) head, tail = head_tail(line)
if head == "extends": if head == 'extends':
yield handle_extends(tail, lines.line_index) yield handle_extends(tail, lines.line_index)
elif head in "snippet": elif head in 'snippet':
snippet = _parse_snippet(line, lines, filename) snippet = _parse_snippet(line, lines, filename)
if snippet is not None: if snippet is not None:
yield snippet yield snippet
elif head and not head.startswith('#'): elif head and not head.startswith('#'):
yield "error", ("Invalid line %r" % line.rstrip(), lines.line_index) yield 'error', ('Invalid line %r' % line.rstrip(), lines.line_index)
class SnipMateFileSource(SnippetFileSource): class SnipMateFileSource(SnippetFileSource):
"""Manages all snipMate snippet definitions found in rtp.""" """Manages all snipMate snippet definitions found in rtp."""
def _get_all_snippet_files_for(self, ft): def _get_all_snippet_files_for(self, ft):
return snipmate_files_for(ft) return snipmate_files_for(ft)
def _parse_snippet_file(self, filedata, filename): def _parse_snippet_file(self, filedata, filename):
if filename.lower().endswith("snippet"): if filename.lower().endswith('snippet'):
for event, data in _parse_snippet_file(filedata, filename): for event, data in _parse_snippet_file(filedata, filename):
yield event, data yield event, data
else: else:

View File

@ -13,9 +13,10 @@ from UltiSnips.snippet.source.file._base import SnippetFileSource
from UltiSnips.snippet.source.file._common import handle_extends from UltiSnips.snippet.source.file._common import handle_extends
from UltiSnips.text import LineIterator, head_tail from UltiSnips.text import LineIterator, head_tail
def find_snippet_files(ft, directory): def find_snippet_files(ft, directory):
"""Returns all matching snippet files for 'ft' in 'directory'.""" """Returns all matching snippet files for 'ft' in 'directory'."""
patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")] patterns = ['%s.snippets', '%s_*.snippets', os.path.join('%s', '*')]
ret = set() ret = set()
directory = os.path.expanduser(directory) directory = os.path.expanduser(directory)
for pattern in patterns: for pattern in patterns:
@ -23,23 +24,24 @@ def find_snippet_files(ft, directory):
ret.add(os.path.realpath(fn)) ret.add(os.path.realpath(fn))
return ret return ret
def find_all_snippet_files(ft): def find_all_snippet_files(ft):
"""Returns all snippet files matching 'ft' in the given runtime path """Returns all snippet files matching 'ft' in the given runtime path
directory.""" directory."""
if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1": if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == '1':
snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories") snippet_dirs = _vim.eval('b:UltiSnipsSnippetDirectories')
else: else:
snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories") snippet_dirs = _vim.eval('g:UltiSnipsSnippetDirectories')
patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")] patterns = ['%s.snippets', '%s_*.snippets', os.path.join('%s', '*')]
ret = set() ret = set()
for rtp in _vim.eval("&runtimepath").split(','): for rtp in _vim.eval('&runtimepath').split(','):
for snippet_dir in snippet_dirs: for snippet_dir in snippet_dirs:
if snippet_dir == "snippets": if snippet_dir == 'snippets':
raise RuntimeError( raise RuntimeError(
"You have 'snippets' in UltiSnipsSnippetDirectories. This " "You have 'snippets' in UltiSnipsSnippetDirectories. This "
"directory is reserved for snipMate snippets. Use another " 'directory is reserved for snipMate snippets. Use another '
"directory for UltiSnips snippets.") 'directory for UltiSnips snippets.')
pth = os.path.realpath(os.path.expanduser( pth = os.path.realpath(os.path.expanduser(
os.path.join(rtp, snippet_dir))) os.path.join(rtp, snippet_dir)))
for pattern in patterns: for pattern in patterns:
@ -47,11 +49,12 @@ def find_all_snippet_files(ft):
ret.add(fn) ret.add(fn)
return ret return ret
def _handle_snippet_or_global(filename, line, lines, python_globals, priority): def _handle_snippet_or_global(filename, line, lines, python_globals, priority):
"""Parses the snippet that begins at the current line.""" """Parses the snippet that begins at the current line."""
start_line_index = lines.line_index start_line_index = lines.line_index
descr = "" descr = ''
opts = "" opts = ''
# Ensure this is a snippet # Ensure this is a snippet
snip = line.split()[0] snip = line.split()[0]
@ -74,13 +77,13 @@ def _handle_snippet_or_global(filename, line, lines, python_globals, priority):
# The rest is the trigger # The rest is the trigger
trig = remain.strip() trig = remain.strip()
if len(trig.split()) > 1 or "r" in opts: if len(trig.split()) > 1 or 'r' in opts:
if trig[0] != trig[-1]: if trig[0] != trig[-1]:
return "error", ("Invalid multiword trigger: '%s'" % trig, return 'error', ("Invalid multiword trigger: '%s'" % trig,
lines.line_index) lines.line_index)
trig = trig[1:-1] trig = trig[1:-1]
end = "end" + snip end = 'end' + snip
content = "" content = ''
found_end = False found_end = False
for line in lines: for line in lines:
@ -91,20 +94,25 @@ def _handle_snippet_or_global(filename, line, lines, python_globals, priority):
content += line content += line
if not found_end: if not found_end:
return "error", ("Missing 'endsnippet' for %r" % trig, lines.line_index) return 'error', ("Missing 'endsnippet' for %r" %
trig, lines.line_index)
if snip == "global": if snip == 'global':
python_globals[trig].append(content) python_globals[trig].append(content)
elif snip == "snippet": elif snip == 'snippet':
return "snippet", (UltiSnipsSnippetDefinition(priority, trig, content, return 'snippet', (UltiSnipsSnippetDefinition(priority, trig, content,
descr, opts, python_globals, descr, opts, python_globals,
"%s:%i" % (filename, start_line_index)),) '%s:%i' % (filename, start_line_index)),)
else: else:
return "error", ("Invalid snippet type: '%s'" % snip, lines.line_index) return 'error', ("Invalid snippet type: '%s'" % snip, lines.line_index)
def _parse_snippets_file(data, filename): def _parse_snippets_file(data, filename):
"""Parse 'data' assuming it is a snippet file. Yields events in the """Parse 'data' assuming it is a snippet file.
file."""
Yields events in the file.
"""
python_globals = defaultdict(list) python_globals = defaultdict(list)
lines = LineIterator(data) lines = LineIterator(data)
@ -114,24 +122,26 @@ def _parse_snippets_file(data, filename):
continue continue
head, tail = head_tail(line) head, tail = head_tail(line)
if head in ("snippet", "global"): if head in ('snippet', 'global'):
snippet = _handle_snippet_or_global(filename, line, lines, snippet = _handle_snippet_or_global(filename, line, lines,
python_globals, current_priority) python_globals, current_priority)
if snippet is not None: if snippet is not None:
yield snippet yield snippet
elif head == "extends": elif head == 'extends':
yield handle_extends(tail, lines.line_index) yield handle_extends(tail, lines.line_index)
elif head == "clearsnippets": elif head == 'clearsnippets':
yield "clearsnippets", (current_priority, tail.split()) yield 'clearsnippets', (current_priority, tail.split())
elif head == "priority": elif head == 'priority':
try: try:
current_priority = int(tail.split()[0]) current_priority = int(tail.split()[0])
except (ValueError, IndexError): except (ValueError, IndexError):
yield "error", ("Invalid priority %r" % tail, lines.line_index) yield 'error', ('Invalid priority %r' % tail, lines.line_index)
elif head and not head.startswith('#'): elif head and not head.startswith('#'):
yield "error", ("Invalid line %r" % line.rstrip(), lines.line_index) yield 'error', ('Invalid line %r' % line.rstrip(), lines.line_index)
class UltiSnipsFileSource(SnippetFileSource): class UltiSnipsFileSource(SnippetFileSource):
"""Manages all snippets definitions found in rtp for ultisnips.""" """Manages all snippets definitions found in rtp for ultisnips."""
def _get_all_snippet_files_for(self, ft): def _get_all_snippet_files_for(self, ft):

View File

@ -15,21 +15,22 @@ from UltiSnips.compatibility import as_unicode
from UltiSnips.position import Position from UltiSnips.position import Position
from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition
from UltiSnips.snippet.source import UltiSnipsFileSource, SnipMateFileSource, \ from UltiSnips.snippet.source import UltiSnipsFileSource, SnipMateFileSource, \
find_all_snippet_files, find_snippet_files, AddedSnippetsSource find_all_snippet_files, find_snippet_files, AddedSnippetsSource
from UltiSnips.text import escape from UltiSnips.text import escape
from UltiSnips.vim_state import VimState, VisualContentPreserver from UltiSnips.vim_state import VimState, VisualContentPreserver
def _ask_user(a, formatted): def _ask_user(a, formatted):
"""Asks the user using inputlist() and returns the selected element or """Asks the user using inputlist() and returns the selected element or
None.""" None."""
try: try:
rv = _vim.eval("inputlist(%s)" % _vim.escape(formatted)) rv = _vim.eval('inputlist(%s)' % _vim.escape(formatted))
if rv is None or rv == '0': if rv is None or rv == '0':
return None return None
rv = int(rv) rv = int(rv)
if rv > len(a): if rv > len(a):
rv = len(a) rv = len(a)
return a[rv-1] return a[rv - 1]
except _vim.error: except _vim.error:
# Likely "invalid expression", but might be translated. We have no way # Likely "invalid expression", but might be translated. We have no way
# of knowing the exact error, therefore, we ignore all errors silently. # of knowing the exact error, therefore, we ignore all errors silently.
@ -37,14 +38,15 @@ def _ask_user(a, formatted):
except KeyboardInterrupt: except KeyboardInterrupt:
return None return None
def _ask_snippets(snippets): def _ask_snippets(snippets):
""" Given a list of snippets, ask the user which one they """Given a list of snippets, ask the user which one they want to use, and
want to use, and return it. return it."""
""" display = [as_unicode('%i: %s (%s)') % (i + 1, escape(s.description, '\\'),
display = [as_unicode("%i: %s (%s)") % (i+1, escape(s.description, '\\'), escape(s.location, '\\')) for i, s in enumerate(snippets)]
escape(s.location, '\\')) for i, s in enumerate(snippets)]
return _ask_user(snippets, display) return _ask_user(snippets, display)
def err_to_scratch_buffer(func): def err_to_scratch_buffer(func):
"""Decorator that will catch any Exception that 'func' throws and displays """Decorator that will catch any Exception that 'func' throws and displays
it in a new Vim scratch buffer.""" it in a new Vim scratch buffer."""
@ -52,9 +54,9 @@ def err_to_scratch_buffer(func):
def wrapper(self, *args, **kwds): def wrapper(self, *args, **kwds):
try: try:
return func(self, *args, **kwds) return func(self, *args, **kwds)
except: # pylint: disable=bare-except except: # pylint: disable=bare-except
msg = \ msg = \
"""An error occured. This is either a bug in UltiSnips or a bug in a """An error occured. This is either a bug in UltiSnips or a bug in a
snippet definition. If you think this is a bug, please report it to snippet definition. If you think this is a bug, please report it to
https://github.com/SirVer/ultisnips/issues/new. https://github.com/SirVer/ultisnips/issues/new.
@ -70,8 +72,12 @@ Following is the full stack trace:
# TODO(sirver): This class is still too long. It should only contain public # TODO(sirver): This class is still too long. It should only contain public
# facing methods, most of the private methods should be moved outside of it. # facing methods, most of the private methods should be moved outside of it.
class SnippetManager(object): class SnippetManager(object):
"""The main entry point for all UltiSnips functionality. All Vim functions
call methods in this class.""" """The main entry point for all UltiSnips functionality.
All Vim functions call methods in this class.
"""
def __init__(self, expand_trigger, forward_trigger, backward_trigger): def __init__(self, expand_trigger, forward_trigger, backward_trigger):
self.expand_trigger = expand_trigger self.expand_trigger = expand_trigger
@ -89,48 +95,50 @@ class SnippetManager(object):
self._snippet_sources = [] self._snippet_sources = []
self._added_snippets_source = AddedSnippetsSource() self._added_snippets_source = AddedSnippetsSource()
self.register_snippet_source("ultisnips_files", UltiSnipsFileSource()) self.register_snippet_source('ultisnips_files', UltiSnipsFileSource())
self.register_snippet_source("added", self._added_snippets_source) self.register_snippet_source('added', self._added_snippets_source)
enable_snipmate = True enable_snipmate = True
if _vim.eval("exists('g:UltiSnipsEnableSnipMate')") == "1": if _vim.eval("exists('g:UltiSnipsEnableSnipMate')") == '1':
enable_snipmate = _vim.eval("g:UltiSnipsEnableSnipMate") enable_snipmate = _vim.eval('g:UltiSnipsEnableSnipMate')
if enable_snipmate == "1": if enable_snipmate == '1':
self.register_snippet_source("snipmate_files", self.register_snippet_source('snipmate_files',
SnipMateFileSource()) SnipMateFileSource())
self._reinit() self._reinit()
@err_to_scratch_buffer @err_to_scratch_buffer
def jump_forwards(self): def jump_forwards(self):
"""Jumps to the next tabstop.""" """Jumps to the next tabstop."""
_vim.command("let g:ulti_jump_forwards_res = 1") _vim.command('let g:ulti_jump_forwards_res = 1')
if not self._jump(): if not self._jump():
_vim.command("let g:ulti_jump_forwards_res = 0") _vim.command('let g:ulti_jump_forwards_res = 0')
return self._handle_failure(self.forward_trigger) return self._handle_failure(self.forward_trigger)
@err_to_scratch_buffer @err_to_scratch_buffer
def jump_backwards(self): def jump_backwards(self):
"""Jumps to the previous tabstop.""" """Jumps to the previous tabstop."""
_vim.command("let g:ulti_jump_backwards_res = 1") _vim.command('let g:ulti_jump_backwards_res = 1')
if not self._jump(True): if not self._jump(True):
_vim.command("let g:ulti_jump_backwards_res = 0") _vim.command('let g:ulti_jump_backwards_res = 0')
return self._handle_failure(self.backward_trigger) return self._handle_failure(self.backward_trigger)
@err_to_scratch_buffer @err_to_scratch_buffer
def expand(self): def expand(self):
"""Try to expand a snippet at the current position.""" """Try to expand a snippet at the current position."""
_vim.command("let g:ulti_expand_res = 1") _vim.command('let g:ulti_expand_res = 1')
if not self._try_expand(): if not self._try_expand():
_vim.command("let g:ulti_expand_res = 0") _vim.command('let g:ulti_expand_res = 0')
self._handle_failure(self.expand_trigger) self._handle_failure(self.expand_trigger)
@err_to_scratch_buffer @err_to_scratch_buffer
def expand_or_jump(self): def expand_or_jump(self):
""" """This function is used for people who wants to have the same trigger
This function is used for people who wants to have the same trigger for for expansion and forward jumping.
expansion and forward jumping. It first tries to expand a snippet, if
this fails, it tries to jump forward. It first tries to expand a snippet, if this fails, it tries to
jump forward.
""" """
_vim.command('let g:ulti_expand_or_jump_res = 1') _vim.command('let g:ulti_expand_or_jump_res = 1')
rv = self._try_expand() rv = self._try_expand()
@ -152,7 +160,7 @@ class SnippetManager(object):
snippets.sort(key=lambda x: x.trigger) snippets.sort(key=lambda x: x.trigger)
for snip in snippets: for snip in snippets:
description = snip.description[snip.description.find(snip.trigger) + description = snip.description[snip.description.find(snip.trigger) +
len(snip.trigger) + 2:] len(snip.trigger) + 2:]
key = as_unicode(snip.trigger) key = as_unicode(snip.trigger)
description = as_unicode(description) description = as_unicode(description)
@ -195,18 +203,18 @@ class SnippetManager(object):
@err_to_scratch_buffer @err_to_scratch_buffer
def add_snippet(self, trigger, value, description, def add_snippet(self, trigger, value, description,
options, ft="all", priority=0): options, ft='all', priority=0):
"""Add a snippet to the list of known snippets of the given 'ft'.""" """Add a snippet to the list of known snippets of the given 'ft'."""
self._added_snippets_source.add_snippet(ft, self._added_snippets_source.add_snippet(ft,
UltiSnipsSnippetDefinition(priority, trigger, value, UltiSnipsSnippetDefinition(priority, trigger, value,
description, options, {}, "added")) description, options, {}, 'added'))
@err_to_scratch_buffer @err_to_scratch_buffer
def expand_anon(self, value, trigger="", description="", options=""): def expand_anon(self, value, trigger='', description='', options=''):
"""Expand an anonymous snippet right here.""" """Expand an anonymous snippet right here."""
before = _vim.buf.line_till_cursor before = _vim.buf.line_till_cursor
snip = UltiSnipsSnippetDefinition(0, trigger, value, description, snip = UltiSnipsSnippetDefinition(0, trigger, value, description,
options, {}, "") options, {}, '')
if not trigger or snip.matches(before): if not trigger or snip.matches(before):
self._do_snippet(snip, before) self._do_snippet(snip, before)
@ -215,18 +223,24 @@ class SnippetManager(object):
return False return False
def register_snippet_source(self, name, snippet_source): def register_snippet_source(self, name, snippet_source):
"""Registers a new 'snippet_source' with the given 'name'. The given """Registers a new 'snippet_source' with the given 'name'.
class must be an instance of SnippetSource. This source will be queried
for snippets.""" The given class must be an instance of SnippetSource. This
source will be queried for snippets.
"""
self._snippet_sources.append((name, snippet_source)) self._snippet_sources.append((name, snippet_source))
def unregister_snippet_source(self, name): def unregister_snippet_source(self, name):
"""Unregister the source with the given 'name'. Does nothing if it is """Unregister the source with the given 'name'.
not registered."""
Does nothing if it is not registered.
"""
for index, (source_name, _) in enumerate(self._snippet_sources): for index, (source_name, _) in enumerate(self._snippet_sources):
if name == source_name: if name == source_name:
self._snippet_sources = self._snippet_sources[:index] + \ self._snippet_sources = self._snippet_sources[:index] + \
self._snippet_sources[index+1:] self._snippet_sources[index + 1:]
break break
def reset_buffer_filetypes(self): def reset_buffer_filetypes(self):
@ -236,10 +250,10 @@ class SnippetManager(object):
def add_buffer_filetypes(self, ft): def add_buffer_filetypes(self, ft):
"""Checks for changes in the list of snippet files or the contents of """Checks for changes in the list of snippet files or the contents of
the snippet files and reloads them if necessary. """ the snippet files and reloads them if necessary."""
buf_fts = self._buffer_filetypes[_vim.buf.number] buf_fts = self._buffer_filetypes[_vim.buf.number]
idx = -1 idx = -1
for ft in ft.split("."): for ft in ft.split('.'):
ft = ft.strip() ft = ft.strip()
if not ft: if not ft:
continue continue
@ -255,7 +269,7 @@ class SnippetManager(object):
if not self._csnippets and self._inner_mappings_in_place: if not self._csnippets and self._inner_mappings_in_place:
self._unmap_inner_keys() self._unmap_inner_keys()
self._vstate.remember_position() self._vstate.remember_position()
if _vim.eval("mode()") not in 'in': if _vim.eval('mode()') not in 'in':
return return
if self._ignore_movements: if self._ignore_movements:
@ -265,7 +279,7 @@ class SnippetManager(object):
if self._csnippets: if self._csnippets:
cstart = self._csnippets[0].start.line cstart = self._csnippets[0].start.line
cend = self._csnippets[0].end.line + \ cend = self._csnippets[0].end.line + \
self._vstate.diff_in_buffer_length self._vstate.diff_in_buffer_length
ct = _vim.buf[cstart:cend + 1] ct = _vim.buf[cstart:cend + 1]
lt = self._vstate.remembered_buffer lt = self._vstate.remembered_buffer
pos = _vim.buf.cursor pos = _vim.buf.cursor
@ -277,9 +291,9 @@ class SnippetManager(object):
# Cut down on lines searched for changes. Start from behind and # Cut down on lines searched for changes. Start from behind and
# remove all equal lines. Then do the same from the front. # remove all equal lines. Then do the same from the front.
if lt and ct: if lt and ct:
while (lt[lt_span[1]-1] == ct[ct_span[1]-1] and while (lt[lt_span[1] - 1] == ct[ct_span[1] - 1] and
self._vstate.ppos.line < initial_line + lt_span[1]-1 and self._vstate.ppos.line < initial_line + lt_span[1] - 1 and
pos.line < initial_line + ct_span[1]-1 and pos.line < initial_line + ct_span[1] - 1 and
(lt_span[0] < lt_span[1]) and (lt_span[0] < lt_span[1]) and
(ct_span[0] < ct_span[1])): (ct_span[0] < ct_span[1])):
ct_span[1] -= 1 ct_span[1] -= 1
@ -319,14 +333,14 @@ class SnippetManager(object):
def _map_inner_keys(self): def _map_inner_keys(self):
"""Map keys that should only be defined when a snippet is active.""" """Map keys that should only be defined when a snippet is active."""
if self.expand_trigger != self.forward_trigger: if self.expand_trigger != self.forward_trigger:
_vim.command("inoremap <buffer> <silent> " + self.forward_trigger + _vim.command('inoremap <buffer> <silent> ' + self.forward_trigger +
" <C-R>=UltiSnips#JumpForwards()<cr>") ' <C-R>=UltiSnips#JumpForwards()<cr>')
_vim.command("snoremap <buffer> <silent> " + self.forward_trigger + _vim.command('snoremap <buffer> <silent> ' + self.forward_trigger +
" <Esc>:call UltiSnips#JumpForwards()<cr>") ' <Esc>:call UltiSnips#JumpForwards()<cr>')
_vim.command("inoremap <buffer> <silent> " + self.backward_trigger + _vim.command('inoremap <buffer> <silent> ' + self.backward_trigger +
" <C-R>=UltiSnips#JumpBackwards()<cr>") ' <C-R>=UltiSnips#JumpBackwards()<cr>')
_vim.command("snoremap <buffer> <silent> " + self.backward_trigger + _vim.command('snoremap <buffer> <silent> ' + self.backward_trigger +
" <Esc>:call UltiSnips#JumpBackwards()<cr>") ' <Esc>:call UltiSnips#JumpBackwards()<cr>')
self._inner_mappings_in_place = True self._inner_mappings_in_place = True
def _unmap_inner_keys(self): def _unmap_inner_keys(self):
@ -335,10 +349,10 @@ class SnippetManager(object):
return return
try: try:
if self.expand_trigger != self.forward_trigger: if self.expand_trigger != self.forward_trigger:
_vim.command("iunmap <buffer> %s" % self.forward_trigger) _vim.command('iunmap <buffer> %s' % self.forward_trigger)
_vim.command("sunmap <buffer> %s" % self.forward_trigger) _vim.command('sunmap <buffer> %s' % self.forward_trigger)
_vim.command("iunmap <buffer> %s" % self.backward_trigger) _vim.command('iunmap <buffer> %s' % self.backward_trigger)
_vim.command("sunmap <buffer> %s" % self.backward_trigger) _vim.command('sunmap <buffer> %s' % self.backward_trigger)
self._inner_mappings_in_place = False self._inner_mappings_in_place = False
except _vim.error: except _vim.error:
# This happens when a preview window was opened. This issues # This happens when a preview window was opened. This issues
@ -348,16 +362,21 @@ class SnippetManager(object):
@err_to_scratch_buffer @err_to_scratch_buffer
def _save_last_visual_selection(self): def _save_last_visual_selection(self):
""" """This is called when the expand trigger is pressed in visual mode.
This is called when the expand trigger is pressed in visual mode. Our job is to remember everything between '< and '> and pass it on to.
Our job is to remember everything between '< and '> and pass it on to
${VISUAL} in case it will be needed. ${VISUAL} in case it will be needed.
""" """
self._visual_content.conserve() self._visual_content.conserve()
def _leaving_buffer(self): def _leaving_buffer(self):
"""Called when the user switches tabs/windows/buffers. It basically """Called when the user switches tabs/windows/buffers.
means that all snippets must be properly terminated."""
It basically means that all snippets must be properly
terminated.
"""
while len(self._csnippets): while len(self._csnippets):
self._current_snippet_is_done() self._current_snippet_is_done()
self._reinit() self._reinit()
@ -392,7 +411,7 @@ class SnippetManager(object):
if self._cs: if self._cs:
ntab = self._cs.select_next_tab(backwards) ntab = self._cs.select_next_tab(backwards)
if ntab: if ntab:
if self._cs.snippet.has_option("s"): if self._cs.snippet.has_option('s'):
lineno = _vim.buf.cursor.line lineno = _vim.buf.cursor.line
_vim.buf[lineno] = _vim.buf[lineno].rstrip() _vim.buf[lineno] = _vim.buf[lineno].rstrip()
_vim.select(ntab.start, ntab.end) _vim.select(ntab.start, ntab.end)
@ -423,18 +442,18 @@ class SnippetManager(object):
def _handle_failure(self, trigger): def _handle_failure(self, trigger):
"""Mainly make sure that we play well with SuperTab.""" """Mainly make sure that we play well with SuperTab."""
if trigger.lower() == "<tab>": if trigger.lower() == '<tab>':
feedkey = "\\" + trigger feedkey = '\\' + trigger
elif trigger.lower() == "<s-tab>": elif trigger.lower() == '<s-tab>':
feedkey = "\\" + trigger feedkey = '\\' + trigger
else: else:
feedkey = None feedkey = None
mode = "n" mode = 'n'
if not self._supertab_keys: if not self._supertab_keys:
if _vim.eval("exists('g:SuperTabMappingForward')") != "0": if _vim.eval("exists('g:SuperTabMappingForward')") != '0':
self._supertab_keys = ( self._supertab_keys = (
_vim.eval("g:SuperTabMappingForward"), _vim.eval('g:SuperTabMappingForward'),
_vim.eval("g:SuperTabMappingBackward"), _vim.eval('g:SuperTabMappingBackward'),
) )
else: else:
self._supertab_keys = ['', ''] self._supertab_keys = ['', '']
@ -443,22 +462,25 @@ class SnippetManager(object):
if trigger.lower() == sttrig.lower(): if trigger.lower() == sttrig.lower():
if idx == 0: if idx == 0:
feedkey = r"\<Plug>SuperTabForward" feedkey = r"\<Plug>SuperTabForward"
mode = "n" mode = 'n'
elif idx == 1: elif idx == 1:
feedkey = r"\<Plug>SuperTabBackward" feedkey = r"\<Plug>SuperTabBackward"
mode = "p" mode = 'p'
# Use remap mode so SuperTab mappings will be invoked. # Use remap mode so SuperTab mappings will be invoked.
break break
if (feedkey == r"\<Plug>SuperTabForward" or if (feedkey == r"\<Plug>SuperTabForward" or
feedkey == r"\<Plug>SuperTabBackward"): feedkey == r"\<Plug>SuperTabBackward"):
_vim.command("return SuperTab(%s)" % _vim.escape(mode)) _vim.command('return SuperTab(%s)' % _vim.escape(mode))
elif feedkey: elif feedkey:
_vim.command("return %s" % _vim.escape(feedkey)) _vim.command('return %s' % _vim.escape(feedkey))
def _snips(self, before, partial): def _snips(self, before, partial):
"""Returns all the snippets for the given text before the cursor. If """Returns all the snippets for the given text before the cursor.
partial is True, then get also return partial matches. """
If partial is True, then get also return partial matches.
"""
filetypes = self._buffer_filetypes[_vim.buf.number][::-1] filetypes = self._buffer_filetypes[_vim.buf.number][::-1]
matching_snippets = defaultdict(list) matching_snippets = defaultdict(list)
clear_priority = None clear_priority = None
@ -470,7 +492,7 @@ class SnippetManager(object):
for _, source in self._snippet_sources: for _, source in self._snippet_sources:
sclear_priority = source.get_clear_priority(filetypes) sclear_priority = source.get_clear_priority(filetypes)
if sclear_priority is not None and (clear_priority is None if sclear_priority is not None and (clear_priority is None
or sclear_priority > clear_priority): or sclear_priority > clear_priority):
clear_priority = sclear_priority clear_priority = sclear_priority
for key, value in source.get_cleared(filetypes).items(): for key, value in source.get_cleared(filetypes).items():
if key not in cleared or value > cleared[key]: if key not in cleared or value > cleared[key]:
@ -480,7 +502,7 @@ class SnippetManager(object):
for snippet in source.get_snippets(filetypes, before, partial): for snippet in source.get_snippets(filetypes, before, partial):
if ((clear_priority is None or snippet.priority > clear_priority) if ((clear_priority is None or snippet.priority > clear_priority)
and (snippet.trigger not in cleared or and (snippet.trigger not in cleared or
snippet.priority > cleared[snippet.trigger])): snippet.priority > cleared[snippet.trigger])):
matching_snippets[snippet.trigger].append(snippet) matching_snippets[snippet.trigger].append(snippet)
if not matching_snippets: if not matching_snippets:
return [] return []
@ -491,7 +513,7 @@ class SnippetManager(object):
for snippets_with_trigger in matching_snippets.values(): for snippets_with_trigger in matching_snippets.values():
highest_priority = max(s.priority for s in snippets_with_trigger) highest_priority = max(s.priority for s in snippets_with_trigger)
snippets.extend(s for s in snippets_with_trigger snippets.extend(s for s in snippets_with_trigger
if s.priority == highest_priority) if s.priority == highest_priority)
# For partial matches we are done, but if we want to expand a snippet, # For partial matches we are done, but if we want to expand a snippet,
# we have to go over them again and only keep those with the maximum # we have to go over them again and only keep those with the maximum
@ -503,8 +525,8 @@ class SnippetManager(object):
return [s for s in snippets if s.priority == highest_priority] return [s for s in snippets if s.priority == highest_priority]
def _do_snippet(self, snippet, before): def _do_snippet(self, snippet, before):
"""Expands the given snippet, and handles everything """Expands the given snippet, and handles everything that needs to be
that needs to be done with it.""" done with it."""
self._map_inner_keys() self._map_inner_keys()
# Adjust before, maybe the trigger is not the complete word # Adjust before, maybe the trigger is not the complete word
@ -522,13 +544,13 @@ class SnippetManager(object):
# pretending that the user deleted and retyped the text that our # pretending that the user deleted and retyped the text that our
# trigger matched. # trigger matched.
edit_actions = [ edit_actions = [
("D", start.line, start.col, snippet.matched), ('D', start.line, start.col, snippet.matched),
("I", start.line, start.col, snippet.matched), ('I', start.line, start.col, snippet.matched),
] ]
self._csnippets[0].replay_user_edits(edit_actions) self._csnippets[0].replay_user_edits(edit_actions)
si = snippet.launch(text_before, self._visual_content, si = snippet.launch(text_before, self._visual_content,
self._cs.find_parent_for_new_to(start), start, end) self._cs.find_parent_for_new_to(start), start, end)
else: else:
start = Position(_vim.buf.cursor.line, len(text_before)) start = Position(_vim.buf.cursor.line, len(text_before))
end = Position(_vim.buf.cursor.line, len(before)) end = Position(_vim.buf.cursor.line, len(before))
@ -570,26 +592,29 @@ class SnippetManager(object):
return self._csnippets[-1] return self._csnippets[-1]
def _file_to_edit(self, requested_ft, bang): # pylint: disable=no-self-use def _file_to_edit(self, requested_ft, bang): # pylint: disable=no-self-use
"""Returns a file to be edited for the given requested_ft. If 'bang' is """Returns a file to be edited for the given requested_ft.
If 'bang' is
empty only private files in g:UltiSnipsSnippetsDir are considered, empty only private files in g:UltiSnipsSnippetsDir are considered,
otherwise all files are considered and the user gets to choose. otherwise all files are considered and the user gets to choose.
""" """
# This method is not using self, but is called by UltiSnips.vim and is # This method is not using self, but is called by UltiSnips.vim and is
# therefore in this class because it is the facade to Vim. # therefore in this class because it is the facade to Vim.
potentials = set() potentials = set()
if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == "1": if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == '1':
snippet_dir = _vim.eval("g:UltiSnipsSnippetsDir") snippet_dir = _vim.eval('g:UltiSnipsSnippetsDir')
else: else:
if platform.system() == "Windows": if platform.system() == 'Windows':
snippet_dir = os.path.join(_vim.eval("$HOME"), snippet_dir = os.path.join(_vim.eval('$HOME'),
"vimfiles", "UltiSnips") 'vimfiles', 'UltiSnips')
elif _vim.eval("has('nvim')") == "1": elif _vim.eval("has('nvim')") == '1':
snippet_dir = os.path.join(_vim.eval("$HOME"), snippet_dir = os.path.join(_vim.eval('$HOME'),
".nvim", "UltiSnips") '.nvim', 'UltiSnips')
else: else:
snippet_dir = os.path.join(_vim.eval("$HOME"), snippet_dir = os.path.join(_vim.eval('$HOME'),
".vim", "UltiSnips") '.vim', 'UltiSnips')
filetypes = [] filetypes = []
if requested_ft: if requested_ft:
@ -603,20 +628,20 @@ class SnippetManager(object):
for ft in filetypes: for ft in filetypes:
potentials.update(find_snippet_files(ft, snippet_dir)) potentials.update(find_snippet_files(ft, snippet_dir))
potentials.add(os.path.join(snippet_dir, potentials.add(os.path.join(snippet_dir,
ft + '.snippets')) ft + '.snippets'))
if bang: if bang:
potentials.update(find_all_snippet_files(ft)) potentials.update(find_all_snippet_files(ft))
potentials = set(os.path.realpath(os.path.expanduser(p)) potentials = set(os.path.realpath(os.path.expanduser(p))
for p in potentials) for p in potentials)
if len(potentials) > 1: if len(potentials) > 1:
files = sorted(potentials) files = sorted(potentials)
formatted = [as_unicode('%i: %s') % (i, escape(fn, '\\')) for formatted = [as_unicode('%i: %s') % (i, escape(fn, '\\')) for
i, fn in enumerate(files, 1)] i, fn in enumerate(files, 1)]
file_to_edit = _ask_user(files, formatted) file_to_edit = _ask_user(files, formatted)
if file_to_edit is None: if file_to_edit is None:
return "" return ''
else: else:
file_to_edit = potentials.pop() file_to_edit = potentials.pop()

View File

@ -10,17 +10,17 @@ from position import Position
def transform(a, cmds): def transform(a, cmds):
buf = a.split("\n") buf = a.split('\n')
for cmd in cmds: for cmd in cmds:
ctype, line, col, char = cmd ctype, line, col, char = cmd
if ctype == "D": if ctype == 'D':
if char != '\n': if char != '\n':
buf[line] = buf[line][:col] + buf[line][col+len(char):] buf[line] = buf[line][:col] + buf[line][col + len(char):]
else: else:
buf[line] = buf[line] + buf[line+1] buf[line] = buf[line] + buf[line + 1]
del buf[line+1] del buf[line + 1]
elif ctype == "I": elif ctype == 'I':
buf[line] = buf[line][:col] + char + buf[line][col:] buf[line] = buf[line][:col] + char + buf[line][col:]
buf = '\n'.join(buf).split('\n') buf = '\n'.join(buf).split('\n')
return '\n'.join(buf) return '\n'.join(buf)
@ -29,106 +29,127 @@ def transform(a, cmds):
import unittest import unittest
# Test Guessing {{{ # Test Guessing {{{
class _BaseGuessing(object): class _BaseGuessing(object):
def runTest(self): def runTest(self):
rv, es = guess_edit(self.initial_line, self.a, self.b, Position(*self.ppos), Position(*self.pos)) rv, es = guess_edit(
self.initial_line, self.a, self.b, Position(*self.ppos), Position(*self.pos))
self.assertEqual(rv, True) self.assertEqual(rv, True)
self.assertEqual(self.wanted, es) self.assertEqual(self.wanted, es)
class TestGuessing_Noop0(_BaseGuessing, unittest.TestCase): class TestGuessing_Noop0(_BaseGuessing, unittest.TestCase):
a, b = [], [] a, b = [], []
initial_line = 0 initial_line = 0
ppos, pos = (0, 6), (0, 7) ppos, pos = (0, 6), (0, 7)
wanted = () wanted = ()
class TestGuessing_InsertOneChar(_BaseGuessing, unittest.TestCase): class TestGuessing_InsertOneChar(_BaseGuessing, unittest.TestCase):
a, b = ["Hello World"], ["Hello World"] a, b = ['Hello World'], ['Hello World']
initial_line = 0 initial_line = 0
ppos, pos = (0, 6), (0, 7) ppos, pos = (0, 6), (0, 7)
wanted = ( wanted = (
("I", 0, 6, " "), ('I', 0, 6, ' '),
) )
class TestGuessing_InsertOneChar1(_BaseGuessing, unittest.TestCase): class TestGuessing_InsertOneChar1(_BaseGuessing, unittest.TestCase):
a, b = ["Hello World"], ["Hello World"] a, b = ['Hello World'], ['Hello World']
initial_line = 0 initial_line = 0
ppos, pos = (0, 7), (0, 8) ppos, pos = (0, 7), (0, 8)
wanted = ( wanted = (
("I", 0, 7, " "), ('I', 0, 7, ' '),
) )
class TestGuessing_BackspaceOneChar(_BaseGuessing, unittest.TestCase): class TestGuessing_BackspaceOneChar(_BaseGuessing, unittest.TestCase):
a, b = ["Hello World"], ["Hello World"] a, b = ['Hello World'], ['Hello World']
initial_line = 0 initial_line = 0
ppos, pos = (0, 7), (0, 6) ppos, pos = (0, 7), (0, 6)
wanted = ( wanted = (
("D", 0, 6, " "), ('D', 0, 6, ' '),
) )
class TestGuessing_DeleteOneChar(_BaseGuessing, unittest.TestCase): class TestGuessing_DeleteOneChar(_BaseGuessing, unittest.TestCase):
a, b = ["Hello World"], ["Hello World"] a, b = ['Hello World'], ['Hello World']
initial_line = 0 initial_line = 0
ppos, pos = (0, 5), (0, 5) ppos, pos = (0, 5), (0, 5)
wanted = ( wanted = (
("D", 0, 5, " "), ('D', 0, 5, ' '),
) )
# End: Test Guessing }}} # End: Test Guessing }}}
class _Base(object): class _Base(object):
def runTest(self): def runTest(self):
es = diff(self.a, self.b) es = diff(self.a, self.b)
tr = transform(self.a, es) tr = transform(self.a, es)
self.assertEqual(self.b, tr) self.assertEqual(self.b, tr)
self.assertEqual(self.wanted, es) self.assertEqual(self.wanted, es)
class TestEmptyString(_Base, unittest.TestCase): class TestEmptyString(_Base, unittest.TestCase):
a, b = "", "" a, b = '', ''
wanted = () wanted = ()
class TestAllMatch(_Base, unittest.TestCase): class TestAllMatch(_Base, unittest.TestCase):
a, b = "abcdef", "abcdef" a, b = 'abcdef', 'abcdef'
wanted = () wanted = ()
class TestLotsaNewlines(_Base, unittest.TestCase): class TestLotsaNewlines(_Base, unittest.TestCase):
a, b = "Hello", "Hello\nWorld\nWorld\nWorld" a, b = 'Hello', 'Hello\nWorld\nWorld\nWorld'
wanted = ( wanted = (
("I", 0, 5, "\n"), ('I', 0, 5, '\n'),
("I", 1, 0, "World"), ('I', 1, 0, 'World'),
("I", 1, 5, "\n"), ('I', 1, 5, '\n'),
("I", 2, 0, "World"), ('I', 2, 0, 'World'),
("I", 2, 5, "\n"), ('I', 2, 5, '\n'),
("I", 3, 0, "World"), ('I', 3, 0, 'World'),
) )
class TestCrash(_Base, unittest.TestCase): class TestCrash(_Base, unittest.TestCase):
a = 'hallo Blah mitte=sdfdsfsd\nhallo kjsdhfjksdhfkjhsdfkh mittekjshdkfhkhsdfdsf' a = 'hallo Blah mitte=sdfdsfsd\nhallo kjsdhfjksdhfkjhsdfkh mittekjshdkfhkhsdfdsf'
b = 'hallo Blah mitte=sdfdsfsd\nhallo b mittekjshdkfhkhsdfdsf' b = 'hallo Blah mitte=sdfdsfsd\nhallo b mittekjshdkfhkhsdfdsf'
wanted = ( wanted = (
("D", 1, 6, "kjsdhfjksdhfkjhsdfkh"), ('D', 1, 6, 'kjsdhfjksdhfkjhsdfkh'),
("I", 1, 6, "b"), ('I', 1, 6, 'b'),
) )
class TestRealLife(_Base, unittest.TestCase): class TestRealLife(_Base, unittest.TestCase):
a = 'hallo End Beginning' a = 'hallo End Beginning'
b = 'hallo End t' b = 'hallo End t'
wanted = ( wanted = (
("D", 0, 10, "Beginning"), ('D', 0, 10, 'Beginning'),
("I", 0, 10, "t"), ('I', 0, 10, 't'),
) )
class TestRealLife1(_Base, unittest.TestCase): class TestRealLife1(_Base, unittest.TestCase):
a = 'Vorne hallo Hinten' a = 'Vorne hallo Hinten'
b = 'Vorne hallo Hinten' b = 'Vorne hallo Hinten'
wanted = ( wanted = (
("I", 0, 11, " "), ('I', 0, 11, ' '),
) )
class TestWithNewline(_Base, unittest.TestCase): class TestWithNewline(_Base, unittest.TestCase):
a = 'First Line\nSecond Line' a = 'First Line\nSecond Line'
b = 'n' b = 'n'
wanted = ( wanted = (
("D", 0, 0, "First Line"), ('D', 0, 0, 'First Line'),
("D", 0, 0, "\n"), ('D', 0, 0, '\n'),
("D", 0, 0, "Second Line"), ('D', 0, 0, 'Second Line'),
("I", 0, 0, "n"), ('I', 0, 0, 'n'),
) )
@ -136,51 +157,56 @@ class TestCheapDelete(_Base, unittest.TestCase):
a = 'Vorne hallo Hinten' a = 'Vorne hallo Hinten'
b = 'Vorne Hinten' b = 'Vorne Hinten'
wanted = ( wanted = (
("D", 0, 5, " hallo"), ('D', 0, 5, ' hallo'),
) )
class TestNoSubstring(_Base, unittest.TestCase): class TestNoSubstring(_Base, unittest.TestCase):
a,b = "abc", "def" a, b = 'abc', 'def'
wanted = ( wanted = (
("D", 0, 0, "abc"), ('D', 0, 0, 'abc'),
("I", 0, 0, "def"), ('I', 0, 0, 'def'),
) )
class TestCommonCharacters(_Base, unittest.TestCase): class TestCommonCharacters(_Base, unittest.TestCase):
a,b = "hasomelongertextbl", "hol" a, b = 'hasomelongertextbl', 'hol'
wanted = ( wanted = (
("D", 0, 1, "asomelongertextb"), ('D', 0, 1, 'asomelongertextb'),
("I", 0, 1, "o"), ('I', 0, 1, 'o'),
) )
class TestUltiSnipsProblem(_Base, unittest.TestCase): class TestUltiSnipsProblem(_Base, unittest.TestCase):
a = "this is it this is it this is it" a = 'this is it this is it this is it'
b = "this is it a this is it" b = 'this is it a this is it'
wanted = ( wanted = (
("D", 0, 11, "this is it"), ('D', 0, 11, 'this is it'),
("I", 0, 11, "a"), ('I', 0, 11, 'a'),
) )
class MatchIsTooCheap(_Base, unittest.TestCase): class MatchIsTooCheap(_Base, unittest.TestCase):
a = "stdin.h" a = 'stdin.h'
b = "s" b = 's'
wanted = ( wanted = (
("D", 0, 1, "tdin.h"), ('D', 0, 1, 'tdin.h'),
) )
class MultiLine(_Base, unittest.TestCase): class MultiLine(_Base, unittest.TestCase):
a = "hi first line\nsecond line first line\nsecond line world" a = 'hi first line\nsecond line first line\nsecond line world'
b = "hi first line\nsecond line k world" b = 'hi first line\nsecond line k world'
wanted = ( wanted = (
("D", 1, 12, "first line"), ('D', 1, 12, 'first line'),
("D", 1, 12, "\n"), ('D', 1, 12, '\n'),
("D", 1, 12, "second line"), ('D', 1, 12, 'second line'),
("I", 1, 12, "k"), ('I', 1, 12, 'k'),
) )
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
# k = TestEditScript() # k = TestEditScript()
# unittest.TextTestRunner().run(k) # unittest.TextTestRunner().run(k)

View File

@ -7,13 +7,16 @@ import unittest
from position import Position from position import Position
class _MPBase(object): class _MPBase(object):
def runTest(self): def runTest(self):
obj = Position(*self.obj) obj = Position(*self.obj)
for pivot, delta, wanted in self.steps: for pivot, delta, wanted in self.steps:
obj.move(Position(*pivot), Position(*delta)) obj.move(Position(*pivot), Position(*delta))
self.assertEqual(Position(*wanted), obj) self.assertEqual(Position(*wanted), obj)
class MovePosition_DelSameLine(_MPBase, unittest.TestCase): class MovePosition_DelSameLine(_MPBase, unittest.TestCase):
# hello wor*ld -> h*ld -> hl*ld # hello wor*ld -> h*ld -> hl*ld
obj = (0, 9) obj = (0, 9)
@ -21,13 +24,17 @@ class MovePosition_DelSameLine(_MPBase, unittest.TestCase):
((0, 1), (0, -8), (0, 1)), ((0, 1), (0, -8), (0, 1)),
((0, 1), (0, 1), (0, 2)), ((0, 1), (0, 1), (0, 2)),
) )
class MovePosition_DelSameLine1(_MPBase, unittest.TestCase): class MovePosition_DelSameLine1(_MPBase, unittest.TestCase):
# hel*lo world -> hel*world -> hel*worl # hel*lo world -> hel*world -> hel*worl
obj = (0,3) obj = (0, 3)
steps = ( steps = (
((0, 4), (0, -3), (0,3)), ((0, 4), (0, -3), (0, 3)),
((0, 8), (0, -1), (0,3)), ((0, 8), (0, -1), (0, 3)),
) )
class MovePosition_InsSameLine1(_MPBase, unittest.TestCase): class MovePosition_InsSameLine1(_MPBase, unittest.TestCase):
# hel*lo world -> hel*woresld # hel*lo world -> hel*woresld
obj = (0, 3) obj = (0, 3)
@ -36,6 +43,8 @@ class MovePosition_InsSameLine1(_MPBase, unittest.TestCase):
((0, 6), (0, 2), (0, 3)), ((0, 6), (0, 2), (0, 3)),
((0, 8), (0, -1), (0, 3)) ((0, 8), (0, -1), (0, 3))
) )
class MovePosition_InsSameLine2(_MPBase, unittest.TestCase): class MovePosition_InsSameLine2(_MPBase, unittest.TestCase):
# hello wor*ld -> helesdlo wor*ld # hello wor*ld -> helesdlo wor*ld
obj = (0, 9) obj = (0, 9)
@ -43,6 +52,7 @@ class MovePosition_InsSameLine2(_MPBase, unittest.TestCase):
((0, 3), (0, 3), (0, 12)), ((0, 3), (0, 3), (0, 12)),
) )
class MovePosition_DelSecondLine(_MPBase, unittest.TestCase): class MovePosition_DelSecondLine(_MPBase, unittest.TestCase):
# hello world. sup hello world.*a, was # hello world. sup hello world.*a, was
# *a, was ach nix # *a, was ach nix
@ -52,6 +62,8 @@ class MovePosition_DelSecondLine(_MPBase, unittest.TestCase):
((0, 12), (0, -4), (1, 0)), ((0, 12), (0, -4), (1, 0)),
((0, 12), (-1, 0), (0, 12)), ((0, 12), (-1, 0), (0, 12)),
) )
class MovePosition_DelSecondLine1(_MPBase, unittest.TestCase): class MovePosition_DelSecondLine1(_MPBase, unittest.TestCase):
# hello world. sup # hello world. sup
# a, *was # a, *was
@ -63,7 +75,7 @@ class MovePosition_DelSecondLine1(_MPBase, unittest.TestCase):
((0, 12), (0, -4), (1, 3)), ((0, 12), (0, -4), (1, 3)),
((0, 12), (-1, 0), (0, 15)), ((0, 12), (-1, 0), (0, 15)),
((0, 12), (0, -3), (0, 12)), ((0, 12), (0, -3), (0, 12)),
((0, 12), (0, 1), (0, 13)), ((0, 12), (0, 1), (0, 13)),
) )
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -3,22 +3,24 @@
"""Utilities to deal with text.""" """Utilities to deal with text."""
def unescape(text): def unescape(text):
"""Removes '\\' escaping from 'text'.""" """Removes '\\' escaping from 'text'."""
rv = "" rv = ''
i = 0 i = 0
while i < len(text): while i < len(text):
if i+1 < len(text) and text[i] == '\\': if i + 1 < len(text) and text[i] == '\\':
rv += text[i+1] rv += text[i + 1]
i += 1 i += 1
else: else:
rv += text[i] rv += text[i]
i += 1 i += 1
return rv return rv
def escape(text, chars): def escape(text, chars):
"""Escapes all characters in 'chars' in text using backspaces.""" """Escapes all characters in 'chars' in text using backspaces."""
rv = "" rv = ''
for char in text: for char in text:
if char in chars: if char in chars:
rv += '\\' rv += '\\'
@ -28,13 +30,14 @@ def escape(text, chars):
def fill_in_whitespace(text): def fill_in_whitespace(text):
"""Returns 'text' with escaped whitespace replaced through whitespaces.""" """Returns 'text' with escaped whitespace replaced through whitespaces."""
text = text.replace(r"\n", "\n") text = text.replace(r"\n", '\n')
text = text.replace(r"\t", "\t") text = text.replace(r"\t", '\t')
text = text.replace(r"\r", "\r") text = text.replace(r"\r", '\r')
text = text.replace(r"\a", "\a") text = text.replace(r"\a", '\a')
text = text.replace(r"\b", "\b") text = text.replace(r"\b", '\b')
return text return text
def head_tail(line): def head_tail(line):
"""Returns the first word in 'line' and the rest of 'line' or None if the """Returns the first word in 'line' and the rest of 'line' or None if the
line is too short.""" line is too short."""
@ -47,7 +50,9 @@ def head_tail(line):
pass pass
return head, tail return head, tail
class LineIterator(object): class LineIterator(object):
"""Convenience class that keeps track of line numbers in files.""" """Convenience class that keeps track of line numbers in files."""
def __init__(self, text): def __init__(self, text):

View File

@ -6,14 +6,16 @@
from UltiSnips import _vim from UltiSnips import _vim
from UltiSnips.position import Position from UltiSnips.position import Position
def _calc_end(text, start): def _calc_end(text, start):
"""Calculate the end position of the 'text' starting at 'start.""" """Calculate the end position of the 'text' starting at 'start."""
if len(text) == 1: if len(text) == 1:
new_end = start + Position(0, len(text[0])) new_end = start + Position(0, len(text[0]))
else: else:
new_end = Position(start.line + len(text)-1, len(text[-1])) new_end = Position(start.line + len(text) - 1, len(text[-1]))
return new_end return new_end
def _text_to_vim(start, end, text): def _text_to_vim(start, end, text):
"""Copy the given text to the current buffer, overwriting the span 'start' """Copy the given text to the current buffer, overwriting the span 'start'
to 'end'.""" to 'end'."""
@ -33,30 +35,33 @@ def _text_to_vim(start, end, text):
# Open any folds this might have created # Open any folds this might have created
_vim.buf.cursor = start _vim.buf.cursor = start
_vim.command("normal! zv") _vim.command('normal! zv')
return new_end return new_end
# These classes use their subclasses a lot and we really do not want to expose # These classes use their subclasses a lot and we really do not want to expose
# their functions more globally. # their functions more globally.
# pylint: disable=protected-access # pylint: disable=protected-access
class TextObject(object): class TextObject(object):
"""Represents any object in the text that has a span in any ways.""" """Represents any object in the text that has a span in any ways."""
def __init__(self, parent, token, end=None, def __init__(self, parent, token, end=None,
initial_text="", tiebreaker=None): initial_text='', tiebreaker=None):
self._parent = parent self._parent = parent
if end is not None: # Took 4 arguments if end is not None: # Took 4 arguments
self._start = token self._start = token
self._end = end self._end = end
self._initial_text = initial_text self._initial_text = initial_text
else: # Initialize from token else: # Initialize from token
self._start = token.start self._start = token.start
self._end = token.end self._end = token.end
self._initial_text = token.initial_text self._initial_text = token.initial_text
self._tiebreaker = tiebreaker or Position( self._tiebreaker = tiebreaker or Position(
self._start.line, self._end.line) self._start.line, self._end.line)
if parent is not None: if parent is not None:
parent._add_child(self) parent._add_child(self)
@ -67,27 +72,27 @@ class TextObject(object):
def __lt__(self, other): def __lt__(self, other):
me_tuple = (self.start.line, self.start.col, me_tuple = (self.start.line, self.start.col,
self._tiebreaker.line, self._tiebreaker.col) self._tiebreaker.line, self._tiebreaker.col)
other_tuple = (other._start.line, other._start.col, other_tuple = (other._start.line, other._start.col,
other._tiebreaker.line, other._tiebreaker.col) other._tiebreaker.line, other._tiebreaker.col)
return me_tuple < other_tuple return me_tuple < other_tuple
def __le__(self, other): def __le__(self, other):
me_tuple = (self._start.line, self._start.col, me_tuple = (self._start.line, self._start.col,
self._tiebreaker.line, self._tiebreaker.col) self._tiebreaker.line, self._tiebreaker.col)
other_tuple = (other._start.line, other._start.col, other_tuple = (other._start.line, other._start.col,
other._tiebreaker.line, other._tiebreaker.col) other._tiebreaker.line, other._tiebreaker.col)
return me_tuple <= other_tuple return me_tuple <= other_tuple
def __repr__(self): def __repr__(self):
ct = "" ct = ''
try: try:
ct = self.current_text ct = self.current_text
except IndexError: except IndexError:
ct = "<err>" ct = '<err>'
return "%s(%r->%r,%r)" % (self.__class__.__name__, return '%s(%r->%r,%r)' % (self.__class__.__name__,
self._start, self._end, ct) self._start, self._end, ct)
@property @property
def current_text(self): def current_text(self):
@ -96,7 +101,7 @@ class TextObject(object):
return _vim.buf[self._start.line][self._start.col:self._end.col] return _vim.buf[self._start.line][self._start.col:self._end.col]
else: else:
lines = [_vim.buf[self._start.line][self._start.col:]] lines = [_vim.buf[self._start.line][self._start.col:]]
lines.extend(_vim.buf[self._start.line+1:self._end.line]) lines.extend(_vim.buf[self._start.line + 1:self._end.line])
lines.append(_vim.buf[self._end.line][:self._end.col]) lines.append(_vim.buf[self._end.line][:self._end.col])
return '\n'.join(lines) return '\n'.join(lines)
@ -112,8 +117,10 @@ class TextObject(object):
def overwrite(self, gtext=None): def overwrite(self, gtext=None):
"""Overwrite the text of this object in the Vim Buffer and update its """Overwrite the text of this object in the Vim Buffer and update its
length information. If 'gtext' is None use the initial text of this length information.
object.
If 'gtext' is None use the initial text of this object.
""" """
# We explicitly do not want to move our children around here as we # We explicitly do not want to move our children around here as we
# either have non or we are replacing text initially which means we do # either have non or we are replacing text initially which means we do
@ -122,7 +129,7 @@ class TextObject(object):
return return
old_end = self._end old_end = self._end
self._end = _text_to_vim( self._end = _text_to_vim(
self._start, self._end, gtext or self._initial_text) self._start, self._end, gtext or self._initial_text)
if self._parent: if self._parent:
self._parent._child_has_moved( self._parent._child_has_moved(
self._parent._children.index(self), min(old_end, self._end), self._parent._children.index(self), min(old_end, self._end),
@ -134,14 +141,16 @@ class TextObject(object):
Return False if you need to be called again for this edit cycle. Return False if you need to be called again for this edit cycle.
Otherwise return True. Otherwise return True.
""" """
raise NotImplementedError("Must be implemented by subclasses.") raise NotImplementedError('Must be implemented by subclasses.')
class EditableTextObject(TextObject): class EditableTextObject(TextObject):
"""
This base class represents any object in the text """This base class represents any object in the text that can be changed by
that can be changed by the user the user."""
"""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
TextObject.__init__(self, *args, **kwargs) TextObject.__init__(self, *args, **kwargs)
self._children = [] self._children = []
@ -157,7 +166,7 @@ class EditableTextObject(TextObject):
@property @property
def _editable_children(self): def _editable_children(self):
"""List of all children that are EditableTextObjects""" """List of all children that are EditableTextObjects."""
return [child for child in self._children if return [child for child in self._children if
isinstance(child, EditableTextObject)] isinstance(child, EditableTextObject)]
@ -177,13 +186,13 @@ class EditableTextObject(TextObject):
def _do_edit(self, cmd): def _do_edit(self, cmd):
"""Apply the edit 'cmd' to this object.""" """Apply the edit 'cmd' to this object."""
ctype, line, col, text = cmd ctype, line, col, text = cmd
assert ('\n' not in text) or (text == "\n") assert ('\n' not in text) or (text == '\n')
pos = Position(line, col) pos = Position(line, col)
to_kill = set() to_kill = set()
new_cmds = [] new_cmds = []
for child in self._children: for child in self._children:
if ctype == "I": # Insertion if ctype == 'I': # Insertion
if (child._start < pos < if (child._start < pos <
Position(child._end.line, child._end.col) and Position(child._end.line, child._end.col) and
isinstance(child, NoneditableTextObject)): isinstance(child, NoneditableTextObject)):
@ -194,9 +203,9 @@ class EditableTextObject(TextObject):
isinstance(child, EditableTextObject)): isinstance(child, EditableTextObject)):
child._do_edit(cmd) child._do_edit(cmd)
return return
else: # Deletion else: # Deletion
delend = pos + Position(0, len(text)) if text != "\n" \ delend = pos + Position(0, len(text)) if text != '\n' \
else Position(line + 1, 0) else Position(line + 1, 0)
if ((child._start <= pos < child._end) and if ((child._start <= pos < child._end) and
(child._start < delend <= child._end)): (child._start < delend <= child._end)):
# this edit command is completely for the child # this edit command is completely for the child
@ -216,16 +225,16 @@ class EditableTextObject(TextObject):
elif (pos < child._start and elif (pos < child._start and
(child._start < delend <= child._end)): (child._start < delend <= child._end)):
# Case: partially for us, partially for the child # Case: partially for us, partially for the child
my_text = text[:(child._start-pos).col] my_text = text[:(child._start - pos).col]
c_text = text[(child._start-pos).col:] c_text = text[(child._start - pos).col:]
new_cmds.append((ctype, line, col, my_text)) new_cmds.append((ctype, line, col, my_text))
new_cmds.append((ctype, line, col, c_text)) new_cmds.append((ctype, line, col, c_text))
break break
elif (delend >= child._end and ( elif (delend >= child._end and (
child._start <= pos < child._end)): child._start <= pos < child._end)):
# Case: partially for us, partially for the child # Case: partially for us, partially for the child
c_text = text[(child._end-pos).col:] c_text = text[(child._end - pos).col:]
my_text = text[:(child._end-pos).col] my_text = text[:(child._end - pos).col]
new_cmds.append((ctype, line, col, c_text)) new_cmds.append((ctype, line, col, c_text))
new_cmds.append((ctype, line, col, my_text)) new_cmds.append((ctype, line, col, my_text))
break break
@ -238,8 +247,8 @@ class EditableTextObject(TextObject):
return return
# We have to handle this ourselves # We have to handle this ourselves
delta = Position(1, 0) if text == "\n" else Position(0, len(text)) delta = Position(1, 0) if text == '\n' else Position(0, len(text))
if ctype == "D": if ctype == 'D':
# Makes no sense to delete in empty textobject # Makes no sense to delete in empty textobject
if self._start == self._end: if self._start == self._end:
return return
@ -263,7 +272,7 @@ class EditableTextObject(TextObject):
'diff'.""" 'diff'."""
self._end.move(pivot, diff) self._end.move(pivot, diff)
for child in self._children[idx+1:]: for child in self._children[idx + 1:]:
child._move(pivot, diff) child._move(pivot, diff)
if self._parent: if self._parent:
@ -295,7 +304,6 @@ class EditableTextObject(TextObject):
return min(possible_sol) return min(possible_sol)
def _get_prev_tab(self, number): def _get_prev_tab(self, number):
"""Returns the previous tabstop before 'number'.""" """Returns the previous tabstop before 'number'."""
if not len(self._tabstops.keys()): if not len(self._tabstops.keys()):
@ -321,8 +329,11 @@ class EditableTextObject(TextObject):
return max(possible_sol) return max(possible_sol)
def _get_tabstop(self, requester, number): def _get_tabstop(self, requester, number):
"""Returns the tabstop 'number'. 'requester' is the class that is """Returns the tabstop 'number'.
interested in this."""
'requester' is the class that is interested in this.
"""
if number in self._tabstops: if number in self._tabstops:
return self._tabstops[number] return self._tabstops[number]
for child in self._editable_children: for child in self._editable_children:
@ -357,7 +368,10 @@ class EditableTextObject(TextObject):
except (AttributeError, KeyError): except (AttributeError, KeyError):
pass pass
class NoneditableTextObject(TextObject): class NoneditableTextObject(TextObject):
"""All passive text objects that the user can't edit by hand.""" """All passive text objects that the user can't edit by hand."""
def _update(self, done): def _update(self, done):
return True return True

View File

@ -5,11 +5,12 @@
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
class EscapedChar(NoneditableTextObject): class EscapedChar(NoneditableTextObject):
r""" r"""
This class is a escape char like \$. It is handled in a text object to make This class is a escape char like \$. It is handled in a text object to make
sure that siblings are correctly moved after replacing the text. sure that siblings are correctly moved after replacing the text.
This is a base class without functionality just to mark it in the code. This is a base class without functionality just to mark it in the code.
""" """
pass

View File

@ -5,7 +5,9 @@
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
class Mirror(NoneditableTextObject): class Mirror(NoneditableTextObject):
"""See module docstring.""" """See module docstring."""
def __init__(self, parent, tabstop, token): def __init__(self, parent, tabstop, token):
@ -15,7 +17,7 @@ class Mirror(NoneditableTextObject):
def _update(self, done): def _update(self, done):
if self._ts.is_killed: if self._ts.is_killed:
self.overwrite("") self.overwrite('')
self._parent._del_child(self) # pylint:disable=protected-access self._parent._del_child(self) # pylint:disable=protected-access
return True return True
@ -26,5 +28,9 @@ class Mirror(NoneditableTextObject):
return True return True
def _get_text(self): def _get_text(self):
"""Returns the text used for mirroring. Overwritten by base classes.""" """Returns the text used for mirroring.
Overwritten by base classes.
"""
return self._ts.current_text return self._ts.current_text

View File

@ -13,66 +13,78 @@ from UltiSnips.text_objects._base import NoneditableTextObject
class _Tabs(object): class _Tabs(object):
"""Allows access to tabstop content via t[] inside of python code.""" """Allows access to tabstop content via t[] inside of python code."""
def __init__(self, to): def __init__(self, to):
self._to = to self._to = to
def __getitem__(self, no): def __getitem__(self, no):
ts = self._to._get_tabstop(self._to, int(no)) # pylint:disable=protected-access ts = self._to._get_tabstop(
self._to,
int(no)) # pylint:disable=protected-access
if ts is None: if ts is None:
return "" return ''
return ts.current_text return ts.current_text
_VisualContent = namedtuple('_VisualContent', ['mode', 'text']) _VisualContent = namedtuple('_VisualContent', ['mode', 'text'])
class SnippetUtil(object): class SnippetUtil(object):
"""Provides easy access to indentation, etc. This is the 'snip' object in
python code.""" """Provides easy access to indentation, etc.
This is the 'snip' object in python code.
"""
def __init__(self, initial_indent, vmode, vtext): def __init__(self, initial_indent, vmode, vtext):
self._ind = IndentUtil() self._ind = IndentUtil()
self._visual = _VisualContent(vmode, vtext) self._visual = _VisualContent(vmode, vtext)
self._initial_indent = self._ind.indent_to_spaces(initial_indent) self._initial_indent = self._ind.indent_to_spaces(initial_indent)
self._reset("") self._reset('')
def _reset(self, cur): def _reset(self, cur):
"""Gets the snippet ready for another update. """Gets the snippet ready for another update.
:cur: the new value for c. :cur: the new value for c.
""" """
self._ind.reset() self._ind.reset()
self._cur = cur self._cur = cur
self._rv = "" self._rv = ''
self._changed = False self._changed = False
self.reset_indent() self.reset_indent()
def shift(self, amount=1): def shift(self, amount=1):
"""Shifts the indentation level. """Shifts the indentation level. Note that this uses the shiftwidth
Note that this uses the shiftwidth because thats what code because thats what code formatters use.
formatters use.
:amount: the amount by which to shift. :amount: the amount by which to shift.
""" """
self.indent += " " * self._ind.shiftwidth * amount self.indent += ' ' * self._ind.shiftwidth * amount
def unshift(self, amount=1): def unshift(self, amount=1):
"""Unshift the indentation level. """Unshift the indentation level. Note that this uses the shiftwidth
Note that this uses the shiftwidth because thats what code because thats what code formatters use.
formatters use.
:amount: the amount by which to unshift. :amount: the amount by which to unshift.
""" """
by = -self._ind.shiftwidth * amount by = -self._ind.shiftwidth * amount
try: try:
self.indent = self.indent[:by] self.indent = self.indent[:by]
except IndexError: except IndexError:
self.indent = "" self.indent = ''
def mkline(self, line="", indent=None): def mkline(self, line='', indent=None):
"""Creates a properly set up line. """Creates a properly set up line.
:line: the text to add :line: the text to add
:indent: the indentation to have at the beginning :indent: the indentation to have at the beginning
if None, it uses the default amount if None, it uses the default amount
""" """
if indent is None: if indent is None:
indent = self.indent indent = self.indent
@ -82,7 +94,7 @@ class SnippetUtil(object):
try: try:
indent = indent[len(self._initial_indent):] indent = indent[len(self._initial_indent):]
except IndexError: except IndexError:
indent = "" indent = ''
indent = self._ind.spaces_to_indent(indent) indent = self._ind.spaces_to_indent(indent)
return indent + line return indent + line
@ -95,22 +107,25 @@ class SnippetUtil(object):
@property @property
def fn(self): # pylint:disable=no-self-use,invalid-name def fn(self): # pylint:disable=no-self-use,invalid-name
"""The filename.""" """The filename."""
return _vim.eval('expand("%:t")') or "" return _vim.eval('expand("%:t")') or ''
@property @property
def basename(self): # pylint:disable=no-self-use def basename(self): # pylint:disable=no-self-use
"""The filename without extension.""" """The filename without extension."""
return _vim.eval('expand("%:t:r")') or "" return _vim.eval('expand("%:t:r")') or ''
@property @property
def ft(self): # pylint:disable=invalid-name def ft(self): # pylint:disable=invalid-name
"""The filetype.""" """The filetype."""
return self.opt("&filetype", "") return self.opt('&filetype', '')
@property @property
def rv(self): # pylint:disable=invalid-name def rv(self): # pylint:disable=invalid-name
"""The return value. The text to insert at the location of the """The return value.
placeholder."""
The text to insert at the location of the placeholder.
"""
return self._rv return self._rv
@rv.setter @rv.setter
@ -131,12 +146,12 @@ class SnippetUtil(object):
@property @property
def v(self): # pylint:disable=invalid-name def v(self): # pylint:disable=invalid-name
"""Content of visual expansions""" """Content of visual expansions."""
return self._visual return self._visual
def opt(self, option, default=None): # pylint:disable=no-self-use def opt(self, option, default=None): # pylint:disable=no-self-use
"""Gets a Vim variable.""" """Gets a Vim variable."""
if _vim.eval("exists('%s')" % option) == "1": if _vim.eval("exists('%s')" % option) == '1':
try: try:
return _vim.eval(option) return _vim.eval(option)
except _vim.error: except _vim.error:
@ -159,6 +174,7 @@ class SnippetUtil(object):
class PythonCode(NoneditableTextObject): class PythonCode(NoneditableTextObject):
"""See module docstring.""" """See module docstring."""
def __init__(self, parent, token): def __init__(self, parent, token):
@ -176,14 +192,14 @@ class PythonCode(NoneditableTextObject):
self._snip = SnippetUtil(token.indent, mode, text) self._snip = SnippetUtil(token.indent, mode, text)
self._codes = (( self._codes = ((
"import re, os, vim, string, random", 'import re, os, vim, string, random',
"\n".join(snippet.globals.get("!p", [])).replace("\r\n", "\n"), '\n'.join(snippet.globals.get('!p', [])).replace('\r\n', '\n'),
token.code.replace("\\`", "`") token.code.replace('\\`', '`')
)) ))
NoneditableTextObject.__init__(self, parent, token) NoneditableTextObject.__init__(self, parent, token)
def _update(self, done): def _update(self, done):
path = _vim.eval('expand("%")') or "" path = _vim.eval('expand("%")') or ''
ct = self.current_text ct = self.current_text
self._locals.update({ self._locals.update({
't': _Tabs(self._parent), 't': _Tabs(self._parent),

View File

@ -12,6 +12,7 @@ import tempfile
from UltiSnips.compatibility import as_unicode from UltiSnips.compatibility import as_unicode
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
def _chomp(string): def _chomp(string):
"""Rather than rstrip(), remove only the last newline and preserve """Rather than rstrip(), remove only the last newline and preserve
purposeful whitespace.""" purposeful whitespace."""
@ -21,8 +22,9 @@ def _chomp(string):
string = string[:-1] string = string[:-1]
return string return string
def _run_shell_command(cmd, tmpdir): def _run_shell_command(cmd, tmpdir):
"""Write the code to a temporary file""" """Write the code to a temporary file."""
cmdsuf = '' cmdsuf = ''
if platform.system() == 'Windows': if platform.system() == 'Windows':
# suffix required to run command on windows # suffix required to run command on windows
@ -30,7 +32,7 @@ def _run_shell_command(cmd, tmpdir):
# turn echo off # turn echo off
cmd = '@echo off\r\n' + cmd cmd = '@echo off\r\n' + cmd
handle, path = tempfile.mkstemp(text=True, dir=tmpdir, suffix=cmdsuf) handle, path = tempfile.mkstemp(text=True, dir=tmpdir, suffix=cmdsuf)
os.write(handle, cmd.encode("utf-8")) os.write(handle, cmd.encode('utf-8'))
os.close(handle) os.close(handle)
os.chmod(path, stat.S_IRWXU) os.chmod(path, stat.S_IRWXU)
@ -41,29 +43,32 @@ def _run_shell_command(cmd, tmpdir):
os.unlink(path) os.unlink(path)
return _chomp(as_unicode(stdout)) return _chomp(as_unicode(stdout))
def _get_tmp(): def _get_tmp():
"""Find an executable tmp directory.""" """Find an executable tmp directory."""
userdir = os.path.expanduser("~") userdir = os.path.expanduser('~')
for testdir in [tempfile.gettempdir(), os.path.join(userdir, '.cache'), for testdir in [tempfile.gettempdir(), os.path.join(userdir, '.cache'),
os.path.join(userdir, '.tmp'), userdir]: os.path.join(userdir, '.tmp'), userdir]:
if (not os.path.exists(testdir) or if (not os.path.exists(testdir) or
not _run_shell_command('echo success', testdir) == 'success'): not _run_shell_command('echo success', testdir) == 'success'):
continue continue
return testdir return testdir
return '' return ''
class ShellCode(NoneditableTextObject): class ShellCode(NoneditableTextObject):
"""See module docstring.""" """See module docstring."""
def __init__(self, parent, token): def __init__(self, parent, token):
NoneditableTextObject.__init__(self, parent, token) NoneditableTextObject.__init__(self, parent, token)
self._code = token.code.replace("\\`", "`") self._code = token.code.replace('\\`', '`')
self._tmpdir = _get_tmp() self._tmpdir = _get_tmp()
def _update(self, done): def _update(self, done):
if not self._tmpdir: if not self._tmpdir:
output = \ output = \
"Unable to find executable tmp directory, check noexec on /tmp" 'Unable to find executable tmp directory, check noexec on /tmp'
else: else:
output = _run_shell_command(self._code, self._tmpdir) output = _run_shell_command(self._code, self._tmpdir)
self.overwrite(output) self.overwrite(output)

View File

@ -1,21 +1,27 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""A Snippet instance is an instance of a Snippet Definition. That is, when the """A Snippet instance is an instance of a Snippet Definition.
user expands a snippet, a SnippetInstance is created to keep track of the
corresponding TextObjects. The Snippet itself is also a TextObject. """ That is, when the user expands a snippet, a SnippetInstance is created
to keep track of the corresponding TextObjects. The Snippet itself is
also a TextObject.
"""
from UltiSnips import _vim from UltiSnips import _vim
from UltiSnips.position import Position from UltiSnips.position import Position
from UltiSnips.text_objects._base import EditableTextObject, \ from UltiSnips.text_objects._base import EditableTextObject, \
NoneditableTextObject NoneditableTextObject
class SnippetInstance(EditableTextObject): class SnippetInstance(EditableTextObject):
"""See module docstring.""" """See module docstring."""
# pylint:disable=protected-access # pylint:disable=protected-access
def __init__(self, snippet, parent, initial_text, def __init__(self, snippet, parent, initial_text,
start, end, visual_content, last_re, globals): start, end, visual_content, last_re, globals):
if start is None: if start is None:
start = Position(0, 0) start = Position(0, 0)
if end is None: if end is None:
@ -23,7 +29,7 @@ class SnippetInstance(EditableTextObject):
self.snippet = snippet self.snippet = snippet
self._cts = 0 self._cts = 0
self.locals = {"match" : last_re} self.locals = {'match': last_re}
self.globals = globals self.globals = globals
self.visual_content = visual_content self.visual_content = visual_content
@ -40,18 +46,22 @@ class SnippetInstance(EditableTextObject):
_place_initial_text(self) _place_initial_text(self)
def replay_user_edits(self, cmds): def replay_user_edits(self, cmds):
"""Replay the edits the user has done to keep endings of our """Replay the edits the user has done to keep endings of our Text
Text objects in sync with reality""" objects in sync with reality."""
for cmd in cmds: for cmd in cmds:
self._do_edit(cmd) self._do_edit(cmd)
def update_textobjects(self): def update_textobjects(self):
"""Update the text objects that should change automagically after """Update the text objects that should change automagically after the
the users edits have been replayed. This might also move the Cursor users edits have been replayed.
This might also move the Cursor
""" """
vc = _VimCursor(self) vc = _VimCursor(self)
done = set() done = set()
not_done = set() not_done = set()
def _find_recursive(obj): def _find_recursive(obj):
"""Finds all text objects and puts them into 'not_done'.""" """Finds all text objects and puts them into 'not_done'."""
if isinstance(obj, EditableTextObject): if isinstance(obj, EditableTextObject):
@ -69,10 +79,10 @@ class SnippetInstance(EditableTextObject):
counter -= 1 counter -= 1
if not counter: if not counter:
raise RuntimeError( raise RuntimeError(
"The snippets content did not converge: Check for Cyclic " 'The snippets content did not converge: Check for Cyclic '
"dependencies or random strings in your snippet. You can use " 'dependencies or random strings in your snippet. You can use '
"'if not snip.c' to make sure to only expand random output " "'if not snip.c' to make sure to only expand random output "
"once.") 'once.')
vc.to_vim() vc.to_vim()
self._del_child(vc) self._del_child(vc)
@ -112,6 +122,7 @@ class SnippetInstance(EditableTextObject):
class _VimCursor(NoneditableTextObject): class _VimCursor(NoneditableTextObject):
"""Helper class to keep track of the Vim Cursor when text objects expand """Helper class to keep track of the Vim Cursor when text objects expand
and move.""" and move."""

View File

@ -1,12 +1,18 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""This is the most important TextObject. A TabStop is were the cursor """This is the most important TextObject.
comes to rest when the user taps through the Snippet."""
A TabStop is were the cursor comes to rest when the user taps through
the Snippet.
"""
from UltiSnips.text_objects._base import EditableTextObject from UltiSnips.text_objects._base import EditableTextObject
class TabStop(EditableTextObject): class TabStop(EditableTextObject):
"""See module docstring.""" """See module docstring."""
def __init__(self, parent, token, start=None, end=None): def __init__(self, parent, token, start=None, end=None):
@ -16,7 +22,8 @@ class TabStop(EditableTextObject):
else: else:
self._number = token.number self._number = token.number
EditableTextObject.__init__(self, parent, token) EditableTextObject.__init__(self, parent, token)
parent._tabstops[self._number] = self # pylint:disable=protected-access parent._tabstops[
self._number] = self # pylint:disable=protected-access
@property @property
def number(self): def number(self):
@ -30,5 +37,5 @@ class TabStop(EditableTextObject):
return self._parent is None return self._parent is None
def __repr__(self): def __repr__(self):
return "TabStop(%s,%r->%r,%r)" % (self.number, self._start, return 'TabStop(%s,%r->%r,%r)' % (self.number, self._start,
self._end, self.current_text) self._end, self.current_text)

View File

@ -9,47 +9,50 @@ import sys
from UltiSnips.text import unescape, fill_in_whitespace from UltiSnips.text import unescape, fill_in_whitespace
from UltiSnips.text_objects._mirror import Mirror from UltiSnips.text_objects._mirror import Mirror
def _find_closing_brace(string, start_pos): def _find_closing_brace(string, start_pos):
"""Finds the corresponding closing brace after start_pos.""" """Finds the corresponding closing brace after start_pos."""
bracks_open = 1 bracks_open = 1
for idx, char in enumerate(string[start_pos:]): for idx, char in enumerate(string[start_pos:]):
if char == '(': if char == '(':
if string[idx+start_pos-1] != '\\': if string[idx + start_pos - 1] != '\\':
bracks_open += 1 bracks_open += 1
elif char == ')': elif char == ')':
if string[idx+start_pos-1] != '\\': if string[idx + start_pos - 1] != '\\':
bracks_open -= 1 bracks_open -= 1
if not bracks_open: if not bracks_open:
return start_pos+idx+1 return start_pos + idx + 1
def _split_conditional(string): def _split_conditional(string):
"""Split the given conditional 'string' into its arguments.""" """Split the given conditional 'string' into its arguments."""
bracks_open = 0 bracks_open = 0
args = [] args = []
carg = "" carg = ''
for idx, char in enumerate(string): for idx, char in enumerate(string):
if char == '(': if char == '(':
if string[idx-1] != '\\': if string[idx - 1] != '\\':
bracks_open += 1 bracks_open += 1
elif char == ')': elif char == ')':
if string[idx-1] != '\\': if string[idx - 1] != '\\':
bracks_open -= 1 bracks_open -= 1
elif char == ':' and not bracks_open and not string[idx-1] == '\\': elif char == ':' and not bracks_open and not string[idx - 1] == '\\':
args.append(carg) args.append(carg)
carg = "" carg = ''
continue continue
carg += char carg += char
args.append(carg) args.append(carg)
return args return args
def _replace_conditional(match, string): def _replace_conditional(match, string):
"""Replaces a conditional match in a transformation.""" """Replaces a conditional match in a transformation."""
conditional_match = _CONDITIONAL.search(string) conditional_match = _CONDITIONAL.search(string)
while conditional_match: while conditional_match:
start = conditional_match.start() start = conditional_match.start()
end = _find_closing_brace(string, start+4) end = _find_closing_brace(string, start + 4)
args = _split_conditional(string[start+4:end-1]) args = _split_conditional(string[start + 4:end - 1])
rv = "" rv = ''
if match.group(int(conditional_match.group(1))): if match.group(int(conditional_match.group(1))):
rv = unescape(_replace_conditional(match, args[0])) rv = unescape(_replace_conditional(match, args[0]))
elif len(args) > 1: elif len(args) > 1:
@ -62,7 +65,10 @@ _ONE_CHAR_CASE_SWITCH = re.compile(r"\\([ul].)", re.DOTALL)
_LONG_CASEFOLDINGS = re.compile(r"\\([UL].*?)\\E", re.DOTALL) _LONG_CASEFOLDINGS = re.compile(r"\\([UL].*?)\\E", re.DOTALL)
_DOLLAR = re.compile(r"\$(\d+)", re.DOTALL) _DOLLAR = re.compile(r"\$(\d+)", re.DOTALL)
_CONDITIONAL = re.compile(r"\(\?(\d+):", re.DOTALL) _CONDITIONAL = re.compile(r"\(\?(\d+):", re.DOTALL)
class _CleverReplace(object): class _CleverReplace(object):
"""Mimics TextMates replace syntax.""" """Mimics TextMates replace syntax."""
def __init__(self, expression): def __init__(self, expression):
@ -73,7 +79,7 @@ class _CleverReplace(object):
transformed = self._expression transformed = self._expression
# Replace all $? with capture groups # Replace all $? with capture groups
transformed = _DOLLAR.subn( transformed = _DOLLAR.subn(
lambda m: match.group(int(m.group(1))), transformed)[0] lambda m: match.group(int(m.group(1))), transformed)[0]
# Replace Case switches # Replace Case switches
def _one_char_case_change(match): def _one_char_case_change(match):
@ -83,7 +89,7 @@ class _CleverReplace(object):
else: else:
return match.group(1)[-1].lower() return match.group(1)[-1].lower()
transformed = _ONE_CHAR_CASE_SWITCH.subn( transformed = _ONE_CHAR_CASE_SWITCH.subn(
_one_char_case_change, transformed)[0] _one_char_case_change, transformed)[0]
def _multi_char_case_change(match): def _multi_char_case_change(match):
"""Replaces multi character case changes.""" """Replaces multi character case changes."""
@ -92,13 +98,16 @@ class _CleverReplace(object):
else: else:
return match.group(1)[1:].lower() return match.group(1)[1:].lower()
transformed = _LONG_CASEFOLDINGS.subn( transformed = _LONG_CASEFOLDINGS.subn(
_multi_char_case_change, transformed)[0] _multi_char_case_change, transformed)[0]
transformed = _replace_conditional(match, transformed) transformed = _replace_conditional(match, transformed)
return unescape(fill_in_whitespace(transformed)) return unescape(fill_in_whitespace(transformed))
# flag used to display only one time the lack of unidecode # flag used to display only one time the lack of unidecode
UNIDECODE_ALERT_RAISED = False UNIDECODE_ALERT_RAISED = False
class TextObjectTransformation(object): class TextObjectTransformation(object):
"""Base class for Transformations and ${VISUAL}.""" """Base class for Transformations and ${VISUAL}."""
def __init__(self, token): def __init__(self, token):
@ -111,11 +120,11 @@ class TextObjectTransformation(object):
flags = 0 flags = 0
self._match_this_many = 1 self._match_this_many = 1
if token.options: if token.options:
if "g" in token.options: if 'g' in token.options:
self._match_this_many = 0 self._match_this_many = 0
if "i" in token.options: if 'i' in token.options:
flags |= re.IGNORECASE flags |= re.IGNORECASE
if "a" in token.options: if 'a' in token.options:
self._convert_to_ascii = True self._convert_to_ascii = True
self._find = re.compile(token.search, flags | re.DOTALL) self._find = re.compile(token.search, flags | re.DOTALL)
@ -132,14 +141,16 @@ class TextObjectTransformation(object):
if UNIDECODE_ALERT_RAISED == False: if UNIDECODE_ALERT_RAISED == False:
UNIDECODE_ALERT_RAISED = True UNIDECODE_ALERT_RAISED = True
sys.stderr.write( sys.stderr.write(
"Please install unidecode python package in order to " 'Please install unidecode python package in order to '
"be able to make ascii conversions.\n") 'be able to make ascii conversions.\n')
if self._find is None: if self._find is None:
return text return text
return self._find.subn( return self._find.subn(
self._replace.replace, text, self._match_this_many)[0] self._replace.replace, text, self._match_this_many)[0]
class Transformation(Mirror, TextObjectTransformation): class Transformation(Mirror, TextObjectTransformation):
"""See module docstring.""" """See module docstring."""
def __init__(self, parent, ts, token): def __init__(self, parent, ts, token):

View File

@ -6,10 +6,13 @@
from UltiSnips import _vim from UltiSnips import _vim
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
class VimLCode(NoneditableTextObject): class VimLCode(NoneditableTextObject):
"""See module docstring.""" """See module docstring."""
def __init__(self, parent, token): def __init__(self, parent, token):
self._code = token.code.replace("\\`", "`").strip() self._code = token.code.replace('\\`', '`').strip()
NoneditableTextObject.__init__(self, parent, token) NoneditableTextObject.__init__(self, parent, token)

View File

@ -2,8 +2,11 @@
# encoding: utf-8 # encoding: utf-8
"""A ${VISUAL} placeholder that will use the text that was last visually """A ${VISUAL} placeholder that will use the text that was last visually
selected and insert it here. If there was no text visually selected, this will selected and insert it here.
be the empty string. """
If there was no text visually selected, this will be the empty string.
"""
import re import re
import textwrap import textwrap
@ -14,7 +17,10 @@ from UltiSnips.text_objects._transformation import TextObjectTransformation
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
_REPLACE_NON_WS = re.compile(r"[^ \t]") _REPLACE_NON_WS = re.compile(r"[^ \t]")
class Visual(NoneditableTextObject, TextObjectTransformation): class Visual(NoneditableTextObject, TextObjectTransformation):
"""See module docstring.""" """See module docstring."""
def __init__(self, parent, token): def __init__(self, parent, token):
@ -29,27 +35,27 @@ class Visual(NoneditableTextObject, TextObjectTransformation):
snippet = snippet._parent # pylint:disable=protected-access snippet = snippet._parent # pylint:disable=protected-access
if not self._text: if not self._text:
self._text = token.alternative_text self._text = token.alternative_text
self._mode = "v" self._mode = 'v'
NoneditableTextObject.__init__(self, parent, token) NoneditableTextObject.__init__(self, parent, token)
TextObjectTransformation.__init__(self, token) TextObjectTransformation.__init__(self, token)
def _update(self, done): def _update(self, done):
if self._mode == "v": # Normal selection. if self._mode == 'v': # Normal selection.
text = self._text text = self._text
else: # Block selection or line selection. else: # Block selection or line selection.
text_before = _vim.buf[self.start.line][:self.start.col] text_before = _vim.buf[self.start.line][:self.start.col]
indent = _REPLACE_NON_WS.sub(" ", text_before) indent = _REPLACE_NON_WS.sub(' ', text_before)
iu = IndentUtil() iu = IndentUtil()
indent = iu.indent_to_spaces(indent) indent = iu.indent_to_spaces(indent)
indent = iu.spaces_to_indent(indent) indent = iu.spaces_to_indent(indent)
text = "" text = ''
for idx, line in enumerate(textwrap.dedent( for idx, line in enumerate(textwrap.dedent(
self._text).splitlines(True)): self._text).splitlines(True)):
if idx != 0: if idx != 0:
text += indent text += indent
text += line text += line
text = text[:-1] # Strip final '\n' text = text[:-1] # Strip final '\n'
text = self._transform(text) text = self._transform(text)
self.overwrite(text) self.overwrite(text)

View File

@ -9,13 +9,15 @@ from UltiSnips import _vim
from UltiSnips.compatibility import as_unicode, byte2col from UltiSnips.compatibility import as_unicode, byte2col
from UltiSnips.position import Position from UltiSnips.position import Position
class VimPosition(Position): class VimPosition(Position):
"""Represents the current position in the buffer, together with some status """Represents the current position in the buffer, together with some status
variables that might change our decisions down the line.""" variables that might change our decisions down the line."""
def __init__(self): def __init__(self):
pos = _vim.buf.cursor pos = _vim.buf.cursor
self._mode = _vim.eval("mode()") self._mode = _vim.eval('mode()')
Position.__init__(self, pos.line, pos.col) Position.__init__(self, pos.line, pos.col)
@property @property
@ -23,7 +25,9 @@ class VimPosition(Position):
"""Returns the mode() this position was created.""" """Returns the mode() this position was created."""
return self._mode return self._mode
class VimState(object): class VimState(object):
"""Caches some state information from Vim to better guess what editing """Caches some state information from Vim to better guess what editing
tasks the user might have done in the last step.""" tasks the user might have done in the last step."""
@ -31,7 +35,7 @@ class VimState(object):
self._poss = deque(maxlen=5) self._poss = deque(maxlen=5)
self._lvb = None self._lvb = None
self._text_to_expect = "" self._text_to_expect = ''
self._unnamed_reg_cached = False self._unnamed_reg_cached = False
# We store the cached value of the unnamed register in Vim directly to # We store the cached value of the unnamed register in Vim directly to
@ -43,10 +47,14 @@ class VimState(object):
_vim.command('let g:_ultisnips_unnamed_reg_cache = ""') _vim.command('let g:_ultisnips_unnamed_reg_cache = ""')
def remember_unnamed_register(self, text_to_expect): def remember_unnamed_register(self, text_to_expect):
"""Save the unnamed register. 'text_to_expect' is text that we expect """Save the unnamed register.
'text_to_expect' is text that we expect
to be contained in the register the next time this method is called - to be contained in the register the next time this method is called -
this could be text from the tabstop that was selected and might have this could be text from the tabstop that was selected and might have
been overwritten. We will not cache that then.""" been overwritten. We will not cache that then.
"""
self._unnamed_reg_cached = True self._unnamed_reg_cached = True
escaped_text = self._text_to_expect.replace("'", "''") escaped_text = self._text_to_expect.replace("'", "''")
res = int(_vim.eval('@" != ' + "'" + escaped_text + "'")) res = int(_vim.eval('@" != ' + "'" + escaped_text + "'"))
@ -67,7 +75,7 @@ class VimState(object):
def remember_buffer(self, to): def remember_buffer(self, to):
"""Remember the content of the buffer and the position.""" """Remember the content of the buffer and the position."""
self._lvb = _vim.buf[to.start.line:to.end.line+1] self._lvb = _vim.buf[to.start.line:to.end.line + 1]
self._lvb_len = len(_vim.buf) self._lvb_len = len(_vim.buf)
self.remember_position() self.remember_position()
@ -92,7 +100,9 @@ class VimState(object):
"""The content of the remembered buffer.""" """The content of the remembered buffer."""
return self._lvb[:] return self._lvb[:]
class VisualContentPreserver(object): class VisualContentPreserver(object):
"""Saves the current visual selection and the selection mode it was done in """Saves the current visual selection and the selection mode it was done in
(e.g. line selection, block selection or regular selection.)""" (e.g. line selection, block selection or regular selection.)"""
@ -101,28 +111,28 @@ class VisualContentPreserver(object):
def reset(self): def reset(self):
"""Forget the preserved state.""" """Forget the preserved state."""
self._mode = "" self._mode = ''
self._text = as_unicode("") self._text = as_unicode('')
def conserve(self): def conserve(self):
"""Save the last visual selection ond the mode it was made in.""" """Save the last visual selection ond the mode it was made in."""
sl, sbyte = map(int, sl, sbyte = map(int,
(_vim.eval("""line("'<")"""), _vim.eval("""col("'<")"""))) (_vim.eval("""line("'<")"""), _vim.eval("""col("'<")""")))
el, ebyte = map(int, el, ebyte = map(int,
(_vim.eval("""line("'>")"""), _vim.eval("""col("'>")"""))) (_vim.eval("""line("'>")"""), _vim.eval("""col("'>")""")))
sc = byte2col(sl, sbyte - 1) sc = byte2col(sl, sbyte - 1)
ec = byte2col(el, ebyte - 1) ec = byte2col(el, ebyte - 1)
self._mode = _vim.eval("visualmode()") self._mode = _vim.eval('visualmode()')
_vim_line_with_eol = lambda ln: _vim.buf[ln] + '\n' _vim_line_with_eol = lambda ln: _vim.buf[ln] + '\n'
if sl == el: if sl == el:
text = _vim_line_with_eol(sl-1)[sc:ec+1] text = _vim_line_with_eol(sl - 1)[sc:ec + 1]
else: else:
text = _vim_line_with_eol(sl-1)[sc:] text = _vim_line_with_eol(sl - 1)[sc:]
for cl in range(sl, el-1): for cl in range(sl, el - 1):
text += _vim_line_with_eol(cl) text += _vim_line_with_eol(cl)
text += _vim_line_with_eol(el-1)[:ec+1] text += _vim_line_with_eol(el - 1)[:ec + 1]
self._text = text self._text = text
@property @property

View File

@ -12,13 +12,13 @@ ARR_D = '\x1bOB'
SEQUENCES = [ARR_L, ARR_R, ARR_U, ARR_D] SEQUENCES = [ARR_L, ARR_R, ARR_U, ARR_D]
# Defined Constants # Defined Constants
JF = "?" # Jump forwards JF = '?' # Jump forwards
JB = "+" # Jump backwards JB = '+' # Jump backwards
LS = "@" # List snippets LS = '@' # List snippets
EX = "\t" # EXPAND EX = '\t' # EXPAND
EA = "#" # Expand anonymous EA = '#' # Expand anonymous
COMPL_KW = chr(24) + chr(14) COMPL_KW = chr(24) + chr(14)
COMPL_ACCEPT = chr(25) COMPL_ACCEPT = chr(25)
PYTHON3 = sys.version_info >= (3,0) PYTHON3 = sys.version_info >= (3, 0)

View File

@ -2,53 +2,66 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Anonymous Expansion {{{# # Anonymous Expansion {{{#
class _AnonBase(_VimTest): class _AnonBase(_VimTest):
args = "" args = ''
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("inoremap <silent> %s <C-R>=UltiSnips#Anon(%s)<cr>" vim_config.append('inoremap <silent> %s <C-R>=UltiSnips#Anon(%s)<cr>'
% (EA, self.args)) % (EA, self.args))
class Anon_NoTrigger_Simple(_AnonBase): class Anon_NoTrigger_Simple(_AnonBase):
args = '"simple expand"' args = '"simple expand"'
keys = "abc" + EA keys = 'abc' + EA
wanted = "abcsimple expand" wanted = 'abcsimple expand'
class Anon_NoTrigger_AfterSpace(_AnonBase): class Anon_NoTrigger_AfterSpace(_AnonBase):
args = '"simple expand"' args = '"simple expand"'
keys = "abc " + EA keys = 'abc ' + EA
wanted = "abc simple expand" wanted = 'abc simple expand'
class Anon_NoTrigger_BeginningOfLine(_AnonBase): class Anon_NoTrigger_BeginningOfLine(_AnonBase):
args = r"':latex:\`$1\`$0'" args = r"':latex:\`$1\`$0'"
keys = EA + "Hello" + JF + "World" keys = EA + 'Hello' + JF + 'World'
wanted = ":latex:`Hello`World" wanted = ':latex:`Hello`World'
class Anon_NoTrigger_FirstCharOfLine(_AnonBase): class Anon_NoTrigger_FirstCharOfLine(_AnonBase):
args = r"':latex:\`$1\`$0'" args = r"':latex:\`$1\`$0'"
keys = " " + EA + "Hello" + JF + "World" keys = ' ' + EA + 'Hello' + JF + 'World'
wanted = " :latex:`Hello`World" wanted = ' :latex:`Hello`World'
class Anon_NoTrigger_Multi(_AnonBase): class Anon_NoTrigger_Multi(_AnonBase):
args = '"simple $1 expand $1 $0"' args = '"simple $1 expand $1 $0"'
keys = "abc" + EA + "123" + JF + "456" keys = 'abc' + EA + '123' + JF + '456'
wanted = "abcsimple 123 expand 123 456" wanted = 'abcsimple 123 expand 123 456'
class Anon_Trigger_Multi(_AnonBase): class Anon_Trigger_Multi(_AnonBase):
args = '"simple $1 expand $1 $0", "abc"' args = '"simple $1 expand $1 $0", "abc"'
keys = "123 abc" + EA + "123" + JF + "456" keys = '123 abc' + EA + '123' + JF + '456'
wanted = "123 simple 123 expand 123 456" wanted = '123 simple 123 expand 123 456'
class Anon_Trigger_Simple(_AnonBase): class Anon_Trigger_Simple(_AnonBase):
args = '"simple expand", "abc"' args = '"simple expand", "abc"'
keys = "abc" + EA keys = 'abc' + EA
wanted = "simple expand" wanted = 'simple expand'
class Anon_Trigger_Twice(_AnonBase): class Anon_Trigger_Twice(_AnonBase):
args = '"simple expand", "abc"' args = '"simple expand", "abc"'
keys = "abc" + EA + "\nabc" + EX keys = 'abc' + EA + '\nabc' + EX
wanted = "simple expand\nabc" + EX wanted = 'simple expand\nabc' + EX
class Anon_Trigger_Opts(_AnonBase): class Anon_Trigger_Opts(_AnonBase):
args = '"simple expand", ".*abc", "desc", "r"' args = '"simple expand", ".*abc", "desc", "r"'
keys = "blah blah abc" + EA keys = 'blah blah abc' + EA
wanted = "simple expand" wanted = 'simple expand'
# End: Anonymous Expansion #}}} # End: Anonymous Expansion #}}}

View File

@ -5,122 +5,141 @@ from test.util import running_on_windows
# Quotes in Snippets {{{# # Quotes in Snippets {{{#
# Test for Bug #774917 # Test for Bug #774917
def _snip_quote(qt): def _snip_quote(qt):
return ( return (
("te" + qt + "st", "Expand me" + qt + "!", "test: "+qt), ('te' + qt + 'st', 'Expand me' + qt + '!', 'test: ' + qt),
("te", "Bad", ""), ('te', 'Bad', ''),
) )
class Snippet_With_SingleQuote(_VimTest): class Snippet_With_SingleQuote(_VimTest):
snippets = _snip_quote("'") snippets = _snip_quote("'")
keys = "te'st" + EX keys = "te'st" + EX
wanted = "Expand me'!" wanted = "Expand me'!"
class Snippet_With_SingleQuote_List(_VimTest): class Snippet_With_SingleQuote_List(_VimTest):
snippets = _snip_quote("'") snippets = _snip_quote("'")
keys = "te" + LS + "2\n" keys = 'te' + LS + '2\n'
wanted = "Expand me'!" wanted = "Expand me'!"
class Snippet_With_DoubleQuote(_VimTest): class Snippet_With_DoubleQuote(_VimTest):
snippets = _snip_quote('"') snippets = _snip_quote('"')
keys = 'te"st' + EX keys = 'te"st' + EX
wanted = "Expand me\"!" wanted = "Expand me\"!"
class Snippet_With_DoubleQuote_List(_VimTest): class Snippet_With_DoubleQuote_List(_VimTest):
snippets = _snip_quote('"') snippets = _snip_quote('"')
keys = "te" + LS + "2\n" keys = 'te' + LS + '2\n'
wanted = "Expand me\"!" wanted = "Expand me\"!"
# End: Quotes in Snippets #}}} # End: Quotes in Snippets #}}}
# Trailing whitespace {{{# # Trailing whitespace {{{#
class RemoveTrailingWhitespace(_VimTest): class RemoveTrailingWhitespace(_VimTest):
snippets = ("test", """Hello\t ${1:default}\n$2""", "", "s") snippets = ('test', """Hello\t ${1:default}\n$2""", '', 's')
wanted = """Hello\nGoodbye""" wanted = """Hello\nGoodbye"""
keys = "test" + EX + BS + JF + "Goodbye" keys = 'test' + EX + BS + JF + 'Goodbye'
class LeaveTrailingWhitespace(_VimTest): class LeaveTrailingWhitespace(_VimTest):
snippets = ("test", """Hello \t ${1:default}\n$2""") snippets = ('test', """Hello \t ${1:default}\n$2""")
wanted = """Hello \t \nGoodbye""" wanted = """Hello \t \nGoodbye"""
keys = "test" + EX + BS + JF + "Goodbye" keys = 'test' + EX + BS + JF + 'Goodbye'
# End: Trailing whitespace #}}} # End: Trailing whitespace #}}}
# Newline in default text {{{# # Newline in default text {{{#
# Tests for bug 616315 # # Tests for bug 616315 #
class TrailingNewline_TabStop_NLInsideStuffBehind(_VimTest): class TrailingNewline_TabStop_NLInsideStuffBehind(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1: x${1:
}<-behind1 }<-behind1
$2<-behind2""") $2<-behind2""")
keys = "test" + EX + "j" + JF + "k" keys = 'test' + EX + 'j' + JF + 'k'
wanted = """ wanted = """
xj<-behind1 xj<-behind1
k<-behind2""" k<-behind2"""
class TrailingNewline_TabStop_JustNL(_VimTest): class TrailingNewline_TabStop_JustNL(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1: x${1:
} }
$2""") $2""")
keys = "test" + EX + "j" + JF + "k" keys = 'test' + EX + 'j' + JF + 'k'
wanted = """ wanted = """
xj xj
k""" k"""
class TrailingNewline_TabStop_EndNL(_VimTest): class TrailingNewline_TabStop_EndNL(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1:a x${1:a
} }
$2""") $2""")
keys = "test" + EX + "j" + JF + "k" keys = 'test' + EX + 'j' + JF + 'k'
wanted = """ wanted = """
xj xj
k""" k"""
class TrailingNewline_TabStop_StartNL(_VimTest): class TrailingNewline_TabStop_StartNL(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1: x${1:
a} a}
$2""") $2""")
keys = "test" + EX + "j" + JF + "k" keys = 'test' + EX + 'j' + JF + 'k'
wanted = """ wanted = """
xj xj
k""" k"""
class TrailingNewline_TabStop_EndStartNL(_VimTest): class TrailingNewline_TabStop_EndStartNL(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1: x${1:
a a
} }
$2""") $2""")
keys = "test" + EX + "j" + JF + "k" keys = 'test' + EX + 'j' + JF + 'k'
wanted = """ wanted = """
xj xj
k""" k"""
class TrailingNewline_TabStop_NotEndStartNL(_VimTest): class TrailingNewline_TabStop_NotEndStartNL(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1:a x${1:a
a} a}
$2""") $2""")
keys = "test" + EX + "j" + JF + "k" keys = 'test' + EX + 'j' + JF + 'k'
wanted = """ wanted = """
xj xj
k""" k"""
class TrailingNewline_TabStop_ExtraNL_ECR(_VimTest): class TrailingNewline_TabStop_ExtraNL_ECR(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1:a x${1:a
a} a}
$2 $2
""") """)
keys = "test" + EX + "j" + JF + "k" keys = 'test' + EX + 'j' + JF + 'k'
wanted = """ wanted = """
xj xj
k k
""" """
class _MultiLineDefault(_VimTest): class _MultiLineDefault(_VimTest):
snippets = ("test", r""" snippets = ('test', r"""
x${1:a x${1:a
b b
c c
@ -129,8 +148,9 @@ e
f} f}
$2""") $2""")
class MultiLineDefault_Jump(_MultiLineDefault): class MultiLineDefault_Jump(_MultiLineDefault):
keys = "test" + EX + JF + "y" keys = 'test' + EX + JF + 'y'
wanted = """ wanted = """
xa xa
b b
@ -140,14 +160,16 @@ e
f f
y""" y"""
class MultiLineDefault_Type(_MultiLineDefault): class MultiLineDefault_Type(_MultiLineDefault):
keys = "test" + EX + "z" + JF + "y" keys = 'test' + EX + 'z' + JF + 'y'
wanted = """ wanted = """
xz xz
y""" y"""
class MultiLineDefault_BS(_MultiLineDefault): class MultiLineDefault_BS(_MultiLineDefault):
keys = "test" + EX + BS + JF + "y" keys = 'test' + EX + BS + JF + 'y'
wanted = """ wanted = """
x x
y""" y"""
@ -155,42 +177,57 @@ y"""
# End: Newline in default text #}}} # End: Newline in default text #}}}
# Umlauts and Special Chars {{{# # Umlauts and Special Chars {{{#
class _UmlautsBase(_VimTest): class _UmlautsBase(_VimTest):
skip_if = lambda self: running_on_windows() # SendKeys can't send UTF characters # SendKeys can't send UTF characters
skip_if = lambda self: running_on_windows()
class Snippet_With_Umlauts_List(_UmlautsBase): class Snippet_With_Umlauts_List(_UmlautsBase):
snippets = _snip_quote('ü') snippets = _snip_quote('ü')
keys = 'te' + LS + "2\n" keys = 'te' + LS + '2\n'
wanted = "Expand meü!" wanted = 'Expand meü!'
class Snippet_With_Umlauts(_UmlautsBase): class Snippet_With_Umlauts(_UmlautsBase):
snippets = _snip_quote('ü') snippets = _snip_quote('ü')
keys = 'teüst' + EX keys = 'teüst' + EX
wanted = "Expand meü!" wanted = 'Expand meü!'
class Snippet_With_Umlauts_TypeOn(_UmlautsBase): class Snippet_With_Umlauts_TypeOn(_UmlautsBase):
snippets = ('ül', 'üüüüüßßßß') snippets = ('ül', 'üüüüüßßßß')
keys = 'te ül' + EX + "more text" keys = 'te ül' + EX + 'more text'
wanted = "te üüüüüßßßßmore text" wanted = 'te üüüüüßßßßmore text'
class Snippet_With_Umlauts_OverwriteFirst(_UmlautsBase): class Snippet_With_Umlauts_OverwriteFirst(_UmlautsBase):
snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü') snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü')
keys = 'te ül' + EX + "more text" + JF + JF + "end" keys = 'te ül' + EX + 'more text' + JF + JF + 'end'
wanted = "te üü more text üü helloßß\nüüüüend" wanted = 'te üü more text üü helloßß\nüüüüend'
class Snippet_With_Umlauts_OverwriteSecond(_UmlautsBase): class Snippet_With_Umlauts_OverwriteSecond(_UmlautsBase):
snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü') snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü')
keys = 'te ül' + EX + JF + "more text" + JF + "end" keys = 'te ül' + EX + JF + 'more text' + JF + 'end'
wanted = "te üü world üü more textßß\nüüüüend" wanted = 'te üü world üü more textßß\nüüüüend'
class Snippet_With_Umlauts_OverwriteNone(_UmlautsBase): class Snippet_With_Umlauts_OverwriteNone(_UmlautsBase):
snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü') snippets = ('ül', 'üü ${1:world} üü ${2:hello}ßß\nüüüü')
keys = 'te ül' + EX + JF + JF + "end" keys = 'te ül' + EX + JF + JF + 'end'
wanted = "te üü world üü helloßß\nüüüüend" wanted = 'te üü world üü helloßß\nüüüüend'
class Snippet_With_Umlauts_Mirrors(_UmlautsBase): class Snippet_With_Umlauts_Mirrors(_UmlautsBase):
snippets = ('ül', 'üü ${1:world} üü $1') snippets = ('ül', 'üü ${1:world} üü $1')
keys = 'te ül' + EX + "hello" keys = 'te ül' + EX + 'hello'
wanted = "te üü hello üü hello" wanted = 'te üü hello üü hello'
class Snippet_With_Umlauts_Python(_UmlautsBase): class Snippet_With_Umlauts_Python(_UmlautsBase):
snippets = ('ül', 'üü ${1:world} üü `!p snip.rv = len(t[1])*"a"`') snippets = ('ül', 'üü ${1:world} üü `!p snip.rv = len(t[1])*"a"`')
keys = 'te ül' + EX + "hüüll" keys = 'te ül' + EX + 'hüüll'
wanted = "te üü hüüll üü aaaaa" wanted = 'te üü hüüll üü aaaaa'
# End: Umlauts and Special Chars #}}} # End: Umlauts and Special Chars #}}}

View File

@ -2,29 +2,33 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Tab Completion of Words {{{# # Tab Completion of Words {{{#
class Completion_SimpleExample_ECR(_VimTest): class Completion_SimpleExample_ECR(_VimTest):
snippets = ("test", "$1 ${1:blah}") snippets = ('test', '$1 ${1:blah}')
keys = "superkallifragilistik\ntest" + EX + "sup" + COMPL_KW + \ keys = 'superkallifragilistik\ntest' + EX + 'sup' + COMPL_KW + \
COMPL_ACCEPT + " some more" COMPL_ACCEPT + ' some more'
wanted = "superkallifragilistik\nsuperkallifragilistik some more " \ wanted = 'superkallifragilistik\nsuperkallifragilistik some more ' \
"superkallifragilistik some more" 'superkallifragilistik some more'
# We need >2 different words with identical starts to create the # We need >2 different words with identical starts to create the
# popup-menu: # popup-menu:
COMPLETION_OPTIONS = "completion1\ncompletion2\n" COMPLETION_OPTIONS = 'completion1\ncompletion2\n'
class Completion_ForwardsJumpWithoutCOMPL_ACCEPT(_VimTest): class Completion_ForwardsJumpWithoutCOMPL_ACCEPT(_VimTest):
# completions should not be truncated when JF is activated without having # completions should not be truncated when JF is activated without having
# pressed COMPL_ACCEPT (Bug #598903) # pressed COMPL_ACCEPT (Bug #598903)
snippets = ("test", "$1 $2") snippets = ('test', '$1 $2')
keys = COMPLETION_OPTIONS + "test" + EX + "com" + COMPL_KW + JF + "foo" keys = COMPLETION_OPTIONS + 'test' + EX + 'com' + COMPL_KW + JF + 'foo'
wanted = COMPLETION_OPTIONS + "completion1 foo" wanted = COMPLETION_OPTIONS + 'completion1 foo'
class Completion_BackwardsJumpWithoutCOMPL_ACCEPT(_VimTest): class Completion_BackwardsJumpWithoutCOMPL_ACCEPT(_VimTest):
# completions should not be truncated when JB is activated without having # completions should not be truncated when JB is activated without having
# pressed COMPL_ACCEPT (Bug #598903) # pressed COMPL_ACCEPT (Bug #598903)
snippets = ("test", "$1 $2") snippets = ('test', '$1 $2')
keys = COMPLETION_OPTIONS + "test" + EX + "foo" + JF + "com" + COMPL_KW + \ keys = COMPLETION_OPTIONS + 'test' + EX + 'foo' + JF + 'com' + COMPL_KW + \
JB + "foo" JB + 'foo'
wanted = COMPLETION_OPTIONS + "foo completion1" wanted = COMPLETION_OPTIONS + 'foo completion1'
# End: Tab Completion of Words #}}} # End: Tab Completion of Words #}}}

View File

@ -2,63 +2,88 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Undo of Snippet insertion {{{# # Undo of Snippet insertion {{{#
class Undo_RemoveMultilineSnippet(_VimTest): class Undo_RemoveMultilineSnippet(_VimTest):
snippets = ("test", "Hello\naaa ${1} bbb\nWorld") snippets = ('test', 'Hello\naaa ${1} bbb\nWorld')
keys = "test" + EX + ESC + "u" + "inothing" keys = 'test' + EX + ESC + 'u' + 'inothing'
wanted = "nothing" wanted = 'nothing'
class Undo_RemoveEditInTabstop(_VimTest): class Undo_RemoveEditInTabstop(_VimTest):
snippets = ("test", "$1 Hello\naaa ${1} bbb\nWorld") snippets = ('test', '$1 Hello\naaa ${1} bbb\nWorld')
keys = "hello test" + EX + "upsi" + ESC + "hh" + "iabcdef" + ESC + "u" keys = 'hello test' + EX + 'upsi' + ESC + 'hh' + 'iabcdef' + ESC + 'u'
wanted = "hello upsi Hello\naaa upsi bbb\nWorld" wanted = 'hello upsi Hello\naaa upsi bbb\nWorld'
class Undo_RemoveWholeSnippet(_VimTest): class Undo_RemoveWholeSnippet(_VimTest):
snippets = ("test", "Hello\n${1:Hello}World") snippets = ('test', 'Hello\n${1:Hello}World')
keys = "first line\n\n\n\n\n\nthird line" + \ keys = 'first line\n\n\n\n\n\nthird line' + \
ESC + "3k0itest" + EX + ESC + "uiupsy" ESC + '3k0itest' + EX + ESC + 'uiupsy'
wanted = "first line\n\n\nupsy\n\n\nthird line" wanted = 'first line\n\n\nupsy\n\n\nthird line'
class JumpForward_DefSnippet(_VimTest): class JumpForward_DefSnippet(_VimTest):
snippets = ("test", "${1}\n`!p snip.rv = '\\n'.join(t[1].split())`\n\n${0:pass}") snippets = (
keys = "test" + EX + "a b c" + JF + "shallnot" 'test',
wanted = "a b c\na\nb\nc\n\nshallnot" "${1}\n`!p snip.rv = '\\n'.join(t[1].split())`\n\n${0:pass}")
keys = 'test' + EX + 'a b c' + JF + 'shallnot'
wanted = 'a b c\na\nb\nc\n\nshallnot'
class DeleteSnippetInsertion0(_VimTest): class DeleteSnippetInsertion0(_VimTest):
snippets = ("test", "${1:hello} $1") snippets = ('test', '${1:hello} $1')
keys = "test" + EX + ESC + "Vkx" + "i\nworld\n" keys = 'test' + EX + ESC + 'Vkx' + 'i\nworld\n'
wanted = "world" wanted = 'world'
class DeleteSnippetInsertion1(_VimTest): class DeleteSnippetInsertion1(_VimTest):
snippets = ("test", r"$1${1/(.*)/(?0::.)/}") snippets = ('test', r"$1${1/(.*)/(?0::.)/}")
keys = "test" + EX + ESC + "u" + "i" + JF + "\t" keys = 'test' + EX + ESC + 'u' + 'i' + JF + '\t'
wanted = "\t" wanted = '\t'
# End: Undo of Snippet insertion #}}} # End: Undo of Snippet insertion #}}}
# Normal mode editing {{{# # Normal mode editing {{{#
# Test for bug #927844 # Test for bug #927844
class DeleteLastTwoLinesInSnippet(_VimTest): class DeleteLastTwoLinesInSnippet(_VimTest):
snippets = ("test", "$1hello\nnice\nworld") snippets = ('test', '$1hello\nnice\nworld')
keys = "test" + EX + ESC + "j2dd" keys = 'test' + EX + ESC + 'j2dd'
wanted = "hello" wanted = 'hello'
class DeleteCurrentTabStop1_JumpBack(_VimTest): class DeleteCurrentTabStop1_JumpBack(_VimTest):
snippets = ("test", "${1:hi}\nend") snippets = ('test', '${1:hi}\nend')
keys = "test" + EX + ESC + "ddi" + JB keys = 'test' + EX + ESC + 'ddi' + JB
wanted = "end" wanted = 'end'
class DeleteCurrentTabStop2_JumpBack(_VimTest): class DeleteCurrentTabStop2_JumpBack(_VimTest):
snippets = ("test", "${1:hi}\n${2:world}\nend") snippets = ('test', '${1:hi}\n${2:world}\nend')
keys = "test" + EX + JF + ESC + "ddi" + JB + "hello" keys = 'test' + EX + JF + ESC + 'ddi' + JB + 'hello'
wanted = "hello\nend" wanted = 'hello\nend'
class DeleteCurrentTabStop3_JumpAround(_VimTest): class DeleteCurrentTabStop3_JumpAround(_VimTest):
snippets = ("test", "${1:hi}\n${2:world}\nend") snippets = ('test', '${1:hi}\n${2:world}\nend')
keys = "test" + EX + JF + ESC + "ddkji" + JB + "hello" + JF + "world" keys = 'test' + EX + JF + ESC + 'ddkji' + JB + 'hello' + JF + 'world'
wanted = "hello\nendworld" wanted = 'hello\nendworld'
# End: Normal mode editing #}}} # End: Normal mode editing #}}}
# Pressing BS in TabStop {{{# # Pressing BS in TabStop {{{#
# Test for Bug #774917 # Test for Bug #774917
class Backspace_TabStop_Zero(_VimTest): class Backspace_TabStop_Zero(_VimTest):
snippets = ("test", "A${1:C} ${0:DDD}", "This is Case 1") snippets = ('test', 'A${1:C} ${0:DDD}', 'This is Case 1')
keys = "test" + EX + "A" + JF + BS + "BBB" keys = 'test' + EX + 'A' + JF + BS + 'BBB'
wanted = "AA BBB" wanted = 'AA BBB'
class Backspace_TabStop_NotZero(_VimTest): class Backspace_TabStop_NotZero(_VimTest):
snippets = ("test", "A${1:C} ${2:DDD}", "This is Case 1") snippets = ('test', 'A${1:C} ${2:DDD}', 'This is Case 1')
keys = "test" + EX + "A" + JF + BS + "BBB" keys = 'test' + EX + 'A' + JF + BS + 'BBB'
wanted = "AA BBB" wanted = 'AA BBB'
# End: Pressing BS in TabStop #}}} # End: Pressing BS in TabStop #}}}

View File

@ -2,54 +2,72 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Simple Expands {{{# # Simple Expands {{{#
class _SimpleExpands(_VimTest): class _SimpleExpands(_VimTest):
snippets = ("hallo", "Hallo Welt!") snippets = ('hallo', 'Hallo Welt!')
class SimpleExpand_ExpectCorrectResult(_SimpleExpands): class SimpleExpand_ExpectCorrectResult(_SimpleExpands):
keys = "hallo" + EX keys = 'hallo' + EX
wanted = "Hallo Welt!" wanted = 'Hallo Welt!'
class SimpleExpandTwice_ExpectCorrectResult(_SimpleExpands): class SimpleExpandTwice_ExpectCorrectResult(_SimpleExpands):
keys = "hallo" + EX + '\nhallo' + EX keys = 'hallo' + EX + '\nhallo' + EX
wanted = "Hallo Welt!\nHallo Welt!" wanted = 'Hallo Welt!\nHallo Welt!'
class SimpleExpandNewLineAndBackspae_ExpectCorrectResult(_SimpleExpands): class SimpleExpandNewLineAndBackspae_ExpectCorrectResult(_SimpleExpands):
keys = "hallo" + EX + "\nHallo Welt!\n\n\b\b\b\b\b" keys = 'hallo' + EX + '\nHallo Welt!\n\n\b\b\b\b\b'
wanted = "Hallo Welt!\nHallo We" wanted = 'Hallo Welt!\nHallo We'
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set backspace=eol,start") vim_config.append('set backspace=eol,start')
class SimpleExpandTypeAfterExpand_ExpectCorrectResult(_SimpleExpands): class SimpleExpandTypeAfterExpand_ExpectCorrectResult(_SimpleExpands):
keys = "hallo" + EX + "and again" keys = 'hallo' + EX + 'and again'
wanted = "Hallo Welt!and again" wanted = 'Hallo Welt!and again'
class SimpleExpandTypeAndDelete_ExpectCorrectResult(_SimpleExpands): class SimpleExpandTypeAndDelete_ExpectCorrectResult(_SimpleExpands):
keys = "na du hallo" + EX + "and again\b\b\b\b\bblub" keys = 'na du hallo' + EX + 'and again\b\b\b\b\bblub'
wanted = "na du Hallo Welt!and blub" wanted = 'na du Hallo Welt!and blub'
class DoNotExpandAfterSpace_ExpectCorrectResult(_SimpleExpands): class DoNotExpandAfterSpace_ExpectCorrectResult(_SimpleExpands):
keys = "hallo " + EX keys = 'hallo ' + EX
wanted = "hallo " + EX wanted = 'hallo ' + EX
class ExitSnippetModeAfterTabstopZero(_VimTest): class ExitSnippetModeAfterTabstopZero(_VimTest):
snippets = ("test", "SimpleText") snippets = ('test', 'SimpleText')
keys = "test" + EX + EX keys = 'test' + EX + EX
wanted = "SimpleText" + EX wanted = 'SimpleText' + EX
class ExpandInTheMiddleOfLine_ExpectCorrectResult(_SimpleExpands): class ExpandInTheMiddleOfLine_ExpectCorrectResult(_SimpleExpands):
keys = "Wie hallo gehts" + ESC + "bhi" + EX keys = 'Wie hallo gehts' + ESC + 'bhi' + EX
wanted = "Wie Hallo Welt! gehts" wanted = 'Wie Hallo Welt! gehts'
class MultilineExpand_ExpectCorrectResult(_VimTest): class MultilineExpand_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "Hallo Welt!\nUnd Wie gehts") snippets = ('hallo', 'Hallo Welt!\nUnd Wie gehts')
keys = "Wie hallo gehts" + ESC + "bhi" + EX keys = 'Wie hallo gehts' + ESC + 'bhi' + EX
wanted = "Wie Hallo Welt!\nUnd Wie gehts gehts" wanted = 'Wie Hallo Welt!\nUnd Wie gehts gehts'
class MultilineExpandTestTyping_ExpectCorrectResult(_VimTest): class MultilineExpandTestTyping_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "Hallo Welt!\nUnd Wie gehts") snippets = ('hallo', 'Hallo Welt!\nUnd Wie gehts')
wanted = "Wie Hallo Welt!\nUnd Wie gehtsHuiui! gehts" wanted = 'Wie Hallo Welt!\nUnd Wie gehtsHuiui! gehts'
keys = "Wie hallo gehts" + ESC + "bhi" + EX + "Huiui!" keys = 'Wie hallo gehts' + ESC + 'bhi' + EX + 'Huiui!'
class SimpleExpandEndingWithNewline_ExpectCorrectResult(_VimTest): class SimpleExpandEndingWithNewline_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "Hallo Welt\n") snippets = ('hallo', 'Hallo Welt\n')
keys = "hallo" + EX + "\nAnd more" keys = 'hallo' + EX + '\nAnd more'
wanted = "Hallo Welt\n\nAnd more" wanted = 'Hallo Welt\n\nAnd more'
# End: Simple Expands #}}} # End: Simple Expands #}}}

View File

@ -2,17 +2,21 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Test for bug 1251994 {{{# # Test for bug 1251994 {{{#
class Bug1251994(_VimTest): class Bug1251994(_VimTest):
snippets = ("test", "${2:#2} ${1:#1};$0") snippets = ('test', '${2:#2} ${1:#1};$0')
keys = " test" + EX + "hello" + JF + "world" + JF + "blub" keys = ' test' + EX + 'hello' + JF + 'world' + JF + 'blub'
wanted = " world hello;blub" wanted = ' world hello;blub'
# End: 1251994 #}}} # End: 1251994 #}}}
# Test for https://github.com/SirVer/ultisnips/issues/157 (virtualedit) {{{# # Test for https://github.com/SirVer/ultisnips/issues/157 (virtualedit) {{{#
class VirtualEdit(_VimTest): class VirtualEdit(_VimTest):
snippets = ("pd", "padding: ${1:0}px") snippets = ('pd', 'padding: ${1:0}px')
keys = "\t\t\tpd" + EX + "2" keys = '\t\t\tpd' + EX + '2'
wanted = "\t\t\tpadding: 2px" wanted = '\t\t\tpadding: 2px'
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append('set virtualedit=all') vim_config.append('set virtualedit=all')
@ -20,51 +24,61 @@ class VirtualEdit(_VimTest):
# End: 1251994 #}}} # End: 1251994 #}}}
# Test for Github Pull Request #134 - Retain unnamed register {{{# # Test for Github Pull Request #134 - Retain unnamed register {{{#
class RetainsTheUnnamedRegister(_VimTest): class RetainsTheUnnamedRegister(_VimTest):
snippets = ("test", "${1:hello} ${2:world} ${0}") snippets = ('test', '${1:hello} ${2:world} ${0}')
keys = "yank" + ESC + "by4lea test" + EX + "HELLO" + JF + JF + ESC + "p" keys = 'yank' + ESC + 'by4lea test' + EX + 'HELLO' + JF + JF + ESC + 'p'
wanted = "yank HELLO world yank" wanted = 'yank HELLO world yank'
class RetainsTheUnnamedRegister_ButOnlyOnce(_VimTest): class RetainsTheUnnamedRegister_ButOnlyOnce(_VimTest):
snippets = ("test", "${1:hello} ${2:world} ${0}") snippets = ('test', '${1:hello} ${2:world} ${0}')
keys = "blahfasel" + ESC + "v" + 4*ARR_L + "xotest" + EX + ESC + ARR_U + "v0xo" + ESC + "p" keys = 'blahfasel' + ESC + 'v' + 4 * ARR_L + \
wanted = "\nblah\nhello world " 'xotest' + EX + ESC + ARR_U + 'v0xo' + ESC + 'p'
wanted = '\nblah\nhello world '
# End: Github Pull Request # 134 #}}} # End: Github Pull Request # 134 #}}}
# Test to ensure that shiftwidth follows tabstop when it's set to zero post # Test to ensure that shiftwidth follows tabstop when it's set to zero post
# version 7.3.693. Prior to that version a shiftwidth of zero effectively # version 7.3.693. Prior to that version a shiftwidth of zero effectively
# removes tabs. # removes tabs.
class ShiftWidthZero(_VimTest): class ShiftWidthZero(_VimTest):
def _extra_options_pre_init(self, vim_config):
vim_config += [ def _extra_options_pre_init(self, vim_config):
"if exists('*shiftwidth')", vim_config += [
" set shiftwidth=0", "if exists('*shiftwidth')",
"endif", ' set shiftwidth=0',
] 'endif',
snippets = ("test", "\t${1}${0}") ]
keys = "test" + EX + "foo" snippets = ('test', '\t${1}${0}')
wanted = "\tfoo" keys = 'test' + EX + 'foo'
wanted = '\tfoo'
# Test for https://github.com/SirVer/ultisnips/issues/171 {{{# # Test for https://github.com/SirVer/ultisnips/issues/171 {{{#
# Make sure that we don't crash when trying to save and restore the clipboard # Make sure that we don't crash when trying to save and restore the clipboard
# when it contains data that we can't coerce into Unicode. # when it contains data that we can't coerce into Unicode.
class NonUnicodeDataInUnnamedRegister(_VimTest): class NonUnicodeDataInUnnamedRegister(_VimTest):
snippets = ("test", "hello") snippets = ('test', 'hello')
keys = "test" + EX + ESC + \ keys = 'test' + EX + ESC + \
"\n".join([":redir @a", '\n'.join([':redir @a',
":messages", ':messages',
":redir END", ':redir END',
(":if match(@a, 'Error') != -1 | " + (":if match(@a, 'Error') != -1 | " +
"call setline('.', 'error detected') | " + "call setline('.', 'error detected') | " +
"3put a | " + '3put a | ' +
"endif"), 'endif'),
""]) ''])
wanted = "hello" wanted = 'hello'
def _before_test(self): def _before_test(self):
# The string below was the one a user had on their clipboard when # The string below was the one a user had on their clipboard when
# encountering the UnicodeDecodeError and could not be coerced into # encountering the UnicodeDecodeError and could not be coerced into
# unicode. # unicode.
self.vim.send( self.vim.send(
':let @" = "\\x80kdI{\\x80@7 1},' + ':let @" = "\\x80kdI{\\x80@7 1},' +
'\\x80kh\\x80kh\\x80kd\\x80kdq\\x80kb\\x1b"\n') '\\x80kh\\x80kh\\x80kd\\x80kdq\\x80kb\\x1b"\n')
# End: #171 #}}} # End: #171 #}}}

View File

@ -2,41 +2,50 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Folding Interaction {{{# # Folding Interaction {{{#
class FoldingEnabled_SnippetWithFold_ExpectNoFolding(_VimTest): class FoldingEnabled_SnippetWithFold_ExpectNoFolding(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set foldlevel=0") vim_config.append('set foldlevel=0')
vim_config.append("set foldmethod=marker") vim_config.append('set foldmethod=marker')
snippets = ("test", r"""Hello {{{ snippets = ('test', r"""Hello {{{
${1:Welt} }}}""") ${1:Welt} }}}""")
keys = "test" + EX + "Ball" keys = 'test' + EX + 'Ball'
wanted = """Hello {{{ wanted = """Hello {{{
Ball }}}""" Ball }}}"""
class FoldOverwrite_Simple_ECR(_VimTest): class FoldOverwrite_Simple_ECR(_VimTest):
snippets = ("fold", snippets = ('fold',
"""# ${1:Description} `!p snip.rv = vim.eval("&foldmarker").split(",")[0]` """# ${1:Description} `!p snip.rv = vim.eval("&foldmarker").split(",")[0]`
# End: $1 `!p snip.rv = vim.eval("&foldmarker").split(",")[1]`""") # End: $1 `!p snip.rv = vim.eval("&foldmarker").split(",")[1]`""")
keys = "fold" + EX + "hi" keys = 'fold' + EX + 'hi'
wanted = "# hi {{{\n\n# End: hi }}}" wanted = '# hi {{{\n\n# End: hi }}}'
class Fold_DeleteMiddleLine_ECR(_VimTest): class Fold_DeleteMiddleLine_ECR(_VimTest):
snippets = ("fold", snippets = ('fold',
"""# ${1:Description} `!p snip.rv = vim.eval("&foldmarker").split(",")[0]` """# ${1:Description} `!p snip.rv = vim.eval("&foldmarker").split(",")[0]`
# End: $1 `!p snip.rv = vim.eval("&foldmarker").split(",")[1]`""") # End: $1 `!p snip.rv = vim.eval("&foldmarker").split(",")[1]`""")
keys = "fold" + EX + "hi" + ESC + "jdd" keys = 'fold' + EX + 'hi' + ESC + 'jdd'
wanted = "# hi {{{\n\n# End: hi }}}" wanted = '# hi {{{\n\n# End: hi }}}'
class PerlSyntaxFold(_VimTest): class PerlSyntaxFold(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set foldlevel=0") vim_config.append('set foldlevel=0')
vim_config.append("syntax enable") vim_config.append('syntax enable')
vim_config.append("set foldmethod=syntax") vim_config.append('set foldmethod=syntax')
vim_config.append("let g:perl_fold = 1") vim_config.append('let g:perl_fold = 1')
vim_config.append("so $VIMRUNTIME/syntax/perl.vim") vim_config.append('so $VIMRUNTIME/syntax/perl.vim')
snippets = ("test", r"""package ${1:`!v printf('c%02d', 3)`}; snippets = ('test', r"""package ${1:`!v printf('c%02d', 3)`};
${0} ${0}
1;""") 1;""")
keys = "test" + EX + JF + "sub junk {}" keys = 'test' + EX + JF + 'sub junk {}'
wanted = "package c03;\nsub junk {}\n1;" wanted = 'package c03;\nsub junk {}\n1;'
# End: Folding Interaction #}}} # End: Folding Interaction #}}}

View File

@ -3,15 +3,20 @@ from test.constant import *
from test.util import running_on_windows from test.util import running_on_windows
# ExpandTab {{{# # ExpandTab {{{#
class _ExpandTabs(_VimTest): class _ExpandTabs(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set expandtab") vim_config.append('set expandtab')
class RecTabStopsWithExpandtab_SimpleExample_ECR(_ExpandTabs): class RecTabStopsWithExpandtab_SimpleExample_ECR(_ExpandTabs):
snippets = ("m", "\tBlaahblah \t\t ") snippets = ('m', '\tBlaahblah \t\t ')
keys = "m" + EX keys = 'm' + EX
wanted = " Blaahblah \t\t " wanted = ' Blaahblah \t\t '
class RecTabStopsWithExpandtab_SpecialIndentProblem_ECR(_ExpandTabs): class RecTabStopsWithExpandtab_SpecialIndentProblem_ECR(_ExpandTabs):
# Windows indents the Something line after pressing return, though it # Windows indents the Something line after pressing return, though it
@ -22,37 +27,47 @@ class RecTabStopsWithExpandtab_SpecialIndentProblem_ECR(_ExpandTabs):
# completely. # completely.
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ( snippets = (
("m1", "Something"), ('m1', 'Something'),
("m", "\t$0"), ('m', '\t$0'),
) )
keys = "m" + EX + "m1" + EX + '\nHallo' keys = 'm' + EX + 'm1' + EX + '\nHallo'
wanted = " Something\n Hallo" wanted = ' Something\n Hallo'
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
_ExpandTabs._extra_options_pre_init(self, vim_config) _ExpandTabs._extra_options_pre_init(self, vim_config)
vim_config.append("set indentkeys=o,O,*<Return>,<>>,{,}") vim_config.append('set indentkeys=o,O,*<Return>,<>>,{,}')
vim_config.append("set indentexpr=8") vim_config.append('set indentexpr=8')
# End: ExpandTab #}}} # End: ExpandTab #}}}
# Proper Indenting {{{# # Proper Indenting {{{#
class ProperIndenting_SimpleCase_ECR(_VimTest): class ProperIndenting_SimpleCase_ECR(_VimTest):
snippets = ("test", "for\n blah") snippets = ('test', 'for\n blah')
keys = " test" + EX + "Hui" keys = ' test' + EX + 'Hui'
wanted = " for\n blahHui" wanted = ' for\n blahHui'
class ProperIndenting_SingleLineNoReindenting_ECR(_VimTest): class ProperIndenting_SingleLineNoReindenting_ECR(_VimTest):
snippets = ("test", "hui") snippets = ('test', 'hui')
keys = " test" + EX + "blah" keys = ' test' + EX + 'blah'
wanted = " huiblah" wanted = ' huiblah'
class ProperIndenting_AutoIndentAndNewline_ECR(_VimTest): class ProperIndenting_AutoIndentAndNewline_ECR(_VimTest):
snippets = ("test", "hui") snippets = ('test', 'hui')
keys = " test" + EX + "\n"+ "blah" keys = ' test' + EX + '\n' + 'blah'
wanted = " hui\n blah" wanted = ' hui\n blah'
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set autoindent") vim_config.append('set autoindent')
# Test for bug 1073816 # Test for bug 1073816
class ProperIndenting_FirstLineInFile_ECR(_VimTest): class ProperIndenting_FirstLineInFile_ECR(_VimTest):
text_before = "" text_before = ''
text_after = "" text_after = ''
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
global !p global !p
def complete(t, opts): def complete(t, opts):
if t: if t:
@ -69,31 +84,41 @@ snippet '^#?inc' "#include <>" !r
#include <$1`!p snip.rv = complete(t[1], ['cassert', 'cstdio', 'cstdlib', 'cstring', 'fstream', 'iostream', 'sstream'])`> #include <$1`!p snip.rv = complete(t[1], ['cassert', 'cstdio', 'cstdlib', 'cstring', 'fstream', 'iostream', 'sstream'])`>
endsnippet endsnippet
"""} """}
keys = "inc" + EX + "foo" keys = 'inc' + EX + 'foo'
wanted = "#include <foo>" wanted = '#include <foo>'
class ProperIndenting_FirstLineInFileComplete_ECR(ProperIndenting_FirstLineInFile_ECR):
keys = "inc" + EX + "cstdl"
wanted = "#include <cstdlib>" class ProperIndenting_FirstLineInFileComplete_ECR(
ProperIndenting_FirstLineInFile_ECR):
keys = 'inc' + EX + 'cstdl'
wanted = '#include <cstdlib>'
# End: Proper Indenting #}}} # End: Proper Indenting #}}}
# Format options tests {{{# # Format options tests {{{#
class _FormatoptionsBase(_VimTest): class _FormatoptionsBase(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set tw=20") vim_config.append('set tw=20')
vim_config.append("set fo=lrqntc") vim_config.append('set fo=lrqntc')
class FOSimple_Break_ExpectCorrectResult(_FormatoptionsBase): class FOSimple_Break_ExpectCorrectResult(_FormatoptionsBase):
snippets = ("test", "${1:longer expand}\n$1\n$0", "", "f") snippets = ('test', '${1:longer expand}\n$1\n$0', '', 'f')
keys = "test" + EX + "This is a longer text that should wrap as formatoptions are enabled" + JF + "end" keys = 'test' + EX + \
wanted = "This is a longer\ntext that should\nwrap as\nformatoptions are\nenabled\n" + \ 'This is a longer text that should wrap as formatoptions are enabled' + \
"This is a longer\ntext that should\nwrap as\nformatoptions are\nenabled\n" + "end" JF + 'end'
wanted = 'This is a longer\ntext that should\nwrap as\nformatoptions are\nenabled\n' + \
'This is a longer\ntext that should\nwrap as\nformatoptions are\nenabled\n' + \
'end'
class FOTextBeforeAndAfter_ExpectCorrectResult(_FormatoptionsBase): class FOTextBeforeAndAfter_ExpectCorrectResult(_FormatoptionsBase):
snippets = ("test", "Before${1:longer expand}After\nstart$1end") snippets = ('test', 'Before${1:longer expand}After\nstart$1end')
keys = "test" + EX + "This is a longer text that should wrap" keys = 'test' + EX + 'This is a longer text that should wrap'
wanted = \ wanted = \
"""BeforeThis is a """BeforeThis is a
longer text that longer text that
should wrapAfter should wrapAfter
startThis is a startThis is a
@ -103,11 +128,11 @@ should wrapend"""
# Tests for https://bugs.launchpad.net/bugs/719998 # Tests for https://bugs.launchpad.net/bugs/719998
class FOTextAfter_ExpectCorrectResult(_FormatoptionsBase): class FOTextAfter_ExpectCorrectResult(_FormatoptionsBase):
snippets = ("test", "${1:longer expand}after\nstart$1end") snippets = ('test', '${1:longer expand}after\nstart$1end')
keys = ("test" + EX + "This is a longer snippet that should wrap properly " keys = ('test' + EX + 'This is a longer snippet that should wrap properly '
"and the mirror below should work as well") 'and the mirror below should work as well')
wanted = \ wanted = \
"""This is a longer """This is a longer
snippet that should snippet that should
wrap properly and wrap properly and
the mirror below the mirror below
@ -118,11 +143,12 @@ wrap properly and
the mirror below the mirror below
should work as wellend""" should work as wellend"""
class FOWrapOnLongWord_ExpectCorrectResult(_FormatoptionsBase): class FOWrapOnLongWord_ExpectCorrectResult(_FormatoptionsBase):
snippets = ("test", "${1:longer expand}after\nstart$1end") snippets = ('test', '${1:longer expand}after\nstart$1end')
keys = ("test" + EX + "This is a longersnippet that should wrap properly") keys = ('test' + EX + 'This is a longersnippet that should wrap properly')
wanted = \ wanted = \
"""This is a """This is a
longersnippet that longersnippet that
should wrap properlyafter should wrap properlyafter
startThis is a startThis is a

View File

@ -4,141 +4,181 @@ from test.constant import *
from test.util import running_on_windows from test.util import running_on_windows
# ShellCode Interpolation {{{# # ShellCode Interpolation {{{#
class TabStop_Shell_SimpleExample(_VimTest): class TabStop_Shell_SimpleExample(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", "hi `echo hallo` you!") snippets = ('test', 'hi `echo hallo` you!')
keys = "test" + EX + "and more" keys = 'test' + EX + 'and more'
wanted = "hi hallo you!and more" wanted = 'hi hallo you!and more'
class TabStop_Shell_WithUmlauts(_VimTest): class TabStop_Shell_WithUmlauts(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", "hi `echo höüäh` you!") snippets = ('test', 'hi `echo höüäh` you!')
keys = "test" + EX + "and more" keys = 'test' + EX + 'and more'
wanted = "hi höüäh you!and more" wanted = 'hi höüäh you!and more'
class TabStop_Shell_TextInNextLine(_VimTest): class TabStop_Shell_TextInNextLine(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", "hi `echo hallo`\nWeiter") snippets = ('test', 'hi `echo hallo`\nWeiter')
keys = "test" + EX + "and more" keys = 'test' + EX + 'and more'
wanted = "hi hallo\nWeiterand more" wanted = 'hi hallo\nWeiterand more'
class TabStop_Shell_InDefValue_Leave(_VimTest): class TabStop_Shell_InDefValue_Leave(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", "Hallo ${1:now `echo fromecho`} end") snippets = ('test', 'Hallo ${1:now `echo fromecho`} end')
keys = "test" + EX + JF + "and more" keys = 'test' + EX + JF + 'and more'
wanted = "Hallo now fromecho endand more" wanted = 'Hallo now fromecho endand more'
class TabStop_Shell_InDefValue_Overwrite(_VimTest): class TabStop_Shell_InDefValue_Overwrite(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", "Hallo ${1:now `echo fromecho`} end") snippets = ('test', 'Hallo ${1:now `echo fromecho`} end')
keys = "test" + EX + "overwrite" + JF + "and more" keys = 'test' + EX + 'overwrite' + JF + 'and more'
wanted = "Hallo overwrite endand more" wanted = 'Hallo overwrite endand more'
class TabStop_Shell_TestEscapedChars_Overwrite(_VimTest): class TabStop_Shell_TestEscapedChars_Overwrite(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", r"""`echo \`echo "\\$hi"\``""") snippets = ('test', r"""`echo \`echo "\\$hi"\``""")
keys = "test" + EX keys = 'test' + EX
wanted = "$hi" wanted = '$hi'
class TabStop_Shell_TestEscapedCharsAndShellVars_Overwrite(_VimTest): class TabStop_Shell_TestEscapedCharsAndShellVars_Overwrite(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", r"""`hi="blah"; echo \`echo "$hi"\``""") snippets = ('test', r"""`hi="blah"; echo \`echo "$hi"\``""")
keys = "test" + EX keys = 'test' + EX
wanted = "blah" wanted = 'blah'
class TabStop_Shell_ShebangPython(_VimTest): class TabStop_Shell_ShebangPython(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = ("test", """Hallo ${1:now `#!/usr/bin/env python snippets = ('test', """Hallo ${1:now `#!/usr/bin/env python
print "Hallo Welt" print "Hallo Welt"
`} end""") `} end""")
keys = "test" + EX + JF + "and more" keys = 'test' + EX + JF + 'and more'
wanted = "Hallo now Hallo Welt endand more" wanted = 'Hallo now Hallo Welt endand more'
# End: ShellCode Interpolation #}}} # End: ShellCode Interpolation #}}}
# VimScript Interpolation {{{# # VimScript Interpolation {{{#
class TabStop_VimScriptInterpolation_SimpleExample(_VimTest): class TabStop_VimScriptInterpolation_SimpleExample(_VimTest):
snippets = ("test", """hi `!v indent(".")` End""") snippets = ('test', """hi `!v indent(".")` End""")
keys = " test" + EX keys = ' test' + EX
wanted = " hi 4 End" wanted = ' hi 4 End'
# End: VimScript Interpolation #}}} # End: VimScript Interpolation #}}}
# PythonCode Interpolation {{{# # PythonCode Interpolation {{{#
# Deprecated Implementation {{{# # Deprecated Implementation {{{#
class PythonCodeOld_SimpleExample(_VimTest): class PythonCodeOld_SimpleExample(_VimTest):
snippets = ("test", """hi `!p res = "Hallo"` End""") snippets = ('test', """hi `!p res = "Hallo"` End""")
keys = "test" + EX keys = 'test' + EX
wanted = "hi Hallo End" wanted = 'hi Hallo End'
class PythonCodeOld_ReferencePlaceholderAfter(_VimTest): class PythonCodeOld_ReferencePlaceholderAfter(_VimTest):
snippets = ("test", """${1:hi} `!p res = t[1]+".blah"` End""") snippets = ('test', """${1:hi} `!p res = t[1]+".blah"` End""")
keys = "test" + EX + "ho" keys = 'test' + EX + 'ho'
wanted = "ho ho.blah End" wanted = 'ho ho.blah End'
class PythonCodeOld_ReferencePlaceholderBefore(_VimTest): class PythonCodeOld_ReferencePlaceholderBefore(_VimTest):
snippets = ("test", """`!p res = len(t[1])*"#"`\n${1:some text}""") snippets = ('test', """`!p res = len(t[1])*"#"`\n${1:some text}""")
keys = "test" + EX + "Hallo Welt" keys = 'test' + EX + 'Hallo Welt'
wanted = "##########\nHallo Welt" wanted = '##########\nHallo Welt'
class PythonCodeOld_TransformedBeforeMultiLine(_VimTest): class PythonCodeOld_TransformedBeforeMultiLine(_VimTest):
snippets = ("test", """${1/.+/egal/m} ${1:`!p snippets = ('test', """${1/.+/egal/m} ${1:`!p
res = "Hallo"`} End""") res = "Hallo"`} End""")
keys = "test" + EX keys = 'test' + EX
wanted = "egal Hallo End" wanted = 'egal Hallo End'
class PythonCodeOld_IndentedMultiline(_VimTest): class PythonCodeOld_IndentedMultiline(_VimTest):
snippets = ("test", """start `!p a = 1 snippets = ('test', """start `!p a = 1
b = 2 b = 2
if b > a: if b > a:
res = "b isbigger a" res = "b isbigger a"
else: else:
res = "a isbigger b"` end""") res = "a isbigger b"` end""")
keys = " test" + EX keys = ' test' + EX
wanted = " start b isbigger a end" wanted = ' start b isbigger a end'
# End: Deprecated Implementation #}}} # End: Deprecated Implementation #}}}
# New Implementation {{{# # New Implementation {{{#
class PythonCode_UseNewOverOld(_VimTest): class PythonCode_UseNewOverOld(_VimTest):
snippets = ("test", """hi `!p res = "Old" snippets = ('test', """hi `!p res = "Old"
snip.rv = "New"` End""") snip.rv = "New"` End""")
keys = "test" + EX keys = 'test' + EX
wanted = "hi New End" wanted = 'hi New End'
class PythonCode_SimpleExample(_VimTest): class PythonCode_SimpleExample(_VimTest):
snippets = ("test", """hi `!p snip.rv = "Hallo"` End""") snippets = ('test', """hi `!p snip.rv = "Hallo"` End""")
keys = "test" + EX keys = 'test' + EX
wanted = "hi Hallo End" wanted = 'hi Hallo End'
class PythonCode_SimpleExample_ReturnValueIsEmptyString(_VimTest): class PythonCode_SimpleExample_ReturnValueIsEmptyString(_VimTest):
snippets = ("test", """hi`!p snip.rv = ""`End""") snippets = ('test', """hi`!p snip.rv = ""`End""")
keys = "test" + EX keys = 'test' + EX
wanted = "hiEnd" wanted = 'hiEnd'
class PythonCode_ReferencePlaceholder(_VimTest): class PythonCode_ReferencePlaceholder(_VimTest):
snippets = ("test", """${1:hi} `!p snip.rv = t[1]+".blah"` End""") snippets = ('test', """${1:hi} `!p snip.rv = t[1]+".blah"` End""")
keys = "test" + EX + "ho" keys = 'test' + EX + 'ho'
wanted = "ho ho.blah End" wanted = 'ho ho.blah End'
class PythonCode_ReferencePlaceholderBefore(_VimTest): class PythonCode_ReferencePlaceholderBefore(_VimTest):
snippets = ("test", """`!p snip.rv = len(t[1])*"#"`\n${1:some text}""") snippets = ('test', """`!p snip.rv = len(t[1])*"#"`\n${1:some text}""")
keys = "test" + EX + "Hallo Welt" keys = 'test' + EX + 'Hallo Welt'
wanted = "##########\nHallo Welt" wanted = '##########\nHallo Welt'
class PythonCode_TransformedBeforeMultiLine(_VimTest): class PythonCode_TransformedBeforeMultiLine(_VimTest):
snippets = ("test", """${1/.+/egal/m} ${1:`!p snippets = ('test', """${1/.+/egal/m} ${1:`!p
snip.rv = "Hallo"`} End""") snip.rv = "Hallo"`} End""")
keys = "test" + EX keys = 'test' + EX
wanted = "egal Hallo End" wanted = 'egal Hallo End'
class PythonCode_MultilineIndented(_VimTest): class PythonCode_MultilineIndented(_VimTest):
snippets = ("test", """start `!p a = 1 snippets = ('test', """start `!p a = 1
b = 2 b = 2
if b > a: if b > a:
snip.rv = "b isbigger a" snip.rv = "b isbigger a"
else: else:
snip.rv = "a isbigger b"` end""") snip.rv = "a isbigger b"` end""")
keys = " test" + EX keys = ' test' + EX
wanted = " start b isbigger a end" wanted = ' start b isbigger a end'
class PythonCode_SimpleAppend(_VimTest): class PythonCode_SimpleAppend(_VimTest):
snippets = ("test", """hi `!p snip.rv = "Hallo1" snippets = ('test', """hi `!p snip.rv = "Hallo1"
snip += "Hallo2"` End""") snip += "Hallo2"` End""")
keys = "test" + EX keys = 'test' + EX
wanted = "hi Hallo1\nHallo2 End" wanted = 'hi Hallo1\nHallo2 End'
class PythonCode_MultiAppend(_VimTest): class PythonCode_MultiAppend(_VimTest):
snippets = ("test", """hi `!p snip.rv = "Hallo1" snippets = ('test', """hi `!p snip.rv = "Hallo1"
snip += "Hallo2" snip += "Hallo2"
snip += "Hallo3"` End""") snip += "Hallo3"` End""")
keys = "test" + EX keys = 'test' + EX
wanted = "hi Hallo1\nHallo2\nHallo3 End" wanted = 'hi Hallo1\nHallo2\nHallo3 End'
class PythonCode_MultiAppendSimpleIndent(_VimTest): class PythonCode_MultiAppendSimpleIndent(_VimTest):
snippets = ("test", """hi snippets = ('test', """hi
`!p snip.rv="Hallo1" `!p snip.rv="Hallo1"
snip += "Hallo2" snip += "Hallo2"
snip += "Hallo3"` snip += "Hallo3"`
@ -152,8 +192,9 @@ End""")
Hallo3 Hallo3
End""" End"""
class PythonCode_SimpleMkline(_VimTest): class PythonCode_SimpleMkline(_VimTest):
snippets = ("test", r"""hi snippets = ('test', r"""hi
`!p snip.rv="Hallo1\n" `!p snip.rv="Hallo1\n"
snip.rv += snip.mkline("Hallo2") + "\n" snip.rv += snip.mkline("Hallo2") + "\n"
snip.rv += snip.mkline("Hallo3")` snip.rv += snip.mkline("Hallo3")`
@ -167,8 +208,9 @@ End""")
Hallo3 Hallo3
End""" End"""
class PythonCode_MultiAppendShift(_VimTest): class PythonCode_MultiAppendShift(_VimTest):
snippets = ("test", r"""hi snippets = ('test', r"""hi
`!p snip.rv="i1" `!p snip.rv="i1"
snip += "i1" snip += "i1"
snip >> 1 snip >> 1
@ -189,8 +231,9 @@ i0
i3 i3
End""" End"""
class PythonCode_MultiAppendShiftMethods(_VimTest): class PythonCode_MultiAppendShiftMethods(_VimTest):
snippets = ("test", r"""hi snippets = ('test', r"""hi
`!p snip.rv="i1\n" `!p snip.rv="i1\n"
snip.rv += snip.mkline("i1\n") snip.rv += snip.mkline("i1\n")
snip.shift(1) snip.shift(1)
@ -213,7 +256,7 @@ i0
class PythonCode_ResetIndent(_VimTest): class PythonCode_ResetIndent(_VimTest):
snippets = ("test", r"""hi snippets = ('test', r"""hi
`!p snip.rv="i1" `!p snip.rv="i1"
snip >> 1 snip >> 1
snip += "i2" snip += "i2"
@ -235,11 +278,13 @@ i0
i1 i1
End""" End"""
class PythonCode_IndentEtSw(_VimTest): class PythonCode_IndentEtSw(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set expandtab") vim_config.append('set expandtab')
snippets = ("test", r"""hi snippets = ('test', r"""hi
`!p snip.rv = "i1" `!p snip.rv = "i1"
snip >> 1 snip >> 1
snip += "i2" snip += "i2"
@ -257,11 +302,13 @@ i0
i1 i1
End""" End"""
class PythonCode_IndentEtSwOffset(_VimTest): class PythonCode_IndentEtSwOffset(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set expandtab") vim_config.append('set expandtab')
snippets = ("test", r"""hi snippets = ('test', r"""hi
`!p snip.rv = "i1" `!p snip.rv = "i1"
snip >> 1 snip >> 1
snip += "i2" snip += "i2"
@ -279,11 +326,13 @@ End""")
i1 i1
End""" End"""
class PythonCode_IndentNoetSwTs(_VimTest): class PythonCode_IndentNoetSwTs(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set ts=4") vim_config.append('set ts=4')
snippets = ("test", r"""hi snippets = ('test', r"""hi
`!p snip.rv = "i1" `!p snip.rv = "i1"
snip >> 1 snip >> 1
snip += "i2" snip += "i2"
@ -302,74 +351,108 @@ i0
End""" End"""
# Test using 'opt' # Test using 'opt'
class PythonCode_OptExists(_VimTest): class PythonCode_OptExists(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append('let g:UStest="yes"') vim_config.append('let g:UStest="yes"')
snippets = ("test", r"""hi `!p snip.rv = snip.opt("g:UStest") or "no"` End""") snippets = (
'test',
r"""hi `!p snip.rv = snip.opt("g:UStest") or "no"` End""")
keys = """test""" + EX keys = """test""" + EX
wanted = """hi yes End""" wanted = """hi yes End"""
class PythonCode_OptNoExists(_VimTest): class PythonCode_OptNoExists(_VimTest):
snippets = ("test", r"""hi `!p snip.rv = snip.opt("g:UStest") or "no"` End""") snippets = (
'test',
r"""hi `!p snip.rv = snip.opt("g:UStest") or "no"` End""")
keys = """test""" + EX keys = """test""" + EX
wanted = """hi no End""" wanted = """hi no End"""
class PythonCode_IndentProblem(_VimTest): class PythonCode_IndentProblem(_VimTest):
# A test case which is likely related to bug 719649 # A test case which is likely related to bug 719649
snippets = ("test", r"""hi `!p snippets = ('test', r"""hi `!p
snip.rv = "World" snip.rv = "World"
` End""") ` End""")
keys = " " * 8 + "test" + EX # < 8 works. keys = ' ' * 8 + 'test' + EX # < 8 works.
wanted = """ hi World End""" wanted = """ hi World End"""
class PythonCode_TrickyReferences(_VimTest): class PythonCode_TrickyReferences(_VimTest):
snippets = ("test", r"""${2:${1/.+/egal/}} ${1:$3} ${3:`!p snip.rv = "hi"`}""") snippets = (
keys = "ups test" + EX 'test',
wanted = "ups egal hi hi" r"""${2:${1/.+/egal/}} ${1:$3} ${3:`!p snip.rv = "hi"`}""")
keys = 'ups test' + EX
wanted = 'ups egal hi hi'
# locals # locals
class PythonCode_Locals(_VimTest): class PythonCode_Locals(_VimTest):
snippets = ("test", r"""hi `!p a = "test" snippets = ('test', r"""hi `!p a = "test"
snip.rv = "nothing"` `!p snip.rv = 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"""
class PythonCode_LongerTextThanSource_Chars(_VimTest): class PythonCode_LongerTextThanSource_Chars(_VimTest):
snippets = ("test", r"""hi`!p snip.rv = "a" * 100`end""") snippets = ('test', r"""hi`!p snip.rv = "a" * 100`end""")
keys = """test""" + EX + "ups" keys = """test""" + EX + 'ups'
wanted = "hi" + 100*"a" + "endups" wanted = 'hi' + 100 * 'a' + 'endups'
class PythonCode_LongerTextThanSource_MultiLine(_VimTest): class PythonCode_LongerTextThanSource_MultiLine(_VimTest):
snippets = ("test", r"""hi`!p snip.rv = "a" * 100 + '\n'*100 + "a"*100`end""") snippets = (
keys = """test""" + EX + "ups" 'test',
wanted = "hi" + 100*"a" + 100*"\n" + 100*"a" + "endups" r"""hi`!p snip.rv = "a" * 100 + '\n'*100 + "a"*100`end""")
keys = """test""" + EX + 'ups'
wanted = 'hi' + 100 * 'a' + 100 * '\n' + 100 * 'a' + 'endups'
class PythonCode_AccessKilledTabstop_OverwriteSecond(_VimTest): class PythonCode_AccessKilledTabstop_OverwriteSecond(_VimTest):
snippets = ("test", r"`!p snip.rv = t[2].upper()`${1:h${2:welt}o}`!p snip.rv = t[2].upper()`") snippets = (
keys = "test" + EX + JF + "okay" 'test',
wanted = "OKAYhokayoOKAY" r"`!p snip.rv = t[2].upper()`${1:h${2:welt}o}`!p snip.rv = t[2].upper()`")
keys = 'test' + EX + JF + 'okay'
wanted = 'OKAYhokayoOKAY'
class PythonCode_AccessKilledTabstop_OverwriteFirst(_VimTest): class PythonCode_AccessKilledTabstop_OverwriteFirst(_VimTest):
snippets = ("test", r"`!p snip.rv = t[2].upper()`${1:h${2:welt}o}`!p snip.rv = t[2].upper()`") snippets = (
keys = "test" + EX + "aaa" 'test',
wanted = "aaa" r"`!p snip.rv = t[2].upper()`${1:h${2:welt}o}`!p snip.rv = t[2].upper()`")
keys = 'test' + EX + 'aaa'
wanted = 'aaa'
class PythonVisual_NoVisualSelection_Ignore(_VimTest): class PythonVisual_NoVisualSelection_Ignore(_VimTest):
snippets = ("test", "h`!p snip.rv = snip.v.mode + snip.v.text`b") snippets = ('test', 'h`!p snip.rv = snip.v.mode + snip.v.text`b')
keys = "test" + EX + "abc" keys = 'test' + EX + 'abc'
wanted = "hbabc" wanted = 'hbabc'
class PythonVisual_SelectOneWord(_VimTest): class PythonVisual_SelectOneWord(_VimTest):
snippets = ("test", "h`!p snip.rv = snip.v.mode + snip.v.text`b") snippets = ('test', 'h`!p snip.rv = snip.v.mode + snip.v.text`b')
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX
wanted = "hvblablubb" wanted = 'hvblablubb'
class PythonVisual_LineSelect_Simple(_VimTest): class PythonVisual_LineSelect_Simple(_VimTest):
snippets = ("test", "h`!p snip.rv = snip.v.mode + snip.v.text`b") snippets = ('test', 'h`!p snip.rv = snip.v.mode + snip.v.text`b')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX
wanted = "hVhello\nnice\nworld\nb" wanted = 'hVhello\nnice\nworld\nb'
# Tests for https://bugs.launchpad.net/bugs/1259349 # Tests for https://bugs.launchpad.net/bugs/1259349
class Python_WeirdScoping_Error(_VimTest): class Python_WeirdScoping_Error(_VimTest):
snippets = ("test", "h`!p import re; snip.rv = '%i' % len([re.search for i in 'aiiia'])`b") snippets = (
keys = "test" + EX 'test',
wanted = "h5b" "h`!p import re; snip.rv = '%i' % len([re.search for i in 'aiiia'])`b")
keys = 'test' + EX
wanted = 'h5b'
# End: New Implementation #}}} # End: New Implementation #}}}
# End: PythonCode Interpolation #}}} # End: PythonCode Interpolation #}}}

View File

@ -2,29 +2,42 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# List Snippets {{{# # List Snippets {{{#
class _ListAllSnippets(_VimTest): class _ListAllSnippets(_VimTest):
snippets = ( ("testblah", "BLAAH", "Say BLAH"), snippets = (('testblah', 'BLAAH', 'Say BLAH'),
("test", "TEST ONE", "Say tst one"), ('test', 'TEST ONE', 'Say tst one'),
("aloha", "OHEEEE", "Say OHEE"), ('aloha', 'OHEEEE', 'Say OHEE'),
) )
class ListAllAvailable_NothingTyped_ExpectCorrectResult(_ListAllSnippets): class ListAllAvailable_NothingTyped_ExpectCorrectResult(_ListAllSnippets):
keys = "" + LS + "3\n" keys = '' + LS + '3\n'
wanted = "BLAAH" wanted = 'BLAAH'
class ListAllAvailable_SpaceInFront_ExpectCorrectResult(_ListAllSnippets): class ListAllAvailable_SpaceInFront_ExpectCorrectResult(_ListAllSnippets):
keys = " " + LS + "3\n" keys = ' ' + LS + '3\n'
wanted = " BLAAH" wanted = ' BLAAH'
class ListAllAvailable_BraceInFront_ExpectCorrectResult(_ListAllSnippets): class ListAllAvailable_BraceInFront_ExpectCorrectResult(_ListAllSnippets):
keys = "} " + LS + "3\n" keys = '} ' + LS + '3\n'
wanted = "} BLAAH" wanted = '} BLAAH'
class ListAllAvailable_testtyped_ExpectCorrectResult(_ListAllSnippets): class ListAllAvailable_testtyped_ExpectCorrectResult(_ListAllSnippets):
keys = "hallo test" + LS + "2\n" keys = 'hallo test' + LS + '2\n'
wanted = "hallo BLAAH" wanted = 'hallo BLAAH'
class ListAllAvailable_testtypedSecondOpt_ExpectCorrectResult(_ListAllSnippets):
keys = "hallo test" + LS + "1\n"
wanted = "hallo TEST ONE" class ListAllAvailable_testtypedSecondOpt_ExpectCorrectResult(
_ListAllSnippets):
keys = 'hallo test' + LS + '1\n'
wanted = 'hallo TEST ONE'
class ListAllAvailable_NonDefined_NoExpectionShouldBeRaised(_ListAllSnippets): class ListAllAvailable_NonDefined_NoExpectionShouldBeRaised(_ListAllSnippets):
keys = "hallo qualle" + LS + "Hi" keys = 'hallo qualle' + LS + 'Hi'
wanted = "hallo qualleHi" wanted = 'hallo qualleHi'
# End: List Snippets #}}} # End: List Snippets #}}}

View File

@ -2,192 +2,271 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Mirrors {{{# # Mirrors {{{#
class TextTabStopTextAfterTab_ExpectCorrectResult(_VimTest): class TextTabStopTextAfterTab_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 Hinten\n$1") snippets = ('test', '$1 Hinten\n$1')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo Hinten\nhallo" wanted = 'hallo Hinten\nhallo'
class TextTabStopTextBeforeTab_ExpectCorrectResult(_VimTest): class TextTabStopTextBeforeTab_ExpectCorrectResult(_VimTest):
snippets = ("test", "Vorne $1\n$1") snippets = ('test', 'Vorne $1\n$1')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "Vorne hallo\nhallo" wanted = 'Vorne hallo\nhallo'
class TextTabStopTextSurroundedTab_ExpectCorrectResult(_VimTest): class TextTabStopTextSurroundedTab_ExpectCorrectResult(_VimTest):
snippets = ("test", "Vorne $1 Hinten\n$1") snippets = ('test', 'Vorne $1 Hinten\n$1')
keys = "test" + EX + "hallo test" keys = 'test' + EX + 'hallo test'
wanted = "Vorne hallo test Hinten\nhallo test" wanted = 'Vorne hallo test Hinten\nhallo test'
class TextTabStopTextBeforeMirror_ExpectCorrectResult(_VimTest): class TextTabStopTextBeforeMirror_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\nVorne $1") snippets = ('test', '$1\nVorne $1')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo\nVorne hallo" wanted = 'hallo\nVorne hallo'
class TextTabStopAfterMirror_ExpectCorrectResult(_VimTest): class TextTabStopAfterMirror_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\n$1 Hinten") snippets = ('test', '$1\n$1 Hinten')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo\nhallo Hinten" wanted = 'hallo\nhallo Hinten'
class TextTabStopSurroundMirror_ExpectCorrectResult(_VimTest): class TextTabStopSurroundMirror_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\nVorne $1 Hinten") snippets = ('test', '$1\nVorne $1 Hinten')
keys = "test" + EX + "hallo welt" keys = 'test' + EX + 'hallo welt'
wanted = "hallo welt\nVorne hallo welt Hinten" wanted = 'hallo welt\nVorne hallo welt Hinten'
class TextTabStopAllSurrounded_ExpectCorrectResult(_VimTest): class TextTabStopAllSurrounded_ExpectCorrectResult(_VimTest):
snippets = ("test", "ObenVorne $1 ObenHinten\nVorne $1 Hinten") snippets = ('test', 'ObenVorne $1 ObenHinten\nVorne $1 Hinten')
keys = "test" + EX + "hallo welt" keys = 'test' + EX + 'hallo welt'
wanted = "ObenVorne hallo welt ObenHinten\nVorne hallo welt Hinten" wanted = 'ObenVorne hallo welt ObenHinten\nVorne hallo welt Hinten'
class MirrorBeforeTabstopLeave_ExpectCorrectResult(_VimTest): class MirrorBeforeTabstopLeave_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1:this is it} $1") snippets = ('test', '$1 ${1:this is it} $1')
keys = "test" + EX keys = 'test' + EX
wanted = "this is it this is it this is it" wanted = 'this is it this is it this is it'
class MirrorBeforeTabstopOverwrite_ExpectCorrectResult(_VimTest): class MirrorBeforeTabstopOverwrite_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1:this is it} $1") snippets = ('test', '$1 ${1:this is it} $1')
keys = "test" + EX + "a" keys = 'test' + EX + 'a'
wanted = "a a a" wanted = 'a a a'
class TextTabStopSimpleMirrorMultiline_ExpectCorrectResult(_VimTest): class TextTabStopSimpleMirrorMultiline_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\n$1") snippets = ('test', '$1\n$1')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo\nhallo" wanted = 'hallo\nhallo'
class SimpleMirrorMultilineMany_ExpectCorrectResult(_VimTest): class SimpleMirrorMultilineMany_ExpectCorrectResult(_VimTest):
snippets = ("test", " $1\n$1\na$1b\n$1\ntest $1 mich") snippets = ('test', ' $1\n$1\na$1b\n$1\ntest $1 mich')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = " hallo\nhallo\nahallob\nhallo\ntest hallo mich" wanted = ' hallo\nhallo\nahallob\nhallo\ntest hallo mich'
class MultilineTabStopSimpleMirrorMultiline_ExpectCorrectResult(_VimTest): class MultilineTabStopSimpleMirrorMultiline_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\n\n$1\n\n$1") snippets = ('test', '$1\n\n$1\n\n$1')
keys = "test" + EX + "hallo Du\nHi" keys = 'test' + EX + 'hallo Du\nHi'
wanted = "hallo Du\nHi\n\nhallo Du\nHi\n\nhallo Du\nHi" wanted = 'hallo Du\nHi\n\nhallo Du\nHi\n\nhallo Du\nHi'
class MultilineTabStopSimpleMirrorMultiline1_ExpectCorrectResult(_VimTest): class MultilineTabStopSimpleMirrorMultiline1_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\n$1\n$1") snippets = ('test', '$1\n$1\n$1')
keys = "test" + EX + "hallo Du\nHi" keys = 'test' + EX + 'hallo Du\nHi'
wanted = "hallo Du\nHi\nhallo Du\nHi\nhallo Du\nHi" wanted = 'hallo Du\nHi\nhallo Du\nHi\nhallo Du\nHi'
class MultilineTabStopSimpleMirrorDeleteInLine_ExpectCorrectResult(_VimTest): class MultilineTabStopSimpleMirrorDeleteInLine_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\n$1\n$1") snippets = ('test', '$1\n$1\n$1')
keys = "test" + EX + "hallo Du\nHi\b\bAch Blah" keys = 'test' + EX + 'hallo Du\nHi\b\bAch Blah'
wanted = "hallo Du\nAch Blah\nhallo Du\nAch Blah\nhallo Du\nAch Blah" wanted = 'hallo Du\nAch Blah\nhallo Du\nAch Blah\nhallo Du\nAch Blah'
class TextTabStopSimpleMirrorMultilineMirrorInFront_ECR(_VimTest): class TextTabStopSimpleMirrorMultilineMirrorInFront_ECR(_VimTest):
snippets = ("test", "$1\n${1:sometext}") snippets = ('test', '$1\n${1:sometext}')
keys = "test" + EX + "hallo\nagain" keys = 'test' + EX + 'hallo\nagain'
wanted = "hallo\nagain\nhallo\nagain" wanted = 'hallo\nagain\nhallo\nagain'
class SimpleMirrorDelete_ExpectCorrectResult(_VimTest): class SimpleMirrorDelete_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\n$1") snippets = ('test', '$1\n$1')
keys = "test" + EX + "hallo\b\b" keys = 'test' + EX + 'hallo\b\b'
wanted = "hal\nhal" wanted = 'hal\nhal'
class SimpleMirrorSameLine_ExpectCorrectResult(_VimTest): class SimpleMirrorSameLine_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 $1") snippets = ('test', '$1 $1')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo hallo" wanted = 'hallo hallo'
class SimpleMirrorSameLine_InText_ExpectCorrectResult(_VimTest): class SimpleMirrorSameLine_InText_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 $1") snippets = ('test', '$1 $1')
keys = "ups test blah" + ESC + "02f i" + EX + "hallo" keys = 'ups test blah' + ESC + '02f i' + EX + 'hallo'
wanted = "ups hallo hallo blah" wanted = 'ups hallo hallo blah'
class SimpleMirrorSameLineBeforeTabDefVal_ECR(_VimTest): class SimpleMirrorSameLineBeforeTabDefVal_ECR(_VimTest):
snippets = ("test", "$1 ${1:replace me}") snippets = ('test', '$1 ${1:replace me}')
keys = "test" + EX + "hallo foo" keys = 'test' + EX + 'hallo foo'
wanted = "hallo foo hallo foo" wanted = 'hallo foo hallo foo'
class SimpleMirrorSameLineBeforeTabDefVal_DelB4Typing_ECR(_VimTest): class SimpleMirrorSameLineBeforeTabDefVal_DelB4Typing_ECR(_VimTest):
snippets = ("test", "$1 ${1:replace me}") snippets = ('test', '$1 ${1:replace me}')
keys = "test" + EX + BS + "hallo foo" keys = 'test' + EX + BS + 'hallo foo'
wanted = "hallo foo hallo foo" wanted = 'hallo foo hallo foo'
class SimpleMirrorSameLineMany_ExpectCorrectResult(_VimTest): class SimpleMirrorSameLineMany_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 $1 $1 $1") snippets = ('test', '$1 $1 $1 $1')
keys = "test" + EX + "hallo du" keys = 'test' + EX + 'hallo du'
wanted = "hallo du hallo du hallo du hallo du" wanted = 'hallo du hallo du hallo du hallo du'
class SimpleMirrorSameLineManyMultiline_ExpectCorrectResult(_VimTest): class SimpleMirrorSameLineManyMultiline_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 $1 $1 $1") snippets = ('test', '$1 $1 $1 $1')
keys = "test" + EX + "hallo du\nwie gehts" keys = 'test' + EX + 'hallo du\nwie gehts'
wanted = "hallo du\nwie gehts hallo du\nwie gehts hallo du\nwie gehts" \ wanted = 'hallo du\nwie gehts hallo du\nwie gehts hallo du\nwie gehts' \
" hallo du\nwie gehts" ' hallo du\nwie gehts'
class SimpleMirrorDeleteSomeEnterSome_ExpectCorrectResult(_VimTest): class SimpleMirrorDeleteSomeEnterSome_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1\n$1") snippets = ('test', '$1\n$1')
keys = "test" + EX + "hallo\b\bhups" keys = 'test' + EX + 'hallo\b\bhups'
wanted = "halhups\nhalhups" wanted = 'halhups\nhalhups'
class SimpleTabstopWithDefaultSimpelType_ExpectCorrectResult(_VimTest): class SimpleTabstopWithDefaultSimpelType_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha ${1:defa}\n$1") snippets = ('test', 'ha ${1:defa}\n$1')
keys = "test" + EX + "world" keys = 'test' + EX + 'world'
wanted = "ha world\nworld" wanted = 'ha world\nworld'
class SimpleTabstopWithDefaultComplexType_ExpectCorrectResult(_VimTest): class SimpleTabstopWithDefaultComplexType_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha ${1:default value} $1\nanother: $1 mirror") snippets = ('test', 'ha ${1:default value} $1\nanother: $1 mirror')
keys = "test" + EX + "world" keys = 'test' + EX + 'world'
wanted = "ha world world\nanother: world mirror" wanted = 'ha world world\nanother: world mirror'
class SimpleTabstopWithDefaultSimpelKeep_ExpectCorrectResult(_VimTest): class SimpleTabstopWithDefaultSimpelKeep_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha ${1:defa}\n$1") snippets = ('test', 'ha ${1:defa}\n$1')
keys = "test" + EX keys = 'test' + EX
wanted = "ha defa\ndefa" wanted = 'ha defa\ndefa'
class SimpleTabstopWithDefaultComplexKeep_ExpectCorrectResult(_VimTest): class SimpleTabstopWithDefaultComplexKeep_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha ${1:default value} $1\nanother: $1 mirror") snippets = ('test', 'ha ${1:default value} $1\nanother: $1 mirror')
keys = "test" + EX keys = 'test' + EX
wanted = "ha default value default value\nanother: default value mirror" wanted = 'ha default value default value\nanother: default value mirror'
class TabstopWithMirrorManyFromAll_ExpectCorrectResult(_VimTest): class TabstopWithMirrorManyFromAll_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha $5 ${1:blub} $4 $0 ${2:$1.h} $1 $3 ${4:More}") snippets = ('test', 'ha $5 ${1:blub} $4 $0 ${2:$1.h} $1 $3 ${4:More}')
keys = "test" + EX + "hi" + JF + "hu" + JF + "hub" + JF + "hulla" + \ keys = 'test' + EX + 'hi' + JF + 'hu' + JF + 'hub' + JF + 'hulla' + \
JF + "blah" + JF + "end" JF + 'blah' + JF + 'end'
wanted = "ha blah hi hulla end hu hi hub hulla" wanted = 'ha blah hi hulla end hu hi hub hulla'
class TabstopWithMirrorInDefaultNoType_ExpectCorrectResult(_VimTest): class TabstopWithMirrorInDefaultNoType_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha ${1:blub} ${2:$1.h}") snippets = ('test', 'ha ${1:blub} ${2:$1.h}')
keys = "test" + EX keys = 'test' + EX
wanted = "ha blub blub.h" wanted = 'ha blub blub.h'
class TabstopWithMirrorInDefaultNoType1_ExpectCorrectResult(_VimTest): class TabstopWithMirrorInDefaultNoType1_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha ${1:blub} ${2:$1}") snippets = ('test', 'ha ${1:blub} ${2:$1}')
keys = "test" + EX keys = 'test' + EX
wanted = "ha blub blub" wanted = 'ha blub blub'
class TabstopWithMirrorInDefaultTwiceAndExtra_ExpectCorrectResult(_VimTest): class TabstopWithMirrorInDefaultTwiceAndExtra_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha $1 ${2:$1.h $1.c}\ntest $1") snippets = ('test', 'ha $1 ${2:$1.h $1.c}\ntest $1')
keys = "test" + EX + "stdin" keys = 'test' + EX + 'stdin'
wanted = "ha stdin stdin.h stdin.c\ntest stdin" wanted = 'ha stdin stdin.h stdin.c\ntest stdin'
class TabstopWithMirrorInDefaultMultipleLeave_ExpectCorrectResult(_VimTest): class TabstopWithMirrorInDefaultMultipleLeave_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha $1 ${2:snip} ${3:$1.h $2}") snippets = ('test', 'ha $1 ${2:snip} ${3:$1.h $2}')
keys = "test" + EX + "stdin" keys = 'test' + EX + 'stdin'
wanted = "ha stdin snip stdin.h snip" wanted = 'ha stdin snip stdin.h snip'
class TabstopWithMirrorInDefaultMultipleOverwrite_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha $1 ${2:snip} ${3:$1.h $2}")
keys = "test" + EX + "stdin" + JF + "do snap" class TabstopWithMirrorInDefaultMultipleOverwrite_ExpectCorrectResult(
wanted = "ha stdin do snap stdin.h do snap" _VimTest):
snippets = ('test', 'ha $1 ${2:snip} ${3:$1.h $2}')
keys = 'test' + EX + 'stdin' + JF + 'do snap'
wanted = 'ha stdin do snap stdin.h do snap'
class TabstopWithMirrorInDefaultOverwrite_ExpectCorrectResult(_VimTest): class TabstopWithMirrorInDefaultOverwrite_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha $1 ${2:$1.h}") snippets = ('test', 'ha $1 ${2:$1.h}')
keys = "test" + EX + "stdin" + JF + "overwritten" keys = 'test' + EX + 'stdin' + JF + 'overwritten'
wanted = "ha stdin overwritten" wanted = 'ha stdin overwritten'
class TabstopWithMirrorInDefaultOverwrite1_ExpectCorrectResult(_VimTest): class TabstopWithMirrorInDefaultOverwrite1_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha $1 ${2:$1}") snippets = ('test', 'ha $1 ${2:$1}')
keys = "test" + EX + "stdin" + JF + "overwritten" keys = 'test' + EX + 'stdin' + JF + 'overwritten'
wanted = "ha stdin overwritten" wanted = 'ha stdin overwritten'
class TabstopWithMirrorInDefaultNoOverwrite1_ExpectCorrectResult(_VimTest): class TabstopWithMirrorInDefaultNoOverwrite1_ExpectCorrectResult(_VimTest):
snippets = ("test", "ha $1 ${2:$1}") snippets = ('test', 'ha $1 ${2:$1}')
keys = "test" + EX + "stdin" + JF + JF + "end" keys = 'test' + EX + 'stdin' + JF + JF + 'end'
wanted = "ha stdin stdinend" wanted = 'ha stdin stdinend'
class MirrorRealLifeExample_ExpectCorrectResult(_VimTest): class MirrorRealLifeExample_ExpectCorrectResult(_VimTest):
snippets = ( snippets = (
("for", "for(size_t ${2:i} = 0; $2 < ${1:count}; ${3:++$2})" \ ('for', 'for(size_t ${2:i} = 0; $2 < ${1:count}; ${3:++$2})'
"\n{\n\t${0:/* code */}\n}"), '\n{\n\t${0:/* code */}\n}'),
) )
keys ="for" + EX + "100" + JF + "avar\b\b\b\ba_variable" + JF + \ keys = 'for' + EX + '100' + JF + 'avar\b\b\b\ba_variable' + JF + \
"a_variable *= 2" + JF + "// do nothing" 'a_variable *= 2' + JF + '// do nothing'
wanted = """for(size_t a_variable = 0; a_variable < 100; a_variable *= 2) wanted = """for(size_t a_variable = 0; a_variable < 100; a_variable *= 2)
{ {
\t// do nothing \t// do nothing
}""" }"""
class Mirror_TestKill_InsertBefore_NoKill(_VimTest): class Mirror_TestKill_InsertBefore_NoKill(_VimTest):
snippets = "test", "$1 $1_" snippets = 'test', '$1 $1_'
keys = "hallo test" + EX + "auch" + ESC + "wihi" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'auch' + ESC + \
wanted = "hallo noauch hinoauch_end" 'wihi' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noauch hinoauch_end'
class Mirror_TestKill_InsertAfter_NoKill(_VimTest): class Mirror_TestKill_InsertAfter_NoKill(_VimTest):
snippets = "test", "$1 $1_" snippets = 'test', '$1 $1_'
keys = "hallo test" + EX + "auch" + ESC + "eiab" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'auch' + ESC + \
wanted = "hallo noauch noauchab_end" 'eiab' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noauch noauchab_end'
class Mirror_TestKill_InsertBeginning_Kill(_VimTest): class Mirror_TestKill_InsertBeginning_Kill(_VimTest):
snippets = "test", "$1 $1_" snippets = 'test', '$1 $1_'
keys = "hallo test" + EX + "auch" + ESC + "wahi" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'auch' + ESC + \
wanted = "hallo noauch ahiuch_end" 'wahi' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noauch ahiuch_end'
class Mirror_TestKill_InsertEnd_Kill(_VimTest): class Mirror_TestKill_InsertEnd_Kill(_VimTest):
snippets = "test", "$1 $1_" snippets = 'test', '$1 $1_'
keys = "hallo test" + EX + "auch" + ESC + "ehihi" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'auch' + ESC + \
wanted = "hallo noauch auchih_end" 'ehihi' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noauch auchih_end'
class Mirror_TestKillTabstop_Kill(_VimTest): class Mirror_TestKillTabstop_Kill(_VimTest):
snippets = "test", "welt${1:welt${2:welt}welt} $2" snippets = 'test', 'welt${1:welt${2:welt}welt} $2'
keys = "hallo test" + EX + "elt" keys = 'hallo test' + EX + 'elt'
wanted = "hallo weltelt " wanted = 'hallo weltelt '
# End: Mirrors #}}} # End: Mirrors #}}}

View File

@ -2,59 +2,82 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Cursor Movement {{{# # Cursor Movement {{{#
class CursorMovement_Multiline_ECR(_VimTest): class CursorMovement_Multiline_ECR(_VimTest):
snippets = ("test", r"$1 ${1:a tab}") snippets = ('test', r"$1 ${1:a tab}")
keys = "test" + EX + "this is something\nvery nice\nnot" + JF + "more text" keys = 'test' + EX + 'this is something\nvery nice\nnot' + JF + 'more text'
wanted = "this is something\nvery nice\nnot " \ wanted = 'this is something\nvery nice\nnot ' \
"this is something\nvery nice\nnotmore text" 'this is something\nvery nice\nnotmore text'
class CursorMovement_BS_InEditMode(_VimTest): class CursorMovement_BS_InEditMode(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set backspace=eol,indent,start") vim_config.append('set backspace=eol,indent,start')
snippets = ("<trh", "<tr>\n\t<th>$1</th>\n\t$2\n</tr>\n$3") snippets = ('<trh', '<tr>\n\t<th>$1</th>\n\t$2\n</tr>\n$3')
keys = "<trh" + EX + "blah" + JF + BS + BS + JF + "end" keys = '<trh' + EX + 'blah' + JF + BS + BS + JF + 'end'
wanted = "<tr>\n\t<th>blah</th>\n</tr>\nend" wanted = '<tr>\n\t<th>blah</th>\n</tr>\nend'
# End: Cursor Movement #}}} # End: Cursor Movement #}}}
# Insert Mode Moving {{{# # Insert Mode Moving {{{#
class IMMoving_CursorsKeys_ECR(_VimTest):
snippets = ("test", "${1:Some}")
keys = "test" + EX + "text" + 3*ARR_U + 6*ARR_D
wanted = "text"
class IMMoving_AcceptInputWhenMoved_ECR(_VimTest):
snippets = ("test", r"$1 ${1:a tab}")
keys = "test" + EX + "this" + 2*ARR_L + "hallo\nwelt"
wanted = "thhallo\nweltis thhallo\nweltis"
class IMMoving_NoExiting_ECR(_VimTest):
snippets = ("test", r"$1 ${2:a tab} ${1:Tab}")
keys = "hello test this" + ESC + "02f i" + EX + "tab" + 7*ARR_L + \
JF + "hallo"
wanted = "hello tab hallo tab this"
class IMMoving_NoExitingEventAtEnd_ECR(_VimTest):
snippets = ("test", r"$1 ${2:a tab} ${1:Tab}")
keys = "hello test this" + ESC + "02f i" + EX + "tab" + JF + "hallo"
wanted = "hello tab hallo tab this"
class IMMoving_ExitWhenOutsideRight_ECR(_VimTest):
snippets = ("test", r"$1 ${2:blub} ${1:Tab}")
keys = "hello test this" + ESC + "02f i" + EX + "tab" + ARR_R + JF + "hallo"
wanted = "hello tab blub tab " + JF + "hallothis"
class IMMoving_NotExitingWhenBarelyOutsideLeft_ECR(_VimTest):
snippets = ("test", r"${1:Hi} ${2:blub}")
keys = "hello test this" + ESC + "02f i" + EX + "tab" + 3*ARR_L + \
JF + "hallo"
wanted = "hello tab hallo this"
class IMMoving_ExitWhenOutsideLeft_ECR(_VimTest):
snippets = ("test", r"${1:Hi} ${2:blub}")
keys = "hello test this" + ESC + "02f i" + EX + "tab" + 4*ARR_L + \
JF + "hallo"
wanted = "hello" + JF + "hallo tab blub this"
class IMMoving_ExitWhenOutsideAbove_ECR(_VimTest):
snippets = ("test", "${1:Hi}\n${2:blub}")
keys = "hello test this" + ESC + "02f i" + EX + "tab" + 1*ARR_U + "\n" + JF + \
"hallo"
wanted = JF + "hallo\nhello tab\nblub this"
class IMMoving_ExitWhenOutsideBelow_ECR(_VimTest):
snippets = ("test", "${1:Hi}\n${2:blub}")
keys = "hello test this" + ESC + "02f i" + EX + "tab" + 2*ARR_D + JF + \
"testhallo\n"
wanted = "hello tab\nblub this\n" + JF + "testhallo"
# End: Insert Mode Moving #}}}
class IMMoving_CursorsKeys_ECR(_VimTest):
snippets = ('test', '${1:Some}')
keys = 'test' + EX + 'text' + 3 * ARR_U + 6 * ARR_D
wanted = 'text'
class IMMoving_AcceptInputWhenMoved_ECR(_VimTest):
snippets = ('test', r"$1 ${1:a tab}")
keys = 'test' + EX + 'this' + 2 * ARR_L + 'hallo\nwelt'
wanted = 'thhallo\nweltis thhallo\nweltis'
class IMMoving_NoExiting_ECR(_VimTest):
snippets = ('test', r"$1 ${2:a tab} ${1:Tab}")
keys = 'hello test this' + ESC + '02f i' + EX + 'tab' + 7 * ARR_L + \
JF + 'hallo'
wanted = 'hello tab hallo tab this'
class IMMoving_NoExitingEventAtEnd_ECR(_VimTest):
snippets = ('test', r"$1 ${2:a tab} ${1:Tab}")
keys = 'hello test this' + ESC + '02f i' + EX + 'tab' + JF + 'hallo'
wanted = 'hello tab hallo tab this'
class IMMoving_ExitWhenOutsideRight_ECR(_VimTest):
snippets = ('test', r"$1 ${2:blub} ${1:Tab}")
keys = 'hello test this' + ESC + '02f i' + \
EX + 'tab' + ARR_R + JF + 'hallo'
wanted = 'hello tab blub tab ' + JF + 'hallothis'
class IMMoving_NotExitingWhenBarelyOutsideLeft_ECR(_VimTest):
snippets = ('test', r"${1:Hi} ${2:blub}")
keys = 'hello test this' + ESC + '02f i' + EX + 'tab' + 3 * ARR_L + \
JF + 'hallo'
wanted = 'hello tab hallo this'
class IMMoving_ExitWhenOutsideLeft_ECR(_VimTest):
snippets = ('test', r"${1:Hi} ${2:blub}")
keys = 'hello test this' + ESC + '02f i' + EX + 'tab' + 4 * ARR_L + \
JF + 'hallo'
wanted = 'hello' + JF + 'hallo tab blub this'
class IMMoving_ExitWhenOutsideAbove_ECR(_VimTest):
snippets = ('test', '${1:Hi}\n${2:blub}')
keys = 'hello test this' + ESC + '02f i' + EX + 'tab' + 1 * ARR_U + '\n' + JF + \
'hallo'
wanted = JF + 'hallo\nhello tab\nblub this'
class IMMoving_ExitWhenOutsideBelow_ECR(_VimTest):
snippets = ('test', '${1:Hi}\n${2:blub}')
keys = 'hello test this' + ESC + '02f i' + EX + 'tab' + 2 * ARR_D + JF + \
'testhallo\n'
wanted = 'hello tab\nblub this\n' + JF + 'testhallo'
# End: Insert Mode Moving #}}}

View File

@ -2,58 +2,71 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Selecting Between Same Triggers {{{# # Selecting Between Same Triggers {{{#
class _MultipleMatches(_VimTest): class _MultipleMatches(_VimTest):
snippets = ( ("test", "Case1", "This is Case 1"), snippets = (('test', 'Case1', 'This is Case 1'),
("test", "Case2", "This is Case 2") ) ('test', 'Case2', 'This is Case 2'))
class Multiple_SimpleCaseSelectFirst_ECR(_MultipleMatches): class Multiple_SimpleCaseSelectFirst_ECR(_MultipleMatches):
keys = "test" + EX + "1\n" keys = 'test' + EX + '1\n'
wanted = "Case1" wanted = 'Case1'
class Multiple_SimpleCaseSelectSecond_ECR(_MultipleMatches): class Multiple_SimpleCaseSelectSecond_ECR(_MultipleMatches):
keys = "test" + EX + "2\n" keys = 'test' + EX + '2\n'
wanted = "Case2" wanted = 'Case2'
class Multiple_SimpleCaseSelectTooHigh_ESelectLast(_MultipleMatches): class Multiple_SimpleCaseSelectTooHigh_ESelectLast(_MultipleMatches):
keys = "test" + EX + "5\n" keys = 'test' + EX + '5\n'
wanted = "Case2" wanted = 'Case2'
class Multiple_SimpleCaseSelectZero_EEscape(_MultipleMatches): class Multiple_SimpleCaseSelectZero_EEscape(_MultipleMatches):
keys = "test" + EX + "0\n" + "hi" keys = 'test' + EX + '0\n' + 'hi'
wanted = "testhi" wanted = 'testhi'
class Multiple_SimpleCaseEscapeOut_ECR(_MultipleMatches): class Multiple_SimpleCaseEscapeOut_ECR(_MultipleMatches):
keys = "test" + EX + ESC + "hi" keys = 'test' + EX + ESC + 'hi'
wanted = "testhi" wanted = 'testhi'
class Multiple_ManySnippetsOneTrigger_ECR(_VimTest): class Multiple_ManySnippetsOneTrigger_ECR(_VimTest):
# Snippet definition {{{# # Snippet definition {{{#
snippets = ( snippets = (
("test", "Case1", "This is Case 1"), ('test', 'Case1', 'This is Case 1'),
("test", "Case2", "This is Case 2"), ('test', 'Case2', 'This is Case 2'),
("test", "Case3", "This is Case 3"), ('test', 'Case3', 'This is Case 3'),
("test", "Case4", "This is Case 4"), ('test', 'Case4', 'This is Case 4'),
("test", "Case5", "This is Case 5"), ('test', 'Case5', 'This is Case 5'),
("test", "Case6", "This is Case 6"), ('test', 'Case6', 'This is Case 6'),
("test", "Case7", "This is Case 7"), ('test', 'Case7', 'This is Case 7'),
("test", "Case8", "This is Case 8"), ('test', 'Case8', 'This is Case 8'),
("test", "Case9", "This is Case 9"), ('test', 'Case9', 'This is Case 9'),
("test", "Case10", "This is Case 10"), ('test', 'Case10', 'This is Case 10'),
("test", "Case11", "This is Case 11"), ('test', 'Case11', 'This is Case 11'),
("test", "Case12", "This is Case 12"), ('test', 'Case12', 'This is Case 12'),
("test", "Case13", "This is Case 13"), ('test', 'Case13', 'This is Case 13'),
("test", "Case14", "This is Case 14"), ('test', 'Case14', 'This is Case 14'),
("test", "Case15", "This is Case 15"), ('test', 'Case15', 'This is Case 15'),
("test", "Case16", "This is Case 16"), ('test', 'Case16', 'This is Case 16'),
("test", "Case17", "This is Case 17"), ('test', 'Case17', 'This is Case 17'),
("test", "Case18", "This is Case 18"), ('test', 'Case18', 'This is Case 18'),
("test", "Case19", "This is Case 19"), ('test', 'Case19', 'This is Case 19'),
("test", "Case20", "This is Case 20"), ('test', 'Case20', 'This is Case 20'),
("test", "Case21", "This is Case 21"), ('test', 'Case21', 'This is Case 21'),
("test", "Case22", "This is Case 22"), ('test', 'Case22', 'This is Case 22'),
("test", "Case23", "This is Case 23"), ('test', 'Case23', 'This is Case 23'),
("test", "Case24", "This is Case 24"), ('test', 'Case24', 'This is Case 24'),
("test", "Case25", "This is Case 25"), ('test', 'Case25', 'This is Case 25'),
("test", "Case26", "This is Case 26"), ('test', 'Case26', 'This is Case 26'),
("test", "Case27", "This is Case 27"), ('test', 'Case27', 'This is Case 27'),
("test", "Case28", "This is Case 28"), ('test', 'Case28', 'This is Case 28'),
("test", "Case29", "This is Case 29"), ('test', 'Case29', 'This is Case 29'),
) #}}} ) # }}}
keys = "test" + EX + " " + ESC + ESC + "ahi" keys = 'test' + EX + ' ' + ESC + ESC + 'ahi'
wanted = "testhi" wanted = 'testhi'
# End: Selecting Between Same Triggers #}}} # End: Selecting Between Same Triggers #}}}

View File

@ -1,69 +1,77 @@
from test.vim_test_case import VimTestCase as _VimTest from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
class ParseSnippets_SimpleSnippet(_VimTest): class ParseSnippets_SimpleSnippet(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet testsnip "Test Snippet" b! snippet testsnip "Test Snippet" b!
This is a test snippet! This is a test snippet!
endsnippet endsnippet
"""} """}
keys = "testsnip" + EX keys = 'testsnip' + EX
wanted = "This is a test snippet!" wanted = 'This is a test snippet!'
class ParseSnippets_MissingEndSnippet(_VimTest): class ParseSnippets_MissingEndSnippet(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet testsnip "Test Snippet" b! snippet testsnip "Test Snippet" b!
This is a test snippet! This is a test snippet!
"""} """}
keys = "testsnip" + EX keys = 'testsnip' + EX
wanted = "testsnip" + EX wanted = 'testsnip' + EX
expected_error = r"Missing 'endsnippet' for 'testsnip' in \S+:4" expected_error = r"Missing 'endsnippet' for 'testsnip' in \S+:4"
class ParseSnippets_UnknownDirective(_VimTest): class ParseSnippets_UnknownDirective(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
unknown directive unknown directive
"""} """}
keys = "testsnip" + EX keys = 'testsnip' + EX
wanted = "testsnip" + EX wanted = 'testsnip' + EX
expected_error = r"Invalid line 'unknown directive' in \S+:2" expected_error = r"Invalid line 'unknown directive' in \S+:2"
class ParseSnippets_InvalidPriorityLine(_VimTest): class ParseSnippets_InvalidPriorityLine(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
priority - 50 priority - 50
"""} """}
keys = "testsnip" + EX keys = 'testsnip' + EX
wanted = "testsnip" + EX wanted = 'testsnip' + EX
expected_error = r"Invalid priority '- 50' in \S+:2" expected_error = r"Invalid priority '- 50' in \S+:2"
class ParseSnippets_InvalidPriorityLine1(_VimTest): class ParseSnippets_InvalidPriorityLine1(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
priority priority
"""} """}
keys = "testsnip" + EX keys = 'testsnip' + EX
wanted = "testsnip" + EX wanted = 'testsnip' + EX
expected_error = r"Invalid priority '' in \S+:2" expected_error = r"Invalid priority '' in \S+:2"
class ParseSnippets_ExtendsWithoutFiletype(_VimTest): class ParseSnippets_ExtendsWithoutFiletype(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
extends extends
"""} """}
keys = "testsnip" + EX keys = 'testsnip' + EX
wanted = "testsnip" + EX wanted = 'testsnip' + EX
expected_error = r"'extends' without file types in \S+:2" expected_error = r"'extends' without file types in \S+:2"
class ParseSnippets_ClearAll(_VimTest): class ParseSnippets_ClearAll(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet testsnip "Test snippet" snippet testsnip "Test snippet"
This is a test. This is a test.
endsnippet endsnippet
clearsnippets clearsnippets
"""} """}
keys = "testsnip" + EX keys = 'testsnip' + EX
wanted = "testsnip" + EX wanted = 'testsnip' + EX
class ParseSnippets_ClearOne(_VimTest): class ParseSnippets_ClearOne(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
clearsnippets toclear clearsnippets toclear
snippet testsnip "Test snippet" snippet testsnip "Test snippet"
@ -74,11 +82,12 @@ class ParseSnippets_ClearOne(_VimTest):
Do not expand. Do not expand.
endsnippet endsnippet
"""} """}
keys = "toclear" + EX + "\n" + "testsnip" + EX keys = 'toclear' + EX + '\n' + 'testsnip' + EX
wanted = "toclear" + EX + "\n" + "This is a test." wanted = 'toclear' + EX + '\n' + 'This is a test.'
class ParseSnippets_ClearTwo(_VimTest): class ParseSnippets_ClearTwo(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
clearsnippets testsnip toclear clearsnippets testsnip toclear
snippet testsnip "Test snippet" snippet testsnip "Test snippet"
@ -89,12 +98,12 @@ class ParseSnippets_ClearTwo(_VimTest):
Do not expand. Do not expand.
endsnippet endsnippet
"""} """}
keys = "toclear" + EX + "\n" + "testsnip" + EX keys = 'toclear' + EX + '\n' + 'testsnip' + EX
wanted = "toclear" + EX + "\n" + "testsnip" + EX wanted = 'toclear' + EX + '\n' + 'testsnip' + EX
class _ParseSnippets_MultiWord(_VimTest): class _ParseSnippets_MultiWord(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet /test snip/ snippet /test snip/
This is a test. This is a test.
endsnippet endsnippet
@ -107,18 +116,25 @@ class _ParseSnippets_MultiWord(_VimTest):
This is yet another test. This is yet another test.
endsnippet endsnippet
"""} """}
class ParseSnippets_MultiWord_Simple(_ParseSnippets_MultiWord): class ParseSnippets_MultiWord_Simple(_ParseSnippets_MultiWord):
keys = "test snip" + EX keys = 'test snip' + EX
wanted = "This is a test." wanted = 'This is a test.'
class ParseSnippets_MultiWord_Description(_ParseSnippets_MultiWord): class ParseSnippets_MultiWord_Description(_ParseSnippets_MultiWord):
keys = "snip test" + EX keys = 'snip test' + EX
wanted = "This is another test." wanted = 'This is another test.'
class ParseSnippets_MultiWord_Description_Option(_ParseSnippets_MultiWord): class ParseSnippets_MultiWord_Description_Option(_ParseSnippets_MultiWord):
keys = "snippet test" + EX keys = 'snippet test' + EX
wanted = "This is yet another test." wanted = 'This is yet another test.'
class _ParseSnippets_MultiWord_RE(_VimTest): class _ParseSnippets_MultiWord_RE(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet /[d-f]+/ "" r snippet /[d-f]+/ "" r
az test az test
endsnippet endsnippet
@ -131,55 +147,67 @@ class _ParseSnippets_MultiWord_RE(_VimTest):
re-test re-test
endsnippet endsnippet
"""} """}
class ParseSnippets_MultiWord_RE1(_ParseSnippets_MultiWord_RE): class ParseSnippets_MultiWord_RE1(_ParseSnippets_MultiWord_RE):
keys = "abc def" + EX keys = 'abc def' + EX
wanted = "abc az test" wanted = 'abc az test'
class ParseSnippets_MultiWord_RE2(_ParseSnippets_MultiWord_RE): class ParseSnippets_MultiWord_RE2(_ParseSnippets_MultiWord_RE):
keys = "foo" + EX + " bar" + EX + "\nbar" + EX keys = 'foo' + EX + ' bar' + EX + '\nbar' + EX
wanted = "foo-bar test bar\t\nfoo-bar test" wanted = 'foo-bar test bar\t\nfoo-bar test'
class ParseSnippets_MultiWord_RE3(_ParseSnippets_MultiWord_RE): class ParseSnippets_MultiWord_RE3(_ParseSnippets_MultiWord_RE):
keys = "test test test" + EX keys = 'test test test' + EX
wanted = "re-test" wanted = 're-test'
class ParseSnippets_MultiWord_Quotes(_VimTest): class ParseSnippets_MultiWord_Quotes(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet "test snip" snippet "test snip"
This is a test. This is a test.
endsnippet endsnippet
"""} """}
keys = "test snip" + EX keys = 'test snip' + EX
wanted = "This is a test." wanted = 'This is a test.'
class ParseSnippets_MultiWord_WithQuotes(_VimTest): class ParseSnippets_MultiWord_WithQuotes(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet !"test snip"! snippet !"test snip"!
This is a test. This is a test.
endsnippet endsnippet
"""} """}
keys = '"test snip"' + EX keys = '"test snip"' + EX
wanted = "This is a test." wanted = 'This is a test.'
class ParseSnippets_MultiWord_NoContainer(_VimTest): class ParseSnippets_MultiWord_NoContainer(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet test snip snippet test snip
This is a test. This is a test.
endsnippet endsnippet
"""} """}
keys = "test snip" + EX keys = 'test snip' + EX
wanted = keys wanted = keys
expected_error = "Invalid multiword trigger: 'test snip' in \S+:2" expected_error = "Invalid multiword trigger: 'test snip' in \S+:2"
class ParseSnippets_MultiWord_UnmatchedContainer(_VimTest): class ParseSnippets_MultiWord_UnmatchedContainer(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet !inv snip/ snippet !inv snip/
This is a test. This is a test.
endsnippet endsnippet
"""} """}
keys = "inv snip" + EX keys = 'inv snip' + EX
wanted = keys wanted = keys
expected_error = "Invalid multiword trigger: '!inv snip/' in \S+:2" expected_error = "Invalid multiword trigger: '!inv snip/' in \S+:2"
class ParseSnippets_Global_Python(_VimTest): class ParseSnippets_Global_Python(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
global !p global !p
def tex(ins): def tex(ins):
return "a " + ins + " b" return "a " + ins + " b"
@ -193,11 +221,12 @@ class ParseSnippets_Global_Python(_VimTest):
x `!p snip.rv = tex("jon")` y x `!p snip.rv = tex("jon")` y
endsnippet endsnippet
"""} """}
keys = "ab" + EX + "\nac" + EX keys = 'ab' + EX + '\nac' + EX
wanted = "x a bob b y\nx a jon b y" wanted = 'x a bob b y\nx a jon b y'
class ParseSnippets_Global_Local_Python(_VimTest): class ParseSnippets_Global_Local_Python(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
global !p global !p
def tex(ins): def tex(ins):
return "a " + ins + " b" return "a " + ins + " b"
@ -208,5 +237,5 @@ x `!p first = tex("bob")
snip.rv = "first"` `!p snip.rv = first` y snip.rv = "first"` `!p snip.rv = first` y
endsnippet endsnippet
"""} """}
keys = "ab" + EX keys = 'ab' + EX
wanted = "x first a bob b y" wanted = 'x first a bob b y'

View File

@ -3,11 +3,12 @@ import sys
from test.vim_test_case import VimTestCase as _VimTest from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
PYTHON3 = sys.version_info >= (3,0) PYTHON3 = sys.version_info >= (3, 0)
def python3(): def python3():
if PYTHON3: if PYTHON3:
return "Test does not work on python3." return 'Test does not work on python3.'
# Plugin: YouCompleteMe {{{# # Plugin: YouCompleteMe {{{#
# TODO(sirver): disabled because it fails right now. # TODO(sirver): disabled because it fails right now.
@ -15,9 +16,9 @@ def python3():
# def skip_if(self): # def skip_if(self):
# r = python3() # r = python3()
# if r: # if r:
# return r # return r
# if "7.4" not in self.version: # if "7.4" not in self.version:
# return "Needs Vim 7.4." # return "Needs Vim 7.4."
# plugins = ["Valloric/YouCompleteMe"] # plugins = ["Valloric/YouCompleteMe"]
# snippets = ("superlongtrigger", "Hello") # snippets = ("superlongtrigger", "Hello")
# keys = "superlo\ty" # keys = "superlo\ty"
@ -34,15 +35,18 @@ def python3():
# time.sleep(1) # time.sleep(1)
# End: Plugin: YouCompleteMe #}}} # End: Plugin: YouCompleteMe #}}}
# Plugin: Neocomplete {{{# # Plugin: Neocomplete {{{#
class Plugin_Neocomplete_BugTest(_VimTest): class Plugin_Neocomplete_BugTest(_VimTest):
# Test for https://github.com/SirVer/ultisnips/issues/228 # Test for https://github.com/SirVer/ultisnips/issues/228
def skip_if(self): def skip_if(self):
if "+lua" not in self.version: if '+lua' not in self.version:
return "Needs +lua" return 'Needs +lua'
plugins = ["Shougo/neocomplete.vim"] plugins = ['Shougo/neocomplete.vim']
snippets = ("t", "Hello", "", "w") snippets = ('t', 'Hello', '', 'w')
keys = "iab\\ t" + EX keys = 'iab\\ t' + EX
wanted = "iab\\ Hello" wanted = 'iab\\ Hello'
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append(r'set iskeyword+=\\ ') vim_config.append(r'set iskeyword+=\\ ')
@ -53,34 +57,39 @@ class Plugin_Neocomplete_BugTest(_VimTest):
vim_config.append('let g:neocomplete#enable_refresh_always = 1') vim_config.append('let g:neocomplete#enable_refresh_always = 1')
# End: Plugin: Neocomplete #}}} # End: Plugin: Neocomplete #}}}
# Plugin: unite {{{# # Plugin: unite {{{#
class Plugin_unite_BugTest(_VimTest): class Plugin_unite_BugTest(_VimTest):
plugins = ["Shougo/unite.vim"] plugins = ['Shougo/unite.vim']
snippets = ("t", "Hello", "", "w") snippets = ('t', 'Hello', '', 'w')
keys = "iab\\ t=UltiSnipsCallUnite()\n" keys = 'iab\\ t=UltiSnipsCallUnite()\n'
wanted = "iab\\ Hello " wanted = 'iab\\ Hello '
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append(r'set iskeyword+=\\ ') vim_config.append(r'set iskeyword+=\\ ')
vim_config.append('function! UltiSnipsCallUnite()') vim_config.append('function! UltiSnipsCallUnite()')
vim_config.append(' Unite -start-insert -winheight=100 -immediately -no-empty ultisnips') vim_config.append(
' Unite -start-insert -winheight=100 -immediately -no-empty ultisnips')
vim_config.append(' return ""') vim_config.append(' return ""')
vim_config.append('endfunction') vim_config.append('endfunction')
# End: Plugin: unite #}}} # End: Plugin: unite #}}}
# Plugin: Supertab {{{# # Plugin: Supertab {{{#
class Plugin_SuperTab_SimpleTest(_VimTest): class Plugin_SuperTab_SimpleTest(_VimTest):
plugins = ["ervandew/supertab"] plugins = ['ervandew/supertab']
snippets = ("long", "Hello", "", "w") snippets = ('long', 'Hello', '', 'w')
keys = ( "longtextlongtext\n" + keys = ('longtextlongtext\n' +
"longt" + EX + "\n" + # Should complete word 'longt' + EX + '\n' + # Should complete word
"long" + EX ) # Should expand 'long' + EX) # Should expand
wanted = "longtextlongtext\nlongtextlongtext\nHello" wanted = 'longtextlongtext\nlongtextlongtext\nHello'
def _before_test(self): def _before_test(self):
# Make sure that UltiSnips has the keymap # Make sure that UltiSnips has the keymap
self.vim.send(":call UltiSnips#map_keys#MapKeys()\n") self.vim.send(':call UltiSnips#map_keys#MapKeys()\n')
def _extra_options_post_init(self, vim_config): def _extra_options_post_init(self, vim_config):
assert EX == "\t" # Otherwise this test needs changing. assert EX == '\t' # Otherwise this test needs changing.
vim_config.append('let g:SuperTabDefaultCompletionType = "<c-p>"') vim_config.append('let g:SuperTabDefaultCompletionType = "<c-p>"')
vim_config.append('let g:SuperTabRetainCompletionDuration = "insert"') vim_config.append('let g:SuperTabRetainCompletionDuration = "insert"')
vim_config.append('let g:SuperTabLongestHighlight = 1') vim_config.append('let g:SuperTabLongestHighlight = 1')

View File

@ -2,193 +2,248 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Recursive (Nested) Snippets {{{# # Recursive (Nested) Snippets {{{#
class RecTabStops_SimpleCase_ExpectCorrectResult(_VimTest): class RecTabStops_SimpleCase_ExpectCorrectResult(_VimTest):
snippets = ("m", "[ ${1:first} ${2:sec} ]") snippets = ('m', '[ ${1:first} ${2:sec} ]')
keys = "m" + EX + "m" + EX + "hello" + JF + "world" + JF + "ups" + JF + "end" keys = 'm' + EX + 'm' + EX + 'hello' + \
wanted = "[ [ hello world ]ups end ]" JF + 'world' + JF + 'ups' + JF + 'end'
wanted = '[ [ hello world ]ups end ]'
class RecTabStops_SimpleCaseLeaveSecondSecond_ExpectCorrectResult(_VimTest): class RecTabStops_SimpleCaseLeaveSecondSecond_ExpectCorrectResult(_VimTest):
snippets = ("m", "[ ${1:first} ${2:sec} ]") snippets = ('m', '[ ${1:first} ${2:sec} ]')
keys = "m" + EX + "m" + EX + "hello" + JF + "world" + JF + JF + JF + "end" keys = 'm' + EX + 'm' + EX + 'hello' + JF + 'world' + JF + JF + JF + 'end'
wanted = "[ [ hello world ] sec ]end" wanted = '[ [ hello world ] sec ]end'
class RecTabStops_SimpleCaseLeaveFirstSecond_ExpectCorrectResult(_VimTest): class RecTabStops_SimpleCaseLeaveFirstSecond_ExpectCorrectResult(_VimTest):
snippets = ("m", "[ ${1:first} ${2:sec} ]") snippets = ('m', '[ ${1:first} ${2:sec} ]')
keys = "m" + EX + "m" + EX + "hello" + JF + JF + JF + "world" + JF + "end" keys = 'm' + EX + 'm' + EX + 'hello' + JF + JF + JF + 'world' + JF + 'end'
wanted = "[ [ hello sec ] world ]end" wanted = '[ [ hello sec ] world ]end'
class RecTabStops_InnerWOTabStop_ECR(_VimTest): class RecTabStops_InnerWOTabStop_ECR(_VimTest):
snippets = ( snippets = (
("m1", "Just some Text"), ('m1', 'Just some Text'),
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m1" + EX + "hi" + JF + "two" + JF + "end" keys = 'm' + EX + 'm1' + EX + 'hi' + JF + 'two' + JF + 'end'
wanted = "[ Just some Texthi two ]end" wanted = '[ Just some Texthi two ]end'
class RecTabStops_InnerWOTabStopTwiceDirectly_ECR(_VimTest): class RecTabStops_InnerWOTabStopTwiceDirectly_ECR(_VimTest):
snippets = ( snippets = (
("m1", "JST"), ('m1', 'JST'),
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m1" + EX + " m1" + EX + "hi" + JF + "two" + JF + "end" keys = 'm' + EX + 'm1' + EX + ' m1' + EX + 'hi' + JF + 'two' + JF + 'end'
wanted = "[ JST JSThi two ]end" wanted = '[ JST JSThi two ]end'
class RecTabStops_InnerWOTabStopTwice_ECR(_VimTest): class RecTabStops_InnerWOTabStopTwice_ECR(_VimTest):
snippets = ( snippets = (
("m1", "JST"), ('m1', 'JST'),
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m1" + EX + JF + "m1" + EX + "hi" + JF + "end" keys = 'm' + EX + 'm1' + EX + JF + 'm1' + EX + 'hi' + JF + 'end'
wanted = "[ JST JSThi ]end" wanted = '[ JST JSThi ]end'
class RecTabStops_OuterOnlyWithZeroTS_ECR(_VimTest): class RecTabStops_OuterOnlyWithZeroTS_ECR(_VimTest):
snippets = ( snippets = (
("m", "A $0 B"), ('m', 'A $0 B'),
("m1", "C $1 D $0 E"), ('m1', 'C $1 D $0 E'),
) )
keys = "m" + EX + "m1" + EX + "CD" + JF + "DE" keys = 'm' + EX + 'm1' + EX + 'CD' + JF + 'DE'
wanted = "A C CD D DE E B" wanted = 'A C CD D DE E B'
class RecTabStops_OuterOnlyWithZero_ECR(_VimTest): class RecTabStops_OuterOnlyWithZero_ECR(_VimTest):
snippets = ( snippets = (
("m", "A $0 B"), ('m', 'A $0 B'),
("m1", "C $1 D $0 E"), ('m1', 'C $1 D $0 E'),
) )
keys = "m" + EX + "m1" + EX + "CD" + JF + "DE" keys = 'm' + EX + 'm1' + EX + 'CD' + JF + 'DE'
wanted = "A C CD D DE E B" wanted = 'A C CD D DE E B'
class RecTabStops_ExpandedInZeroTS_ECR(_VimTest): class RecTabStops_ExpandedInZeroTS_ECR(_VimTest):
snippets = ( snippets = (
("m", "A $0 B $1"), ('m', 'A $0 B $1'),
("m1", "C $1 D $0 E"), ('m1', 'C $1 D $0 E'),
) )
keys = "m" + EX + "hi" + JF + "m1" + EX + "CD" + JF + "DE" keys = 'm' + EX + 'hi' + JF + 'm1' + EX + 'CD' + JF + 'DE'
wanted = "A C CD D DE E B hi" wanted = 'A C CD D DE E B hi'
class RecTabStops_ExpandedInZeroTSTwice_ECR(_VimTest): class RecTabStops_ExpandedInZeroTSTwice_ECR(_VimTest):
snippets = ( snippets = (
("m", "A $0 B $1"), ('m', 'A $0 B $1'),
("m1", "C $1 D $0 E"), ('m1', 'C $1 D $0 E'),
) )
keys = "m" + EX + "hi" + JF + "m" + EX + "again" + JF + "m1" + \ keys = 'm' + EX + 'hi' + JF + 'm' + EX + 'again' + JF + 'm1' + \
EX + "CD" + JF + "DE" EX + 'CD' + JF + 'DE'
wanted = "A A C CD D DE E B again B hi" wanted = 'A A C CD D DE E B again B hi'
class RecTabStops_ExpandedInZeroTSSecondTime_ECR(_VimTest): class RecTabStops_ExpandedInZeroTSSecondTime_ECR(_VimTest):
snippets = ( snippets = (
("m", "A $0 B $1"), ('m', 'A $0 B $1'),
("m1", "C $1 D $0 E"), ('m1', 'C $1 D $0 E'),
) )
keys = "m" + EX + "hi" + JF + "m" + EX + "m1" + EX + "CD" + JF + "DE" + JF + "AB" keys = 'm' + EX + 'hi' + JF + 'm' + EX + \
wanted = "A A AB B C CD D DE E B hi" 'm1' + EX + 'CD' + JF + 'DE' + JF + 'AB'
wanted = 'A A AB B C CD D DE E B hi'
class RecTabsStops_TypeInZero_ECR(_VimTest): class RecTabsStops_TypeInZero_ECR(_VimTest):
snippets = ( snippets = (
("v", r"\vec{$1}", "Vector", "w"), ('v', r"\vec{$1}", 'Vector', 'w'),
("frac", r"\frac{${1:one}}${0:zero}{${2:two}}", "Fractio", "w"), ('frac', r"\frac{${1:one}}${0:zero}{${2:two}}", 'Fractio', 'w'),
) )
keys = "v" + EX + "frac" + EX + "a" + JF + "b" + JF + "frac" + EX + "aa" + JF + JF + "cc" + JF + \ keys = 'v' + EX + 'frac' + EX + 'a' + JF + 'b' + JF + 'frac' + EX + 'aa' + JF + JF + 'cc' + JF + \
"hello frac" + EX + JF + JF + "world" 'hello frac' + EX + JF + JF + 'world'
wanted = r"\vec{\frac{a}\frac{aa}cc{two}{b}}hello \frac{one}world{two}" wanted = r"\vec{\frac{a}\frac{aa}cc{two}{b}}hello \frac{one}world{two}"
class RecTabsStops_TypeInZero2_ECR(_VimTest): class RecTabsStops_TypeInZero2_ECR(_VimTest):
snippets = ( snippets = (
("m", r"_${0:explicit zero}", "snip", "i"), ('m', r"_${0:explicit zero}", 'snip', 'i'),
) )
keys = "m" + EX + "hello m" + EX + "world m" + EX + "end" keys = 'm' + EX + 'hello m' + EX + 'world m' + EX + 'end'
wanted = r"_hello _world _end" wanted = r"_hello _world _end"
class RecTabsStops_BackspaceZero_ECR(_VimTest): class RecTabsStops_BackspaceZero_ECR(_VimTest):
snippets = ( snippets = (
("m", r"${1:one}${0:explicit zero}${2:two}", "snip", "i"), ('m', r"${1:one}${0:explicit zero}${2:two}", 'snip', 'i'),
) )
keys = "m" + EX + JF + JF + BS + "m" + EX keys = 'm' + EX + JF + JF + BS + 'm' + EX
wanted = r"oneoneexplicit zerotwotwo" wanted = r"oneoneexplicit zerotwotwo"
class RecTabStops_MirrorInnerSnippet_ECR(_VimTest): class RecTabStops_MirrorInnerSnippet_ECR(_VimTest):
snippets = ( snippets = (
("m", "[ $1 $2 ] $1"), ('m', '[ $1 $2 ] $1'),
("m1", "ASnip $1 ASnip $2 ASnip"), ('m1', 'ASnip $1 ASnip $2 ASnip'),
) )
keys = "m" + EX + "m1" + EX + "Hallo" + JF + "Hi" + JF + "endone" + JF + "two" + JF + "totalend" keys = 'm' + EX + 'm1' + EX + 'Hallo' + JF + 'Hi' + \
wanted = "[ ASnip Hallo ASnip Hi ASnipendone two ] ASnip Hallo ASnip Hi ASnipendonetotalend" JF + 'endone' + JF + 'two' + JF + 'totalend'
wanted = '[ ASnip Hallo ASnip Hi ASnipendone two ] ASnip Hallo ASnip Hi ASnipendonetotalend'
class RecTabStops_NotAtBeginningOfTS_ExpectCorrectResult(_VimTest): class RecTabStops_NotAtBeginningOfTS_ExpectCorrectResult(_VimTest):
snippets = ("m", "[ ${1:first} ${2:sec} ]") snippets = ('m', '[ ${1:first} ${2:sec} ]')
keys = "m" + EX + "hello m" + EX + "hi" + JF + "two" + JF + "ups" + JF + "three" + \ keys = 'm' + EX + 'hello m' + EX + 'hi' + JF + 'two' + JF + 'ups' + JF + 'three' + \
JF + "end" JF + 'end'
wanted = "[ hello [ hi two ]ups three ]end" wanted = '[ hello [ hi two ]ups three ]end'
class RecTabStops_InNewlineInTabstop_ExpectCorrectResult(_VimTest): class RecTabStops_InNewlineInTabstop_ExpectCorrectResult(_VimTest):
snippets = ("m", "[ ${1:first} ${2:sec} ]") snippets = ('m', '[ ${1:first} ${2:sec} ]')
keys = "m" + EX + "hello\nm" + EX + "hi" + JF + "two" + JF + "ups" + JF + "three" + \ keys = 'm' + EX + 'hello\nm' + EX + 'hi' + JF + 'two' + JF + 'ups' + JF + 'three' + \
JF + "end" JF + 'end'
wanted = "[ hello\n[ hi two ]ups three ]end" wanted = '[ hello\n[ hi two ]ups three ]end'
class RecTabStops_InNewlineInTabstopNotAtBeginOfLine_ECR(_VimTest): class RecTabStops_InNewlineInTabstopNotAtBeginOfLine_ECR(_VimTest):
snippets = ("m", "[ ${1:first} ${2:sec} ]") snippets = ('m', '[ ${1:first} ${2:sec} ]')
keys = "m" + EX + "hello\nhello again m" + EX + "hi" + JF + "two" + \ keys = 'm' + EX + 'hello\nhello again m' + EX + 'hi' + JF + 'two' + \
JF + "ups" + JF + "three" + JF + "end" JF + 'ups' + JF + 'three' + JF + 'end'
wanted = "[ hello\nhello again [ hi two ]ups three ]end" wanted = '[ hello\nhello again [ hi two ]ups three ]end'
class RecTabStops_InNewlineMultiline_ECR(_VimTest): class RecTabStops_InNewlineMultiline_ECR(_VimTest):
snippets = ("m", "M START\n$0\nM END") snippets = ('m', 'M START\n$0\nM END')
keys = "m" + EX + "m" + EX keys = 'm' + EX + 'm' + EX
wanted = "M START\nM START\n\nM END\nM END" wanted = 'M START\nM START\n\nM END\nM END'
class RecTabStops_InNewlineManualIndent_ECR(_VimTest): class RecTabStops_InNewlineManualIndent_ECR(_VimTest):
snippets = ("m", "M START\n$0\nM END") snippets = ('m', 'M START\n$0\nM END')
keys = "m" + EX + " m" + EX + "hi" keys = 'm' + EX + ' m' + EX + 'hi'
wanted = "M START\n M START\n hi\n M END\nM END" wanted = 'M START\n M START\n hi\n M END\nM END'
class RecTabStops_InNewlineManualIndentTextInFront_ECR(_VimTest): class RecTabStops_InNewlineManualIndentTextInFront_ECR(_VimTest):
snippets = ("m", "M START\n$0\nM END") snippets = ('m', 'M START\n$0\nM END')
keys = "m" + EX + " hallo m" + EX + "hi" keys = 'm' + EX + ' hallo m' + EX + 'hi'
wanted = "M START\n hallo M START\n hi\n M END\nM END" wanted = 'M START\n hallo M START\n hi\n M END\nM END'
class RecTabStops_InNewlineMultilineWithIndent_ECR(_VimTest): class RecTabStops_InNewlineMultilineWithIndent_ECR(_VimTest):
snippets = ("m", "M START\n $0\nM END") snippets = ('m', 'M START\n $0\nM END')
keys = "m" + EX + "m" + EX + "hi" keys = 'm' + EX + 'm' + EX + 'hi'
wanted = "M START\n M START\n hi\n M END\nM END" wanted = 'M START\n M START\n hi\n M END\nM END'
class RecTabStops_InNewlineMultilineWithNonZeroTS_ECR(_VimTest): class RecTabStops_InNewlineMultilineWithNonZeroTS_ECR(_VimTest):
snippets = ("m", "M START\n $1\nM END -> $0") snippets = ('m', 'M START\n $1\nM END -> $0')
keys = "m" + EX + "m" + EX + "hi" + JF + "hallo" + JF + "end" keys = 'm' + EX + 'm' + EX + 'hi' + JF + 'hallo' + JF + 'end'
wanted = "M START\n M START\n hi\n M END -> hallo\n" \ wanted = 'M START\n M START\n hi\n M END -> hallo\n' \
"M END -> end" 'M END -> end'
class RecTabStops_BarelyNotLeavingInner_ECR(_VimTest): class RecTabStops_BarelyNotLeavingInner_ECR(_VimTest):
snippets = ( snippets = (
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m" + EX + "a" + 3*ARR_L + JF + "hallo" + \ keys = 'm' + EX + 'm' + EX + 'a' + 3 * ARR_L + JF + 'hallo' + \
JF + "ups" + JF + "world" + JF + "end" JF + 'ups' + JF + 'world' + JF + 'end'
wanted = "[ [ a hallo ]ups world ]end" wanted = '[ [ a hallo ]ups world ]end'
class RecTabStops_LeavingInner_ECR(_VimTest): class RecTabStops_LeavingInner_ECR(_VimTest):
snippets = ( snippets = (
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m" + EX + "a" + 4*ARR_L + JF + "hallo" + \ keys = 'm' + EX + 'm' + EX + 'a' + 4 * ARR_L + JF + 'hallo' + \
JF + "world" JF + 'world'
wanted = "[ [ a sec ] hallo ]world" wanted = '[ [ a sec ] hallo ]world'
class RecTabStops_LeavingInnerInner_ECR(_VimTest): class RecTabStops_LeavingInnerInner_ECR(_VimTest):
snippets = ( snippets = (
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m" + EX + "m" + EX + "a" + 4*ARR_L + JF + "hallo" + \ keys = 'm' + EX + 'm' + EX + 'm' + EX + 'a' + 4 * ARR_L + JF + 'hallo' + \
JF + "ups" + JF + "world" + JF + "end" JF + 'ups' + JF + 'world' + JF + 'end'
wanted = "[ [ [ a sec ] hallo ]ups world ]end" wanted = '[ [ [ a sec ] hallo ]ups world ]end'
class RecTabStops_LeavingInnerInnerTwo_ECR(_VimTest): class RecTabStops_LeavingInnerInnerTwo_ECR(_VimTest):
snippets = ( snippets = (
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m" + EX + "m" + EX + "a" + 6*ARR_L + JF + "hallo" + \ keys = 'm' + EX + 'm' + EX + 'm' + EX + 'a' + 6 * ARR_L + JF + 'hallo' + \
JF + "end" JF + 'end'
wanted = "[ [ [ a sec ] sec ] hallo ]end" wanted = '[ [ [ a sec ] sec ] hallo ]end'
class RecTabStops_ZeroTSisNothingSpecial_ECR(_VimTest): class RecTabStops_ZeroTSisNothingSpecial_ECR(_VimTest):
snippets = ( snippets = (
("m1", "[ ${1:first} $0 ${2:sec} ]"), ('m1', '[ ${1:first} $0 ${2:sec} ]'),
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m1" + EX + "one" + JF + "two" + \ keys = 'm' + EX + 'm1' + EX + 'one' + JF + 'two' + \
JF + "three" + JF + "four" + JF + "end" JF + 'three' + JF + 'four' + JF + 'end'
wanted = "[ [ one three two ] four ]end" wanted = '[ [ one three two ] four ]end'
class RecTabStops_MirroredZeroTS_ECR(_VimTest): class RecTabStops_MirroredZeroTS_ECR(_VimTest):
snippets = ( snippets = (
("m1", "[ ${1:first} ${0:Year, some default text} $0 ${2:sec} ]"), ('m1', '[ ${1:first} ${0:Year, some default text} $0 ${2:sec} ]'),
("m", "[ ${1:first} ${2:sec} ]"), ('m', '[ ${1:first} ${2:sec} ]'),
) )
keys = "m" + EX + "m1" + EX + "one" + JF + "two" + \ keys = 'm' + EX + 'm1' + EX + 'one' + JF + 'two' + \
JF + "three" + JF + "four" + JF + "end" JF + 'three' + JF + 'four' + JF + 'end'
wanted = "[ [ one three three two ] four ]end" wanted = '[ [ one three three two ] four ]end'
class RecTabStops_ChildTriggerContainsParentTextObjects(_VimTest): class RecTabStops_ChildTriggerContainsParentTextObjects(_VimTest):
# https://bugs.launchpad.net/bugs/1191617 # https://bugs.launchpad.net/bugs/1191617
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
global !p global !p
def complete(t, opts): def complete(t, opts):
if t: if t:
@ -205,7 +260,6 @@ auto = autocomplete_options(t, match.group(2), attr=["id: ", "class: ", "title:
snip.rv = "form_for" + match.group(1) + "{"`$1`!p if (snip.c != auto) : snip.rv=auto` snip.rv = "form_for" + match.group(1) + "{"`$1`!p if (snip.c != auto) : snip.rv=auto`
endsnippet endsnippet
"""} """}
keys = "form_for user, namespace: some_namespace, html: {i" + EX + "i" + EX keys = 'form_for user, namespace: some_namespace, html: {i' + EX + 'i' + EX
wanted = "form_for user, namespace: some_namespace, html: {(id: |class: |title: )d: " wanted = 'form_for user, namespace: some_namespace, html: {(id: |class: |title: )d: '
# End: Recursive (Nested) Snippets #}}} # End: Recursive (Nested) Snippets #}}}

View File

@ -3,18 +3,25 @@ from test.constant import *
# Unmap SelectMode Mappings {{{# # Unmap SelectMode Mappings {{{#
# Test for bug 427298 # # Test for bug 427298 #
class _SelectModeMappings(_VimTest): class _SelectModeMappings(_VimTest):
snippets = ("test", "${1:World}") snippets = ('test', '${1:World}')
keys = "test" + EX + "Hello" keys = 'test' + EX + 'Hello'
wanted = "Hello" wanted = 'Hello'
maps = ("", "") maps = ('', '')
buffer_maps = ("", "") buffer_maps = ('', '')
do_unmapping = True do_unmapping = True
ignores = [] ignores = []
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append(":let g:UltiSnipsRemoveSelectModeMappings=%i" % int(self.do_unmapping)) vim_config.append(
vim_config.append(":let g:UltiSnipsMappingsToIgnore=%s" % repr(self.ignores)) ':let g:UltiSnipsRemoveSelectModeMappings=%i' % int(
self.do_unmapping))
vim_config.append(
':let g:UltiSnipsMappingsToIgnore=%s' %
repr(
self.ignores))
if not isinstance(self.maps[0], tuple): if not isinstance(self.maps[0], tuple):
self.maps = (self.maps,) self.maps = (self.maps,)
@ -22,71 +29,96 @@ class _SelectModeMappings(_VimTest):
self.buffer_maps = (self.buffer_maps,) self.buffer_maps = (self.buffer_maps,)
for key, m in self.maps: for key, m in self.maps:
if not len(key): continue if not len(key):
vim_config.append(":smap %s %s" % (key,m)) continue
vim_config.append(':smap %s %s' % (key, m))
for key, m in self.buffer_maps: for key, m in self.buffer_maps:
if not len(key): continue if not len(key):
vim_config.append(":smap <buffer> %s %s" % (key,m)) continue
vim_config.append(':smap <buffer> %s %s' % (key, m))
class SelectModeMappings_RemoveBeforeSelecting_ECR(_SelectModeMappings): class SelectModeMappings_RemoveBeforeSelecting_ECR(_SelectModeMappings):
maps = ("H", "x") maps = ('H', 'x')
wanted = "Hello" wanted = 'Hello'
class SelectModeMappings_DisableRemoveBeforeSelecting_ECR(_SelectModeMappings): class SelectModeMappings_DisableRemoveBeforeSelecting_ECR(_SelectModeMappings):
do_unmapping = False do_unmapping = False
maps = ("H", "x") maps = ('H', 'x')
wanted = "xello" wanted = 'xello'
class SelectModeMappings_IgnoreMappings_ECR(_SelectModeMappings): class SelectModeMappings_IgnoreMappings_ECR(_SelectModeMappings):
ignores = ["e"] ignores = ['e']
maps = ("H", "x"), ("e", "l") maps = ('H', 'x'), ('e', 'l')
wanted = "Hello" wanted = 'Hello'
class SelectModeMappings_IgnoreMappings1_ECR(_SelectModeMappings): class SelectModeMappings_IgnoreMappings1_ECR(_SelectModeMappings):
ignores = ["H"] ignores = ['H']
maps = ("H", "x"), ("e", "l") maps = ('H', 'x'), ('e', 'l')
wanted = "xello" wanted = 'xello'
class SelectModeMappings_IgnoreMappings2_ECR(_SelectModeMappings): class SelectModeMappings_IgnoreMappings2_ECR(_SelectModeMappings):
ignores = ["e", "H"] ignores = ['e', 'H']
maps = ("e", "l"), ("H", "x") maps = ('e', 'l'), ('H', 'x')
wanted = "xello" wanted = 'xello'
class SelectModeMappings_BufferLocalMappings_ECR(_SelectModeMappings): class SelectModeMappings_BufferLocalMappings_ECR(_SelectModeMappings):
buffer_maps = ("H", "blah") buffer_maps = ('H', 'blah')
wanted = "Hello" wanted = 'Hello'
# End: Unmap SelectMode Mappings #}}} # End: Unmap SelectMode Mappings #}}}
# Exclusive Selection {{{# # Exclusive Selection {{{#
class _ES_Base(_VimTest): class _ES_Base(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set selection=exclusive") vim_config.append('set selection=exclusive')
class ExclusiveSelection_SimpleTabstop_Test(_ES_Base): class ExclusiveSelection_SimpleTabstop_Test(_ES_Base):
snippets = ("test", "h${1:blah}w $1") snippets = ('test', 'h${1:blah}w $1')
keys = "test" + EX + "ui" + JF keys = 'test' + EX + 'ui' + JF
wanted = "huiw ui" wanted = 'huiw ui'
class ExclusiveSelection_RealWorldCase_Test(_ES_Base): class ExclusiveSelection_RealWorldCase_Test(_ES_Base):
snippets = ("for", snippets = ('for',
"""for ($${1:i} = ${2:0}; $$1 < ${3:count}; $$1${4:++}) { """for ($${1:i} = ${2:0}; $$1 < ${3:count}; $$1${4:++}) {
${5:// code} ${5:// code}
}""") }""")
keys = "for" + EX + "k" + JF keys = 'for' + EX + 'k' + JF
wanted = """for ($k = 0; $k < count; $k++) { wanted = """for ($k = 0; $k < count; $k++) {
// code // code
}""" }"""
# End: Exclusive Selection #}}} # End: Exclusive Selection #}}}
# Old Selection {{{# # Old Selection {{{#
class _OS_Base(_VimTest): class _OS_Base(_VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set selection=old") vim_config.append('set selection=old')
class OldSelection_SimpleTabstop_Test(_OS_Base): class OldSelection_SimpleTabstop_Test(_OS_Base):
snippets =("test", "h${1:blah}w $1") snippets = ('test', 'h${1:blah}w $1')
keys = "test" + EX + "ui" + JF keys = 'test' + EX + 'ui' + JF
wanted = "huiw ui" wanted = 'huiw ui'
class OldSelection_RealWorldCase_Test(_OS_Base): class OldSelection_RealWorldCase_Test(_OS_Base):
snippets = ("for", snippets = ('for',
"""for ($${1:i} = ${2:0}; $$1 < ${3:count}; $$1${4:++}) { """for ($${1:i} = ${2:0}; $$1 < ${3:count}; $$1${4:++}) {
${5:// code} ${5:// code}
}""") }""")
keys = "for" + EX + "k" + JF keys = 'for' + EX + 'k' + JF
wanted = """for ($k = 0; $k < count; $k++) { wanted = """for ($k = 0; $k < count; $k++) {
// code // code
}""" }"""

View File

@ -3,97 +3,125 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# snipMate support {{{# # snipMate support {{{#
class snipMate_SimpleSnippet(_VimTest): class snipMate_SimpleSnippet(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet hello snippet hello
\tThis is a test snippet \tThis is a test snippet
\t# With a comment"""} \t# With a comment"""}
keys = "hello" + EX keys = 'hello' + EX
wanted = "This is a test snippet\n# With a comment" wanted = 'This is a test snippet\n# With a comment'
class snipMate_OtherFiletype(_VimTest): class snipMate_OtherFiletype(_VimTest):
files = { "snippets/blubi.snippets": """ files = { 'snippets/blubi.snippets': """
snippet hello snippet hello
\tworked"""} \tworked"""}
keys = "hello" + EX + ESC + ":set ft=blubi\nohello" + EX keys = 'hello' + EX + ESC + ':set ft=blubi\nohello' + EX
wanted = "hello" + EX + "\nworked" wanted = 'hello' + EX + '\nworked'
class snipMate_MultiMatches(_VimTest): class snipMate_MultiMatches(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet hello The first snippet." snippet hello The first snippet."
\tone \tone
snippet hello The second snippet. snippet hello The second snippet.
\ttwo"""} \ttwo"""}
keys = "hello" + EX + "2\n" keys = 'hello' + EX + '2\n'
wanted = "two" wanted = 'two'
class snipMate_SimpleSnippetSubDirectory(_VimTest): class snipMate_SimpleSnippetSubDirectory(_VimTest):
files = { "snippets/_/blub.snippets": """ files = { 'snippets/_/blub.snippets': """
snippet hello snippet hello
\tThis is a test snippet"""} \tThis is a test snippet"""}
keys = "hello" + EX keys = 'hello' + EX
wanted = "This is a test snippet" wanted = 'This is a test snippet'
class snipMate_SimpleSnippetInSnippetFile(_VimTest): class snipMate_SimpleSnippetInSnippetFile(_VimTest):
files = { files = {
"snippets/_/hello.snippet": """This is a stand alone snippet""", 'snippets/_/hello.snippet': """This is a stand alone snippet""",
"snippets/_/hello1.snippet": """This is two stand alone snippet""", 'snippets/_/hello1.snippet': """This is two stand alone snippet""",
"snippets/_/hello2/this_is_my_cool_snippet.snippet": """Three""", 'snippets/_/hello2/this_is_my_cool_snippet.snippet': """Three""",
} }
keys = "hello" + EX + "\nhello1" + EX + "\nhello2" + EX keys = 'hello' + EX + '\nhello1' + EX + '\nhello2' + EX
wanted = "This is a stand alone snippet\nThis is two stand alone snippet\nThree" wanted = 'This is a stand alone snippet\nThis is two stand alone snippet\nThree'
class snipMate_Interpolation(_VimTest): class snipMate_Interpolation(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet test snippet test
\tla`printf('c%02d', 3)`lu"""} \tla`printf('c%02d', 3)`lu"""}
keys = "test" + EX keys = 'test' + EX
wanted = "lac03lu" wanted = 'lac03lu'
class snipMate_InterpolationWithSystem(_VimTest): class snipMate_InterpolationWithSystem(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet test snippet test
\tla`system('echo -ne öäü')`lu"""} \tla`system('echo -ne öäü')`lu"""}
keys = "test" + EX keys = 'test' + EX
wanted = "laöäülu" wanted = 'laöäülu'
class snipMate_TestMirrors(_VimTest): class snipMate_TestMirrors(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet for snippet for
\tfor (${2:i}; $2 < ${1:count}; $1++) { \tfor (${2:i}; $2 < ${1:count}; $1++) {
\t\t${4} \t\t${4}
\t}"""} \t}"""}
keys = "for" + EX + "blub" + JF + "j" + JF + "hi" keys = 'for' + EX + 'blub' + JF + 'j' + JF + 'hi'
wanted = "for (j; j < blub; blub++) {\n\thi\n}" wanted = 'for (j; j < blub; blub++) {\n\thi\n}'
class snipMate_TestMirrorsInPlaceholders(_VimTest): class snipMate_TestMirrorsInPlaceholders(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet opt snippet opt
\t<option value="${1:option}">${2:$1}</option>"""} \t<option value="${1:option}">${2:$1}</option>"""}
keys = "opt" + EX + "some" + JF + JF + "ende" keys = 'opt' + EX + 'some' + JF + JF + 'ende'
wanted = """<option value="some">some</option>ende""" wanted = """<option value="some">some</option>ende"""
class snipMate_TestMirrorsInPlaceholders_Overwrite(_VimTest): class snipMate_TestMirrorsInPlaceholders_Overwrite(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet opt snippet opt
\t<option value="${1:option}">${2:$1}</option>"""} \t<option value="${1:option}">${2:$1}</option>"""}
keys = "opt" + EX + "some" + JF + "not" + JF + "ende" keys = 'opt' + EX + 'some' + JF + 'not' + JF + 'ende'
wanted = """<option value="some">not</option>ende""" wanted = """<option value="some">not</option>ende"""
class snipMate_Visual_Simple(_VimTest): class snipMate_Visual_Simple(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet v snippet v
\th${VISUAL}b"""} \th${VISUAL}b"""}
keys = "blablub" + ESC + "0v6l" + EX + "v" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'v' + EX
wanted = "hblablubb" wanted = 'hblablubb'
class snipMate_NoNestedTabstops(_VimTest): class snipMate_NoNestedTabstops(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet test snippet test
\th$${1:${2:blub}}$$"""} \th$${1:${2:blub}}$$"""}
keys = "test" + EX + JF + "hi" keys = 'test' + EX + JF + 'hi'
wanted = "h$${2:blub}$$hi" wanted = 'h$${2:blub}$$hi'
class snipMate_Extends(_VimTest): class snipMate_Extends(_VimTest):
files = { "snippets/a.snippets": """ files = { 'snippets/a.snippets': """
extends b extends b
snippet test snippet test
\tblub""", "snippets/b.snippets": """ \tblub""", 'snippets/b.snippets': """
snippet test1 snippet test1
\tblah""" \tblah"""
} }
keys = ESC + ":set ft=a\n" + "itest1" + EX keys = ESC + ':set ft=a\n' + 'itest1' + EX
wanted = "blah" wanted = 'blah'
class snipMate_EmptyLinesContinueSnippets(_VimTest): class snipMate_EmptyLinesContinueSnippets(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet test snippet test
\tblub \tblub
@ -101,20 +129,21 @@ snippet test
snippet test1 snippet test1
\ta""" \ta"""
} }
keys = "test" + EX keys = 'test' + EX
wanted = "blub\n\nblah\n" wanted = 'blub\n\nblah\n'
class snipMate_OverwrittenByRegExpTrigger(_VimTest): class snipMate_OverwrittenByRegExpTrigger(_VimTest):
files = { "snippets/_.snippets": """ files = { 'snippets/_.snippets': """
snippet def snippet def
\tsnipmate \tsnipmate
""", """,
"us/all.snippets": r""" 'us/all.snippets': r"""
snippet "(de)?f" "blub" r snippet "(de)?f" "blub" r
ultisnips ultisnips
endsnippet endsnippet
""" } """ }
keys = "def" + EX keys = 'def' + EX
wanted = "ultisnips" wanted = 'ultisnips'
# End: snipMate support #}}} # End: snipMate support #}}}

View File

@ -4,126 +4,178 @@ from test.constant import *
from test.util import running_on_windows from test.util import running_on_windows
# Snippet Options {{{# # Snippet Options {{{#
class SnippetOptions_OnlyExpandWhenWSInFront_Expand(_VimTest): class SnippetOptions_OnlyExpandWhenWSInFront_Expand(_VimTest):
snippets = ("test", "Expand me!", "", "b") snippets = ('test', 'Expand me!', '', 'b')
keys = "test" + EX keys = 'test' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class SnippetOptions_OnlyExpandWhenWSInFront_Expand2(_VimTest): class SnippetOptions_OnlyExpandWhenWSInFront_Expand2(_VimTest):
snippets = ("test", "Expand me!", "", "b") snippets = ('test', 'Expand me!', '', 'b')
keys = " test" + EX keys = ' test' + EX
wanted = " Expand me!" wanted = ' Expand me!'
class SnippetOptions_OnlyExpandWhenWSInFront_DontExpand(_VimTest): class SnippetOptions_OnlyExpandWhenWSInFront_DontExpand(_VimTest):
snippets = ("test", "Expand me!", "", "b") snippets = ('test', 'Expand me!', '', 'b')
keys = "a test" + EX keys = 'a test' + EX
wanted = "a test" + EX wanted = 'a test' + EX
class SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWO(_VimTest): class SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWO(_VimTest):
snippets = ( snippets = (
("test", "Expand me!", "", "b"), ('test', 'Expand me!', '', 'b'),
("test", "not at beginning", "", ""), ('test', 'not at beginning', '', ''),
) )
keys = "a test" + EX keys = 'a test' + EX
wanted = "a not at beginning" wanted = 'a not at beginning'
class SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWOChoose(_VimTest): class SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWOChoose(_VimTest):
snippets = ( snippets = (
("test", "Expand me!", "", "b"), ('test', 'Expand me!', '', 'b'),
("test", "not at beginning", "", ""), ('test', 'not at beginning', '', ''),
) )
keys = " test" + EX + "1\n" keys = ' test' + EX + '1\n'
wanted = " Expand me!" wanted = ' Expand me!'
class SnippetOptions_ExpandInwordSnippets_SimpleExpand(_VimTest): class SnippetOptions_ExpandInwordSnippets_SimpleExpand(_VimTest):
snippets = (("test", "Expand me!", "", "i"), ) snippets = (('test', 'Expand me!', '', 'i'), )
keys = "atest" + EX keys = 'atest' + EX
wanted = "aExpand me!" wanted = 'aExpand me!'
class SnippetOptions_ExpandInwordSnippets_ExpandSingle(_VimTest): class SnippetOptions_ExpandInwordSnippets_ExpandSingle(_VimTest):
snippets = (("test", "Expand me!", "", "i"), ) snippets = (('test', 'Expand me!', '', 'i'), )
keys = "test" + EX keys = 'test' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand(_VimTest): class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand(_VimTest):
snippets = (("test", "Expand me!", "", "i"), ) snippets = (('test', 'Expand me!', '', 'i'), )
keys = "$test" + EX keys = '$test' + EX
wanted = "$Expand me!" wanted = '$Expand me!'
class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand2(_VimTest): class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand2(_VimTest):
snippets = (("test", "Expand me!", "", "i"), ) snippets = (('test', 'Expand me!', '', 'i'), )
keys = "-test" + EX keys = '-test' + EX
wanted = "-Expand me!" wanted = '-Expand me!'
class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand3(_VimTest): class SnippetOptions_ExpandInwordSnippetsWithOtherChars_Expand3(_VimTest):
skip_if = lambda self: running_on_windows() skip_if = lambda self: running_on_windows()
snippets = (("test", "Expand me!", "", "i"), ) snippets = (('test', 'Expand me!', '', 'i'), )
keys = "ßßtest" + EX keys = 'ßßtest' + EX
wanted = "ßßExpand me!" wanted = 'ßßExpand me!'
class _SnippetOptions_ExpandWordSnippets(_VimTest): class _SnippetOptions_ExpandWordSnippets(_VimTest):
snippets = (("test", "Expand me!", "", "w"), ) snippets = (('test', 'Expand me!', '', 'w'), )
class SnippetOptions_ExpandWordSnippets_NormalExpand( class SnippetOptions_ExpandWordSnippets_NormalExpand(
_SnippetOptions_ExpandWordSnippets): _SnippetOptions_ExpandWordSnippets):
keys = "test" + EX keys = 'test' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class SnippetOptions_ExpandWordSnippets_NoExpand( class SnippetOptions_ExpandWordSnippets_NoExpand(
_SnippetOptions_ExpandWordSnippets): _SnippetOptions_ExpandWordSnippets):
keys = "atest" + EX keys = 'atest' + EX
wanted = "atest" + EX wanted = 'atest' + EX
class SnippetOptions_ExpandWordSnippets_ExpandSuffix( class SnippetOptions_ExpandWordSnippets_ExpandSuffix(
_SnippetOptions_ExpandWordSnippets): _SnippetOptions_ExpandWordSnippets):
keys = "a-test" + EX keys = 'a-test' + EX
wanted = "a-Expand me!" wanted = 'a-Expand me!'
class SnippetOptions_ExpandWordSnippets_ExpandSuffix2( class SnippetOptions_ExpandWordSnippets_ExpandSuffix2(
_SnippetOptions_ExpandWordSnippets): _SnippetOptions_ExpandWordSnippets):
keys = "a(test" + EX keys = 'a(test' + EX
wanted = "a(Expand me!" wanted = 'a(Expand me!'
class SnippetOptions_ExpandWordSnippets_ExpandSuffix3( class SnippetOptions_ExpandWordSnippets_ExpandSuffix3(
_SnippetOptions_ExpandWordSnippets): _SnippetOptions_ExpandWordSnippets):
keys = "[[test" + EX keys = '[[test' + EX
wanted = "[[Expand me!" wanted = '[[Expand me!'
class _No_Tab_Expand(_VimTest): class _No_Tab_Expand(_VimTest):
snippets = ("test", "\t\tExpand\tme!\t", "", "t") snippets = ('test', '\t\tExpand\tme!\t', '', 't')
class No_Tab_Expand_Simple(_No_Tab_Expand): class No_Tab_Expand_Simple(_No_Tab_Expand):
keys = "test" + EX keys = 'test' + EX
wanted = "\t\tExpand\tme!\t" wanted = '\t\tExpand\tme!\t'
class No_Tab_Expand_Leading_Spaces(_No_Tab_Expand): class No_Tab_Expand_Leading_Spaces(_No_Tab_Expand):
keys = " test" + EX keys = ' test' + EX
wanted = " \t\tExpand\tme!\t" wanted = ' \t\tExpand\tme!\t'
class No_Tab_Expand_Leading_Tabs(_No_Tab_Expand): class No_Tab_Expand_Leading_Tabs(_No_Tab_Expand):
keys = "\ttest" + EX keys = '\ttest' + EX
wanted = "\t\t\tExpand\tme!\t" wanted = '\t\t\tExpand\tme!\t'
class No_Tab_Expand_No_TS(_No_Tab_Expand): class No_Tab_Expand_No_TS(_No_Tab_Expand):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set sts=3") vim_config.append('set sts=3')
keys = "test" + EX keys = 'test' + EX
wanted = "\t\tExpand\tme!\t" wanted = '\t\tExpand\tme!\t'
class No_Tab_Expand_ET(_No_Tab_Expand): class No_Tab_Expand_ET(_No_Tab_Expand):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set expandtab") vim_config.append('set expandtab')
keys = "test" + EX keys = 'test' + EX
wanted = "\t\tExpand\tme!\t" wanted = '\t\tExpand\tme!\t'
class No_Tab_Expand_ET_Leading_Spaces(_No_Tab_Expand): class No_Tab_Expand_ET_Leading_Spaces(_No_Tab_Expand):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set expandtab") vim_config.append('set expandtab')
keys = " test" + EX keys = ' test' + EX
wanted = " \t\tExpand\tme!\t" wanted = ' \t\tExpand\tme!\t'
class No_Tab_Expand_ET_SW(_No_Tab_Expand): class No_Tab_Expand_ET_SW(_No_Tab_Expand):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=8") vim_config.append('set sw=8')
vim_config.append("set expandtab") vim_config.append('set expandtab')
keys = "test" + EX keys = 'test' + EX
wanted = "\t\tExpand\tme!\t" wanted = '\t\tExpand\tme!\t'
class No_Tab_Expand_ET_SW_TS(_No_Tab_Expand): class No_Tab_Expand_ET_SW_TS(_No_Tab_Expand):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set sw=3") vim_config.append('set sw=3')
vim_config.append("set sts=3") vim_config.append('set sts=3')
vim_config.append("set ts=3") vim_config.append('set ts=3')
vim_config.append("set expandtab") vim_config.append('set expandtab')
keys = "test" + EX keys = 'test' + EX
wanted = "\t\tExpand\tme!\t" wanted = '\t\tExpand\tme!\t'
class _TabExpand_RealWorld(object): class _TabExpand_RealWorld(object):
snippets = ("hi", snippets = ('hi',
r"""hi r"""hi
`!p snip.rv="i1\n" `!p snip.rv="i1\n"
snip.rv += snip.mkline("i1\n") snip.rv += snip.mkline("i1\n")
snip.shift(1) snip.shift(1)
@ -135,10 +187,12 @@ snip.rv += snip.mkline("i3")`
snip.rv = repr(snip.rv) snip.rv = repr(snip.rv)
End""") End""")
class No_Tab_Expand_RealWorld(_TabExpand_RealWorld,_VimTest):
class No_Tab_Expand_RealWorld(_TabExpand_RealWorld, _VimTest):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set noexpandtab") vim_config.append('set noexpandtab')
keys = "\t\thi" + EX keys = '\t\thi' + EX
wanted = """\t\thi wanted = """\t\thi
\t\ti1 \t\ti1
\t\ti1 \t\ti1
@ -150,106 +204,148 @@ class No_Tab_Expand_RealWorld(_TabExpand_RealWorld,_VimTest):
class SnippetOptions_Regex_Expand(_VimTest): class SnippetOptions_Regex_Expand(_VimTest):
snippets = ("(test)", "Expand me!", "", "r") snippets = ('(test)', 'Expand me!', '', 'r')
keys = "test" + EX keys = 'test' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class SnippetOptions_Regex_Multiple(_VimTest): class SnippetOptions_Regex_Multiple(_VimTest):
snippets = ("(test *)+", "Expand me!", "", "r") snippets = ('(test *)+', 'Expand me!', '', 'r')
keys = "test test test" + EX keys = 'test test test' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class _Regex_Self(_VimTest): class _Regex_Self(_VimTest):
snippets = ("((?<=\W)|^)(\.)", "self.", "", "r") snippets = ('((?<=\W)|^)(\.)', 'self.', '', 'r')
class SnippetOptions_Regex_Self_Start(_Regex_Self): class SnippetOptions_Regex_Self_Start(_Regex_Self):
keys = "." + EX keys = '.' + EX
wanted = "self." wanted = 'self.'
class SnippetOptions_Regex_Self_Space(_Regex_Self): class SnippetOptions_Regex_Self_Space(_Regex_Self):
keys = " ." + EX keys = ' .' + EX
wanted = " self." wanted = ' self.'
class SnippetOptions_Regex_Self_TextAfter(_Regex_Self): class SnippetOptions_Regex_Self_TextAfter(_Regex_Self):
keys = " .a" + EX keys = ' .a' + EX
wanted = " .a" + EX wanted = ' .a' + EX
class SnippetOptions_Regex_Self_TextBefore(_Regex_Self): class SnippetOptions_Regex_Self_TextBefore(_Regex_Self):
keys = "a." + EX keys = 'a.' + EX
wanted = "a." + EX wanted = 'a.' + EX
class SnippetOptions_Regex_PythonBlockMatch(_VimTest): class SnippetOptions_Regex_PythonBlockMatch(_VimTest):
snippets = (r"([abc]+)([def]+)", r"""`!p m = 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 = 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'
# Tests for Bug #691575 # Tests for Bug #691575
class SnippetOptions_Regex_SameLine_Long_End(_VimTest): class SnippetOptions_Regex_SameLine_Long_End(_VimTest):
snippets = ("(test.*)", "Expand me!", "", "r") snippets = ('(test.*)', 'Expand me!', '', 'r')
keys = "test test abc" + EX keys = 'test test abc' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class SnippetOptions_Regex_SameLine_Long_Start(_VimTest): class SnippetOptions_Regex_SameLine_Long_Start(_VimTest):
snippets = ("(.*test)", "Expand me!", "", "r") snippets = ('(.*test)', 'Expand me!', '', 'r')
keys = "abc test test" + EX keys = 'abc test test' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class SnippetOptions_Regex_SameLine_Simple(_VimTest): class SnippetOptions_Regex_SameLine_Simple(_VimTest):
snippets = ("(test)", "Expand me!", "", "r") snippets = ('(test)', 'Expand me!', '', 'r')
keys = "abc test test" + EX keys = 'abc test test' + EX
wanted = "abc test Expand me!" wanted = 'abc test Expand me!'
class MultiWordSnippet_Simple(_VimTest): class MultiWordSnippet_Simple(_VimTest):
snippets = ("test me", "Expand me!") snippets = ('test me', 'Expand me!')
keys = "test me" + EX keys = 'test me' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_Expand(_VimTest): class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_Expand(_VimTest):
snippets = ("test it", "Expand me!", "", "b") snippets = ('test it', 'Expand me!', '', 'b')
keys = "test it" + EX keys = 'test it' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_Expand2(_VimTest): class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_Expand2(_VimTest):
snippets = ("test it", "Expand me!", "", "b") snippets = ('test it', 'Expand me!', '', 'b')
keys = " test it" + EX keys = ' test it' + EX
wanted = " Expand me!" wanted = ' Expand me!'
class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_DontExpand(_VimTest): class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_DontExpand(_VimTest):
snippets = ("test it", "Expand me!", "", "b") snippets = ('test it', 'Expand me!', '', 'b')
keys = "a test it" + EX keys = 'a test it' + EX
wanted = "a test it" + EX wanted = 'a test it' + EX
class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWO(_VimTest): class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWO(_VimTest):
snippets = ( snippets = (
("test it", "Expand me!", "", "b"), ('test it', 'Expand me!', '', 'b'),
("test it", "not at beginning", "", ""), ('test it', 'not at beginning', '', ''),
) )
keys = "a test it" + EX keys = 'a test it' + EX
wanted = "a not at beginning" wanted = 'a not at beginning'
class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWOChoose(_VimTest):
class MultiWord_SnippetOptions_OnlyExpandWhenWSInFront_OneWithOneWOChoose(
_VimTest):
snippets = ( snippets = (
("test it", "Expand me!", "", "b"), ('test it', 'Expand me!', '', 'b'),
("test it", "not at beginning", "", ""), ('test it', 'not at beginning', '', ''),
) )
keys = " test it" + EX + "1\n" keys = ' test it' + EX + '1\n'
wanted = " Expand me!" wanted = ' Expand me!'
class MultiWord_SnippetOptions_ExpandInwordSnippets_SimpleExpand(_VimTest): class MultiWord_SnippetOptions_ExpandInwordSnippets_SimpleExpand(_VimTest):
snippets = (("test it", "Expand me!", "", "i"), ) snippets = (('test it', 'Expand me!', '', 'i'), )
keys = "atest it" + EX keys = 'atest it' + EX
wanted = "aExpand me!" wanted = 'aExpand me!'
class MultiWord_SnippetOptions_ExpandInwordSnippets_ExpandSingle(_VimTest): class MultiWord_SnippetOptions_ExpandInwordSnippets_ExpandSingle(_VimTest):
snippets = (("test it", "Expand me!", "", "i"), ) snippets = (('test it', 'Expand me!', '', 'i'), )
keys = "test it" + EX keys = 'test it' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class _MultiWord_SnippetOptions_ExpandWordSnippets(_VimTest): class _MultiWord_SnippetOptions_ExpandWordSnippets(_VimTest):
snippets = (("test it", "Expand me!", "", "w"), ) snippets = (('test it', 'Expand me!', '', 'w'), )
class MultiWord_SnippetOptions_ExpandWordSnippets_NormalExpand( class MultiWord_SnippetOptions_ExpandWordSnippets_NormalExpand(
_MultiWord_SnippetOptions_ExpandWordSnippets): _MultiWord_SnippetOptions_ExpandWordSnippets):
keys = "test it" + EX keys = 'test it' + EX
wanted = "Expand me!" wanted = 'Expand me!'
class MultiWord_SnippetOptions_ExpandWordSnippets_NoExpand( class MultiWord_SnippetOptions_ExpandWordSnippets_NoExpand(
_MultiWord_SnippetOptions_ExpandWordSnippets): _MultiWord_SnippetOptions_ExpandWordSnippets):
keys = "atest it" + EX keys = 'atest it' + EX
wanted = "atest it" + EX wanted = 'atest it' + EX
class MultiWord_SnippetOptions_ExpandWordSnippets_ExpandSuffix( class MultiWord_SnippetOptions_ExpandWordSnippets_ExpandSuffix(
_MultiWord_SnippetOptions_ExpandWordSnippets): _MultiWord_SnippetOptions_ExpandWordSnippets):
keys = "a-test it" + EX keys = 'a-test it' + EX
wanted = "a-Expand me!" wanted = 'a-Expand me!'
# Snippet Options #}}} # Snippet Options #}}}

View File

@ -2,92 +2,102 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# Snippet Priority {{{# # Snippet Priority {{{#
class SnippetPriorities_MultiWordTriggerOverwriteExisting(_VimTest): class SnippetPriorities_MultiWordTriggerOverwriteExisting(_VimTest):
snippets = ( snippets = (
("test me", "${1:Hallo}", "Types Hallo"), ('test me', '${1:Hallo}', 'Types Hallo'),
("test me", "${1:World}", "Types World"), ('test me', '${1:World}', 'Types World'),
("test me", "We overwrite", "Overwrite the two", "", 1), ('test me', 'We overwrite', 'Overwrite the two', '', 1),
) )
keys = "test me" + EX keys = 'test me' + EX
wanted = "We overwrite" wanted = 'We overwrite'
class SnippetPriorities_DoNotCareAboutNonMatchings(_VimTest): class SnippetPriorities_DoNotCareAboutNonMatchings(_VimTest):
snippets = ( snippets = (
("test1", "Hallo", "Types Hallo"), ('test1', 'Hallo', 'Types Hallo'),
("test2", "We overwrite", "Overwrite the two", "", 1), ('test2', 'We overwrite', 'Overwrite the two', '', 1),
) )
keys = "test1" + EX keys = 'test1' + EX
wanted = "Hallo" wanted = 'Hallo'
class SnippetPriorities_OverwriteExisting(_VimTest): class SnippetPriorities_OverwriteExisting(_VimTest):
snippets = ( snippets = (
("test", "${1:Hallo}", "Types Hallo"), ('test', '${1:Hallo}', 'Types Hallo'),
("test", "${1:World}", "Types World"), ('test', '${1:World}', 'Types World'),
("test", "We overwrite", "Overwrite the two", "", 1), ('test', 'We overwrite', 'Overwrite the two', '', 1),
) )
keys = "test" + EX keys = 'test' + EX
wanted = "We overwrite" wanted = 'We overwrite'
class SnippetPriorities_OverwriteTwice_ECR(_VimTest): class SnippetPriorities_OverwriteTwice_ECR(_VimTest):
snippets = ( snippets = (
("test", "${1:Hallo}", "Types Hallo"), ('test', '${1:Hallo}', 'Types Hallo'),
("test", "${1:World}", "Types World"), ('test', '${1:World}', 'Types World'),
("test", "We overwrite", "Overwrite the two", "", 1), ('test', 'We overwrite', 'Overwrite the two', '', 1),
("test", "again", "Overwrite again", "", 2), ('test', 'again', 'Overwrite again', '', 2),
) )
keys = "test" + EX keys = 'test' + EX
wanted = "again" wanted = 'again'
class SnippetPriorities_OverwriteThenChoose_ECR(_VimTest): class SnippetPriorities_OverwriteThenChoose_ECR(_VimTest):
snippets = ( snippets = (
("test", "${1:Hallo}", "Types Hallo"), ('test', '${1:Hallo}', 'Types Hallo'),
("test", "${1:World}", "Types World"), ('test', '${1:World}', 'Types World'),
("test", "We overwrite", "Overwrite the two", "", 1), ('test', 'We overwrite', 'Overwrite the two', '', 1),
("test", "No overwrite", "Not overwritten", "", 1), ('test', 'No overwrite', 'Not overwritten', '', 1),
) )
keys = "test" + EX + "1\n\n" + "test" + EX + "2\n" keys = 'test' + EX + '1\n\n' + 'test' + EX + '2\n'
wanted = "We overwrite\nNo overwrite" wanted = 'We overwrite\nNo overwrite'
class SnippetPriorities_AddedHasHigherThanFile(_VimTest): class SnippetPriorities_AddedHasHigherThanFile(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet test "Test Snippet" b snippet test "Test Snippet" b
This is a test snippet This is a test snippet
endsnippet endsnippet
"""} """}
snippets = ( snippets = (
("test", "We overwrite", "Overwrite the two", "", 1), ('test', 'We overwrite', 'Overwrite the two', '', 1),
) )
keys = "test" + EX keys = 'test' + EX
wanted = "We overwrite" wanted = 'We overwrite'
class SnippetPriorities_FileHasHigherThanAdded(_VimTest): class SnippetPriorities_FileHasHigherThanAdded(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
snippet test "Test Snippet" b snippet test "Test Snippet" b
This is a test snippet This is a test snippet
endsnippet endsnippet
"""} """}
snippets = ( snippets = (
("test", "We do not overwrite", "Overwrite the two", "", -1), ('test', 'We do not overwrite', 'Overwrite the two', '', -1),
) )
keys = "test" + EX keys = 'test' + EX
wanted = "This is a test snippet" wanted = 'This is a test snippet'
class SnippetPriorities_FileHasHigherThanAdded(_VimTest): class SnippetPriorities_FileHasHigherThanAdded(_VimTest):
files = { "us/all.snippets": r""" files = { 'us/all.snippets': r"""
priority -3 priority -3
snippet test "Test Snippet" b snippet test "Test Snippet" b
This is a test snippet This is a test snippet
endsnippet endsnippet
"""} """}
snippets = ( snippets = (
("test", "We overwrite", "Overwrite the two", "", -5), ('test', 'We overwrite', 'Overwrite the two', '', -5),
) )
keys = "test" + EX keys = 'test' + EX
wanted = "This is a test snippet" wanted = 'This is a test snippet'
class SnippetPriorities_SimpleClear(_VimTest): class SnippetPriorities_SimpleClear(_VimTest):
files = { files = {
"us/all.snippets": r""" 'us/all.snippets': r"""
priority 1 priority 1
clearsnippets clearsnippets
priority -1 priority -1
@ -96,50 +106,53 @@ class SnippetPriorities_SimpleClear(_VimTest):
endsnippet endsnippet
""" """
} }
keys = "test" + EX keys = 'test' + EX
wanted = "test" + EX wanted = 'test' + EX
class SnippetPriorities_SimpleClear2(_VimTest): class SnippetPriorities_SimpleClear2(_VimTest):
files = { files = {
"us/all.snippets": r""" 'us/all.snippets': r"""
clearsnippets clearsnippets
snippet test "Test snippet" snippet test "Test snippet"
Should not expand to this. Should not expand to this.
endsnippet endsnippet
""" """
} }
keys = "test" + EX keys = 'test' + EX
wanted = "test" + EX wanted = 'test' + EX
class SnippetPriorities_ClearedByParent(_VimTest): class SnippetPriorities_ClearedByParent(_VimTest):
files = { files = {
"us/p.snippets": r""" 'us/p.snippets': r"""
clearsnippets clearsnippets
""", """,
"us/c.snippets": r""" 'us/c.snippets': r"""
extends p extends p
snippet test "Test snippets" snippet test "Test snippets"
Should not expand to this. Should not expand to this.
endsnippet endsnippet
""" """
} }
keys = ESC + ":set ft=c\n" + "itest" + EX keys = ESC + ':set ft=c\n' + 'itest' + EX
wanted = "test" + EX wanted = 'test' + EX
class SnippetPriorities_ClearedByChild(_VimTest): class SnippetPriorities_ClearedByChild(_VimTest):
files = { files = {
"us/p.snippets": r""" 'us/p.snippets': r"""
snippet test "Test snippets" snippet test "Test snippets"
Should only expand in p. Should only expand in p.
endsnippet endsnippet
""", """,
"us/c.snippets": r""" 'us/c.snippets': r"""
extends p extends p
clearsnippets clearsnippets
""" """
} }
keys = (ESC + ":set ft=p\n" + "itest" + EX + "\n" + keys = (ESC + ':set ft=p\n' + 'itest' + EX + '\n' +
ESC + ":set ft=c\n" + "itest" + EX + ESC + ":set ft=p") ESC + ':set ft=c\n' + 'itest' + EX + ESC + ':set ft=p')
wanted = "Should only expand in p.\ntest" + EX wanted = 'Should only expand in p.\ntest' + EX
# End: Snippet Priority #}}} # End: Snippet Priority #}}}

View File

@ -1,258 +1,366 @@
from test.vim_test_case import VimTestCase as _VimTest from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
class TabStopSimpleReplace_ExpectCorrectResult(_VimTest): class TabStopSimpleReplace_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo ${0:End} ${1:Beginning}") snippets = ('hallo', 'hallo ${0:End} ${1:Beginning}')
keys = "hallo" + EX + "na" + JF + "Du Nase" keys = 'hallo' + EX + 'na' + JF + 'Du Nase'
wanted = "hallo Du Nase na" wanted = 'hallo Du Nase na'
class TabStopSimpleReplaceZeroLengthTabstops_ExpectCorrectResult(_VimTest): class TabStopSimpleReplaceZeroLengthTabstops_ExpectCorrectResult(_VimTest):
snippets = ("test", r":latex:\`$1\`$0") snippets = ('test', r":latex:\`$1\`$0")
keys = "test" + EX + "Hello" + JF + "World" keys = 'test' + EX + 'Hello' + JF + 'World'
wanted = ":latex:`Hello`World" wanted = ':latex:`Hello`World'
class TabStopSimpleReplaceReversed_ExpectCorrectResult(_VimTest): class TabStopSimpleReplaceReversed_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo ${1:End} ${0:Beginning}") snippets = ('hallo', 'hallo ${1:End} ${0:Beginning}')
keys = "hallo" + EX + "na" + JF + "Du Nase" keys = 'hallo' + EX + 'na' + JF + 'Du Nase'
wanted = "hallo na Du Nase" wanted = 'hallo na Du Nase'
class TabStopSimpleReplaceSurrounded_ExpectCorrectResult(_VimTest): class TabStopSimpleReplaceSurrounded_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo ${0:End} a small feed") snippets = ('hallo', 'hallo ${0:End} a small feed')
keys = "hallo" + EX + "Nase" keys = 'hallo' + EX + 'Nase'
wanted = "hallo Nase a small feed" wanted = 'hallo Nase a small feed'
class TabStopSimpleReplaceSurrounded1_ExpectCorrectResult(_VimTest): class TabStopSimpleReplaceSurrounded1_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo $0 a small feed") snippets = ('hallo', 'hallo $0 a small feed')
keys = "hallo" + EX + "Nase" keys = 'hallo' + EX + 'Nase'
wanted = "hallo Nase a small feed" wanted = 'hallo Nase a small feed'
class TabStop_Exit_ExpectCorrectResult(_VimTest): class TabStop_Exit_ExpectCorrectResult(_VimTest):
snippets = ("echo", "$0 run") snippets = ('echo', '$0 run')
keys = "echo" + EX + "test" keys = 'echo' + EX + 'test'
wanted = "test run" wanted = 'test run'
class TabStopNoReplace_ExpectCorrectResult(_VimTest): class TabStopNoReplace_ExpectCorrectResult(_VimTest):
snippets = ("echo", "echo ${1:Hallo}") snippets = ('echo', 'echo ${1:Hallo}')
keys = "echo" + EX keys = 'echo' + EX
wanted = "echo Hallo" wanted = 'echo Hallo'
class TabStop_EscapingCharsBackticks(_VimTest): class TabStop_EscapingCharsBackticks(_VimTest):
snippets = ("test", r"snip \` literal") snippets = ('test', r"snip \` literal")
keys = "test" + EX keys = 'test' + EX
wanted = "snip ` literal" wanted = 'snip ` literal'
class TabStop_EscapingCharsDollars(_VimTest): class TabStop_EscapingCharsDollars(_VimTest):
snippets = ("test", r"snip \$0 $$0 end") snippets = ('test', r"snip \$0 $$0 end")
keys = "test" + EX + "hi" keys = 'test' + EX + 'hi'
wanted = "snip $0 $hi end" wanted = 'snip $0 $hi end'
class TabStop_EscapingCharsDollars1(_VimTest): class TabStop_EscapingCharsDollars1(_VimTest):
snippets = ("test", r"a\${1:literal}") snippets = ('test', r"a\${1:literal}")
keys = "test" + EX keys = 'test' + EX
wanted = "a${1:literal}" wanted = 'a${1:literal}'
class TabStop_EscapingCharsDollars_BeginningOfLine(_VimTest): class TabStop_EscapingCharsDollars_BeginningOfLine(_VimTest):
snippets = ("test", "\n\\${1:literal}") snippets = ('test', '\n\\${1:literal}')
keys = "test" + EX keys = 'test' + EX
wanted = "\n${1:literal}" wanted = '\n${1:literal}'
class TabStop_EscapingCharsDollars_BeginningOfDefinitionText(_VimTest): class TabStop_EscapingCharsDollars_BeginningOfDefinitionText(_VimTest):
snippets = ("test", "\\${1:literal}") snippets = ('test', '\\${1:literal}')
keys = "test" + EX keys = 'test' + EX
wanted = "${1:literal}" wanted = '${1:literal}'
class TabStop_EscapingChars_Backslash(_VimTest): class TabStop_EscapingChars_Backslash(_VimTest):
snippets = ("test", r"This \ is a backslash!") snippets = ('test', r"This \ is a backslash!")
keys = "test" + EX keys = 'test' + EX
wanted = "This \\ is a backslash!" wanted = 'This \\ is a backslash!'
class TabStop_EscapingChars_Backslash2(_VimTest): class TabStop_EscapingChars_Backslash2(_VimTest):
snippets = ("test", r"This is a backslash \\ done") snippets = ('test', r"This is a backslash \\ done")
keys = "test" + EX keys = 'test' + EX
wanted = r"This is a backslash \ done" wanted = r"This is a backslash \ done"
class TabStop_EscapingChars_Backslash3(_VimTest): class TabStop_EscapingChars_Backslash3(_VimTest):
snippets = ("test", r"These are two backslashes \\\\ done") snippets = ('test', r"These are two backslashes \\\\ done")
keys = "test" + EX keys = 'test' + EX
wanted = r"These are two backslashes \\ done" wanted = r"These are two backslashes \\ done"
class TabStop_EscapingChars_Backslash4(_VimTest): class TabStop_EscapingChars_Backslash4(_VimTest):
# Test for bug 746446 # Test for bug 746446
snippets = ("test", r"\\$1{$2}") snippets = ('test', r"\\$1{$2}")
keys = "test" + EX + "hello" + JF + "world" keys = 'test' + EX + 'hello' + JF + 'world'
wanted = r"\hello{world}" wanted = r"\hello{world}"
class TabStop_EscapingChars_RealLife(_VimTest): class TabStop_EscapingChars_RealLife(_VimTest):
snippets = ("test", r"usage: \`basename \$0\` ${1:args}") snippets = ('test', r"usage: \`basename \$0\` ${1:args}")
keys = "test" + EX + "[ -u -v -d ]" keys = 'test' + EX + '[ -u -v -d ]'
wanted = "usage: `basename $0` [ -u -v -d ]" wanted = 'usage: `basename $0` [ -u -v -d ]'
class TabStopEscapingWhenSelected_ECR(_VimTest): class TabStopEscapingWhenSelected_ECR(_VimTest):
snippets = ("test", "snip ${1:default}") snippets = ('test', 'snip ${1:default}')
keys = "test" + EX + ESC + "0ihi" keys = 'test' + EX + ESC + '0ihi'
wanted = "hisnip default" wanted = 'hisnip default'
class TabStopEscapingWhenSelectedSingleCharTS_ECR(_VimTest): class TabStopEscapingWhenSelectedSingleCharTS_ECR(_VimTest):
snippets = ("test", "snip ${1:i}") snippets = ('test', 'snip ${1:i}')
keys = "test" + EX + ESC + "0ihi" keys = 'test' + EX + ESC + '0ihi'
wanted = "hisnip i" wanted = 'hisnip i'
class TabStopEscapingWhenSelectedNoCharTS_ECR(_VimTest): class TabStopEscapingWhenSelectedNoCharTS_ECR(_VimTest):
snippets = ("test", "snip $1") snippets = ('test', 'snip $1')
keys = "test" + EX + ESC + "0ihi" keys = 'test' + EX + ESC + '0ihi'
wanted = "hisnip " wanted = 'hisnip '
class TabStopWithOneChar_ExpectCorrectResult(_VimTest): class TabStopWithOneChar_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "nothing ${1:i} hups") snippets = ('hallo', 'nothing ${1:i} hups')
keys = "hallo" + EX + "ship" keys = 'hallo' + EX + 'ship'
wanted = "nothing ship hups" wanted = 'nothing ship hups'
class TabStopTestJumping_ExpectCorrectResult(_VimTest): class TabStopTestJumping_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo ${2:End} mitte ${1:Beginning}") snippets = ('hallo', 'hallo ${2:End} mitte ${1:Beginning}')
keys = "hallo" + EX + JF + "Test" + JF + "Hi" keys = 'hallo' + EX + JF + 'Test' + JF + 'Hi'
wanted = "hallo Test mitte BeginningHi" wanted = 'hallo Test mitte BeginningHi'
class TabStopTestJumping2_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo $2 $1")
keys = "hallo" + EX + JF + "Test" + JF + "Hi" class TabStopTestJumping2_ExpectCorrectResult(_VimTest):
wanted = "hallo Test Hi" snippets = ('hallo', 'hallo $2 $1')
class TabStopTestJumpingRLExampleWithZeroTab_ExpectCorrectResult(_VimTest): keys = 'hallo' + EX + JF + 'Test' + JF + 'Hi'
snippets = ("test", "each_byte { |${1:byte}| $0 }") wanted = 'hallo Test Hi'
keys = "test" + EX + JF + "Blah"
wanted = "each_byte { |byte| Blah }"
class TabStopTestJumpingRLExampleWithZeroTab_ExpectCorrectResult(_VimTest):
snippets = ('test', 'each_byte { |${1:byte}| $0 }')
keys = 'test' + EX + JF + 'Blah'
wanted = 'each_byte { |byte| Blah }'
class TabStopTestJumpingDontJumpToEndIfThereIsTabZero_ExpectCorrectResult(
_VimTest):
snippets = ('hallo', 'hallo $0 $1')
keys = 'hallo' + EX + 'Test' + JF + 'Hi' + JF + JF + 'du'
wanted = 'hallo Hi' + 2 * JF + 'du Test'
class TabStopTestJumpingDontJumpToEndIfThereIsTabZero_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo $0 $1")
keys = "hallo" + EX + "Test" + JF + "Hi" + JF + JF + "du"
wanted = "hallo Hi" + 2*JF + "du Test"
class TabStopTestBackwardJumping_ExpectCorrectResult(_VimTest): class TabStopTestBackwardJumping_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo ${2:End} mitte${1:Beginning}") snippets = ('hallo', 'hallo ${2:End} mitte${1:Beginning}')
keys = "hallo" + EX + "Somelengthy Text" + JF + "Hi" + JB + \ keys = 'hallo' + EX + 'Somelengthy Text' + JF + 'Hi' + JB + \
"Lets replace it again" + JF + "Blah" + JF + JB*2 + JF 'Lets replace it again' + JF + 'Blah' + JF + JB * 2 + JF
wanted = "hallo Blah mitteLets replace it again" + JB*2 + JF wanted = 'hallo Blah mitteLets replace it again' + JB * 2 + JF
class TabStopTestBackwardJumping2_ExpectCorrectResult(_VimTest): class TabStopTestBackwardJumping2_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo $2 $1") snippets = ('hallo', 'hallo $2 $1')
keys = "hallo" + EX + "Somelengthy Text" + JF + "Hi" + JB + \ keys = 'hallo' + EX + 'Somelengthy Text' + JF + 'Hi' + JB + \
"Lets replace it again" + JF + "Blah" + JF + JB*2 + JF 'Lets replace it again' + JF + 'Blah' + JF + JB * 2 + JF
wanted = "hallo Blah Lets replace it again" + JB*2 + JF wanted = 'hallo Blah Lets replace it again' + JB * 2 + JF
class TabStopTestMultilineExpand_ExpectCorrectResult(_VimTest): class TabStopTestMultilineExpand_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "hallo $0\nnice $1 work\n$3 $2\nSeem to work") snippets = ('hallo', 'hallo $0\nnice $1 work\n$3 $2\nSeem to work')
keys ="test hallo World" + ESC + "02f i" + EX + "world" + JF + "try" + \ keys = 'test hallo World' + ESC + '02f i' + EX + 'world' + JF + 'try' + \
JF + "test" + JF + "one more" + JF JF + 'test' + JF + 'one more' + JF
wanted = "test hallo one more" + JF + "\nnice world work\n" \ wanted = 'test hallo one more' + JF + '\nnice world work\n' \
"test try\nSeem to work World" 'test try\nSeem to work World'
class TabStop_TSInDefaultTextRLExample_OverwriteNone_ECR(_VimTest): class TabStop_TSInDefaultTextRLExample_OverwriteNone_ECR(_VimTest):
snippets = ("test", """<div${1: id="${2:some_id}"}>\n $0\n</div>""") snippets = ('test', """<div${1: id="${2:some_id}"}>\n $0\n</div>""")
keys = "test" + EX keys = 'test' + EX
wanted = """<div id="some_id">\n \n</div>""" wanted = """<div id="some_id">\n \n</div>"""
class TabStop_TSInDefaultTextRLExample_OverwriteFirst_NoJumpBack(_VimTest): class TabStop_TSInDefaultTextRLExample_OverwriteFirst_NoJumpBack(_VimTest):
snippets = ("test", """<div${1: id="${2:some_id}"}>\n $0\n</div>""") snippets = ('test', """<div${1: id="${2:some_id}"}>\n $0\n</div>""")
keys = "test" + EX + " blah" + JF + "Hallo" keys = 'test' + EX + ' blah' + JF + 'Hallo'
wanted = """<div blah>\n Hallo\n</div>""" wanted = """<div blah>\n Hallo\n</div>"""
class TabStop_TSInDefaultTextRLExample_DeleteFirst(_VimTest): class TabStop_TSInDefaultTextRLExample_DeleteFirst(_VimTest):
snippets = ("test", """<div${1: id="${2:some_id}"}>\n $0\n</div>""") snippets = ('test', """<div${1: id="${2:some_id}"}>\n $0\n</div>""")
keys = "test" + EX + BS + JF + "Hallo" keys = 'test' + EX + BS + JF + 'Hallo'
wanted = """<div>\n Hallo\n</div>""" wanted = """<div>\n Hallo\n</div>"""
class TabStop_TSInDefaultTextRLExample_OverwriteFirstJumpBack(_VimTest): class TabStop_TSInDefaultTextRLExample_OverwriteFirstJumpBack(_VimTest):
snippets = ("test", """<div${1: id="${2:some_id}"}>\n $3 $0\n</div>""") snippets = ('test', """<div${1: id="${2:some_id}"}>\n $3 $0\n</div>""")
keys = "test" + EX + "Hi" + JF + "Hallo" + JB + "SomethingElse" + JF + \ keys = 'test' + EX + 'Hi' + JF + 'Hallo' + JB + 'SomethingElse' + JF + \
"Nupl" + JF + "Nox" 'Nupl' + JF + 'Nox'
wanted = """<divSomethingElse>\n Nupl Nox\n</div>""" wanted = """<divSomethingElse>\n Nupl Nox\n</div>"""
class TabStop_TSInDefaultTextRLExample_OverwriteSecond(_VimTest): class TabStop_TSInDefaultTextRLExample_OverwriteSecond(_VimTest):
snippets = ("test", """<div${1: id="${2:some_id}"}>\n $0\n</div>""") snippets = ('test', """<div${1: id="${2:some_id}"}>\n $0\n</div>""")
keys = "test" + EX + JF + "no" + JF + "End" keys = 'test' + EX + JF + 'no' + JF + 'End'
wanted = """<div id="no">\n End\n</div>""" wanted = """<div id="no">\n End\n</div>"""
class TabStop_TSInDefaultTextRLExample_OverwriteSecondTabBack(_VimTest): class TabStop_TSInDefaultTextRLExample_OverwriteSecondTabBack(_VimTest):
snippets = ("test", """<div${1: id="${2:some_id}"}>\n $3 $0\n</div>""") snippets = ('test', """<div${1: id="${2:some_id}"}>\n $3 $0\n</div>""")
keys = "test" + EX + JF + "no" + JF + "End" + JB + "yes" + JF + "Begin" \ keys = 'test' + EX + JF + 'no' + JF + 'End' + JB + 'yes' + JF + 'Begin' \
+ JF + "Hi" + JF + 'Hi'
wanted = """<div id="yes">\n Begin Hi\n</div>""" wanted = """<div id="yes">\n Begin Hi\n</div>"""
class TabStop_TSInDefaultTextRLExample_OverwriteSecondTabBackTwice(_VimTest): class TabStop_TSInDefaultTextRLExample_OverwriteSecondTabBackTwice(_VimTest):
snippets = ("test", """<div${1: id="${2:some_id}"}>\n $3 $0\n</div>""") snippets = ('test', """<div${1: id="${2:some_id}"}>\n $3 $0\n</div>""")
keys = "test" + EX + JF + "no" + JF + "End" + JB + "yes" + JB + \ keys = 'test' + EX + JF + 'no' + JF + 'End' + JB + 'yes' + JB + \
" allaway" + JF + "Third" + JF + "Last" ' allaway' + JF + 'Third' + JF + 'Last'
wanted = """<div allaway>\n Third Last\n</div>""" wanted = """<div allaway>\n Third Last\n</div>"""
class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecond(_VimTest): class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecond(_VimTest):
snippets = ("test", """h${1:a$2b}l""") snippets = ('test', """h${1:a$2b}l""")
keys = "test" + EX + JF + "ups" + JF + "End" keys = 'test' + EX + JF + 'ups' + JF + 'End'
wanted = """haupsblEnd""" wanted = """haupsblEnd"""
class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteFirst(_VimTest): class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteFirst(_VimTest):
snippets = ("test", """h${1:a$2b}l""") snippets = ('test', """h${1:a$2b}l""")
keys = "test" + EX + "ups" + JF + "End" keys = 'test' + EX + 'ups' + JF + 'End'
wanted = """hupslEnd""" wanted = """hupslEnd"""
class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackOverwrite(_VimTest):
snippets = ("test", """h${1:a$2b}l""")
keys = "test" + EX + JF + "longertext" + JB + "overwrite" + JF + "End" class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackOverwrite(
_VimTest):
snippets = ('test', """h${1:a$2b}l""")
keys = 'test' + EX + JF + 'longertext' + JB + 'overwrite' + JF + 'End'
wanted = """hoverwritelEnd""" wanted = """hoverwritelEnd"""
class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackAndForward0(_VimTest):
snippets = ("test", """h${1:a$2b}l""")
keys = "test" + EX + JF + "longertext" + JB + JF + "overwrite" + JF + "End" class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackAndForward0(
_VimTest):
snippets = ('test', """h${1:a$2b}l""")
keys = 'test' + EX + JF + 'longertext' + JB + JF + 'overwrite' + JF + 'End'
wanted = """haoverwriteblEnd""" wanted = """haoverwriteblEnd"""
class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackAndForward1(_VimTest):
snippets = ("test", """h${1:a$2b}l""")
keys = "test" + EX + JF + "longertext" + JB + JF + JF + "End" class TabStop_TSInDefaultText_ZeroLengthNested_OverwriteSecondJumpBackAndForward1(
_VimTest):
snippets = ('test', """h${1:a$2b}l""")
keys = 'test' + EX + JF + 'longertext' + JB + JF + JF + 'End'
wanted = """halongertextblEnd""" wanted = """halongertextblEnd"""
class TabStop_TSInDefaultNested_OverwriteOneJumpBackToOther(_VimTest): class TabStop_TSInDefaultNested_OverwriteOneJumpBackToOther(_VimTest):
snippets = ("test", "hi ${1:this ${2:second ${3:third}}} $4") snippets = ('test', 'hi ${1:this ${2:second ${3:third}}} $4')
keys = "test" + EX + JF + "Hallo" + JF + "Ende" keys = 'test' + EX + JF + 'Hallo' + JF + 'Ende'
wanted = "hi this Hallo Ende" wanted = 'hi this Hallo Ende'
class TabStop_TSInDefaultNested_OverwriteOneJumpToThird(_VimTest): class TabStop_TSInDefaultNested_OverwriteOneJumpToThird(_VimTest):
snippets = ("test", "hi ${1:this ${2:second ${3:third}}} $4") snippets = ('test', 'hi ${1:this ${2:second ${3:third}}} $4')
keys = "test" + EX + JF + JF + "Hallo" + JF + "Ende" keys = 'test' + EX + JF + JF + 'Hallo' + JF + 'Ende'
wanted = "hi this second Hallo Ende" wanted = 'hi this second Hallo Ende'
class TabStop_TSInDefaultNested_OverwriteOneJumpAround(_VimTest): class TabStop_TSInDefaultNested_OverwriteOneJumpAround(_VimTest):
snippets = ("test", "hi ${1:this ${2:second ${3:third}}} $4") snippets = ('test', 'hi ${1:this ${2:second ${3:third}}} $4')
keys = "test" + EX + JF + JF + "Hallo" + JB+JB + "Blah" + JF + "Ende" keys = 'test' + EX + JF + JF + 'Hallo' + JB + JB + 'Blah' + JF + 'Ende'
wanted = "hi Blah Ende" wanted = 'hi Blah Ende'
class TabStop_TSInDefault_MirrorsOutside_DoNothing(_VimTest): class TabStop_TSInDefault_MirrorsOutside_DoNothing(_VimTest):
snippets = ("test", "hi ${1:this ${2:second}} $2") snippets = ('test', 'hi ${1:this ${2:second}} $2')
keys = "test" + EX keys = 'test' + EX
wanted = "hi this second second" wanted = 'hi this second second'
class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond(_VimTest): class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond(_VimTest):
snippets = ("test", "hi ${1:this ${2:second}} $2") snippets = ('test', 'hi ${1:this ${2:second}} $2')
keys = "test" + EX + JF + "Hallo" keys = 'test' + EX + JF + 'Hallo'
wanted = "hi this Hallo Hallo" wanted = 'hi this Hallo Hallo'
class TabStop_TSInDefault_MirrorsOutside_Overwrite0(_VimTest): class TabStop_TSInDefault_MirrorsOutside_Overwrite0(_VimTest):
snippets = ("test", "hi ${1:this ${2:second}} $2") snippets = ('test', 'hi ${1:this ${2:second}} $2')
keys = "test" + EX + "Hallo" keys = 'test' + EX + 'Hallo'
wanted = "hi Hallo " wanted = 'hi Hallo '
class TabStop_TSInDefault_MirrorsOutside_Overwrite1(_VimTest): class TabStop_TSInDefault_MirrorsOutside_Overwrite1(_VimTest):
snippets = ("test", "$1: ${1:'${2:second}'} $2") snippets = ('test', "$1: ${1:'${2:second}'} $2")
keys = "test" + EX + "Hallo" keys = 'test' + EX + 'Hallo'
wanted = "Hallo: Hallo " wanted = 'Hallo: Hallo '
class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond1(_VimTest): class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond1(_VimTest):
snippets = ("test", "$1: ${1:'${2:second}'} $2") snippets = ('test', "$1: ${1:'${2:second}'} $2")
keys = "test" + EX + JF + "Hallo" keys = 'test' + EX + JF + 'Hallo'
wanted = "'Hallo': 'Hallo' Hallo" wanted = "'Hallo': 'Hallo' Hallo"
class TabStop_TSInDefault_MirrorsOutside_OverwriteFirstSwitchNumbers(_VimTest): class TabStop_TSInDefault_MirrorsOutside_OverwriteFirstSwitchNumbers(_VimTest):
snippets = ("test", "$2: ${2:'${1:second}'} $1") snippets = ('test', "$2: ${2:'${1:second}'} $1")
keys = "test" + EX + "Hallo" keys = 'test' + EX + 'Hallo'
wanted = "'Hallo': 'Hallo' Hallo" wanted = "'Hallo': 'Hallo' Hallo"
class TabStop_TSInDefault_MirrorsOutside_OverwriteFirst_RLExample(_VimTest): class TabStop_TSInDefault_MirrorsOutside_OverwriteFirst_RLExample(_VimTest):
snippets = ("test", """`!p snip.rv = t[1].split('/')[-1].lower().strip("'")` = require(${1:'${2:sys}'})""") snippets = (
keys = "test" + EX + "WORLD" + JF + "End" 'test',
wanted = "world = require(WORLD)End" """`!p snip.rv = t[1].split('/')[-1].lower().strip("'")` = require(${1:'${2:sys}'})""")
keys = 'test' + EX + 'WORLD' + JF + 'End'
wanted = 'world = require(WORLD)End'
class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond_RLExample(_VimTest): class TabStop_TSInDefault_MirrorsOutside_OverwriteSecond_RLExample(_VimTest):
snippets = ("test", """`!p snip.rv = t[1].split('/')[-1].lower().strip("'")` = require(${1:'${2:sys}'})""") snippets = (
keys = "test" + EX + JF + "WORLD" + JF + "End" 'test',
"""`!p snip.rv = t[1].split('/')[-1].lower().strip("'")` = require(${1:'${2:sys}'})""")
keys = 'test' + EX + JF + 'WORLD' + JF + 'End'
wanted = "world = require('WORLD')End" wanted = "world = require('WORLD')End"
class TabStop_Multiline_Leave(_VimTest): class TabStop_Multiline_Leave(_VimTest):
snippets = ("test", "hi ${1:first line\nsecond line} world" ) snippets = ('test', 'hi ${1:first line\nsecond line} world')
keys = "test" + EX keys = 'test' + EX
wanted = "hi first line\nsecond line world" wanted = 'hi first line\nsecond line world'
class TabStop_Multiline_Overwrite(_VimTest): class TabStop_Multiline_Overwrite(_VimTest):
snippets = ("test", "hi ${1:first line\nsecond line} world" ) snippets = ('test', 'hi ${1:first line\nsecond line} world')
keys = "test" + EX + "Nothing" keys = 'test' + EX + 'Nothing'
wanted = "hi Nothing world" wanted = 'hi Nothing world'
class TabStop_Multiline_MirrorInFront_Leave(_VimTest): class TabStop_Multiline_MirrorInFront_Leave(_VimTest):
snippets = ("test", "hi $1 ${1:first line\nsecond line} world" ) snippets = ('test', 'hi $1 ${1:first line\nsecond line} world')
keys = "test" + EX keys = 'test' + EX
wanted = "hi first line\nsecond line first line\nsecond line world" wanted = 'hi first line\nsecond line first line\nsecond line world'
class TabStop_Multiline_MirrorInFront_Overwrite(_VimTest): class TabStop_Multiline_MirrorInFront_Overwrite(_VimTest):
snippets = ("test", "hi $1 ${1:first line\nsecond line} world" ) snippets = ('test', 'hi $1 ${1:first line\nsecond line} world')
keys = "test" + EX + "Nothing" keys = 'test' + EX + 'Nothing'
wanted = "hi Nothing Nothing world" wanted = 'hi Nothing Nothing world'
class TabStop_Multiline_DelFirstOverwriteSecond_Overwrite(_VimTest): class TabStop_Multiline_DelFirstOverwriteSecond_Overwrite(_VimTest):
snippets = ("test", "hi $1 $2 ${1:first line\nsecond line} ${2:Hi} world" ) snippets = ('test', 'hi $1 $2 ${1:first line\nsecond line} ${2:Hi} world')
keys = "test" + EX + BS + JF + "Nothing" keys = 'test' + EX + BS + JF + 'Nothing'
wanted = "hi Nothing Nothing world" wanted = 'hi Nothing Nothing world'
class TabStopNavigatingInInsertModeSimple_ExpectCorrectResult(_VimTest): class TabStopNavigatingInInsertModeSimple_ExpectCorrectResult(_VimTest):
snippets = ("hallo", "Hallo ${1:WELT} ups") snippets = ('hallo', 'Hallo ${1:WELT} ups')
keys = "hallo" + EX + "haselnut" + 2*ARR_L + "hips" + JF + "end" keys = 'hallo' + EX + 'haselnut' + 2 * ARR_L + 'hips' + JF + 'end'
wanted = "Hallo haselnhipsut upsend" wanted = 'Hallo haselnhipsut upsend'
class TabStop_CROnlyOnSelectedNear(_VimTest): class TabStop_CROnlyOnSelectedNear(_VimTest):
snippets = ("test", "t$1t${2: }t{\n\t$0\n}") snippets = ('test', 't$1t${2: }t{\n\t$0\n}')
keys = "test" + EX + JF + "\n" + JF + "t" keys = 'test' + EX + JF + '\n' + JF + 't'
wanted = "tt\nt{\n\tt\n}" wanted = 'tt\nt{\n\tt\n}'

View File

@ -4,169 +4,245 @@ from test.constant import *
from test.util import no_unidecode_available from test.util import no_unidecode_available
# Transformations {{{# # Transformations {{{#
class Transformation_SimpleCase_ExpectCorrectResult(_VimTest): class Transformation_SimpleCase_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/foo/batzl/}") snippets = ('test', '$1 ${1/foo/batzl/}')
keys = "test" + EX + "hallo foo boy" keys = 'test' + EX + 'hallo foo boy'
wanted = "hallo foo boy hallo batzl boy" wanted = 'hallo foo boy hallo batzl boy'
class Transformation_SimpleCaseNoTransform_ExpectCorrectResult(_VimTest): class Transformation_SimpleCaseNoTransform_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/foo/batzl/}") snippets = ('test', '$1 ${1/foo/batzl/}')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo hallo" wanted = 'hallo hallo'
class Transformation_SimpleCaseTransformInFront_ExpectCorrectResult(_VimTest): class Transformation_SimpleCaseTransformInFront_ExpectCorrectResult(_VimTest):
snippets = ("test", "${1/foo/batzl/} $1") snippets = ('test', '${1/foo/batzl/} $1')
keys = "test" + EX + "hallo foo" keys = 'test' + EX + 'hallo foo'
wanted = "hallo batzl hallo foo" wanted = 'hallo batzl hallo foo'
class Transformation_SimpleCaseTransformInFrontDefVal_ECR(_VimTest): class Transformation_SimpleCaseTransformInFrontDefVal_ECR(_VimTest):
snippets = ("test", "${1/foo/batzl/} ${1:replace me}") snippets = ('test', '${1/foo/batzl/} ${1:replace me}')
keys = "test" + EX + "hallo foo" keys = 'test' + EX + 'hallo foo'
wanted = "hallo batzl hallo foo" wanted = 'hallo batzl hallo foo'
class Transformation_MultipleTransformations_ECR(_VimTest): class Transformation_MultipleTransformations_ECR(_VimTest):
snippets = ("test", "${1:Some Text}${1/.+/\\U$0\E/}\n${1/.+/\L$0\E/}") snippets = ('test', '${1:Some Text}${1/.+/\\U$0\E/}\n${1/.+/\L$0\E/}')
keys = "test" + EX + "SomE tExt " keys = 'test' + EX + 'SomE tExt '
wanted = "SomE tExt SOME TEXT \nsome text " wanted = 'SomE tExt SOME TEXT \nsome text '
class Transformation_TabIsAtEndAndDeleted_ECR(_VimTest): class Transformation_TabIsAtEndAndDeleted_ECR(_VimTest):
snippets = ("test", "${1/.+/is something/}${1:some}") snippets = ('test', '${1/.+/is something/}${1:some}')
keys = "hallo test" + EX + "some\b\b\b\b\b" keys = 'hallo test' + EX + 'some\b\b\b\b\b'
wanted = "hallo " wanted = 'hallo '
class Transformation_TabIsAtEndAndDeleted1_ECR(_VimTest): class Transformation_TabIsAtEndAndDeleted1_ECR(_VimTest):
snippets = ("test", "${1/.+/is something/}${1:some}") snippets = ('test', '${1/.+/is something/}${1:some}')
keys = "hallo test" + EX + "some\b\b\b\bmore" keys = 'hallo test' + EX + 'some\b\b\b\bmore'
wanted = "hallo is somethingmore" wanted = 'hallo is somethingmore'
class Transformation_TabIsAtEndNoTextLeave_ECR(_VimTest): class Transformation_TabIsAtEndNoTextLeave_ECR(_VimTest):
snippets = ("test", "${1/.+/is something/}${1}") snippets = ('test', '${1/.+/is something/}${1}')
keys = "hallo test" + EX keys = 'hallo test' + EX
wanted = "hallo " wanted = 'hallo '
class Transformation_TabIsAtEndNoTextType_ECR(_VimTest): class Transformation_TabIsAtEndNoTextType_ECR(_VimTest):
snippets = ("test", "${1/.+/is something/}${1}") snippets = ('test', '${1/.+/is something/}${1}')
keys = "hallo test" + EX + "b" keys = 'hallo test' + EX + 'b'
wanted = "hallo is somethingb" wanted = 'hallo is somethingb'
class Transformation_InsideTabLeaveAtDefault_ECR(_VimTest): class Transformation_InsideTabLeaveAtDefault_ECR(_VimTest):
snippets = ("test", r"$1 ${2:${1/.+/(?0:defined $0)/}}") snippets = ('test', r"$1 ${2:${1/.+/(?0:defined $0)/}}")
keys = "test" + EX + "sometext" + JF keys = 'test' + EX + 'sometext' + JF
wanted = "sometext defined sometext" wanted = 'sometext defined sometext'
class Transformation_InsideTabOvertype_ECR(_VimTest): class Transformation_InsideTabOvertype_ECR(_VimTest):
snippets = ("test", r"$1 ${2:${1/.+/(?0:defined $0)/}}") snippets = ('test', r"$1 ${2:${1/.+/(?0:defined $0)/}}")
keys = "test" + EX + "sometext" + JF + "overwrite" keys = 'test' + EX + 'sometext' + JF + 'overwrite'
wanted = "sometext overwrite" wanted = 'sometext overwrite'
class Transformation_Backreference_ExpectCorrectResult(_VimTest): class Transformation_Backreference_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/([ab])oo/$1ull/}") snippets = ('test', '$1 ${1/([ab])oo/$1ull/}')
keys = "test" + EX + "foo boo aoo" keys = 'test' + EX + 'foo boo aoo'
wanted = "foo boo aoo foo bull aoo" wanted = 'foo boo aoo foo bull aoo'
class Transformation_BackreferenceTwice_ExpectCorrectResult(_VimTest): class Transformation_BackreferenceTwice_ExpectCorrectResult(_VimTest):
snippets = ("test", r"$1 ${1/(dead) (par[^ ]*)/this $2 is a bit $1/}") snippets = ('test', r"$1 ${1/(dead) (par[^ ]*)/this $2 is a bit $1/}")
keys = "test" + EX + "dead parrot" keys = 'test' + EX + 'dead parrot'
wanted = "dead parrot this parrot is a bit dead" wanted = 'dead parrot this parrot is a bit dead'
class Transformation_CleverTransformUpercaseChar_ExpectCorrectResult(_VimTest): class Transformation_CleverTransformUpercaseChar_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/(.)/\\u$1/}") snippets = ('test', '$1 ${1/(.)/\\u$1/}')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo Hallo" wanted = 'hallo Hallo'
class Transformation_CleverTransformLowercaseChar_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/(.*)/\l$1/}")
keys = "test" + EX + "Hallo" class Transformation_CleverTransformLowercaseChar_ExpectCorrectResult(
wanted = "Hallo hallo" _VimTest):
snippets = ('test', '$1 ${1/(.*)/\l$1/}')
keys = 'test' + EX + 'Hallo'
wanted = 'Hallo hallo'
class Transformation_CleverTransformLongUpper_ExpectCorrectResult(_VimTest): class Transformation_CleverTransformLongUpper_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/(.*)/\\U$1\E/}") snippets = ('test', '$1 ${1/(.*)/\\U$1\E/}')
keys = "test" + EX + "hallo" keys = 'test' + EX + 'hallo'
wanted = "hallo HALLO" wanted = 'hallo HALLO'
class Transformation_CleverTransformLongLower_ExpectCorrectResult(_VimTest): class Transformation_CleverTransformLongLower_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/(.*)/\L$1\E/}") snippets = ('test', '$1 ${1/(.*)/\L$1\E/}')
keys = "test" + EX + "HALLO" keys = 'test' + EX + 'HALLO'
wanted = "HALLO hallo" wanted = 'HALLO hallo'
class Transformation_SimpleCaseAsciiResult(_VimTest): class Transformation_SimpleCaseAsciiResult(_VimTest):
skip_if = lambda self: no_unidecode_available() skip_if = lambda self: no_unidecode_available()
snippets = ("ascii", "$1 ${1/(.*)/$1/a}") snippets = ('ascii', '$1 ${1/(.*)/$1/a}')
keys = "ascii" + EX + "éèàçôïÉÈÀÇÔÏ€" keys = 'ascii' + EX + 'éèàçôïÉÈÀÇÔÏ€'
wanted = "éèàçôïÉÈÀÇÔÏ€ eeacoiEEACOIEU" wanted = 'éèàçôïÉÈÀÇÔÏ€ eeacoiEEACOIEU'
class Transformation_LowerCaseAsciiResult(_VimTest): class Transformation_LowerCaseAsciiResult(_VimTest):
skip_if = lambda self: no_unidecode_available() skip_if = lambda self: no_unidecode_available()
snippets = ("ascii", "$1 ${1/(.*)/\L$1\E/a}") snippets = ('ascii', '$1 ${1/(.*)/\L$1\E/a}')
keys = "ascii" + EX + "éèàçôïÉÈÀÇÔÏ€" keys = 'ascii' + EX + 'éèàçôïÉÈÀÇÔÏ€'
wanted = "éèàçôïÉÈÀÇÔÏ€ eeacoieeacoieu" wanted = 'éèàçôïÉÈÀÇÔÏ€ eeacoieeacoieu'
class Transformation_ConditionalInsertionSimple_ExpectCorrectResult(_VimTest): class Transformation_ConditionalInsertionSimple_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/(^a).*/(?0:began with an a)/}") snippets = ('test', '$1 ${1/(^a).*/(?0:began with an a)/}')
keys = "test" + EX + "a some more text" keys = 'test' + EX + 'a some more text'
wanted = "a some more text began with an a" wanted = 'a some more text began with an a'
class Transformation_CIBothDefinedNegative_ExpectCorrectResult(_VimTest): class Transformation_CIBothDefinedNegative_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/(?:(^a)|(^b)).*/(?1:yes:no)/}") snippets = ('test', '$1 ${1/(?:(^a)|(^b)).*/(?1:yes:no)/}')
keys = "test" + EX + "b some" keys = 'test' + EX + 'b some'
wanted = "b some no" wanted = 'b some no'
class Transformation_CIBothDefinedPositive_ExpectCorrectResult(_VimTest): class Transformation_CIBothDefinedPositive_ExpectCorrectResult(_VimTest):
snippets = ("test", "$1 ${1/(?:(^a)|(^b)).*/(?1:yes:no)/}") snippets = ('test', '$1 ${1/(?:(^a)|(^b)).*/(?1:yes:no)/}')
keys = "test" + EX + "a some" keys = 'test' + EX + 'a some'
wanted = "a some yes" wanted = 'a some yes'
class Transformation_ConditionalInsertRWEllipsis_ECR(_VimTest): class Transformation_ConditionalInsertRWEllipsis_ECR(_VimTest):
snippets = ("test", r"$1 ${1/(\w+(?:\W+\w+){,7})\W*(.+)?/$1(?2:...)/}") snippets = ('test', r"$1 ${1/(\w+(?:\W+\w+){,7})\W*(.+)?/$1(?2:...)/}")
keys = "test" + EX + "a b c d e f ghhh h oha" keys = 'test' + EX + 'a b c d e f ghhh h oha'
wanted = "a b c d e f ghhh h oha a b c d e f ghhh h..." wanted = 'a b c d e f ghhh h oha a b c d e f ghhh h...'
class Transformation_ConditionalInConditional_ECR(_VimTest): class Transformation_ConditionalInConditional_ECR(_VimTest):
snippets = ("test", r"$1 ${1/^.*?(-)?(>)?$/(?2::(?1:>:.))/}") snippets = ('test', r"$1 ${1/^.*?(-)?(>)?$/(?2::(?1:>:.))/}")
keys = "test" + EX + "hallo" + ESC + "$a\n" + \ keys = 'test' + EX + 'hallo' + ESC + '$a\n' + \
"test" + EX + "hallo-" + ESC + "$a\n" + \ 'test' + EX + 'hallo-' + ESC + '$a\n' + \
"test" + EX + "hallo->" 'test' + EX + 'hallo->'
wanted = "hallo .\nhallo- >\nhallo-> " wanted = 'hallo .\nhallo- >\nhallo-> '
class Transformation_CINewlines_ECR(_VimTest): class Transformation_CINewlines_ECR(_VimTest):
snippets = ("test", r"$1 ${1/, */\n/}") snippets = ('test', r"$1 ${1/, */\n/}")
keys = "test" + EX + "test, hallo" keys = 'test' + EX + 'test, hallo'
wanted = "test, hallo test\nhallo" wanted = 'test, hallo test\nhallo'
class Transformation_CITabstop_ECR(_VimTest): class Transformation_CITabstop_ECR(_VimTest):
snippets = ("test", r"$1 ${1/, */\t/}") snippets = ('test', r"$1 ${1/, */\t/}")
keys = "test" + EX + "test, hallo" keys = 'test' + EX + 'test, hallo'
wanted = "test, hallo test\thallo" wanted = 'test, hallo test\thallo'
class Transformation_CIEscapedParensinReplace_ECR(_VimTest): class Transformation_CIEscapedParensinReplace_ECR(_VimTest):
snippets = ("test", r"$1 ${1/hal((?:lo)|(?:ul))/(?1:ha\($1\))/}") snippets = ('test', r"$1 ${1/hal((?:lo)|(?:ul))/(?1:ha\($1\))/}")
keys = "test" + EX + "test, halul" keys = 'test' + EX + 'test, halul'
wanted = "test, halul test, ha(ul)" wanted = 'test, halul test, ha(ul)'
class Transformation_OptionIgnoreCase_ECR(_VimTest): class Transformation_OptionIgnoreCase_ECR(_VimTest):
snippets = ("test", r"$1 ${1/test/blah/i}") snippets = ('test', r"$1 ${1/test/blah/i}")
keys = "test" + EX + "TEST" keys = 'test' + EX + 'TEST'
wanted = "TEST blah" wanted = 'TEST blah'
class Transformation_OptionReplaceGlobal_ECR(_VimTest): class Transformation_OptionReplaceGlobal_ECR(_VimTest):
snippets = ("test", r"$1 ${1/, */-/g}") snippets = ('test', r"$1 ${1/, */-/g}")
keys = "test" + EX + "a, nice, building" keys = 'test' + EX + 'a, nice, building'
wanted = "a, nice, building a-nice-building" wanted = 'a, nice, building a-nice-building'
class Transformation_OptionReplaceGlobalMatchInReplace_ECR(_VimTest): class Transformation_OptionReplaceGlobalMatchInReplace_ECR(_VimTest):
snippets = ("test", r"$1 ${1/, */, /g}") snippets = ('test', r"$1 ${1/, */, /g}")
keys = "test" + EX + "a, nice, building" keys = 'test' + EX + 'a, nice, building'
wanted = "a, nice, building a, nice, building" wanted = 'a, nice, building a, nice, building'
class TransformationUsingBackspaceToDeleteDefaultValueInFirstTab_ECR(_VimTest): class TransformationUsingBackspaceToDeleteDefaultValueInFirstTab_ECR(_VimTest):
snippets = ("test", "snip ${1/.+/(?0:m1)/} ${2/.+/(?0:m2)/} " snippets = ('test', 'snip ${1/.+/(?0:m1)/} ${2/.+/(?0:m2)/} '
"${1:default} ${2:def}") '${1:default} ${2:def}')
keys = "test" + EX + BS + JF + "hi" keys = 'test' + EX + BS + JF + 'hi'
wanted = "snip m2 hi" wanted = 'snip m2 hi'
class TransformationUsingBackspaceToDeleteDefaultValueInSecondTab_ECR(_VimTest):
snippets = ("test", "snip ${1/.+/(?0:m1)/} ${2/.+/(?0:m2)/} "
"${1:default} ${2:def}") class TransformationUsingBackspaceToDeleteDefaultValueInSecondTab_ECR(
keys = "test" + EX + "hi" + JF + BS _VimTest):
wanted = "snip m1 hi " snippets = ('test', 'snip ${1/.+/(?0:m1)/} ${2/.+/(?0:m2)/} '
class TransformationUsingBackspaceToDeleteDefaultValueTypeSomethingThen_ECR(_VimTest): '${1:default} ${2:def}')
snippets = ("test", "snip ${1/.+/(?0:matched)/} ${1:default}") keys = 'test' + EX + 'hi' + JF + BS
keys = "test" + EX + BS + "hallo" wanted = 'snip m1 hi '
wanted = "snip matched hallo"
class TransformationUsingBackspaceToDeleteDefaultValueTypeSomethingThen_ECR(
_VimTest):
snippets = ('test', 'snip ${1/.+/(?0:matched)/} ${1:default}')
keys = 'test' + EX + BS + 'hallo'
wanted = 'snip matched hallo'
class TransformationUsingBackspaceToDeleteDefaultValue_ECR(_VimTest): class TransformationUsingBackspaceToDeleteDefaultValue_ECR(_VimTest):
snippets = ("test", "snip ${1/.+/(?0:matched)/} ${1:default}") snippets = ('test', 'snip ${1/.+/(?0:matched)/} ${1:default}')
keys = "test" + EX + BS keys = 'test' + EX + BS
wanted = "snip " wanted = 'snip '
class Transformation_TestKill_InsertBefore_NoKill(_VimTest): class Transformation_TestKill_InsertBefore_NoKill(_VimTest):
snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" snippets = 'test', r"$1 ${1/.*/\L$0$0\E/}_"
keys = "hallo test" + EX + "AUCH" + ESC + "wihi" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'AUCH' + ESC + \
wanted = "hallo noAUCH hinoauchnoauch_end" 'wihi' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noAUCH hinoauchnoauch_end'
class Transformation_TestKill_InsertAfter_NoKill(_VimTest): class Transformation_TestKill_InsertAfter_NoKill(_VimTest):
snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" snippets = 'test', r"$1 ${1/.*/\L$0$0\E/}_"
keys = "hallo test" + EX + "AUCH" + ESC + "eiab" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'AUCH' + ESC + \
wanted = "hallo noAUCH noauchnoauchab_end" 'eiab' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noAUCH noauchnoauchab_end'
class Transformation_TestKill_InsertBeginning_Kill(_VimTest): class Transformation_TestKill_InsertBeginning_Kill(_VimTest):
snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" snippets = 'test', r"$1 ${1/.*/\L$0$0\E/}_"
keys = "hallo test" + EX + "AUCH" + ESC + "wahi" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'AUCH' + ESC + \
wanted = "hallo noAUCH ahiuchauch_end" 'wahi' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noAUCH ahiuchauch_end'
class Transformation_TestKill_InsertEnd_Kill(_VimTest): class Transformation_TestKill_InsertEnd_Kill(_VimTest):
snippets = "test", r"$1 ${1/.*/\L$0$0\E/}_" snippets = 'test', r"$1 ${1/.*/\L$0$0\E/}_"
keys = "hallo test" + EX + "AUCH" + ESC + "ehihi" + ESC + "bb" + "ino" + JF + "end" keys = 'hallo test' + EX + 'AUCH' + ESC + \
wanted = "hallo noAUCH auchauchih_end" 'ehihi' + ESC + 'bb' + 'ino' + JF + 'end'
wanted = 'hallo noAUCH auchauchih_end'
# End: Transformations #}}} # End: Transformations #}}}

View File

@ -4,76 +4,94 @@ from test.constant import *
from test.util import running_on_windows from test.util import running_on_windows
# AddSnippet Function {{{# # AddSnippet Function {{{#
class _AddFuncBase(_VimTest): class _AddFuncBase(_VimTest):
args = "" args = ''
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append(":call UltiSnips#AddSnippetWithPriority(%s)" % vim_config.append(':call UltiSnips#AddSnippetWithPriority(%s)' %
self.args) self.args)
class AddFunc_Simple(_AddFuncBase): class AddFunc_Simple(_AddFuncBase):
args = '"test", "simple expand", "desc", "", "all", 0' args = '"test", "simple expand", "desc", "", "all", 0'
keys = "abc test" + EX keys = 'abc test' + EX
wanted = "abc simple expand" wanted = 'abc simple expand'
class AddFunc_Opt(_AddFuncBase): class AddFunc_Opt(_AddFuncBase):
args = '".*test", "simple expand", "desc", "r", "all", 0' args = '".*test", "simple expand", "desc", "r", "all", 0'
keys = "abc test" + EX keys = 'abc test' + EX
wanted = "simple expand" wanted = 'simple expand'
# End: AddSnippet Function #}}} # End: AddSnippet Function #}}}
# Langmap Handling {{{# # Langmap Handling {{{#
# Test for bug 501727 # # Test for bug 501727 #
class TestNonEmptyLangmap_ExpectCorrectResult(_VimTest): class TestNonEmptyLangmap_ExpectCorrectResult(_VimTest):
snippets = ("testme", snippets = ('testme',
"""my snipped ${1:some_default} """my snipped ${1:some_default}
and a mirror: $1 and a mirror: $1
$2...$3 $2...$3
$0""") $0""")
keys = "testme" + EX + "hi1" + JF + "hi2" + JF + "hi3" + JF + "hi4" keys = 'testme' + EX + 'hi1' + JF + 'hi2' + JF + 'hi3' + JF + 'hi4'
wanted ="""my snipped hi1 wanted = """my snipped hi1
and a mirror: hi1 and a mirror: hi1
hi2...hi3 hi2...hi3
hi4""" hi4"""
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
vim_config.append("set langmap=dj,rk,nl,ln,jd,kr,DJ,RK,NL,LN,JD,KR") vim_config.append('set langmap=dj,rk,nl,ln,jd,kr,DJ,RK,NL,LN,JD,KR')
# Test for https://bugs.launchpad.net/bugs/501727 # # Test for https://bugs.launchpad.net/bugs/501727 #
class TestNonEmptyLangmapWithSemi_ExpectCorrectResult(_VimTest): class TestNonEmptyLangmapWithSemi_ExpectCorrectResult(_VimTest):
snippets = ("testme", snippets = ('testme',
"""my snipped ${1:some_default} """my snipped ${1:some_default}
and a mirror: $1 and a mirror: $1
$2...$3 $2...$3
$0""") $0""")
keys = "testme" + EX + "hi;" + JF + "hi2" + JF + "hi3" + JF + "hi4" + ESC + ";Hello" keys = 'testme' + EX + 'hi;' + JF + 'hi2' + \
wanted ="""my snipped hi; JF + 'hi3' + JF + 'hi4' + ESC + ';Hello'
wanted = """my snipped hi;
and a mirror: hi; and a mirror: hi;
hi2...hi3 hi2...hi3
hi4Hello""" hi4Hello"""
def _before_test(self): def _before_test(self):
self.vim.send(":set langmap=\\\\;;A\n") self.vim.send(':set langmap=\\\\;;A\n')
# Test for bug 871357 # # Test for bug 871357 #
class TestLangmapWithUtf8_ExpectCorrectResult(_VimTest): class TestLangmapWithUtf8_ExpectCorrectResult(_VimTest):
skip_if = lambda self: running_on_windows() # SendKeys can't send UTF characters # SendKeys can't send UTF characters
snippets = ("testme", skip_if = lambda self: running_on_windows()
"""my snipped ${1:some_default} snippets = ('testme',
"""my snipped ${1:some_default}
and a mirror: $1 and a mirror: $1
$2...$3 $2...$3
$0""") $0""")
keys = "testme" + EX + "hi1" + JF + "hi2" + JF + "hi3" + JF + "hi4" keys = 'testme' + EX + 'hi1' + JF + 'hi2' + JF + 'hi3' + JF + 'hi4'
wanted ="""my snipped hi1 wanted = """my snipped hi1
and a mirror: hi1 and a mirror: hi1
hi2...hi3 hi2...hi3
hi4""" hi4"""
def _before_test(self): def _before_test(self):
self.vim.send(":set langmap=йq,цw,уe,кr,еt,нy,гu,шi,щo,зp,х[,ъ],фa,ыs,вd,аf,пg,рh,оj,лk,дl,ж\\;,э',яz,чx,сc,мv,иb,тn,ьm,ю.,ё',ЙQ,ЦW,УE,КR,ЕT,НY,ГU,ШI,ЩO,ЗP,Х\{\},ФA,ЫS,ВD,АF,ПG,РH,ОJ,ЛK,ДL,Ж\:,Э\",ЯZ,ЧX,СC,МV,ИB,ТN,ЬM,Б\<,Ю\>\n") self.vim.send(
":set langmap=йq,цw,уe,кr,еt,нy,гu,шi,щo,зp,х[,ъ],фa,ыs,вd,аf,пg,рh,оj,лk,дl,ж\\;,э',яz,чx,сc,мv,иb,тn,ьm,ю.,ё',ЙQ,ЦW,УE,КR,ЕT,НY,ГU,ШI,ЩO,ЗP,Х\{\},ФA,ЫS,ВD,АF,ПG,РH,ОJ,ЛK,ДL,Ж\:,Э\",ЯZ,ЧX,СC,МV,ИB,ТN,ЬM,Б\<,Ю\>\n")
# End: Langmap Handling #}}} # End: Langmap Handling #}}}
# SnippetsInCurrentScope {{{# # SnippetsInCurrentScope {{{#
class VerifyVimDict1(_VimTest): class VerifyVimDict1(_VimTest):
"""check: """check:
correct type (4 means vim dictionary) correct type (4 means vim dictionary)
correct length of dictionary (in this case we have on element if the use same prefix, dictionary should have 1 element) correct length of dictionary (in this case we have on element if the use same prefix, dictionary should have 1 element)
@ -83,48 +101,56 @@ class VerifyVimDict1(_VimTest):
snippets = ('testâ', 'abc123ά', '123\'êabc') snippets = ('testâ', 'abc123ά', '123\'êabc')
keys = ('test=(type(UltiSnips#SnippetsInCurrentScope()) . len(UltiSnips#SnippetsInCurrentScope()) . ' + keys = ('test=(type(UltiSnips#SnippetsInCurrentScope()) . len(UltiSnips#SnippetsInCurrentScope()) . ' +
'UltiSnips#SnippetsInCurrentScope()["testâ"]' + ')\n' + 'UltiSnips#SnippetsInCurrentScope()["testâ"]' + ')\n' +
'=len(UltiSnips#SnippetsInCurrentScope())\n') '=len(UltiSnips#SnippetsInCurrentScope())\n')
wanted = 'test41123\'êabc0' wanted = 'test41123\'êabc0'
class VerifyVimDict2(_VimTest): class VerifyVimDict2(_VimTest):
"""check: """check:
can use " in trigger can use " in trigger
""" """
snippets = ('te"stâ', 'abc123ά', '123êabc') snippets = ('te"stâ', 'abc123ά', '123êabc')
akey = "'te{}stâ'".format('"') akey = "'te{}stâ'".format('"')
keys = ('te"=(UltiSnips#SnippetsInCurrentScope()[{}]'.format(akey) + ')\n') keys = (
'te"=(UltiSnips#SnippetsInCurrentScope()[{}]'.format(akey) + ')\n')
wanted = 'te"123êabc' wanted = 'te"123êabc'
class VerifyVimDict3(_VimTest): class VerifyVimDict3(_VimTest):
"""check: """check:
can use ' in trigger can use ' in trigger
""" """
snippets = ("te'stâ", 'abc123ά', '123êabc') snippets = ("te'stâ", 'abc123ά', '123êabc')
akey = '"te{}stâ"'.format("'") akey = '"te{}stâ"'.format("'")
keys = ("te'=(UltiSnips#SnippetsInCurrentScope()[{}]".format(akey) + ')\n') keys = (
"te'=(UltiSnips#SnippetsInCurrentScope()[{}]".format(akey) + ')\n')
wanted = "te'123êabc" wanted = "te'123êabc"
# End: SnippetsInCurrentScope #}}} # End: SnippetsInCurrentScope #}}}
# Snippet Source {{{# # Snippet Source {{{#
class AddNewSnippetSource(_VimTest): class AddNewSnippetSource(_VimTest):
keys = ( "blumba" + EX + ESC + keys = ('blumba' + EX + ESC +
":%(python)s UltiSnips_Manager.register_snippet_source(" + ':%(python)s UltiSnips_Manager.register_snippet_source(' +
"'temp', MySnippetSource())\n" + "'temp', MySnippetSource())\n" +
"oblumba" + EX + ESC + 'oblumba' + EX + ESC +
":%(python)s UltiSnips_Manager.unregister_snippet_source('temp')\n" + ":%(python)s UltiSnips_Manager.unregister_snippet_source('temp')\n" +
"oblumba" + EX ) % { 'python': 'py3' if PYTHON3 else 'py' } 'oblumba' + EX) % {'python': 'py3' if PYTHON3 else 'py'}
wanted = ( wanted = (
"blumba" + EX + "\n" + 'blumba' + EX + '\n' +
"this is a dynamic snippet" + "\n" + 'this is a dynamic snippet' + '\n' +
"blumba" + EX 'blumba' + EX
) )
def _extra_options_post_init(self, vim_config): def _extra_options_post_init(self, vim_config):
self._create_file("snippet_source.py",""" self._create_file('snippet_source.py', """
from UltiSnips.snippet.source import SnippetSource from UltiSnips.snippet.source import SnippetSource
from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition from UltiSnips.snippet.definition import UltiSnipsSnippetDefinition
@ -138,5 +164,7 @@ class MySnippetSource(SnippetSource):
return [] return []
""") """)
pyfile = 'py3file' if PYTHON3 else 'pyfile' pyfile = 'py3file' if PYTHON3 else 'pyfile'
vim_config.append("%s %s" % (pyfile, self.name_temp("snippet_source.py"))) vim_config.append(
'%s %s' %
(pyfile, self.name_temp('snippet_source.py')))
# End: Snippet Source #}}} # End: Snippet Source #}}}

View File

@ -2,140 +2,203 @@ from test.vim_test_case import VimTestCase as _VimTest
from test.constant import * from test.constant import *
# ${VISUAL} {{{# # ${VISUAL} {{{#
class Visual_NoVisualSelection_Ignore(_VimTest): class Visual_NoVisualSelection_Ignore(_VimTest):
snippets = ("test", "h${VISUAL}b") snippets = ('test', 'h${VISUAL}b')
keys = "test" + EX + "abc" keys = 'test' + EX + 'abc'
wanted = "hbabc" wanted = 'hbabc'
class Visual_SelectOneWord(_VimTest): class Visual_SelectOneWord(_VimTest):
snippets = ("test", "h${VISUAL}b") snippets = ('test', 'h${VISUAL}b')
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX
wanted = "hblablubb" wanted = 'hblablubb'
class Visual_SelectOneWord_ProblemAfterTab(_VimTest): class Visual_SelectOneWord_ProblemAfterTab(_VimTest):
snippets = ("test", "h${VISUAL}b", "", "i") snippets = ('test', 'h${VISUAL}b', '', 'i')
keys = "\tblablub" + ESC + "5hv3l" + EX + "test" + EX keys = '\tblablub' + ESC + '5hv3l' + EX + 'test' + EX
wanted = "\tbhlablbub" wanted = '\tbhlablbub'
class VisualWithDefault_ExpandWithoutVisual(_VimTest): class VisualWithDefault_ExpandWithoutVisual(_VimTest):
snippets = ("test", "h${VISUAL:world}b") snippets = ('test', 'h${VISUAL:world}b')
keys = "test" + EX + "hi" keys = 'test' + EX + 'hi'
wanted = "hworldbhi" wanted = 'hworldbhi'
class VisualWithDefaultWithSlashes_ExpandWithoutVisual(_VimTest): class VisualWithDefaultWithSlashes_ExpandWithoutVisual(_VimTest):
snippets = ("test", r"h${VISUAL:\/\/ body}b") snippets = ('test', r"h${VISUAL:\/\/ body}b")
keys = "test" + EX + "hi" keys = 'test' + EX + 'hi'
wanted = "h// bodybhi" wanted = 'h// bodybhi'
class VisualWithDefault_ExpandWithVisual(_VimTest): class VisualWithDefault_ExpandWithVisual(_VimTest):
snippets = ("test", "h${VISUAL:world}b") snippets = ('test', 'h${VISUAL:world}b')
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX
wanted = "hblablubb" wanted = 'hblablubb'
class Visual_ExpandTwice(_VimTest): class Visual_ExpandTwice(_VimTest):
snippets = ("test", "h${VISUAL}b") snippets = ('test', 'h${VISUAL}b')
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + "\ntest" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX + '\ntest' + EX
wanted = "hblablubb\nhb" wanted = 'hblablubb\nhb'
class Visual_SelectOneWord_TwiceVisual(_VimTest): class Visual_SelectOneWord_TwiceVisual(_VimTest):
snippets = ("test", "h${VISUAL}b${VISUAL}a") snippets = ('test', 'h${VISUAL}b${VISUAL}a')
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX
wanted = "hblablubbblabluba" wanted = 'hblablubbblabluba'
class Visual_SelectOneWord_Inword(_VimTest): class Visual_SelectOneWord_Inword(_VimTest):
snippets = ("test", "h${VISUAL}b", "Description", "i") snippets = ('test', 'h${VISUAL}b', 'Description', 'i')
keys = "blablub" + ESC + "0lv4l" + EX + "test" + EX keys = 'blablub' + ESC + '0lv4l' + EX + 'test' + EX
wanted = "bhlablubb" wanted = 'bhlablubb'
class Visual_SelectOneWord_TillEndOfLine(_VimTest): class Visual_SelectOneWord_TillEndOfLine(_VimTest):
snippets = ("test", "h${VISUAL}b", "Description", "i") snippets = ('test', 'h${VISUAL}b', 'Description', 'i')
keys = "blablub" + ESC + "0v$" + EX + "test" + EX + ESC + "o" keys = 'blablub' + ESC + '0v$' + EX + 'test' + EX + ESC + 'o'
wanted = "hblablub\nb" wanted = 'hblablub\nb'
class Visual_SelectOneWordWithTabstop_TillEndOfLine(_VimTest): class Visual_SelectOneWordWithTabstop_TillEndOfLine(_VimTest):
snippets = ("test", "h${2:ahh}${VISUAL}${1:ups}b", "Description", "i") snippets = ('test', 'h${2:ahh}${VISUAL}${1:ups}b', 'Description', 'i')
keys = "blablub" + ESC + "0v$" + EX + "test" + EX + "mmm" + JF + "n" + JF + "done" + ESC + "o" keys = 'blablub' + ESC + '0v$' + EX + 'test' + \
wanted = "hnblablub\nmmmbdone" EX + 'mmm' + JF + 'n' + JF + 'done' + ESC + 'o'
wanted = 'hnblablub\nmmmbdone'
class Visual_InDefaultText_SelectOneWord_NoOverwrite(_VimTest): class Visual_InDefaultText_SelectOneWord_NoOverwrite(_VimTest):
snippets = ("test", "h${1:${VISUAL}}b") snippets = ('test', 'h${1:${VISUAL}}b')
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + JF + "hello" keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX + JF + 'hello'
wanted = "hblablubbhello" wanted = 'hblablubbhello'
class Visual_InDefaultText_SelectOneWord(_VimTest): class Visual_InDefaultText_SelectOneWord(_VimTest):
snippets = ("test", "h${1:${VISUAL}}b") snippets = ('test', 'h${1:${VISUAL}}b')
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX + "hello" keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX + 'hello'
wanted = "hhellob" wanted = 'hhellob'
class Visual_CrossOneLine(_VimTest): class Visual_CrossOneLine(_VimTest):
snippets = ("test", "h${VISUAL}b") snippets = ('test', 'h${VISUAL}b')
keys = "bla blub\n helloi" + ESC + "0k4lvjll" + EX + "test" + EX keys = 'bla blub\n helloi' + ESC + '0k4lvjll' + EX + 'test' + EX
wanted = "bla hblub\n hellobi" wanted = 'bla hblub\n hellobi'
class Visual_LineSelect_Simple(_VimTest): class Visual_LineSelect_Simple(_VimTest):
snippets = ("test", "h${VISUAL}b") snippets = ('test', 'h${VISUAL}b')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX
wanted = "hhello\n nice\n worldb" wanted = 'hhello\n nice\n worldb'
class Visual_InDefaultText_LineSelect_NoOverwrite(_VimTest): class Visual_InDefaultText_LineSelect_NoOverwrite(_VimTest):
snippets = ("test", "h${1:bef${VISUAL}aft}b") snippets = ('test', 'h${1:bef${VISUAL}aft}b')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX + JF + 'hi'
wanted = "hbefhello\n nice\n worldaftbhi" wanted = 'hbefhello\n nice\n worldaftbhi'
class Visual_InDefaultText_LineSelect_Overwrite(_VimTest): class Visual_InDefaultText_LineSelect_Overwrite(_VimTest):
snippets = ("test", "h${1:bef${VISUAL}aft}b") snippets = ('test', 'h${1:bef${VISUAL}aft}b')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "jup" + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + \
wanted = "hjupbhi" EX + 'test' + EX + 'jup' + JF + 'hi'
wanted = 'hjupbhi'
class Visual_LineSelect_CheckIndentSimple(_VimTest): class Visual_LineSelect_CheckIndentSimple(_VimTest):
snippets = ("test", "beg\n\t${VISUAL}\nend") snippets = ('test', 'beg\n\t${VISUAL}\nend')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX
wanted = "beg\n\thello\n\tnice\n\tworld\nend" wanted = 'beg\n\thello\n\tnice\n\tworld\nend'
class Visual_LineSelect_CheckIndentTwice(_VimTest): class Visual_LineSelect_CheckIndentTwice(_VimTest):
snippets = ("test", "beg\n\t${VISUAL}\nend") snippets = ('test', 'beg\n\t${VISUAL}\nend')
keys = " hello\n nice\n\tworld" + ESC + "Vkk" + EX + "test" + EX keys = ' hello\n nice\n\tworld' + ESC + 'Vkk' + EX + 'test' + EX
wanted = "beg\n\t hello\n\t nice\n\t\tworld\nend" wanted = 'beg\n\t hello\n\t nice\n\t\tworld\nend'
class Visual_InDefaultText_IndentSpacesToTabstop_NoOverwrite(_VimTest): class Visual_InDefaultText_IndentSpacesToTabstop_NoOverwrite(_VimTest):
snippets = ("test", "h${1:beforea${VISUAL}aft}b") snippets = ('test', 'h${1:beforea${VISUAL}aft}b')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX + JF + 'hi'
wanted = "hbeforeahello\n\tnice\n\tworldaftbhi" wanted = 'hbeforeahello\n\tnice\n\tworldaftbhi'
class Visual_InDefaultText_IndentSpacesToTabstop_Overwrite(_VimTest): class Visual_InDefaultText_IndentSpacesToTabstop_Overwrite(_VimTest):
snippets = ("test", "h${1:beforea${VISUAL}aft}b") snippets = ('test', 'h${1:beforea${VISUAL}aft}b')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "ups" + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + \
wanted = "hupsbhi" EX + 'test' + EX + 'ups' + JF + 'hi'
wanted = 'hupsbhi'
class Visual_InDefaultText_IndentSpacesToTabstop_NoOverwrite1(_VimTest): class Visual_InDefaultText_IndentSpacesToTabstop_NoOverwrite1(_VimTest):
snippets = ("test", "h${1:beforeaaa${VISUAL}aft}b") snippets = ('test', 'h${1:beforeaaa${VISUAL}aft}b')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX + JF + 'hi'
wanted = "hbeforeaaahello\n\t nice\n\t worldaftbhi" wanted = 'hbeforeaaahello\n\t nice\n\t worldaftbhi'
class Visual_InDefaultText_IndentBeforeTabstop_NoOverwrite(_VimTest): class Visual_InDefaultText_IndentBeforeTabstop_NoOverwrite(_VimTest):
snippets = ("test", "hello\n\t ${1:${VISUAL}}\nend") snippets = ('test', 'hello\n\t ${1:${VISUAL}}\nend')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX + JF + 'hi'
wanted = "hello\n\t hello\n\t nice\n\t world\nendhi" wanted = 'hello\n\t hello\n\t nice\n\t world\nendhi'
class Visual_LineSelect_WithTabStop(_VimTest): class Visual_LineSelect_WithTabStop(_VimTest):
snippets = ("test", "beg\n\t${VISUAL}\n\t${1:here_we_go}\nend") snippets = ('test', 'beg\n\t${VISUAL}\n\t${1:here_we_go}\nend')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "super" + JF + "done" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + \
wanted = "beg\n\thello\n\tnice\n\tworld\n\tsuper\nenddone" EX + 'test' + EX + 'super' + JF + 'done'
wanted = 'beg\n\thello\n\tnice\n\tworld\n\tsuper\nenddone'
class Visual_LineSelect_CheckIndentWithTS_NoOverwrite(_VimTest): class Visual_LineSelect_CheckIndentWithTS_NoOverwrite(_VimTest):
snippets = ("test", "beg\n\t${0:${VISUAL}}\nend") snippets = ('test', 'beg\n\t${0:${VISUAL}}\nend')
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX
wanted = "beg\n\thello\n\tnice\n\tworld\nend" wanted = 'beg\n\thello\n\tnice\n\tworld\nend'
class Visual_LineSelect_DedentLine(_VimTest): class Visual_LineSelect_DedentLine(_VimTest):
snippets = ("if", "if {\n\t${VISUAL}$0\n}") snippets = ('if', 'if {\n\t${VISUAL}$0\n}')
keys = "if" + EX + "one\n\ttwo\n\tthree" + ESC + ARR_U*2 + "V" + ARR_D + EX + "\tif" + EX keys = 'if' + EX + 'one\n\ttwo\n\tthree' + ESC + \
wanted = "if {\n\tif {\n\t\tone\n\t\ttwo\n\t}\n\tthree\n}" ARR_U * 2 + 'V' + ARR_D + EX + '\tif' + EX
wanted = 'if {\n\tif {\n\t\tone\n\t\ttwo\n\t}\n\tthree\n}'
class VisualTransformation_SelectOneWord(_VimTest): class VisualTransformation_SelectOneWord(_VimTest):
snippets = ("test", r"h${VISUAL/./\U$0\E/g}b") snippets = ('test', r"h${VISUAL/./\U$0\E/g}b")
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX
wanted = "hBLABLUBb" wanted = 'hBLABLUBb'
class VisualTransformationWithDefault_ExpandWithoutVisual(_VimTest): class VisualTransformationWithDefault_ExpandWithoutVisual(_VimTest):
snippets = ("test", r"h${VISUAL:world/./\U$0\E/g}b") snippets = ('test', r"h${VISUAL:world/./\U$0\E/g}b")
keys = "test" + EX + "hi" keys = 'test' + EX + 'hi'
wanted = "hWORLDbhi" wanted = 'hWORLDbhi'
class VisualTransformationWithDefault_ExpandWithVisual(_VimTest): class VisualTransformationWithDefault_ExpandWithVisual(_VimTest):
snippets = ("test", r"h${VISUAL:world/./\U$0\E/g}b") snippets = ('test', r"h${VISUAL:world/./\U$0\E/g}b")
keys = "blablub" + ESC + "0v6l" + EX + "test" + EX keys = 'blablub' + ESC + '0v6l' + EX + 'test' + EX
wanted = "hBLABLUBb" wanted = 'hBLABLUBb'
class VisualTransformation_LineSelect_Simple(_VimTest): class VisualTransformation_LineSelect_Simple(_VimTest):
snippets = ("test", r"h${VISUAL/./\U$0\E/g}b") snippets = ('test', r"h${VISUAL/./\U$0\E/g}b")
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX
wanted = "hHELLO\n NICE\n WORLDb" wanted = 'hHELLO\n NICE\n WORLDb'
class VisualTransformation_InDefaultText_LineSelect_NoOverwrite(_VimTest): class VisualTransformation_InDefaultText_LineSelect_NoOverwrite(_VimTest):
snippets = ("test", r"h${1:bef${VISUAL/./\U$0\E/g}aft}b") snippets = ('test', r"h${1:bef${VISUAL/./\U$0\E/g}aft}b")
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + EX + 'test' + EX + JF + 'hi'
wanted = "hbefHELLO\n NICE\n WORLDaftbhi" wanted = 'hbefHELLO\n NICE\n WORLDaftbhi'
class VisualTransformation_InDefaultText_LineSelect_Overwrite(_VimTest): class VisualTransformation_InDefaultText_LineSelect_Overwrite(_VimTest):
snippets = ("test", r"h${1:bef${VISUAL/./\U$0\E/g}aft}b") snippets = ('test', r"h${1:bef${VISUAL/./\U$0\E/g}aft}b")
keys = "hello\nnice\nworld" + ESC + "Vkk" + EX + "test" + EX + "jup" + JF + "hi" keys = 'hello\nnice\nworld' + ESC + 'Vkk' + \
wanted = "hjupbhi" EX + 'test' + EX + 'jup' + JF + 'hi'
wanted = 'hjupbhi'
# End: ${VISUAL} #}}} # End: ${VISUAL} #}}}

View File

@ -6,10 +6,12 @@ try:
except ImportError: except ImportError:
UNIDECODE_IMPORTED = False UNIDECODE_IMPORTED = False
def running_on_windows(): def running_on_windows():
if platform.system() == "Windows": if platform.system() == 'Windows':
return "Does not work on Windows." return 'Does not work on Windows.'
def no_unidecode_available(): def no_unidecode_available():
if not UNIDECODE_IMPORTED: if not UNIDECODE_IMPORTED:
return "unidecode is not available." return 'unidecode is not available.'

View File

@ -9,6 +9,7 @@ import time
from test.constant import * from test.constant import *
def wait_until_file_exists(file_path, times=None, interval=0.01): def wait_until_file_exists(file_path, times=None, interval=0.01):
while times is None or times: while times is None or times:
if os.path.exists(file_path): if os.path.exists(file_path):
@ -18,17 +19,19 @@ def wait_until_file_exists(file_path, times=None, interval=0.01):
times -= 1 times -= 1
return False return False
def read_text_file(filename): def read_text_file(filename):
"""Reads the contens of a text file.""" """Reads the contens of a text file."""
if PYTHON3: if PYTHON3:
return open(filename,"r", encoding="utf-8").read() return open(filename, 'r', encoding='utf-8').read()
else: else:
return open(filename,"r").read() return open(filename, 'r').read()
def is_process_running(pid): def is_process_running(pid):
"""Returns true if a process with pid is running, false otherwise.""" """Returns true if a process with pid is running, false otherwise."""
# from http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid # from
# http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
try: try:
os.kill(pid, 0) os.kill(pid, 0)
except OSError: except OSError:
@ -36,10 +39,12 @@ def is_process_running(pid):
else: else:
return True return True
def silent_call(cmd): def silent_call(cmd):
"""Calls 'cmd' and returns the exit value.""" """Calls 'cmd' and returns the exit value."""
return subprocess.call(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) return subprocess.call(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
def create_directory(dirname): def create_directory(dirname):
"""Creates 'dirname' and its parents if it does not exist.""" """Creates 'dirname' and its parents if it does not exist."""
try: try:
@ -49,8 +54,9 @@ def create_directory(dirname):
class TempFileManager(object): class TempFileManager(object):
def __init__(self, name=""):
self._temp_dir = tempfile.mkdtemp(prefix="UltiSnipsTest_" + name) def __init__(self, name=''):
self._temp_dir = tempfile.mkdtemp(prefix='UltiSnipsTest_' + name)
def name_temp(self, file_path): def name_temp(self, file_path):
return os.path.join(self._temp_dir, file_path) return os.path.join(self._temp_dir, file_path)
@ -59,15 +65,16 @@ class TempFileManager(object):
abs_path = self.name_temp(file_path) abs_path = self.name_temp(file_path)
create_directory(os.path.dirname(abs_path)) create_directory(os.path.dirname(abs_path))
if PYTHON3: if PYTHON3:
with open(abs_path, "w", encoding="utf-8") as f: with open(abs_path, 'w', encoding='utf-8') as f:
f.write(content) f.write(content)
else: else:
with open(abs_path, "w") as f: with open(abs_path, 'w') as f:
f.write(content) f.write(content)
return abs_path return abs_path
def unique_name_temp(self, suffix="", prefix=""): def unique_name_temp(self, suffix='', prefix=''):
file_handler, abspath = tempfile.mkstemp(suffix, prefix, self._temp_dir) file_handler, abspath = tempfile.mkstemp(
suffix, prefix, self._temp_dir)
os.close(file_handler) os.close(file_handler)
os.remove(abspath) os.remove(abspath)
return abspath return abspath
@ -78,12 +85,13 @@ class TempFileManager(object):
class VimInterface(TempFileManager): class VimInterface(TempFileManager):
def __init__(self, name=""):
def __init__(self, name=''):
TempFileManager.__init__(self, name) TempFileManager.__init__(self, name)
def get_buffer_data(self): def get_buffer_data(self):
buffer_path = self.unique_name_temp(prefix="buffer_") buffer_path = self.unique_name_temp(prefix='buffer_')
self.send(ESC + ":w! %s\n" % buffer_path) self.send(ESC + ':w! %s\n' % buffer_path)
if wait_until_file_exists(buffer_path, 50): if wait_until_file_exists(buffer_path, 50):
return read_text_file(buffer_path)[:-1] return read_text_file(buffer_path)[:-1]
@ -91,35 +99,40 @@ class VimInterface(TempFileManager):
raise NotImplementedError() raise NotImplementedError()
def launch(self, config=[]): def launch(self, config=[]):
pid_file = self.name_temp("vim.pid") pid_file = self.name_temp('vim.pid')
done_file = self.name_temp("loading_done") done_file = self.name_temp('loading_done')
if os.path.exists(done_file): if os.path.exists(done_file):
os.remove(done_file) os.remove(done_file)
post_config = [] post_config = []
post_config.append("%s << EOF" % ("py3" if PYTHON3 else "py")) post_config.append('%s << EOF' % ('py3' if PYTHON3 else 'py'))
post_config.append("import vim") post_config.append('import vim')
post_config.append("with open('%s', 'w') as pid_file: pid_file.write(vim.eval('getpid()'))" % pid_file) post_config.append(
post_config.append("with open('%s', 'w') as done_file: pass" % done_file) "with open('%s', 'w') as pid_file: pid_file.write(vim.eval('getpid()'))" %
post_config.append("EOF") pid_file)
post_config.append(
"with open('%s', 'w') as done_file: pass" %
done_file)
post_config.append('EOF')
config_path = self.write_temp("vim_config.vim", config_path = self.write_temp('vim_config.vim',
textwrap.dedent(os.linesep.join(config + post_config) + "\n")) textwrap.dedent(os.linesep.join(config + post_config) + '\n'))
# Note the space to exclude it from shell history. # Note the space to exclude it from shell history.
self.send(""" vim -u %s\r\n""" % config_path) self.send(""" vim -u %s\r\n""" % config_path)
wait_until_file_exists(done_file) wait_until_file_exists(done_file)
self._vim_pid = int(open(pid_file, "r").read()) self._vim_pid = int(open(pid_file, 'r').read())
def leave_with_wait(self): def leave_with_wait(self):
self.send(3*ESC + ":qa!\n") self.send(3 * ESC + ':qa!\n')
while is_process_running(self._vim_pid): while is_process_running(self._vim_pid):
time.sleep(.05) time.sleep(.05)
class VimInterfaceScreen(VimInterface): class VimInterfaceScreen(VimInterface):
def __init__(self, session): def __init__(self, session):
VimInterface.__init__(self, "Screen") VimInterface.__init__(self, 'Screen')
self.session = session self.session = session
self.need_screen_escapes = 0 self.need_screen_escapes = 0
self.detect_parsing() self.detect_parsing()
@ -128,35 +141,42 @@ class VimInterfaceScreen(VimInterface):
if self.need_screen_escapes: if self.need_screen_escapes:
# escape characters that are special to some versions of screen # escape characters that are special to some versions of screen
repl = lambda m: '\\' + m.group(0) repl = lambda m: '\\' + m.group(0)
s = re.sub( r"[$^#\\']", repl, s ) s = re.sub(r"[$^#\\']", repl, s)
if PYTHON3: if PYTHON3:
s = s.encode("utf-8") s = s.encode('utf-8')
while True: while True:
rv = 0 rv = 0
if len(s) > 30: if len(s) > 30:
rv |= silent_call(["screen", "-x", self.session, "-X", "register", "S", s]) rv |= silent_call(
rv |= silent_call(["screen", "-x", self.session, "-X", "paste", "S"]) ['screen', '-x', self.session, '-X', 'register', 'S', s])
rv |= silent_call(
['screen', '-x', self.session, '-X', 'paste', 'S'])
else: else:
rv |= silent_call(["screen", "-x", self.session, "-X", "stuff", s]) rv |= silent_call(
if not rv: break ['screen', '-x', self.session, '-X', 'stuff', s])
if not rv:
break
time.sleep(.2) time.sleep(.2)
def detect_parsing(self): def detect_parsing(self):
self.launch() self.launch()
# Send a string where the interpretation will depend on version of screen # Send a string where the interpretation will depend on version of
string = "$TERM" # screen
self.send("i" + string + ESC) string = '$TERM'
self.send('i' + string + ESC)
output = self.get_buffer_data() output = self.get_buffer_data()
# If the output doesn't match the input, need to do additional escaping # If the output doesn't match the input, need to do additional escaping
if output != string: if output != string:
self.need_screen_escapes = 1 self.need_screen_escapes = 1
self.leave_with_wait() self.leave_with_wait()
class VimInterfaceTmux(VimInterface): class VimInterfaceTmux(VimInterface):
def __init__(self, session): def __init__(self, session):
VimInterface.__init__(self, "Tmux") VimInterface.__init__(self, 'Tmux')
self.session = session self.session = session
self._check_version() self._check_version()
@ -166,68 +186,73 @@ class VimInterfaceTmux(VimInterface):
s = s.replace(';', r'\;') s = s.replace(';', r'\;')
if PYTHON3: if PYTHON3:
s = s.encode("utf-8") s = s.encode('utf-8')
silent_call(["tmux", "send-keys", "-t", self.session, "-l", s]) silent_call(['tmux', 'send-keys', '-t', self.session, '-l', s])
def _check_version(self): def _check_version(self):
stdout, _ = subprocess.Popen(["tmux", "-V"], stdout, _ = subprocess.Popen(['tmux', '-V'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
if PYTHON3: if PYTHON3:
stdout = stdout.decode("utf-8") stdout = stdout.decode('utf-8')
m = re.match(r"tmux (\d+).(\d+)", stdout) m = re.match(r"tmux (\d+).(\d+)", stdout)
if not m or not (int(m.group(1)), int(m.group(2))) >= (1, 8): if not m or not (int(m.group(1)), int(m.group(2))) >= (1, 8):
raise RuntimeError("Need at least tmux 1.8, you have %s." % stdout.strip()) raise RuntimeError(
'Need at least tmux 1.8, you have %s.' %
stdout.strip())
class VimInterfaceWindows(VimInterface): class VimInterfaceWindows(VimInterface):
BRACES = re.compile("([}{])") BRACES = re.compile('([}{])')
WIN_ESCAPES = ["+", "^", "%", "~", "[", "]", "<", ">", "(", ")"] WIN_ESCAPES = ['+', '^', '%', '~', '[', ']', '<', '>', '(', ')']
WIN_REPLACES = [ WIN_REPLACES = [
(BS, "{BS}"), (BS, '{BS}'),
(ARR_L, "{LEFT}"), (ARR_L, '{LEFT}'),
(ARR_R, "{RIGHT}"), (ARR_R, '{RIGHT}'),
(ARR_U, "{UP}"), (ARR_U, '{UP}'),
(ARR_D, "{DOWN}"), (ARR_D, '{DOWN}'),
("\t", "{TAB}"), ('\t', '{TAB}'),
("\n", "~"), ('\n', '~'),
(ESC, "{ESC}"), (ESC, '{ESC}'),
# On my system ` waits for a second keystroke, so `+SPACE = "`". On # On my system ` waits for a second keystroke, so `+SPACE = "`". On
# most systems, `+Space = "` ". I work around this, by sending the host # most systems, `+Space = "` ". I work around this, by sending the host
# ` as `+_+BS. Awkward, but the only way I found to get this working. # ` as `+_+BS. Awkward, but the only way I found to get this working.
("`", "`_{BS}"), ('`', '`_{BS}'),
("´", "´_{BS}"), ('´', '´_{BS}'),
("{^}", "{^}_{BS}"), ('{^}', '{^}_{BS}'),
] ]
def __init__(self): def __init__(self):
self.seq_buf = [] self.seq_buf = []
# import windows specific modules # import windows specific modules
import win32com.client, win32gui import win32com.client
import win32gui
self.win32gui = win32gui self.win32gui = win32gui
self.shell = win32com.client.Dispatch("WScript.Shell") self.shell = win32com.client.Dispatch('WScript.Shell')
def is_focused(self, title=None): def is_focused(self, title=None):
cur_title = self.win32gui.GetWindowText(self.win32gui.GetForegroundWindow()) cur_title = self.win32gui.GetWindowText(
if (title or "- GVIM") in cur_title: self.win32gui.GetForegroundWindow())
if (title or '- GVIM') in cur_title:
return True return True
return False return False
def focus(self, title=None): def focus(self, title=None):
if not self.shell.AppActivate(title or "- GVIM"): if not self.shell.AppActivate(title or '- GVIM'):
raise Exception("Failed to switch to GVim window") raise Exception('Failed to switch to GVim window')
time.sleep(1) time.sleep(1)
def convert_keys(self, keys): def convert_keys(self, keys):
keys = self.BRACES.sub(r"{\1}", keys) keys = self.BRACES.sub(r"{\1}", keys)
for k in self.WIN_ESCAPES: for k in self.WIN_ESCAPES:
keys = keys.replace(k, "{%s}" % k) keys = keys.replace(k, '{%s}' % k)
for f, r in self.WIN_REPLACES: for f, r in self.WIN_REPLACES:
keys = keys.replace(f, r) keys = keys.replace(f, r)
return keys return keys
def send(self, keys): def send(self, keys):
self.seq_buf.append(keys) self.seq_buf.append(keys)
seq = "".join(self.seq_buf) seq = ''.join(self.seq_buf)
for f in SEQUENCES: for f in SEQUENCES:
if f.startswith(seq) and f != seq: if f.startswith(seq) and f != seq:
@ -241,7 +266,6 @@ class VimInterfaceWindows(VimInterface):
self.focus() self.focus()
if not self.is_focused(): if not self.is_focused():
# This is the only way I can find to stop test execution # This is the only way I can find to stop test execution
raise KeyboardInterrupt("Failed to focus GVIM") raise KeyboardInterrupt('Failed to focus GVIM')
self.shell.SendKeys(seq) self.shell.SendKeys(seq)

View File

@ -6,7 +6,6 @@ import os
import re import re
import shutil import shutil
import subprocess import subprocess
import sys
import tempfile import tempfile
import textwrap import textwrap
import time import time
@ -14,9 +13,11 @@ import unittest
from constant import * from constant import *
def is_process_running(pid): def is_process_running(pid):
"""Returns true if a process with pid is running, false otherwise.""" """Returns true if a process with pid is running, false otherwise."""
# from http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid # from
# http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
try: try:
os.kill(pid, 0) os.kill(pid, 0)
except OSError: except OSError:
@ -24,10 +25,12 @@ def is_process_running(pid):
else: else:
return True return True
def silent_call(cmd): def silent_call(cmd):
"""Calls 'cmd' and returns the exit value.""" """Calls 'cmd' and returns the exit value."""
return subprocess.call(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) return subprocess.call(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
def create_directory(dirname): def create_directory(dirname):
"""Creates 'dirname' and its parents if it does not exist.""" """Creates 'dirname' and its parents if it does not exist."""
try: try:
@ -35,16 +38,19 @@ def create_directory(dirname):
except OSError: except OSError:
pass pass
def plugin_cache_dir(): def plugin_cache_dir():
"""The directory that we check out our bundles to.""" """The directory that we check out our bundles to."""
return os.path.join(tempfile.gettempdir(), "UltiSnips_test_vim_plugins") return os.path.join(tempfile.gettempdir(), 'UltiSnips_test_vim_plugins')
def read_text_file(filename): def read_text_file(filename):
"""Reads the contens of a text file.""" """Reads the contens of a text file."""
if PYTHON3: if PYTHON3:
return open(filename,"r", encoding="utf-8").read() return open(filename, 'r', encoding='utf-8').read()
else: else:
return open(filename,"r").read() return open(filename, 'r').read()
def wait_until_file_exists(file_path, times=None, interval=0.01): def wait_until_file_exists(file_path, times=None, interval=0.01):
while times is None or times: while times is None or times:
@ -55,59 +61,61 @@ def wait_until_file_exists(file_path, times=None, interval=0.01):
times -= 1 times -= 1
return False return False
class TempFileManager(object): class TempFileManager(object):
"""A TempFileManager keeps a unique prefix path for temp
files. A temp file, or a name for a temp file generate by a """A TempFileManager keeps a unique prefix path for temp files.
TempFileManager always belongs to the same directory.
A temp file, or a name for a temp file generate by a TempFileManager
always belongs to the same directory.
""" """
def __init__(self, name=""):
"""The unique prefix path is UltiSnipsTest_{name}XXXXXX. def __init__(self, name=''):
""" """The unique prefix path is UltiSnipsTest_{name}XXXXXX."""
self._temp_dir = tempfile.mkdtemp(prefix="UltiSnipsTest_" + name) self._temp_dir = tempfile.mkdtemp(prefix='UltiSnipsTest_' + name)
def name_temp(self, file_path): def name_temp(self, file_path):
"""Get the absolute path of a temp file by given file path. """Get the absolute path of a temp file by given file path."""
"""
return os.path.join(self._temp_dir, file_path) return os.path.join(self._temp_dir, file_path)
def write_temp(self, file_path, content): def write_temp(self, file_path, content):
"""Write the content to a temp file by given file path inside """Write the content to a temp file by given file path inside the
the _temp_dir, and return the absolute path of that file. _temp_dir, and return the absolute path of that file."""
"""
abs_path = self.name_temp(file_path) abs_path = self.name_temp(file_path)
create_directory(os.path.dirname(abs_path)) create_directory(os.path.dirname(abs_path))
if PYTHON3: if PYTHON3:
with open(abs_path, "w", encoding="utf-8") as f: with open(abs_path, 'w', encoding='utf-8') as f:
f.write(content) f.write(content)
else: else:
with open(abs_path, "w") as f: with open(abs_path, 'w') as f:
f.write(content) f.write(content)
return abs_path return abs_path
def unique_name_temp(self, suffix="", prefix=""): def unique_name_temp(self, suffix='', prefix=''):
"""Generate a unique name for a temp file with given suffix and """Generate a unique name for a temp file with given suffix and prefix,
prefix, and return full absolute path. and return full absolute path."""
""" file_handler, abspath = tempfile.mkstemp(
file_handler, abspath = tempfile.mkstemp(suffix, prefix, self._temp_dir) suffix, prefix, self._temp_dir)
os.close(file_handler) os.close(file_handler)
os.remove(abspath) os.remove(abspath)
return abspath return abspath
def clear_temp(self): def clear_temp(self):
"""Clear the temp file directory, but the directory itself is """Clear the temp file directory, but the directory itself is not
not removed. removed."""
"""
shutil.rmtree(self._temp_dir) shutil.rmtree(self._temp_dir)
create_directory(self._temp_dir) create_directory(self._temp_dir)
class VimInterface(TempFileManager): class VimInterface(TempFileManager):
def __init__(self, name=""):
def __init__(self, name=''):
TempFileManager.__init__(self, name) TempFileManager.__init__(self, name)
def get_buffer_data(self): def get_buffer_data(self):
buffer_path = self.unique_name_temp(prefix="buffer_") buffer_path = self.unique_name_temp(prefix='buffer_')
self.send(ESC + ":w! %s\n" % buffer_path) self.send(ESC + ':w! %s\n' % buffer_path)
if wait_until_file_exists(buffer_path, 50): if wait_until_file_exists(buffer_path, 50):
return read_text_file(buffer_path)[:-1] return read_text_file(buffer_path)[:-1]
@ -115,35 +123,40 @@ class VimInterface(TempFileManager):
raise NotImplementedError() raise NotImplementedError()
def launch(self, config=[]): def launch(self, config=[]):
pid_file = self.name_temp("vim.pid") pid_file = self.name_temp('vim.pid')
done_file = self.name_temp("loading_done") done_file = self.name_temp('loading_done')
if os.path.exists(done_file): if os.path.exists(done_file):
os.remove(done_file) os.remove(done_file)
post_config = [] post_config = []
post_config.append("%s << EOF" % ("py3" if PYTHON3 else "py")) post_config.append('%s << EOF' % ('py3' if PYTHON3 else 'py'))
post_config.append("import vim") post_config.append('import vim')
post_config.append("with open('%s', 'w') as pid_file: pid_file.write(vim.eval('getpid()'))" % pid_file) post_config.append(
post_config.append("with open('%s', 'w') as done_file: pass" % done_file) "with open('%s', 'w') as pid_file: pid_file.write(vim.eval('getpid()'))" %
post_config.append("EOF") pid_file)
post_config.append(
"with open('%s', 'w') as done_file: pass" %
done_file)
post_config.append('EOF')
config_path = self.write_temp("vim_config.vim", config_path = self.write_temp('vim_config.vim',
textwrap.dedent(os.linesep.join(config + post_config) + "\n")) textwrap.dedent(os.linesep.join(config + post_config) + '\n'))
# Note the space to exclude it from shell history. # Note the space to exclude it from shell history.
self.send(""" vim -u %s\r\n""" % config_path) self.send(""" vim -u %s\r\n""" % config_path)
wait_until_file_exists(done_file) wait_until_file_exists(done_file)
self._vim_pid = int(open(pid_file, "r").read()) self._vim_pid = int(open(pid_file, 'r').read())
def leave_with_wait(self): def leave_with_wait(self):
self.send(3*ESC + ":qa!\n") self.send(3 * ESC + ':qa!\n')
while is_process_running(self._vim_pid): while is_process_running(self._vim_pid):
time.sleep(.05) time.sleep(.05)
class VimInterfaceScreen(VimInterface): class VimInterfaceScreen(VimInterface):
def __init__(self, session): def __init__(self, session):
VimInterface.__init__(self, "Screen") VimInterface.__init__(self, 'Screen')
self.session = session self.session = session
self.need_screen_escapes = 0 self.need_screen_escapes = 0
self.detect_parsing() self.detect_parsing()
@ -152,33 +165,40 @@ class VimInterfaceScreen(VimInterface):
if self.need_screen_escapes: if self.need_screen_escapes:
# escape characters that are special to some versions of screen # escape characters that are special to some versions of screen
repl = lambda m: '\\' + m.group(0) repl = lambda m: '\\' + m.group(0)
s = re.sub( r"[$^#\\']", repl, s ) s = re.sub(r"[$^#\\']", repl, s)
if PYTHON3: if PYTHON3:
s = s.encode("utf-8") s = s.encode('utf-8')
while True: while True:
rv = 0 rv = 0
if len(s) > 30: if len(s) > 30:
rv |= silent_call(["screen", "-x", self.session, "-X", "register", "S", s]) rv |= silent_call(
rv |= silent_call(["screen", "-x", self.session, "-X", "paste", "S"]) ['screen', '-x', self.session, '-X', 'register', 'S', s])
rv |= silent_call(
['screen', '-x', self.session, '-X', 'paste', 'S'])
else: else:
rv |= silent_call(["screen", "-x", self.session, "-X", "stuff", s]) rv |= silent_call(
if not rv: break ['screen', '-x', self.session, '-X', 'stuff', s])
if not rv:
break
time.sleep(.2) time.sleep(.2)
def detect_parsing(self): def detect_parsing(self):
self.launch() self.launch()
# Send a string where the interpretation will depend on version of screen # Send a string where the interpretation will depend on version of
string = "$TERM" # screen
self.send("i" + string + ESC) string = '$TERM'
self.send('i' + string + ESC)
output = self.get_buffer_data() output = self.get_buffer_data()
# If the output doesn't match the input, need to do additional escaping # If the output doesn't match the input, need to do additional escaping
if output != string: if output != string:
self.need_screen_escapes = 1 self.need_screen_escapes = 1
self.leave_with_wait() self.leave_with_wait()
class VimInterfaceTmux(VimInterface): class VimInterfaceTmux(VimInterface):
def __init__(self, session): def __init__(self, session):
self.session = session self.session = session
self._check_version() self._check_version()
@ -189,68 +209,73 @@ class VimInterfaceTmux(VimInterface):
s = s.replace(';', r'\;') s = s.replace(';', r'\;')
if PYTHON3: if PYTHON3:
s = s.encode("utf-8") s = s.encode('utf-8')
silent_call(["tmux", "send-keys", "-t", self.session, "-l", s]) silent_call(['tmux', 'send-keys', '-t', self.session, '-l', s])
def _check_version(self): def _check_version(self):
stdout, _ = subprocess.Popen(["tmux", "-V"], stdout, _ = subprocess.Popen(['tmux', '-V'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
if PYTHON3: if PYTHON3:
stdout = stdout.decode("utf-8") stdout = stdout.decode('utf-8')
m = re.match(r"tmux (\d+).(\d+)", stdout) m = re.match(r"tmux (\d+).(\d+)", stdout)
if not m or not (int(m.group(1)), int(m.group(2))) >= (1, 9): if not m or not (int(m.group(1)), int(m.group(2))) >= (1, 9):
raise RuntimeError("Need at least tmux 1.9, you have %s." % stdout.strip()) raise RuntimeError(
'Need at least tmux 1.9, you have %s.' %
stdout.strip())
class VimInterfaceWindows(VimInterface): class VimInterfaceWindows(VimInterface):
BRACES = re.compile("([}{])") BRACES = re.compile('([}{])')
WIN_ESCAPES = ["+", "^", "%", "~", "[", "]", "<", ">", "(", ")"] WIN_ESCAPES = ['+', '^', '%', '~', '[', ']', '<', '>', '(', ')']
WIN_REPLACES = [ WIN_REPLACES = [
(BS, "{BS}"), (BS, '{BS}'),
(ARR_L, "{LEFT}"), (ARR_L, '{LEFT}'),
(ARR_R, "{RIGHT}"), (ARR_R, '{RIGHT}'),
(ARR_U, "{UP}"), (ARR_U, '{UP}'),
(ARR_D, "{DOWN}"), (ARR_D, '{DOWN}'),
("\t", "{TAB}"), ('\t', '{TAB}'),
("\n", "~"), ('\n', '~'),
(ESC, "{ESC}"), (ESC, '{ESC}'),
# On my system ` waits for a second keystroke, so `+SPACE = "`". On # On my system ` waits for a second keystroke, so `+SPACE = "`". On
# most systems, `+Space = "` ". I work around this, by sending the host # most systems, `+Space = "` ". I work around this, by sending the host
# ` as `+_+BS. Awkward, but the only way I found to get this working. # ` as `+_+BS. Awkward, but the only way I found to get this working.
("`", "`_{BS}"), ('`', '`_{BS}'),
("´", "´_{BS}"), ('´', '´_{BS}'),
("{^}", "{^}_{BS}"), ('{^}', '{^}_{BS}'),
] ]
def __init__(self): def __init__(self):
self.seq_buf = [] self.seq_buf = []
# import windows specific modules # import windows specific modules
import win32com.client, win32gui import win32com.client
import win32gui
self.win32gui = win32gui self.win32gui = win32gui
self.shell = win32com.client.Dispatch("WScript.Shell") self.shell = win32com.client.Dispatch('WScript.Shell')
def is_focused(self, title=None): def is_focused(self, title=None):
cur_title = self.win32gui.GetWindowText(self.win32gui.GetForegroundWindow()) cur_title = self.win32gui.GetWindowText(
if (title or "- GVIM") in cur_title: self.win32gui.GetForegroundWindow())
if (title or '- GVIM') in cur_title:
return True return True
return False return False
def focus(self, title=None): def focus(self, title=None):
if not self.shell.AppActivate(title or "- GVIM"): if not self.shell.AppActivate(title or '- GVIM'):
raise Exception("Failed to switch to GVim window") raise Exception('Failed to switch to GVim window')
time.sleep(1) time.sleep(1)
def convert_keys(self, keys): def convert_keys(self, keys):
keys = self.BRACES.sub(r"{\1}", keys) keys = self.BRACES.sub(r"{\1}", keys)
for k in self.WIN_ESCAPES: for k in self.WIN_ESCAPES:
keys = keys.replace(k, "{%s}" % k) keys = keys.replace(k, '{%s}' % k)
for f, r in self.WIN_REPLACES: for f, r in self.WIN_REPLACES:
keys = keys.replace(f, r) keys = keys.replace(f, r)
return keys return keys
def send(self, keys): def send(self, keys):
self.seq_buf.append(keys) self.seq_buf.append(keys)
seq = "".join(self.seq_buf) seq = ''.join(self.seq_buf)
for f in SEQUENCES: for f in SEQUENCES:
if f.startswith(seq) and f != seq: if f.startswith(seq) and f != seq:
@ -264,7 +289,7 @@ class VimInterfaceWindows(VimInterface):
self.focus() self.focus()
if not self.is_focused(): if not self.is_focused():
# This is the only way I can find to stop test execution # This is the only way I can find to stop test execution
raise KeyboardInterrupt("Failed to focus GVIM") raise KeyboardInterrupt('Failed to focus GVIM')
self.shell.SendKeys(seq) self.shell.SendKeys(seq)
@ -272,13 +297,13 @@ class VimInterfaceWindows(VimInterface):
class VimTestCase(unittest.TestCase, TempFileManager): class VimTestCase(unittest.TestCase, TempFileManager):
snippets = () snippets = ()
files = {} files = {}
text_before = " --- some text before --- \n\n" text_before = ' --- some text before --- \n\n'
text_after = "\n\n --- some text after --- " text_after = '\n\n --- some text after --- '
expected_error = "" expected_error = ''
wanted = "" wanted = ''
keys = "" keys = ''
sleeptime = 0.00 sleeptime = 0.00
output = "" output = ''
plugins = [] plugins = []
# Skip this test for the given reason or None for not skipping it. # Skip this test for the given reason or None for not skipping it.
skip_if = lambda self: None skip_if = lambda self: None
@ -286,7 +311,7 @@ class VimTestCase(unittest.TestCase, TempFileManager):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
unittest.TestCase.__init__(self, *args, **kwargs) unittest.TestCase.__init__(self, *args, **kwargs)
TempFileManager.__init__(self, "Case") TempFileManager.__init__(self, 'Case')
def runTest(self): def runTest(self):
# Only checks the output. All work is done in setUp(). # Only checks the output. All work is done in setUp().
@ -304,37 +329,41 @@ class VimTestCase(unittest.TestCase, TempFileManager):
def _extra_options_pre_init(self, vim_config): def _extra_options_pre_init(self, vim_config):
"""Adds extra lines to the vim_config list.""" """Adds extra lines to the vim_config list."""
pass
def _extra_options_post_init(self, vim_config): def _extra_options_post_init(self, vim_config):
"""Adds extra lines to the vim_config list.""" """Adds extra lines to the vim_config list."""
pass
def _before_test(self): def _before_test(self):
"""Send these keys before the test runs. Used for buffer local """Send these keys before the test runs.
variables and other options."""
pass Used for buffer local variables and other options.
"""
def _create_file(self, file_path, content): def _create_file(self, file_path, content):
"""Creates a file in the runtimepath that is created for this test. """Creates a file in the runtimepath that is created for this test.
Returns the absolute path to the file."""
return self.write_temp(file_path, textwrap.dedent(content + "\n")) Returns the absolute path to the file.
"""
return self.write_temp(file_path, textwrap.dedent(content + '\n'))
def _link_file(self, source, relative_destination): def _link_file(self, source, relative_destination):
"""Creates a link from 'source' to the 'relative_destination' in our temp dir.""" """Creates a link from 'source' to the 'relative_destination' in our
temp dir."""
absdir = self.name_temp(relative_destination) absdir = self.name_temp(relative_destination)
create_directory(absdir) create_directory(absdir)
os.symlink(source, os.path.join(absdir, os.path.basename(source))) os.symlink(source, os.path.join(absdir, os.path.basename(source)))
def setUp(self): def setUp(self):
if not VimTestCase.version: if not VimTestCase.version:
VimTestCase.version, _ = subprocess.Popen(["vim", "--version"], VimTestCase.version, _ = subprocess.Popen(['vim', '--version'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
if PYTHON3: if PYTHON3:
VimTestCase.version = VimTestCase.version.decode("utf-8") VimTestCase.version = VimTestCase.version.decode('utf-8')
if self.plugins and not self.test_plugins: if self.plugins and not self.test_plugins:
return self.skipTest("Not testing integration with other plugins.") return self.skipTest('Not testing integration with other plugins.')
reason_for_skipping = self.skip_if() reason_for_skipping = self.skip_if()
if reason_for_skipping is not None: if reason_for_skipping is not None:
return self.skipTest(reason_for_skipping) return self.skipTest(reason_for_skipping)
@ -345,10 +374,19 @@ class VimTestCase(unittest.TestCase, TempFileManager):
os.path.dirname(os.path.dirname(__file__)), self._temp_dir)) os.path.dirname(os.path.dirname(__file__)), self._temp_dir))
if self.plugins: if self.plugins:
self._link_file(os.path.join(plugin_cache_dir(), "vim-pathogen", "autoload"), ".") self._link_file(
os.path.join(
plugin_cache_dir(),
'vim-pathogen',
'autoload'),
'.')
for plugin in self.plugins: for plugin in self.plugins:
self._link_file(os.path.join(plugin_cache_dir(), os.path.basename(plugin)), "bundle") self._link_file(
vim_config.append("execute pathogen#infect()") os.path.join(
plugin_cache_dir(),
os.path.basename(plugin)),
'bundle')
vim_config.append('execute pathogen#infect()')
# Vim parameters. # Vim parameters.
vim_config.append('syntax on') vim_config.append('syntax on')
@ -363,7 +401,9 @@ class VimTestCase(unittest.TestCase, TempFileManager):
vim_config.append('let g:UltiSnipsJumpForwardTrigger="?"') vim_config.append('let g:UltiSnipsJumpForwardTrigger="?"')
vim_config.append('let g:UltiSnipsJumpBackwardTrigger="+"') vim_config.append('let g:UltiSnipsJumpBackwardTrigger="+"')
vim_config.append('let g:UltiSnipsListSnippets="@"') vim_config.append('let g:UltiSnipsListSnippets="@"')
vim_config.append('let g:UltiSnipsUsePythonVersion="%i"' % (3 if PYTHON3 else 2)) vim_config.append(
'let g:UltiSnipsUsePythonVersion="%i"' %
(3 if PYTHON3 else 2))
vim_config.append('let g:UltiSnipsSnippetDirectories=["us"]') vim_config.append('let g:UltiSnipsSnippetDirectories=["us"]')
self._extra_options_pre_init(vim_config) self._extra_options_pre_init(vim_config)
@ -374,14 +414,14 @@ class VimTestCase(unittest.TestCase, TempFileManager):
self._extra_options_post_init(vim_config) self._extra_options_post_init(vim_config)
# Finally, add the snippets and some configuration for the test. # Finally, add the snippets and some configuration for the test.
vim_config.append("%s << EOF" % ("py3" if PYTHON3 else "py")) vim_config.append('%s << EOF' % ('py3' if PYTHON3 else 'py'))
if len(self.snippets) and not isinstance(self.snippets[0],tuple): if len(self.snippets) and not isinstance(self.snippets[0], tuple):
self.snippets = ( self.snippets, ) self.snippets = (self.snippets, )
for s in self.snippets: for s in self.snippets:
sv, content = s[:2] sv, content = s[:2]
description = "" description = ''
options = "" options = ''
priority = 0 priority = 0
if len(s) > 2: if len(s) > 2:
description = s[2] description = s[2]
@ -389,16 +429,17 @@ class VimTestCase(unittest.TestCase, TempFileManager):
options = s[3] options = s[3]
if len(s) > 4: if len(s) > 4:
priority = s[4] priority = s[4]
vim_config.append("UltiSnips_Manager.add_snippet(%r, %r, %r, %r, priority=%i)" % ( vim_config.append('UltiSnips_Manager.add_snippet(%r, %r, %r, %r, priority=%i)' % (
sv, content, description, options, priority)) sv, content, description, options, priority))
# fill buffer with default text and place cursor in between. # fill buffer with default text and place cursor in between.
prefilled_text = (self.text_before + self.text_after).splitlines() prefilled_text = (self.text_before + self.text_after).splitlines()
vim_config.append("vim.current.buffer[:] = %r\n" % prefilled_text) vim_config.append('vim.current.buffer[:] = %r\n' % prefilled_text)
vim_config.append("vim.current.window.cursor = (max(len(vim.current.buffer)//2, 1), 0)") vim_config.append(
'vim.current.window.cursor = (max(len(vim.current.buffer)//2, 1), 0)')
# End of python stuff. # End of python stuff.
vim_config.append("EOF") vim_config.append('EOF')
for name, content in self.files.items(): for name, content in self.files.items():
self._create_file(name, content) self._create_file(name, content)
@ -417,7 +458,7 @@ class VimTestCase(unittest.TestCase, TempFileManager):
def tearDown(self): def tearDown(self):
if self.interrupt: if self.interrupt:
print("Working directory: %s" % (self._temp_dir)) print('Working directory: %s' % (self._temp_dir))
return return
self.vim.leave_with_wait() self.vim.leave_with_wait()
self.clear_temp() self.clear_temp()

View File

@ -47,28 +47,32 @@ import unittest
from test.constant import * from test.constant import *
from test.vim_interface import * from test.vim_interface import *
def plugin_cache_dir(): def plugin_cache_dir():
"""The directory that we check out our bundles to.""" """The directory that we check out our bundles to."""
return os.path.join(tempfile.gettempdir(), "UltiSnips_test_vim_plugins") return os.path.join(tempfile.gettempdir(), 'UltiSnips_test_vim_plugins')
def clone_plugin(plugin): def clone_plugin(plugin):
"""Clone the given plugin into our plugin directory.""" """Clone the given plugin into our plugin directory."""
dirname = os.path.join(plugin_cache_dir(), os.path.basename(plugin)) dirname = os.path.join(plugin_cache_dir(), os.path.basename(plugin))
print("Cloning %s -> %s" % (plugin, dirname)) print('Cloning %s -> %s' % (plugin, dirname))
if os.path.exists(dirname): if os.path.exists(dirname):
print("Skip cloning of %s. Already there." % plugin) print('Skip cloning of %s. Already there.' % plugin)
return return
create_directory(dirname) create_directory(dirname)
subprocess.call(["git", "clone", "--recursive", subprocess.call(['git', 'clone', '--recursive',
"--depth", "1", "https://github.com/%s" % plugin, dirname]) '--depth', '1', 'https://github.com/%s' % plugin, dirname])
if plugin == 'Valloric/YouCompleteMe':
# CLUTCH: this plugin needs something extra.
subprocess.call(os.path.join(dirname, './install.sh'), cwd=dirname)
if plugin == "Valloric/YouCompleteMe":
## CLUTCH: this plugin needs something extra.
subprocess.call(os.path.join(dirname, "./install.sh"), cwd=dirname)
def setup_other_plugins(all_plugins): def setup_other_plugins(all_plugins):
"""Creates /tmp/UltiSnips_test_vim_plugins and clones all plugins into this.""" """Creates /tmp/UltiSnips_test_vim_plugins and clones all plugins into
clone_plugin("tpope/vim-pathogen") this."""
clone_plugin('tpope/vim-pathogen')
for plugin in all_plugins: for plugin in all_plugins:
clone_plugin(plugin) clone_plugin(plugin)
@ -76,35 +80,35 @@ if __name__ == '__main__':
import optparse import optparse
def parse_args(): def parse_args():
p = optparse.OptionParser("%prog [OPTIONS] <test case names to run>") p = optparse.OptionParser('%prog [OPTIONS] <test case names to run>')
p.set_defaults(session="vim", interrupt=False, p.set_defaults(session='vim', interrupt=False,
verbose=False, interface="screen", retries=4, plugins=False) verbose=False, interface='screen', retries=4, plugins=False)
p.add_option("-v", "--verbose", dest="verbose", action="store_true", p.add_option('-v', '--verbose', dest='verbose', action='store_true',
help="print name of tests as they are executed") help='print name of tests as they are executed')
p.add_option("--clone-plugins", action="store_true", p.add_option('--clone-plugins', action='store_true',
help="Only clones dependant plugins and exits the test runner.") help='Only clones dependant plugins and exits the test runner.')
p.add_option("--plugins", action="store_true", p.add_option('--plugins', action='store_true',
help="Run integration tests with other Vim plugins.") help='Run integration tests with other Vim plugins.')
p.add_option("--interface", type=str, p.add_option('--interface', type=str,
help="interface to vim to use on Mac and or Linux [screen|tmux].") help='interface to vim to use on Mac and or Linux [screen|tmux].')
p.add_option("-s", "--session", dest="session", metavar="SESSION", p.add_option('-s', '--session', dest='session', metavar='SESSION',
help="session parameters for the terminal multiplexer SESSION [%default]") help='session parameters for the terminal multiplexer SESSION [%default]')
p.add_option("-i", "--interrupt", dest="interrupt", p.add_option('-i', '--interrupt', dest='interrupt',
action="store_true", action='store_true',
help="Stop after defining the snippet. This allows the user " \ help='Stop after defining the snippet. This allows the user '
"to interactively test the snippet in vim. You must give " \ 'to interactively test the snippet in vim. You must give '
"exactly one test case on the cmdline. The test will always fail." 'exactly one test case on the cmdline. The test will always fail.'
) )
p.add_option("-r", "--retries", dest="retries", type=int, p.add_option('-r', '--retries', dest='retries', type=int,
help="How often should each test be retried before it is " help='How often should each test be retried before it is '
"considered failed. Works around flakyness in the terminal " 'considered failed. Works around flakyness in the terminal '
"multiplexer and race conditions in writing to the file system.") 'multiplexer and race conditions in writing to the file system.')
o, args = p.parse_args() o, args = p.parse_args()
if o.interface not in ("screen", "tmux"): if o.interface not in ('screen', 'tmux'):
p.error("--interface must be [screen|tmux].") p.error('--interface must be [screen|tmux].')
return o, args return o, args
@ -118,20 +122,21 @@ if __name__ == '__main__':
return flatten return flatten
def main(): def main():
options,selected_tests = parse_args() options, selected_tests = parse_args()
all_test_suites = unittest.defaultTestLoader.discover(start_dir="test") all_test_suites = unittest.defaultTestLoader.discover(start_dir='test')
vim = None vim = None
if not options.clone_plugins: if not options.clone_plugins:
if platform.system() == "Windows": if platform.system() == 'Windows':
raise RuntimeError("TODO: TestSuite is broken under windows. Volunteers wanted!.") raise RuntimeError(
'TODO: TestSuite is broken under windows. Volunteers wanted!.')
# vim = VimInterfaceWindows() # vim = VimInterfaceWindows()
vim.focus() vim.focus()
else: else:
if options.interface == "screen": if options.interface == 'screen':
vim = VimInterfaceScreen(options.session) vim = VimInterfaceScreen(options.session)
elif options.interface == "tmux": elif options.interface == 'tmux':
vim = VimInterfaceTmux(options.session) vim = VimInterfaceTmux(options.session)
all_other_plugins = set() all_other_plugins = set()
@ -148,7 +153,7 @@ if __name__ == '__main__':
if len(selected_tests): if len(selected_tests):
id = test.id().split('.')[1] id = test.id().split('.')[1]
if not any([ id.startswith(t) for t in selected_tests ]): if not any([id.startswith(t) for t in selected_tests]):
continue continue
tests.add(test) tests.add(test)
suite.addTests(tests) suite.addTests(tests)

View File

@ -11,28 +11,37 @@ import glob
_UNESCAPE = re.compile(ur'&\w+?;', re.UNICODE) _UNESCAPE = re.compile(ur'&\w+?;', re.UNICODE)
def unescape(s): def unescape(s):
if s is None: if s is None:
return "" return ''
def fixup(m): def fixup(m):
ent = m.group(0)[1:-1] ent = m.group(0)[1:-1]
return unichr(htmlentitydefs.name2codepoint[ent]) return unichr(htmlentitydefs.name2codepoint[ent])
try: try:
return _UNESCAPE.sub(fixup,s) return _UNESCAPE.sub(fixup, s)
except: except:
print "unescape failed: %s" % repr(s) print 'unescape failed: %s' % repr(s)
raise raise
class UnknownVariable(Exception): class UnknownVariable(Exception):
pass pass
class UnsupportedVariableExpression(Exception): class UnsupportedVariableExpression(Exception):
pass pass
def replace_vars(m): def replace_vars(m):
""" Replace vars in 'content' portion. """Replace vars in 'content' portion.
:m: match object :m: match object
:returns: string""" :returns: string
"""
var = m.group(1) var = m.group(1)
default = m.group(2) default = m.group(2)
@ -40,10 +49,10 @@ def replace_vars(m):
raise UnsupportedVariableExpression(var) raise UnsupportedVariableExpression(var)
translate_vars = { translate_vars = {
'TM_PHP_OPEN_TAG_WITH_ECHO': 'g:UltiSnipsOpenTagWithEcho', 'TM_PHP_OPEN_TAG_WITH_ECHO': 'g:UltiSnipsOpenTagWithEcho',
'TM_PHP_OPEN_TAG': 'g:UltiSnipsOpenTag', 'TM_PHP_OPEN_TAG': 'g:UltiSnipsOpenTag',
'PHPDOC_AUTHOR': 'g:snips_author', 'PHPDOC_AUTHOR': 'g:snips_author',
} }
# TODO: TM_SELECTED_TEXT/([\t ]*).*/$1/m # TODO: TM_SELECTED_TEXT/([\t ]*).*/$1/m
if var in translate_vars: if var in translate_vars:
@ -54,44 +63,48 @@ def replace_vars(m):
return "`!v exists('%s') ? %s : '%s'`" % (newvar, newvar, default) return "`!v exists('%s') ? %s : '%s'`" % (newvar, newvar, default)
def parse_content(c): def parse_content(c):
try: try:
data = ElementTree.fromstring(c)[0] data = ElementTree.fromstring(c)[0]
rv = {} rv = {}
for k,v in zip(data[::2], data[1::2]): for k, v in zip(data[::2], data[1::2]):
rv[k.text] = unescape(v.text) rv[k.text] = unescape(v.text)
if re.search( r'\$\{\D', rv["content"] ): if re.search(r'\$\{\D', rv['content']):
rv["content"] = re.sub(r'\$\{([^\d}][^}:]*)(?::([^}]*))?\}', replace_vars, rv["content"]) rv['content'] = re.sub(
r'\$\{([^\d}][^}:]*)(?::([^}]*))?\}',
replace_vars,
rv['content'])
return rv return rv
except (ExpatError, ElementTree.ParseError) as detail: except (ExpatError, ElementTree.ParseError) as detail:
print " Syntax Error: %s" % (detail,) print ' Syntax Error: %s' % (detail,)
print c print c
return None return None
except UnknownVariable as detail: except UnknownVariable as detail:
print " Unknown variable: %s" % (detail,) print ' Unknown variable: %s' % (detail,)
return None return None
except UnsupportedVariableExpression as detail: except UnsupportedVariableExpression as detail:
print " Unsupported variable expression: %s" % (detail,) print ' Unsupported variable expression: %s' % (detail,)
return None return None
def fetch_snippets_from_svn(name): def fetch_snippets_from_svn(name):
base_url = "http://svn.textmate.org/trunk/Bundles/" + name + ".tmbundle/" base_url = 'http://svn.textmate.org/trunk/Bundles/' + name + '.tmbundle/'
snippet_idx = base_url + "Snippets/" snippet_idx = base_url + 'Snippets/'
idx_list = urllib.urlopen(snippet_idx).read() idx_list = urllib.urlopen(snippet_idx).read()
rv = [] rv = []
for link in re.findall("<li>(.*?)</li>", idx_list): for link in re.findall('<li>(.*?)</li>', idx_list):
m = re.match(r'<a\s*href="(.*)"\s*>(.*)</a>', link) m = re.match(r'<a\s*href="(.*)"\s*>(.*)</a>', link)
link, name = m.groups() link, name = m.groups()
if name == "..": if name == '..':
continue continue
name = unescape(name.rsplit('.', 1)[0]) # remove Extension name = unescape(name.rsplit('.', 1)[0]) # remove Extension
print "Fetching data for Snippet '%s'" % name print "Fetching data for Snippet '%s'" % name
content = urllib.urlopen(snippet_idx + link).read() content = urllib.urlopen(snippet_idx + link).read()
@ -101,12 +114,13 @@ def fetch_snippets_from_svn(name):
return rv return rv
def fetch_snippets_from_dir(path): def fetch_snippets_from_dir(path):
""" Fetch snippets from a given path""" """Fetch snippets from a given path."""
rv = [] rv = []
for filename in glob.glob(os.path.join(path, '*.tmSnippet')): for filename in glob.glob(os.path.join(path, '*.tmSnippet')):
print "Reading file %s" % filename print 'Reading file %s' % filename
f = open(filename) f = open(filename)
content = f.read() content = f.read()
@ -116,20 +130,20 @@ def fetch_snippets_from_dir(path):
rv.append((name, cont)) rv.append((name, cont))
return rv return rv
def write_snippets(snip_descr, f): def write_snippets(snip_descr, f):
for name, d in snip_descr: for name, d in snip_descr:
if "tabTrigger" not in d: if 'tabTrigger' not in d:
continue continue
if "content" not in d or d["content"] is None: if 'content' not in d or d['content'] is None:
print "SKIP: %s (no content)" % (d,) print 'SKIP: %s (no content)' % (d,)
continue continue
f.write('snippet %s "%s"\n' % (d["tabTrigger"], name)) f.write('snippet %s "%s"\n' % (d['tabTrigger'], name))
f.write(d["content"].encode("utf-8") + "\n") f.write(d['content'].encode('utf-8') + '\n')
f.write("endsnippet\n\n") f.write('endsnippet\n\n')
if __name__ == '__main__': if __name__ == '__main__':
@ -144,5 +158,4 @@ if __name__ == '__main__':
rv = fetch_snippets_from_svn(bundle) rv = fetch_snippets_from_svn(bundle)
name = bundle.lower() name = bundle.lower()
write_snippets(rv, open("tm_" + name + ".snippets","w")) write_snippets(rv, open('tm_' + name + '.snippets', 'w'))