Now reall all TODOs in TextObjects. Also final proofread.

This commit is contained in:
Holger Rapp 2012-01-22 01:01:03 +01:00
parent f9566d1fc7
commit 35439b579e
13 changed files with 94 additions and 133 deletions

View File

@ -1,9 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
from _mirror import Mirror
from _transformation import Transformation
from _snippet_instance import SnippetInstance
__all__ = [ "Mirror", "Transformation", "SnippetInstance" ]
__all__ = [ "SnippetInstance" ]

View File

@ -3,8 +3,6 @@
import vim
from ..debug import debug, echo_to_hierarchy
from UltiSnips.Buffer import TextBuffer
from UltiSnips.Compatibility import as_unicode
from UltiSnips.Geometry import Span, Position
@ -99,30 +97,6 @@ class TextObject(object):
self._start.move(pivot, diff)
self._end.move(pivot, diff)
def child_end_moved3(self, pivot, diff):
if not (self._parent):
return
self._parent._end.move(pivot, diff)
for c in self._parent._childs[self._parent._childs.index(self)+1:]:
c._move(pivot, diff)
self._parent.child_end_moved3(pivot, diff)
def _child_has_moved(self, idx, pivot, diff):
self._end.move(pivot, diff)
try:
for c in self._childs[idx+1:]:
c._move(pivot, diff)
except AttributeError: # TODO: fix this
pass
if self._parent:
self._parent._child_has_moved(
self._parent._childs.index(self), pivot, diff
)
class EditableTextObject(TextObject):
"""
This base class represents any object in the text
@ -134,9 +108,6 @@ class EditableTextObject(TextObject):
self._childs = []
self._tabstops = {}
self._cts = 0
self._is_killed = False
##############
# Properties #
##############
@ -159,59 +130,47 @@ class EditableTextObject(TextObject):
# Private/Protected functions #
###############################
def _do_edit(self, cmd):
debug("cmd: %r, self: %r" % (cmd, self))
ctype, line, col, char = cmd
assert( ('\n' not in char) or (char == "\n"))
ctype, line, col, text = cmd
assert( ('\n' not in text) or (text == "\n"))
pos = Position(line, col)
to_kill = set()
new_cmds = []
for c in self._childs:
start = c._start
end = c._end
debug("consider: c: %r" % (c))
if ctype == "D":
if char == "\n":
delend = Position(line + 1, 0) # TODO: is this even needed?
else:
delend = pos + Position(0, len(char))
# TODO: char is no longer true -> Text
# Case: this deletion removes the child
# Case: this edit command is completely for the child
if (start <= pos < end) and (start < delend <= end):
debug("Case 2")
if isinstance(c, NoneditableTextObject): # Erasing inside NonTabstop -> Kill element
if ctype == "I": # Insertion
if (c._start <= pos <= c._end):
if isinstance(c, EditableTextObject):
c._do_edit(cmd)
return
else:
to_kill.add(c)
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):
# this edit command is completely for the child
if isinstance(c, NoneditableTextObject):
to_kill.add(c)
continue
c._do_edit(cmd)
return
elif (pos < start and end <= delend) or (pos <= start and end < delend):
debug("Case 1")
elif (pos < c._start and c._end <= delend) or (pos <= c._start and c._end < delend):
# Case: this deletion removes the child
to_kill.add(c)
# Case: partially for us, partially for the child
elif (pos < start and (start < delend <= end)):
debug("Case 3")
my_text = char[:(start-pos).col]
c_text = char[(start-pos).col:]
debug("my_text: %r, c_text: %r" % (my_text, c_text))
elif (pos < c._start and (c._start < delend <= c._end)):
# Case: partially for us, partially for the child
my_text = text[:(c._start-pos).col]
c_text = text[(c._start-pos).col:]
new_cmds.append((ctype, line, col, my_text))
new_cmds.append((ctype, line, col, c_text))
break
elif (delend >= end and (start <= pos < end)):
debug("Case 3")
c_text = char[(end-pos).col:]
my_text = char[:(end-pos).col]
debug("my_text: %r, c_text: %r" % (my_text, c_text))
elif (delend >= c._end and (c._start <= pos < c._end)):
# Case: partially for us, partially for the child
c_text = text[(c._end-pos).col:]
my_text = text[:(c._end-pos).col]
new_cmds.append((ctype, line, col, c_text))
new_cmds.append((ctype, line, col, my_text))
break
elif ctype == "I": # Else would be okay as well
if isinstance(c, NoneditableTextObject): # TODO: make this nicer
continue
if (start <= pos <= end):
c._do_edit(cmd)
return
for c in to_kill:
self._del_child(c)
@ -220,20 +179,12 @@ class EditableTextObject(TextObject):
self._do_edit(c)
return
# We have to handle this ourselves
if ctype == "D": # TODO: code duplication
delta = Position(1, 0) if text == "\n" else Position(0, len(text))
if ctype == "D":
assert(self._start != self._end) # Makes no sense to delete in empty textobject
if char == "\n":
delta = Position(-1, 0) # TODO: this feels somehow incorrect:
else:
delta = Position(0, -len(char))
else:
if char == "\n":
delta = Position(1, 0) # TODO: this feels somehow incorrect
else:
delta = Position(0, len(char))
delta.line *= -1
delta.col *= -1
pivot = Position(line, col)
self._child_has_moved(-1, pivot, delta)
@ -243,6 +194,17 @@ class EditableTextObject(TextObject):
for c in self._childs:
c._move(pivot, diff)
def _child_has_moved(self, idx, pivot, diff):
self._end.move(pivot, diff)
for c in self._childs[idx+1:]:
c._move(pivot, diff)
if self._parent:
self._parent._child_has_moved(
self._parent._childs.index(self), pivot, diff
)
def _get_next_tab(self, no):
if not len(self._tabstops.keys()):
return
@ -290,17 +252,6 @@ class EditableTextObject(TextObject):
return max(possible_sol)
def _update(self, done, not_done):
"""
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)
done.add(self)
return True
def _get_tabstop(self, requester, no):
if no in self._tabstops:
return self._tabstops[no]
@ -314,12 +265,25 @@ class EditableTextObject(TextObject):
if self._parent and requester is not self._parent:
return self._parent._get_tabstop(self, no)
def _update(self, done, not_done):
"""
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)
done.add(self)
return True
def _add_child(self,c):
self._childs.append(c)
self._childs.sort()
def _del_child(self,c):
c._is_killed = True
c._parent = None
self._childs.remove(c)
# If this is a tabstop, delete it

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
from ._base import NoneditableTextObject
from UltiSnips.TextObjects._base import NoneditableTextObject
class EscapedChar(NoneditableTextObject):
"""

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
from ._base import NoneditableTextObject
from UltiSnips.TextObjects._base import NoneditableTextObject
class Mirror(NoneditableTextObject):
"""
@ -13,7 +13,7 @@ class Mirror(NoneditableTextObject):
self._ts = tabstop
def _update(self, done, not_done):
if self._ts._is_killed: # TODO: private parts
if self._ts.is_killed:
self.overwrite("")
self._parent._del_child(self)
return True

View File

@ -2,18 +2,17 @@
# encoding: utf-8
from UltiSnips.Geometry import Position
from ._lexer import tokenize, EscapeCharToken, VisualToken, \
from UltiSnips.TextObjects._lexer import tokenize, EscapeCharToken, VisualToken, \
TransformationToken, TabStopToken, MirrorToken, PythonCodeToken, \
VimLCodeToken, ShellCodeToken
from ._escaped_char import EscapedChar
from ._mirror import Mirror
from ._python_code import PythonCode
from ._shell_code import ShellCode
from ._tabstop import TabStop
from ._transformation import Transformation
from ._viml_code import VimLCode
from ._visual import Visual
from UltiSnips.TextObjects._escaped_char import EscapedChar
from UltiSnips.TextObjects._mirror import Mirror
from UltiSnips.TextObjects._python_code import PythonCode
from UltiSnips.TextObjects._shell_code import ShellCode
from UltiSnips.TextObjects._tabstop import TabStop
from UltiSnips.TextObjects._transformation import Transformation
from UltiSnips.TextObjects._viml_code import VimLCode
from UltiSnips.TextObjects._visual import Visual
__all__ = ["TOParser"]

View File

@ -9,14 +9,14 @@ import vim
from UltiSnips.Compatibility import compatible_exec, as_unicode
from UltiSnips.Util import IndentUtil
from ._base import NoneditableTextObject
from UltiSnips.TextObjects._base import NoneditableTextObject
class _Tabs(object):
def __init__(self, to):
self._to = to
def __getitem__(self, no):
ts = self._to._get_tabstop(self._to, int(no)) # TODO: private parts
ts = self._to._get_tabstop(self._to, int(no))
if ts is None:
return ""
return ts.current_text

View File

@ -6,7 +6,7 @@ import subprocess
import stat
import tempfile
from ._base import NoneditableTextObject
from UltiSnips.TextObjects._base import NoneditableTextObject
class ShellCode(NoneditableTextObject):
def __init__(self, parent, token):

View File

@ -4,10 +4,8 @@
from UltiSnips.Geometry import Position
from UltiSnips.Compatibility import vim_cursor, set_vim_cursor
from ..debug import debug, echo_to_hierarchy # TODO remove all debug
from ._base import EditableTextObject, NoneditableTextObject
from ._parser import TOParser
from UltiSnips.TextObjects._base import EditableTextObject, NoneditableTextObject
from UltiSnips.TextObjects._parser import TOParser
class SnippetInstance(EditableTextObject):
"""
@ -23,6 +21,8 @@ class SnippetInstance(EditableTextObject):
if end is None:
end = Position(0,0)
self._cts = 0
self.locals = {"match" : last_re}
self.globals = globals
self.visual_content = visual_content
@ -50,7 +50,9 @@ class SnippetInstance(EditableTextObject):
self._do_edit(cmd)
def update_textobjects(self):
# Do our own edits; keep track of the Cursor
"""Update the text objects that should change automagically after
the users edits have been replayed. This might also move the Cursor
"""
vc = _VimCursor(self)
done = set()
@ -61,7 +63,6 @@ class SnippetInstance(EditableTextObject):
for c in obj._childs:
_find_recursive(c)
not_done.add(obj)
_find_recursive(self)
counter = 10
@ -73,7 +74,6 @@ class SnippetInstance(EditableTextObject):
if counter == 0:
raise RuntimeError("Cyclic dependency in TextElements!")
vc.to_vim()
self._del_child(vc)
@ -113,8 +113,9 @@ class SnippetInstance(EditableTextObject):
class _VimCursor(NoneditableTextObject):
"""Helper class to keep track of the Vim Cursor"""
def __init__(self, parent):
"""Helper class to keep track of the vim Cursor"""
line, col = vim_cursor()
NoneditableTextObject.__init__(
self, parent, Position(line-1, col), Position(line-1, col)
@ -123,6 +124,3 @@ class _VimCursor(NoneditableTextObject):
def to_vim(self):
assert(self._start == self._end)
set_vim_cursor(self._start.line + 1, self._start.col)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
from ._base import EditableTextObject
from UltiSnips.TextObjects._base import EditableTextObject
__all__ = ['EditableTextObject']
@ -15,12 +15,16 @@ class TabStop(EditableTextObject):
self._no = token
EditableTextObject.__init__(self, parent, start, end)
else:
EditableTextObject.__init__(self, parent, token)
self._no = token.no
EditableTextObject.__init__(self, parent, token)
parent._tabstops[self._no] = self
@property
def no(self):
return self._no
no = property(no)
@property
def is_killed(self):
return self._parent is None

View File

@ -3,7 +3,7 @@
import re
from ._mirror import Mirror
from UltiSnips.TextObjects._mirror import Mirror
class _CleverReplace(object):
"""
@ -67,7 +67,6 @@ class _CleverReplace(object):
while m:
start = m.start()
end = _find_closingbrace(v,start+4)
args = _part_conditional(v[start+4:end-1])
rv = ""
@ -112,7 +111,7 @@ class Transformation(Mirror):
if "g" in token.options:
self._match_this_many = 0
if "i" in token.options:
flags |= re.IGNORECASE
flags |= re.IGNORECASE
self._find = re.compile(token.search, flags | re.DOTALL)
self._replace = _CleverReplace(token.replace)

View File

@ -4,8 +4,7 @@
import vim
from UltiSnips.Compatibility import as_unicode
from ._base import NoneditableTextObject
from UltiSnips.TextObjects._base import NoneditableTextObject
class VimLCode(NoneditableTextObject):
def __init__(self, parent, token):

View File

@ -5,10 +5,9 @@ import re
import vim
from ..Compatibility import as_unicode
from ..Util import IndentUtil
from ._base import NoneditableTextObject
from UltiSnips.Compatibility import as_unicode
from UltiSnips.Util import IndentUtil
from UltiSnips.TextObjects._base import NoneditableTextObject
class Visual(NoneditableTextObject):
"""

View File

@ -27,6 +27,7 @@
#
# TODO: visual line selection -> replace with more, less and == amount of lines
# TODO: edit in mirror or transofmration -> kill element
# TODO: insert/delete in mirror or transformation
import os
import tempfile
import unittest