diff --git a/pylintrc b/pylintrc index 156e2b6..47439b3 100644 --- a/pylintrc +++ b/pylintrc @@ -43,6 +43,7 @@ disable= too-many-public-methods, too-few-public-methods, too-many-branches, + too-many-statements, [REPORTS] diff --git a/pythonx/UltiSnips/indent_util.py b/pythonx/UltiSnips/indent_util.py index 78ef1d5..769af7e 100644 --- a/pythonx/UltiSnips/indent_util.py +++ b/pythonx/UltiSnips/indent_util.py @@ -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 diff --git a/pythonx/UltiSnips/text_objects/_base.py b/pythonx/UltiSnips/text_objects/_base.py index 76289a3..2af825b 100755 --- a/pythonx/UltiSnips/text_objects/_base.py +++ b/pythonx/UltiSnips/text_objects/_base.py @@ -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 diff --git a/pythonx/UltiSnips/text_objects/_mirror.py b/pythonx/UltiSnips/text_objects/_mirror.py index a78caab..c1c6f04 100755 --- a/pythonx/UltiSnips/text_objects/_mirror.py +++ b/pythonx/UltiSnips/text_objects/_mirror.py @@ -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 - - diff --git a/pythonx/UltiSnips/text_objects/_python_code.py b/pythonx/UltiSnips/text_objects/_python_code.py index b2c74a2..bc5d6f6 100755 --- a/pythonx/UltiSnips/text_objects/_python_code.py +++ b/pythonx/UltiSnips/text_objects/_python_code.py @@ -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 = "" diff --git a/pythonx/UltiSnips/text_objects/_shell_code.py b/pythonx/UltiSnips/text_objects/_shell_code.py index d5d886e..ae96634 100755 --- a/pythonx/UltiSnips/text_objects/_shell_code.py +++ b/pythonx/UltiSnips/text_objects/_shell_code.py @@ -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 - diff --git a/pythonx/UltiSnips/text_objects/_snippet_instance.py b/pythonx/UltiSnips/text_objects/_snippet_instance.py index 0ffa50b..201e63a 100755 --- a/pythonx/UltiSnips/text_objects/_snippet_instance.py +++ b/pythonx/UltiSnips/text_objects/_snippet_instance.py @@ -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 - diff --git a/pythonx/UltiSnips/text_objects/_viml_code.py b/pythonx/UltiSnips/text_objects/_viml_code.py index 682b0b7..507872a 100755 --- a/pythonx/UltiSnips/text_objects/_viml_code.py +++ b/pythonx/UltiSnips/text_objects/_viml_code.py @@ -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 - diff --git a/pythonx/UltiSnips/text_objects/_visual.py b/pythonx/UltiSnips/text_objects/_visual.py index f56a563..9a43656 100755 --- a/pythonx/UltiSnips/text_objects/_visual.py +++ b/pythonx/UltiSnips/text_objects/_visual.py @@ -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]