More linting done.
This commit is contained in:
parent
4005608bab
commit
a669654466
1
pylintrc
1
pylintrc
@ -43,6 +43,7 @@ disable=
|
||||
too-many-public-methods,
|
||||
too-few-public-methods,
|
||||
too-many-branches,
|
||||
too-many-statements,
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
@ -1,39 +1,39 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
import os
|
||||
"""See module doc."""
|
||||
|
||||
import UltiSnips._vim as _vim
|
||||
|
||||
class IndentUtil(object):
|
||||
""" Utility class for dealing properly with indentation. """
|
||||
"""Utility class for dealing properly with indentation. """
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
""" Gets the spacing properties from Vim. """
|
||||
self.sw = int(_vim.eval("&sw"))
|
||||
self.sts = int(_vim.eval("&sts"))
|
||||
self.et = (_vim.eval("&expandtab") == "1")
|
||||
self.ts = int(_vim.eval("&ts"))
|
||||
self.shiftwidth = int(_vim.eval("&shiftwidth"))
|
||||
self._expandtab = (_vim.eval("&expandtab") == "1")
|
||||
self._tabstop = int(_vim.eval("&tabstop"))
|
||||
|
||||
def ntabs_to_proper_indent(self, ntabs):
|
||||
line_ind = ntabs * self.sw * " "
|
||||
"""Convert 'ntabs' number of tabs to the proper indent prefix."""
|
||||
line_ind = ntabs * self.shiftwidth * " "
|
||||
line_ind = self.indent_to_spaces(line_ind)
|
||||
line_ind = self.spaces_to_indent(line_ind)
|
||||
return line_ind
|
||||
|
||||
def indent_to_spaces(self, indent):
|
||||
""" Converts indentation to spaces respecting Vim settings. """
|
||||
indent = indent.expandtabs(self.ts)
|
||||
indent = indent.expandtabs(self._tabstop)
|
||||
right = (len(indent) - len(indent.rstrip(" "))) * " "
|
||||
indent = indent.replace(" ", "")
|
||||
indent = indent.replace('\t', " " * self.ts)
|
||||
indent = indent.replace('\t', " " * self._tabstop)
|
||||
return indent + right
|
||||
|
||||
def spaces_to_indent(self, indent):
|
||||
""" Converts spaces to proper indentation respecting Vim settings """
|
||||
if not self.et:
|
||||
indent = indent.replace(" " * self.ts, '\t')
|
||||
if not self._expandtab:
|
||||
indent = indent.replace(" " * self._tabstop, '\t')
|
||||
return indent
|
||||
|
@ -1,16 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
"""Base classes for all text objects."""
|
||||
|
||||
import UltiSnips._vim as _vim
|
||||
from UltiSnips.geometry import Position
|
||||
|
||||
__all__ = ["TextObject", "EditableTextObject", "NoneditableTextObject"]
|
||||
|
||||
def _calc_end(lines, start):
|
||||
if len(lines) == 1:
|
||||
new_end = start + Position(0,len(lines[0]))
|
||||
def _calc_end(text, start):
|
||||
"""Calculate the end position of the 'text' starting at 'start."""
|
||||
if len(text) == 1:
|
||||
new_end = start + Position(0, len(text[0]))
|
||||
else:
|
||||
new_end = Position(start.line + len(lines)-1, len(lines[-1]))
|
||||
new_end = Position(start.line + len(text)-1, len(text[-1]))
|
||||
return new_end
|
||||
|
||||
def _text_to_vim(start, end, text):
|
||||
@ -38,14 +41,12 @@ def _text_to_vim(start, end, text):
|
||||
|
||||
|
||||
class TextObject(object):
|
||||
"""
|
||||
This base class represents any object in the text
|
||||
that has a span in any ways
|
||||
"""
|
||||
def __init__(self, parent, token, end = None, initial_text = "", tiebreaker = None):
|
||||
"""Represents any object in the text that has a span in any ways."""
|
||||
|
||||
def __init__(self, parent, token, end=None,
|
||||
initial_text="", tiebreaker=None):
|
||||
self._parent = parent
|
||||
|
||||
ct = None
|
||||
if end is not None: # Took 4 arguments
|
||||
self._start = token
|
||||
self._end = end
|
||||
@ -54,41 +55,29 @@ class TextObject(object):
|
||||
self._start = token.start
|
||||
self._end = token.end
|
||||
self._initial_text = token.initial_text
|
||||
self._tiebreaker = tiebreaker or Position(self._start.line, self._end.line)
|
||||
|
||||
self._tiebreaker = tiebreaker or Position(
|
||||
self._start.line, self._end.line)
|
||||
if parent is not None:
|
||||
parent._add_child(self)
|
||||
|
||||
def overwrite(self, gtext = None):
|
||||
"""
|
||||
Overwrite the text of this object in the Vim Buffer and update its
|
||||
length information
|
||||
"""
|
||||
# We explicitly do not want to move our childs around here as we
|
||||
# either have non or we are replacing text initially which means we do
|
||||
# not want to mess with their positions
|
||||
if self.current_text == gtext: return
|
||||
old_end = self._end
|
||||
self._end = _text_to_vim(
|
||||
self._start, self._end, gtext or self._initial_text)
|
||||
if self._parent:
|
||||
self._parent._child_has_moved(
|
||||
self._parent._childs.index(self), min(old_end, self._end),
|
||||
self._end.diff(old_end)
|
||||
)
|
||||
def _move(self, pivot, diff):
|
||||
"""Move this object by 'diff' while 'pivot' is the point of change."""
|
||||
self._start.move(pivot, diff)
|
||||
self._end.move(pivot, diff)
|
||||
|
||||
def __lt__(self, other):
|
||||
me = (self._start.line, self._start.col,
|
||||
me_tuple = (self.start.line, self.start.col,
|
||||
self._tiebreaker.line, self._tiebreaker.col)
|
||||
o = (other._start.line, other._start.col,
|
||||
other_tuple = (other._start.line, other._start.col,
|
||||
other._tiebreaker.line, other._tiebreaker.col)
|
||||
return me < o
|
||||
return me_tuple < other_tuple
|
||||
|
||||
def __le__(self, other):
|
||||
me = (self._start.line, self._start.col,
|
||||
me_tuple = (self._start.line, self._start.col,
|
||||
self._tiebreaker.line, self._tiebreaker.col)
|
||||
o = (other._start.line, other._start.col,
|
||||
other_tuple = (other._start.line, other._start.col,
|
||||
other._tiebreaker.line, other._tiebreaker.col)
|
||||
return me <= o
|
||||
return me_tuple <= other_tuple
|
||||
|
||||
def __repr__(self):
|
||||
ct = ""
|
||||
@ -100,11 +89,9 @@ class TextObject(object):
|
||||
return "%s(%r->%r,%r)" % (self.__class__.__name__,
|
||||
self._start, self._end, ct)
|
||||
|
||||
##############
|
||||
# PROPERTIES #
|
||||
##############
|
||||
@property
|
||||
def current_text(self):
|
||||
"""The current text of this object."""
|
||||
if self._start.line == self._end.line:
|
||||
return _vim.buf[self._start.line][self._start.col:self._end.col]
|
||||
else:
|
||||
@ -113,20 +100,35 @@ class TextObject(object):
|
||||
lines.append(_vim.buf[self._end.line][:self._end.col])
|
||||
return '\n'.join(lines)
|
||||
|
||||
@property
|
||||
def start(self):
|
||||
"""The start position."""
|
||||
return self._start
|
||||
start = property(start)
|
||||
|
||||
@property
|
||||
def end(self):
|
||||
"""The end position."""
|
||||
return self._end
|
||||
end = property(end)
|
||||
|
||||
####################
|
||||
# Public functions #
|
||||
####################
|
||||
def _move(self, pivot, diff):
|
||||
self._start.move(pivot, diff)
|
||||
self._end.move(pivot, diff)
|
||||
def overwrite(self, gtext=None):
|
||||
"""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
|
||||
object.
|
||||
"""
|
||||
# We explicitly do not want to move our childs around here as we
|
||||
# either have non or we are replacing text initially which means we do
|
||||
# not want to mess with their positions
|
||||
if self.current_text == gtext:
|
||||
return
|
||||
old_end = self._end
|
||||
self._end = _text_to_vim(
|
||||
self._start, self._end, gtext or self._initial_text)
|
||||
if self._parent:
|
||||
self._parent._child_has_moved(
|
||||
self._parent._childs.index(self), min(old_end, self._end),
|
||||
self._end.diff(old_end)
|
||||
)
|
||||
|
||||
|
||||
class EditableTextObject(TextObject):
|
||||
"""
|
||||
@ -144,73 +146,84 @@ class EditableTextObject(TextObject):
|
||||
##############
|
||||
@property
|
||||
def _editable_childs(self):
|
||||
return [ c for c in self._childs if isinstance(c, EditableTextObject) ]
|
||||
"""All childs that are EditableTextObject s"""
|
||||
return [child for child in self._childs if
|
||||
isinstance(child, EditableTextObject)]
|
||||
|
||||
####################
|
||||
# Public Functions #
|
||||
####################
|
||||
def find_parent_for_new_to(self, pos):
|
||||
for c in self._editable_childs:
|
||||
if (c._start <= pos < c._end):
|
||||
return c.find_parent_for_new_to(pos)
|
||||
"""Figure out the parent object for something at 'pos'."""
|
||||
for childs in self._editable_childs:
|
||||
if childs._start <= pos < childs._end:
|
||||
return childs.find_parent_for_new_to(pos)
|
||||
return self
|
||||
|
||||
###############################
|
||||
# Private/Protected functions #
|
||||
###############################
|
||||
def _do_edit(self, cmd):
|
||||
"""Apply the edit 'cmd' to this object."""
|
||||
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)
|
||||
|
||||
to_kill = set()
|
||||
new_cmds = []
|
||||
for c in self._childs:
|
||||
for child in self._childs:
|
||||
if ctype == "I": # Insertion
|
||||
if c._start < pos < Position(c._end.line, c._end.col) and isinstance(c, NoneditableTextObject):
|
||||
to_kill.add(c)
|
||||
if (child._start < pos <
|
||||
Position(child._end.line, child._end.col) and
|
||||
isinstance(child, NoneditableTextObject)):
|
||||
to_kill.add(child)
|
||||
new_cmds.append(cmd)
|
||||
break
|
||||
elif (c._start <= pos <= c._end) and isinstance(c, EditableTextObject):
|
||||
c._do_edit(cmd)
|
||||
elif ((child._start <= pos <= child._end) and
|
||||
isinstance(child, EditableTextObject)):
|
||||
child._do_edit(cmd)
|
||||
return
|
||||
else: # Deletion
|
||||
delend = pos + Position(0, len(text)) if text != "\n" \
|
||||
else Position(line + 1, 0)
|
||||
if (c._start <= pos < c._end) and (c._start < delend <= c._end):
|
||||
if ((child._start <= pos < child._end) and
|
||||
(child._start < delend <= child._end)):
|
||||
# this edit command is completely for the child
|
||||
if isinstance(c, NoneditableTextObject):
|
||||
to_kill.add(c)
|
||||
if isinstance(child, NoneditableTextObject):
|
||||
to_kill.add(child)
|
||||
new_cmds.append(cmd)
|
||||
break
|
||||
else:
|
||||
c._do_edit(cmd)
|
||||
child._do_edit(cmd)
|
||||
return
|
||||
elif (pos < c._start and c._end <= delend) or (pos <= c._start and c._end < delend):
|
||||
elif ((pos < child._start and child._end <= delend) or
|
||||
(pos <= child._start and child._end < delend)):
|
||||
# Case: this deletion removes the child
|
||||
to_kill.add(c)
|
||||
to_kill.add(child)
|
||||
new_cmds.append(cmd)
|
||||
break
|
||||
elif (pos < c._start and (c._start < delend <= c._end)):
|
||||
elif (pos < child._start and
|
||||
(child._start < delend <= child._end)):
|
||||
# Case: partially for us, partially for the child
|
||||
my_text = text[:(c._start-pos).col]
|
||||
c_text = text[(c._start-pos).col:]
|
||||
my_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, c_text))
|
||||
break
|
||||
elif (delend >= c._end and (c._start <= pos < c._end)):
|
||||
elif (delend >= child._end and (
|
||||
child._start <= pos < child._end)):
|
||||
# Case: partially for us, partially for the child
|
||||
c_text = text[(c._end-pos).col:]
|
||||
my_text = text[:(c._end-pos).col]
|
||||
c_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, my_text))
|
||||
break
|
||||
|
||||
for c in to_kill:
|
||||
self._del_child(c)
|
||||
for child in to_kill:
|
||||
self._del_child(child)
|
||||
if len(new_cmds):
|
||||
for c in new_cmds:
|
||||
self._do_edit(c)
|
||||
for child in new_cmds:
|
||||
self._do_edit(child)
|
||||
return
|
||||
|
||||
# We have to handle this ourselves
|
||||
@ -222,45 +235,48 @@ class EditableTextObject(TextObject):
|
||||
delta.col *= -1
|
||||
pivot = Position(line, col)
|
||||
idx = -1
|
||||
for cidx, c in enumerate(self._childs):
|
||||
if c._start < pivot <= c._end:
|
||||
for cidx, child in enumerate(self._childs):
|
||||
if child._start < pivot <= child._end:
|
||||
idx = cidx
|
||||
self._child_has_moved(idx, pivot, delta)
|
||||
|
||||
def _move(self, pivot, diff):
|
||||
TextObject._move(self, pivot, diff)
|
||||
|
||||
for c in self._childs:
|
||||
c._move(pivot, diff)
|
||||
for child in self._childs:
|
||||
child._move(pivot, diff)
|
||||
|
||||
def _child_has_moved(self, idx, pivot, diff):
|
||||
"""Called when a the child with 'idx' has moved behind 'pivot' by
|
||||
'diff'."""
|
||||
self._end.move(pivot, diff)
|
||||
|
||||
for c in self._childs[idx+1:]:
|
||||
c._move(pivot, diff)
|
||||
for child in self._childs[idx+1:]:
|
||||
child._move(pivot, diff)
|
||||
|
||||
if self._parent:
|
||||
self._parent._child_has_moved(
|
||||
self._parent._childs.index(self), pivot, diff
|
||||
)
|
||||
|
||||
def _get_next_tab(self, no):
|
||||
def _get_next_tab(self, number):
|
||||
"""Returns the next tabstop after 'number'."""
|
||||
if not len(self._tabstops.keys()):
|
||||
return
|
||||
tno_max = max(self._tabstops.keys())
|
||||
|
||||
possible_sol = []
|
||||
i = no + 1
|
||||
i = number + 1
|
||||
while i <= tno_max:
|
||||
if i in self._tabstops:
|
||||
possible_sol.append( (i, self._tabstops[i]) )
|
||||
possible_sol.append((i, self._tabstops[i]))
|
||||
break
|
||||
i += 1
|
||||
|
||||
c = [ c._get_next_tab(no) for c in self._editable_childs ]
|
||||
c = filter(lambda i: i, c)
|
||||
child = [c._get_next_tab(number) for c in self._editable_childs]
|
||||
child = [c for c in child if c]
|
||||
|
||||
possible_sol += c
|
||||
possible_sol += child
|
||||
|
||||
if not len(possible_sol):
|
||||
return None
|
||||
@ -268,73 +284,72 @@ class EditableTextObject(TextObject):
|
||||
return min(possible_sol)
|
||||
|
||||
|
||||
def _get_prev_tab(self, no):
|
||||
def _get_prev_tab(self, number):
|
||||
"""Returns the previous tabstop before 'number'."""
|
||||
if not len(self._tabstops.keys()):
|
||||
return
|
||||
tno_min = min(self._tabstops.keys())
|
||||
|
||||
possible_sol = []
|
||||
i = no - 1
|
||||
i = number - 1
|
||||
while i >= tno_min and i > 0:
|
||||
if i in self._tabstops:
|
||||
possible_sol.append( (i, self._tabstops[i]) )
|
||||
possible_sol.append((i, self._tabstops[i]))
|
||||
break
|
||||
i -= 1
|
||||
|
||||
c = [ c._get_prev_tab(no) for c in self._editable_childs ]
|
||||
c = filter(lambda i: i, c)
|
||||
child = [c._get_prev_tab(number) for c in self._editable_childs]
|
||||
child = [c for c in child if c]
|
||||
|
||||
possible_sol += c
|
||||
possible_sol += child
|
||||
|
||||
if not len(possible_sol):
|
||||
return None
|
||||
|
||||
return max(possible_sol)
|
||||
|
||||
def _get_tabstop(self, requester, no):
|
||||
if no in self._tabstops:
|
||||
return self._tabstops[no]
|
||||
for c in self._editable_childs:
|
||||
if c is requester:
|
||||
def _get_tabstop(self, requester, number):
|
||||
"""Returns the tabstop 'number'. 'requester' is the class that is
|
||||
interested in this."""
|
||||
if number in self._tabstops:
|
||||
return self._tabstops[number]
|
||||
for child in self._editable_childs:
|
||||
if child is requester:
|
||||
continue
|
||||
|
||||
rv = c._get_tabstop(self, no)
|
||||
rv = child._get_tabstop(self, number)
|
||||
if rv is not None:
|
||||
return rv
|
||||
if self._parent and requester is not self._parent:
|
||||
return self._parent._get_tabstop(self, no)
|
||||
return self._parent._get_tabstop(self, number)
|
||||
|
||||
def _update(self, done, not_done):
|
||||
def _update(self, done):
|
||||
"""Update this object inside the Vim Buffer.
|
||||
|
||||
Return False if you need to be called again for this edit cycle.
|
||||
Otherwise return True.
|
||||
"""
|
||||
Update this object inside the Vim Buffer.
|
||||
|
||||
Return False if you want to be called again
|
||||
for this edit cycle. Otherwise return True.
|
||||
"""
|
||||
if all((c in done) for c in self._childs):
|
||||
assert(self not in done)
|
||||
|
||||
if all((child in done) for child in self._childs):
|
||||
assert self not in done
|
||||
done.add(self)
|
||||
return True
|
||||
|
||||
def _add_child(self,c):
|
||||
self._childs.append(c)
|
||||
def _add_child(self, child):
|
||||
"""Add 'child' as a new child of this text object."""
|
||||
self._childs.append(child)
|
||||
self._childs.sort()
|
||||
|
||||
def _del_child(self,c):
|
||||
c._parent = None
|
||||
self._childs.remove(c)
|
||||
def _del_child(self, child):
|
||||
"""Delete this 'child'."""
|
||||
child._parent = None
|
||||
self._childs.remove(child)
|
||||
|
||||
# If this is a tabstop, delete it
|
||||
try:
|
||||
del self._tabstops[c.number]
|
||||
del self._tabstops[child.number]
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
class NoneditableTextObject(TextObject):
|
||||
"""
|
||||
All passive text objects that the user can't edit by hand
|
||||
"""
|
||||
|
||||
def _update(self, done, not_done):
|
||||
"""All passive text objects that the user can't edit by hand."""
|
||||
def _update(self, done):
|
||||
return True
|
||||
|
@ -12,7 +12,7 @@ class Mirror(NoneditableTextObject):
|
||||
|
||||
self._ts = tabstop
|
||||
|
||||
def _update(self, done, not_done):
|
||||
def _update(self, done):
|
||||
if self._ts.is_killed:
|
||||
self.overwrite("")
|
||||
self._parent._del_child(self)
|
||||
@ -26,5 +26,3 @@ class Mirror(NoneditableTextObject):
|
||||
|
||||
def _get_text(self):
|
||||
return self._ts.current_text
|
||||
|
||||
|
||||
|
@ -54,7 +54,7 @@ class SnippetUtil(object):
|
||||
|
||||
:amount: the amount by which to shift.
|
||||
"""
|
||||
self.indent += " " * self._ind.sw * amount
|
||||
self.indent += " " * self._ind.shiftwidth * amount
|
||||
|
||||
def unshift(self, amount=1):
|
||||
""" Unshift the indentation level.
|
||||
@ -63,7 +63,7 @@ class SnippetUtil(object):
|
||||
|
||||
:amount: the amount by which to unshift.
|
||||
"""
|
||||
by = -self._ind.sw * amount
|
||||
by = -self._ind.shiftwidth * amount
|
||||
try:
|
||||
self.indent = self.indent[:by]
|
||||
except IndexError:
|
||||
@ -194,7 +194,7 @@ class PythonCode(NoneditableTextObject):
|
||||
|
||||
NoneditableTextObject.__init__(self, parent, token)
|
||||
|
||||
def _update(self, done, not_done):
|
||||
def _update(self, done):
|
||||
path = _vim.eval('expand("%")')
|
||||
if path is None:
|
||||
path = ""
|
||||
|
@ -55,7 +55,7 @@ class ShellCode(NoneditableTextObject):
|
||||
self._code = token.code.replace("\\`", "`")
|
||||
self._tmpdir = _get_tmp()
|
||||
|
||||
def _update(self, done, not_done):
|
||||
def _update(self, done):
|
||||
if not self._tmpdir:
|
||||
output = "Unable to find executable tmp directory, check noexec on /tmp"
|
||||
else:
|
||||
@ -65,4 +65,3 @@ class ShellCode(NoneditableTextObject):
|
||||
self._parent._del_child(self)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -66,14 +66,17 @@ class SnippetInstance(EditableTextObject):
|
||||
|
||||
counter = 10
|
||||
while (done != not_done) and counter:
|
||||
for obj in sorted(not_done - done): # Order matters for python locals!
|
||||
if obj._update(done, not_done):
|
||||
# Order matters for python locals!
|
||||
for obj in sorted(not_done - done):
|
||||
if obj._update(done):
|
||||
done.add(obj)
|
||||
counter -= 1
|
||||
if counter == 0:
|
||||
raise RuntimeError("The snippets content did not converge: Check for Cyclic dependencies "
|
||||
"or random strings in your snippet. You can use 'if not snip.c' to make sure "
|
||||
"to only expand random output once.")
|
||||
raise RuntimeError(
|
||||
"The snippets content did not converge: Check for Cyclic "
|
||||
"dependencies or random strings in your snippet. You can use "
|
||||
"'if not snip.c' to make sure to only expand random output "
|
||||
"once.")
|
||||
vc.to_vim()
|
||||
self._del_child(vc)
|
||||
|
||||
@ -123,4 +126,3 @@ class _VimCursor(NoneditableTextObject):
|
||||
def to_vim(self):
|
||||
assert(self._start == self._end)
|
||||
_vim.buf.cursor = self._start
|
||||
|
||||
|
@ -11,7 +11,6 @@ class VimLCode(NoneditableTextObject):
|
||||
|
||||
NoneditableTextObject.__init__(self, parent, token)
|
||||
|
||||
def _update(self, done, not_done):
|
||||
def _update(self, done):
|
||||
self.overwrite(_vim.eval(self._code))
|
||||
return True
|
||||
|
||||
|
@ -33,7 +33,7 @@ class Visual(NoneditableTextObject,TextObjectTransformation):
|
||||
NoneditableTextObject.__init__(self, parent, token)
|
||||
TextObjectTransformation.__init__(self, token)
|
||||
|
||||
def _update(self, done, not_done):
|
||||
def _update(self, done):
|
||||
if self._mode != "v":
|
||||
# Keep the indent for Line/Block Selection
|
||||
text_before = _vim.buf[self.start.line][:self.start.col]
|
||||
|
Loading…
Reference in New Issue
Block a user