Some refactoring

This commit is contained in:
Holger Rapp 2009-07-02 15:41:58 +02:00
parent c6116f12ce
commit d5705c7559
2 changed files with 64 additions and 49 deletions

View File

@ -89,10 +89,18 @@ class TextObject(object):
This base class represents any object in the text This base class represents any object in the text
that has a span in any ways that has a span in any ways
""" """
def __init__(self, start, end): def __init__(self, parent, start, end):
self._parent = None
self._start = start self._start = start
self._end = end self._end = end
self._parent = parent
self._children = []
if parent is not None:
parent.add_child(self)
def add_child(self,c):
self._children.append(c)
def parent(): def parent():
doc = "The parent TextObject this TextObject resides in" doc = "The parent TextObject this TextObject resides in"
@ -116,13 +124,14 @@ class Mirror(TextObject):
""" """
A Mirror object mirrors a TabStop that is, text is repeated here A Mirror object mirrors a TabStop that is, text is repeated here
""" """
def __init__(self, ts, idx, start_col): def __init__(self, parent, ts, idx, start_col):
start = Position(idx,start_col) start = Position(idx,start_col)
end = Position(idx,start_col) end = start + (ts.end - ts.start)
TextObject.__init__(self, start, end) TextObject.__init__(self, parent, start, end)
self._tabstop = ts self._tabstop = ts
ts.add_mirror(self)
@property @property
def tabstop(self): def tabstop(self):
return self._tabstop return self._tabstop
@ -144,7 +153,10 @@ class Mirror(TextObject):
newcolspan = self.end.col - self.start.col newcolspan = self.end.col - self.start.col
newlinespan = self.end.line - self.start.line newlinespan = self.end.line - self.start.line
return newlinespan-oldlinespan, newcolspan-oldcolspan moved_lines = newlinespan - oldlinespan
moved_cols = newcolspan - oldcolspan
self._parent._move_textobjects_behind(moved_lines, moved_cols, self)
class TabStop(TextObject): class TabStop(TextObject):
@ -152,13 +164,18 @@ class TabStop(TextObject):
This is the most important TextObject. A TabStop is were the cursor This is the most important TextObject. A TabStop is were the cursor
comes to rest when the user taps through the Snippet. comes to rest when the user taps through the Snippet.
""" """
def __init__(self, idx, span, default_text = ""): def __init__(self, parent, idx, span, default_text = ""):
start = Position(idx,span[0]) start = Position(idx,span[0])
end = Position(idx,span[1]) end = Position(idx,span[1])
TextObject.__init__(self, start, end) TextObject.__init__(self, parent, start, end)
self._ct = default_text self._ct = default_text
self._mirrors = []
def add_mirror(self, m):
self._mirrors.append(m)
def current_text(): def current_text():
def fget(self): def fget(self):
return self._ct return self._ct
@ -180,7 +197,10 @@ class TabStop(TextObject):
self._parent._move_textobjects_behind(moved_lines, moved_cols, self) self._parent._move_textobjects_behind(moved_lines, moved_cols, self)
self._end = new_end self._end = new_end
self._parent._update_mirrors(self)
for m in self._mirrors:
m.update(self)
return locals() return locals()
current_text = property(**current_text()) current_text = property(**current_text())
@ -217,22 +237,18 @@ class SnippetInstance(TextObject):
also a TextObject because it has a start an end also a TextObject because it has a start an end
""" """
def __init__(self, start, end, ts, mirrors): def __init__(self, start, end):
TextObject.__init__(self, start, end) TextObject.__init__(self, None, start, end)
self._tabstops = ts
self._mirrors = mirrors
self._text_objects = ts.values() + mirrors
self._selected_tab = None
self._cts = None self._cts = None
self._selected_tab = None
self._tabstops = {}
for to in self._text_objects: def has_tabs(self):
to.parent = self return len(self._children) > 0
for ts in self._tabstops.values():
self._update_mirrors(ts)
def add_tabstop(self,no, ts):
self._tabstops[no] = ts
def select_next_tab(self, backwards = False): def select_next_tab(self, backwards = False):
if self._cts == 0: if self._cts == 0:
@ -268,12 +284,6 @@ class SnippetInstance(TextObject):
return True return True
def _update_mirrors(self,for_ts):
for m in self._mirrors:
moved_lines, moved_cols = m.update(for_ts)
self._move_textobjects_behind(moved_lines, moved_cols, m)
def _move_textobjects_behind(self, lines, cols, obj): def _move_textobjects_behind(self, lines, cols, obj):
if lines == 0 and cols == 0: if lines == 0 and cols == 0:
return return
@ -281,7 +291,7 @@ class SnippetInstance(TextObject):
debug("Got: %i %i" % (lines,cols)) debug("Got: %i %i" % (lines,cols))
debug(" %s -> %s" % (obj.start,obj.end)) debug(" %s -> %s" % (obj.start,obj.end))
for m in self._text_objects: for m in self._children:
if m == obj: if m == obj:
continue continue
@ -318,8 +328,6 @@ class SnippetInstance(TextObject):
else: else:
cts.current_text += chars cts.current_text += chars
self._update_mirrors(cts)
class Snippet(object): class Snippet(object):
_TABSTOP = re.compile(r'''(?xms) _TABSTOP = re.compile(r'''(?xms)
@ -335,7 +343,7 @@ class Snippet(object):
def trigger(self): def trigger(self):
return self._t return self._t
def _handle_tabstop(self, m, val, tabstops, mirrors): def _handle_tabstop(self, s, m, val, tabstops):
no = int(m.group(1)) no = int(m.group(1))
def_text = m.group(2) def_text = m.group(2)
@ -345,59 +353,65 @@ class Snippet(object):
line_idx = val[:start].count('\n') line_idx = val[:start].count('\n')
line_start = val[:start].rfind('\n') + 1 line_start = val[:start].rfind('\n') + 1
start_in_line = start - line_start start_in_line = start - line_start
ts = TabStop(line_idx, ts = TabStop(s, line_idx,
(start_in_line,start_in_line+len(def_text)), def_text) (start_in_line,start_in_line+len(def_text)), def_text)
tabstops[no] = ts tabstops[no] = ts
s.add_tabstop(no,ts)
return val return val
def _handle_ts_or_mirror(self, m, val, tabstops, mirrors): def _handle_ts_or_mirror(self, s, m, val, tabstops):
no = int(m.group(3)) no = int(m.group(3))
start, end = m.span() start, end = m.span()
val = val[:start] + val[end:]
line_idx = val[:start].count('\n') line_idx = val[:start].count('\n')
line_start = val[:start].rfind('\n') + 1 line_start = val[:start].rfind('\n') + 1
start_in_line = start - line_start start_in_line = start - line_start
if no in tabstops: if no in tabstops:
m = Mirror(tabstops[no], line_idx, start_in_line) m = Mirror(s, tabstops[no], line_idx, start_in_line)
mirrors.append(m) val = val[:start] + tabstops[no].current_text + val[end:]
else: else:
ts = TabStop(line_idx, (start_in_line,start_in_line)) ts = TabStop(s, line_idx, (start_in_line,start_in_line))
val = val[:start] + val[end:]
tabstops[no] = ts tabstops[no] = ts
s.add_tabstop(no,ts)
return val return val
def _find_tabstops(self, val): def _find_tabstops(self, s, val):
tabstops = {} tabstops = {}
mirrors = []
while 1: while 1:
m = self._TABSTOP.search(val) m = self._TABSTOP.search(val)
if m is not None: if m is not None:
if m.group(1) is not None: # ${1:hallo} if m.group(1) is not None: # ${1:hallo}
val = self._handle_tabstop(m,val,tabstops,mirrors) val = self._handle_tabstop(s,m,val,tabstops)
elif m.group(3) is not None: # $1 elif m.group(3) is not None: # $1
val = self._handle_ts_or_mirror(m,val,tabstops,mirrors) val = self._handle_ts_or_mirror(s,m,val,tabstops)
else: else:
break break
return tabstops, mirrors, val return val
def launch(self, before, after): def launch(self, before, after):
ts, mirrors, text = self._find_tabstops(self._v)
lineno, col = vim.current.window.cursor lineno, col = vim.current.window.cursor
start = Position(lineno-1,col - len(self._t)) start = Position(lineno-1,col - len(self._t))
end = Position(lineno-1,col) end = Position(lineno-1,col)
s = SnippetInstance(start,end)
text = self._find_tabstops(s, self._v)
new_end = _replace_text_in_buffer( start, end, text ) new_end = _replace_text_in_buffer( start, end, text )
if len(ts) or len(mirrors): # TODO: hack
s = SnippetInstance(start, new_end, ts, mirrors) s.end.col = new_end.col
s.end.line = new_end.line
if s.has_tabs():
s.select_next_tab() s.select_next_tab()
return s return s
else: else:

View File

@ -203,7 +203,8 @@ class TabStopTestMultilineExpand_ExceptCorrectResult(_VimTest):
def cmd(self): def cmd(self):
self.type("test hallo World") self.type("test hallo World")
self.escape() self.escape()
self.type("02f i\tworld\ttry\ttest\tone more\t\t") self.type("02f i\t")
self.type("world\ttry\ttest\tone more\t\t")
def runTest(self): self.check_output() def runTest(self): self.check_output()
# TODO: pasting with <C-R> while mirroring # TODO: pasting with <C-R> while mirroring