All linting done. Project is now lint warning free.

This commit is contained in:
Holger Rapp 2014-02-08 15:52:06 +01:00
parent 873b5b4ad4
commit 773869b1e1
11 changed files with 183 additions and 122 deletions

View File

@ -1,7 +1,5 @@
[MASTER] [MASTER]
msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}"
# Python code to execute, usually for sys.path manipulation such as # Python code to execute, usually for sys.path manipulation such as
# pygtk.require(). # pygtk.require().
init-hook='import sys; sys.path.append("pythonx/")' init-hook='import sys; sys.path.append("pythonx/")'
@ -38,13 +36,14 @@ disable=
attribute-defined-outside-init, attribute-defined-outside-init,
fixme, fixme,
redefined-builtin, redefined-builtin,
too-many-arguments,
too-many-instance-attributes,
too-many-public-methods,
too-few-public-methods, too-few-public-methods,
too-many-arguments,
too-many-branches, too-many-branches,
too-many-statements, too-many-instance-attributes,
too-many-locals, too-many-locals,
too-many-public-methods,
too-many-return-statements,
too-many-statements,
[REPORTS] [REPORTS]
@ -57,6 +56,9 @@ output-format=text
# Tells whether to display a full report or only the messages # Tells whether to display a full report or only the messages
reports=yes reports=yes
msg-template="{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}"
[BASIC] [BASIC]
@ -99,7 +101,7 @@ class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma # Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_ good-names=i,j,a,b,x,y,k,ex,Run,_
# Bad variable names which should always be refused, separated by a comma # Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata bad-names=foo,bar,baz,toto,tutu,tata

View File

@ -145,6 +145,9 @@ Following is the full stack trace:
_vim.new_scratch_buffer(msg) _vim.new_scratch_buffer(msg)
return wrapper return wrapper
# TODO(sirver): This class has too many responsibilities - it should not also
# care for the parsing and managing of parsed snippets.
class SnippetManager(object): class SnippetManager(object):
"""The main entry point for all UltiSnips functionality. All Vim functions """The main entry point for all UltiSnips functionality. All Vim functions
call methods in this class.""" call methods in this class."""
@ -162,7 +165,7 @@ class SnippetManager(object):
"""Reset the class to the state it had directly after creation.""" """Reset the class to the state it had directly after creation."""
self._vstate = VimState() self._vstate = VimState()
self._test_error = test_error self._test_error = test_error
self._snippets = defaultdict(lambda: SnippetDictionary()) self._snippets = defaultdict(SnippetDictionary)
self._filetypes = defaultdict(lambda: ['all']) self._filetypes = defaultdict(lambda: ['all'])
self._visual_content = VisualContentPreserver() self._visual_content = VisualContentPreserver()
@ -390,11 +393,8 @@ class SnippetManager(object):
self._current_snippet_is_done() self._current_snippet_is_done()
self._reinit() self._reinit()
# TODO(sirver): This is only used by SnippetsFileParser
################################### def report_error(self, msg):
# Private/Protect Functions Below #
###################################
def _error(self, msg):
"""Shows 'msg' as error to the user.""" """Shows 'msg' as error to the user."""
msg = _vim.escape("UltiSnips: " + msg) msg = _vim.escape("UltiSnips: " + msg)
if self._test_error: if self._test_error:
@ -410,6 +410,9 @@ class SnippetManager(object):
else: else:
_vim.command("echoerr %s" % msg) _vim.command("echoerr %s" % msg)
###################################
# Private/Protect Functions Below #
###################################
def _reinit(self): def _reinit(self):
"""Resets transient state.""" """Resets transient state."""
self._ctab = None self._ctab = None

View File

@ -1,14 +1,19 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""Commands to compare text objects and to guess how to transform from one to
another."""
from collections import defaultdict from collections import defaultdict
import sys 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, a, b, cmds): def is_complete_edit(initial_line, original, wanted, cmds):
buf = a[:] """Returns true if 'original' is changed to 'wanted' with the edit commands
in 'cmds'. Initial line is to change the line numbers in 'cmds'."""
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
@ -24,95 +29,133 @@ def is_complete_edit(initial_line, a, b, cmds):
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(b) and all(j==k for j,k in zip(buf, b)) return (len(buf) == len(wanted) and
all(j == k for j, k in zip(buf, wanted)))
def guess_edit(initial_line, lt, ct, vs): def guess_edit(initial_line, last_text, current_text, vim_state):
""" """
Try to guess what the user might have done by heuristically looking at cursor movement Try to guess what the user might have done by heuristically looking at
number of changed lines and if they got longer or shorter. This will detect most simple cursor movement, number of changed lines and if they got longer or shorter.
movements like insertion, deletion of a line or carriage return. This will detect most simple movements like insertion, deletion of a line
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
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)
otherwise.
""" """
if not len(lt) and not len(ct): return True, () if not len(last_text) and not len(current_text):
pos = vs.pos return True, ()
ppos = vs.ppos pos = vim_state.pos
if len(lt) and (not ct or (len(ct) == 1 and not ct[0])): # All text deleted? ppos = vim_state.ppos
# All text deleted?
if (len(last_text) and
(not current_text or
(len(current_text) == 1 and not current_text[0]))
):
es = [] es = []
if not ct: ct = [''] if not current_text:
for i in lt: current_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, lt, ct, es): return True, es if is_complete_edit(initial_line, last_text, current_text, es):
return True, es
if ppos.mode == 'v': # Maybe selectmode? if ppos.mode == 'v': # Maybe selectmode?
sv = list(map(int, _vim.eval("""getpos("'<")"""))); sv = Position(sv[1]-1,sv[2]-1) sv = list(map(int, _vim.eval("""getpos("'<")""")))
ev = list(map(int, _vim.eval("""getpos("'>")"""))); ev = Position(ev[1]-1,ev[2]-1) sv = Position(sv[1]-1, sv[2]-1)
ev = list(map(int, _vim.eval("""getpos("'>")""")))
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, lt[sv.line - initial_line][sv.col:ev.col+1])) es.append(("D", sv.line, sv.col,
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, ct[sv.line - initial_line][sv.col:pos.col+1])) es.append(("I", sv.line, sv.col,
if is_complete_edit(initial_line, lt, ct, es): return True, es current_text[sv.line - initial_line][sv.col:pos.col+1]))
if is_complete_edit(initial_line, last_text, current_text, es):
return True, es
if pos.line == ppos.line: if pos.line == ppos.line:
if len(lt) == len(ct): # Movement only in one line if len(last_text) == len(current_text): # Movement only in one line
llen = len(lt[ppos.line - initial_line]) llen = len(last_text[ppos.line - initial_line])
clen = len(ct[pos.line - initial_line]) clen = len(current_text[pos.line - initial_line])
if ppos < pos and clen > llen: # Likely that only characters have been added if ppos < pos and clen > llen: # maybe only chars have been added
es = ( es = (
("I", ppos.line, ppos.col, ct[ppos.line - initial_line][ppos.col:pos.col]), ("I", ppos.line, ppos.col,
current_text[ppos.line - initial_line]
[ppos.col:pos.col]),
) )
if is_complete_edit(initial_line, lt, ct, es): return True, es if is_complete_edit(initial_line, last_text, current_text, 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, lt[ppos.line - initial_line][ppos.col:ppos.col + (llen - clen)]), ("D", pos.line, pos.col,
last_text[ppos.line - initial_line]
[ppos.col:ppos.col + (llen - clen)]),
) )
if is_complete_edit(initial_line, lt, ct, es): return True, es if is_complete_edit(initial_line, last_text,
current_text, 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, lt[pos.line - initial_line][pos.col:pos.col + llen - clen]), ("D", pos.line, pos.col,
last_text[pos.line - initial_line]
[pos.col:pos.col + llen - clen]),
) )
if is_complete_edit(initial_line, lt, ct, es): return True, es if is_complete_edit(initial_line, last_text,
elif len(ct) < len(lt): # Maybe some lines were deleted? (dd or so) current_text, es):
return True, es
elif len(current_text) < len(last_text):
# where some lines deleted? (dd or so)
es = [] es = []
for i in range(len(lt)-len(ct)): for i in range(len(last_text)-len(current_text)):
es.append( ("D", pos.line, 0, lt[pos.line - initial_line + i])) es.append(("D", pos.line, 0,
es.append( ("D", pos.line, 0, '\n')) last_text[pos.line - initial_line + i]))
if is_complete_edit(initial_line, lt, ct, es): return True, es es.append(("D", pos.line, 0, '\n'))
else: # Movement in more than one line if is_complete_edit(initial_line, last_text,
current_text, es):
return True, es
else:
# 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, lt, ct, es): return True, es if is_complete_edit(initial_line, last_text,
current_text, 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 is Return a list of deletions and insertions that will turn 'a' into 'b'. This
done by traversing an implicit edit graph and searching for the shortest is done by traversing an implicit edit graph and searching for the shortest
route. The basic idea is as follows: route. The basic idea is as follows:
- Matching a character is free as long as there was no deletion/insertion - Matching a character is free as long as there was no
before. Then, matching will be seen as delete + insert [1]. deletion/insertion before. Then, matching will be seen as delete +
insert [1].
- Deleting one character has the same cost everywhere. Each additional - Deleting one character has the same cost everywhere. Each additional
character costs only have of the first deletion. character costs only have of the first deletion.
- Insertion is cheaper the earlier it happes. The first character is more - Insertion is cheaper the earlier it happens. The first character is
expensive that any later [2]. more expensive that any later [2].
[1] This is that world -> aolsa will be "D" world + "I" aolsa instead of [1] This is that world -> aolsa will be "D" world + "I" aolsa instead of
"D" w , "D" rld, "I" a, "I" lsa "D" w , "D" rld, "I" a, "I" lsa
[2] This is that "hello\n\n" -> "hello\n\n\n" will insert a newline after hello [2] This is that "hello\n\n" -> "hello\n\n\n" will insert a newline after
and not after \n hello and not after \n
""" """
d = defaultdict(list) d = defaultdict(list) # pylint:disable=invalid-name
seen = defaultdict(lambda: sys.maxsize) seen = defaultdict(lambda: sys.maxsize)
d[0] = [ (0,0,sline, 0, ()) ] d[0] = [(0, 0, sline, 0, ())]
cost = 0 cost = 0
D_COST = len(a)+len(b) deletion_cost = len(a)+len(b)
I_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()
@ -125,17 +168,16 @@ def diff(a, b, sline = 0):
nline = line nline = line
if a[x] == '\n': if a[x] == '\n':
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 = (D_COST + I_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
@ -144,30 +186,34 @@ def diff(a, b, sline = 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 + (I_COST + ncol) // 2 seen[x, y+1] > cost + (insertion_cost + ncol) // 2
): ):
seen[x,y+1] = cost + (I_COST + ncol) // 2 seen[x, y+1] = cost + (insertion_cost + ncol) // 2
d[cost + (I_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], what[-1][-1] + b[y]),) ) ("I", what[-1][1], what[-1][2],
what[-1][-1] + b[y]),)
)
) )
elif seen[x,y+1] > cost + I_COST + ncol: elif seen[x, y+1] > cost + insertion_cost + ncol:
seen[x,y+1] = cost + I_COST + ncol seen[x, y+1] = cost + insertion_cost + ncol
d[cost + ncol + I_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][-1] != '\n' and what[-1][2] == col and a[x] != '\n' and
seen[x+1,y] > cost + D_COST // 2 what[-1][-1] != '\n' and
seen[x+1, y] > cost + deletion_cost // 2
): ):
seen[x+1,y] = cost + D_COST // 2 seen[x+1, y] = cost + deletion_cost // 2
d[cost + D_COST // 2].append((x+1,y, line, col, what[:-1] + d[cost + deletion_cost // 2].append(
(("D",line, col, what[-1][-1] + a[x]),) ) (x+1, y, line, col, what[:-1] + (
("D", line, col, what[-1][-1] + a[x]),))
) )
elif seen[x+1,y] > cost + D_COST: elif seen[x+1, y] > cost + deletion_cost:
seen[x+1,y] = cost + D_COST seen[x+1, y] = cost + deletion_cost
d[cost + D_COST].append((x+1,y, line, col, what + d[cost + deletion_cost].append((x+1, y, line, col, what +
(("D",line, col, a[x]),) ) (("D", line, col, a[x]),))
) )
cost += 1 cost += 1

View File

@ -1,11 +1,17 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""Parsing of snippet files."""
import re import re
import UltiSnips._vim as _vim import UltiSnips._vim as _vim
# TODO(sirver): This could just as well be a function. # TODO(sirver): This could just as well be a function. Also the
# interface should change to a stream of events - so that it does
# not need knowledge of SnippetManager.
class SnippetsFileParser(object): class SnippetsFileParser(object):
"""Does the actual parsing."""
def __init__(self, ft, fn, snip_manager, file_data=None): def __init__(self, ft, fn, snip_manager, file_data=None):
"""Parser 'fn' as filetype 'ft'.""" """Parser 'fn' as filetype 'ft'."""
self._sm = snip_manager self._sm = snip_manager
@ -19,33 +25,27 @@ class SnippetsFileParser(object):
self._idx = 0 self._idx = 0
def _error(self, msg): def _error(self, msg):
"""Reports 'msg' as an error."""
fn = _vim.eval("""fnamemodify(%s, ":~:.")""" % _vim.escape(self._fn)) fn = _vim.eval("""fnamemodify(%s, ":~:.")""" % _vim.escape(self._fn))
self._sm._error("%s in %s(%d)" % (msg, fn, self._idx + 1)) self._sm.report_error("%s in %s(%d)" % (msg, fn, self._idx + 1))
def _line(self): def _line(self):
if self._idx < len(self._lines): """The current line or the empty string."""
line = self._lines[self._idx] return self._lines[self._idx] if self._idx < len(self._lines) else ""
else:
line = ""
return line
def _line_head_tail(self): def _line_head_tail(self):
"""Returns (first word, rest) of the current line."""
parts = re.split(r"\s+", self._line().rstrip(), maxsplit=1) parts = re.split(r"\s+", self._line().rstrip(), maxsplit=1)
parts.append('') parts.append('')
return parts[:2] return parts[:2]
def _line_head(self):
return self._line_head_tail()[0]
def _line_tail(self):
return self._line_head_tail()[1]
def _goto_next_line(self): def _goto_next_line(self):
"""Advances to and returns the next line."""
self._idx += 1 self._idx += 1
return self._line() return self._line()
def _parse_first(self, line): def _parse_first(self, line):
""" Parses the first line of the snippet definition. Returns the """Parses the first line of the snippet definition. Returns the
snippet type, trigger, description, and options in a tuple in that snippet type, trigger, description, and options in a tuple in that
order. order.
""" """
@ -80,10 +80,10 @@ class SnippetsFileParser(object):
cs = "" cs = ""
else: else:
cs = cs[1:-1] cs = cs[1:-1]
return (snip, cs, cdescr, coptions) return (snip, cs, cdescr, coptions)
def _parse_snippet(self): def _parse_snippet(self):
"""Parses the snippet that begins at the current line."""
line = self._line() line = self._line()
(snip, trig, desc, opts) = self._parse_first(line) (snip, trig, desc, opts) = self._parse_first(line)
@ -109,17 +109,19 @@ class SnippetsFileParser(object):
self._globals[trig] = [] self._globals[trig] = []
self._globals[trig].append(cv) self._globals[trig].append(cv)
elif snip == "snippet": elif snip == "snippet":
self._sm.add_snippet(trig, cv, desc, opts, self._ft, self._globals, fn=self._fn) self._sm.add_snippet(
trig, cv, desc, opts, self._ft, self._globals, fn=self._fn)
else: else:
self._error("Invalid snippet type: '%s'" % snip) self._error("Invalid snippet type: '%s'" % snip)
def parse(self): def parse(self):
"""Parses the given file."""
while self._line(): while self._line():
head, tail = self._line_head_tail() head, tail = self._line_head_tail()
if head == "extends": if head == "extends":
if tail: if tail:
self._sm.add_extending_info(self._ft, self._sm.add_extending_info(self._ft,
[ p.strip() for p in tail.split(',') ]) [p.strip() for p in tail.split(',')])
else: else:
self._error("'extends' without file types") self._error("'extends' without file types")
elif head in ("snippet", "global"): elif head in ("snippet", "global"):

View File

@ -1,9 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
import unittest # pylint: skip-file
import os.path as p, sys; sys.path.append(p.join(p.dirname(__file__), "..")) import unittest
from _diff import diff, guess_edit from _diff import diff, guess_edit
from position import Position from position import Position

View File

@ -1,6 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
# pylint: skip-file
import unittest import unittest
from position import Position from position import Position

View File

@ -1,14 +1,15 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""See module comment."""
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
class EscapedChar(NoneditableTextObject): class EscapedChar(NoneditableTextObject):
""" 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 pass

View File

@ -1,12 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""A Mirror object contains the same text as its related tabstop."""
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
class Mirror(NoneditableTextObject): class Mirror(NoneditableTextObject):
""" """See module docstring."""
A Mirror object mirrors a TabStop that is, text is repeated here
"""
def __init__(self, parent, tabstop, token): def __init__(self, parent, tabstop, token):
NoneditableTextObject.__init__(self, parent, token) NoneditableTextObject.__init__(self, parent, token)
@ -15,7 +16,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) self._parent._del_child(self) # pylint:disable=protected-access
return True return True
if self._ts not in done: if self._ts not in done:
@ -25,4 +26,5 @@ 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."""
return self._ts.current_text return self._ts.current_text

View File

@ -13,6 +13,7 @@ from UltiSnips.text_objects._parser import parse_text_object
class SnippetInstance(EditableTextObject): class SnippetInstance(EditableTextObject):
"""See module docstring.""" """See module docstring."""
# pylint:disable=protected-access
def __init__(self, snippet, parent, indent, initial_text, def __init__(self, snippet, parent, indent, initial_text,
start, end, visual_content, last_re, globals): start, end, visual_content, last_re, globals):

View File

@ -1,11 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""Implements `!v ` VimL interpolation."""
import UltiSnips._vim as _vim import UltiSnips._vim as _vim
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
class VimLCode(NoneditableTextObject): class VimLCode(NoneditableTextObject):
"""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()

View File

@ -1,6 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
# encoding: utf-8 # encoding: utf-8
"""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
be the empty string. """
import re import re
import UltiSnips._vim as _vim import UltiSnips._vim as _vim
@ -8,13 +12,9 @@ from UltiSnips.indent_util import IndentUtil
from UltiSnips.text_objects._transformation import TextObjectTransformation from UltiSnips.text_objects._transformation import TextObjectTransformation
from UltiSnips.text_objects._base import NoneditableTextObject from UltiSnips.text_objects._base import NoneditableTextObject
class Visual(NoneditableTextObject,TextObjectTransformation): _REPLACE_NON_WS = re.compile(r"[^ \t]")
""" class Visual(NoneditableTextObject, TextObjectTransformation):
A ${VISUAL} placeholder that will use the text that was last visually """See module docstring."""
selected and insert it here. If there was no text visually selected,
this will be the empty string
"""
__REPLACE_NON_WS = re.compile(r"[^ \t]")
def __init__(self, parent, token): def __init__(self, parent, token):
# Find our containing snippet for visual_content # Find our containing snippet for visual_content
@ -25,7 +25,7 @@ class Visual(NoneditableTextObject,TextObjectTransformation):
self._mode = snippet.visual_content.mode self._mode = snippet.visual_content.mode
break break
except AttributeError: except AttributeError:
snippet = snippet._parent 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"
@ -37,7 +37,7 @@ class Visual(NoneditableTextObject,TextObjectTransformation):
if self._mode != "v": if self._mode != "v":
# Keep the indent for Line/Block Selection # Keep the indent for Line/Block Selection
text_before = _vim.buf[self.start.line][:self.start.col] text_before = _vim.buf[self.start.line][:self.start.col]
indent = self.__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)
@ -52,6 +52,6 @@ class Visual(NoneditableTextObject,TextObjectTransformation):
text = self._transform(text) text = self._transform(text)
self.overwrite(text) self.overwrite(text)
self._parent._del_child(self) self._parent._del_child(self) # pylint:disable=protected-access
return True return True