From e0f689df41ba8231f621c90b11d5ffa8f7c6c313 Mon Sep 17 00:00:00 2001 From: Holger Rapp Date: Thu, 9 Jul 2009 07:50:48 +0200 Subject: [PATCH] Tab selection no longer takes place inside TabStop --- plugin/PySnipEmu/Buffer.py | 5 +- plugin/PySnipEmu/TextObjects.py | 81 ++++++++++++++++----------------- plugin/PySnipEmu/__init__.py | 49 ++++++++++++++++++-- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/plugin/PySnipEmu/Buffer.py b/plugin/PySnipEmu/Buffer.py index f5e5787..c6e2b7b 100644 --- a/plugin/PySnipEmu/Buffer.py +++ b/plugin/PySnipEmu/Buffer.py @@ -1,12 +1,9 @@ #!/usr/bin/env python # encoding: utf-8 - import vim - from PySnipEmu.Geometry import Position - __all__ = [ "TextBuffer", "VimBuffer" ] class Buffer(object): @@ -70,3 +67,5 @@ class VimBuffer(Buffer): def replace_text( self, start, end, content ): return self._replace( start, end, content, self._bf, self._af) + + diff --git a/plugin/PySnipEmu/TextObjects.py b/plugin/PySnipEmu/TextObjects.py index 83e2e3a..11a5937 100644 --- a/plugin/PySnipEmu/TextObjects.py +++ b/plugin/PySnipEmu/TextObjects.py @@ -9,6 +9,8 @@ import re from PySnipEmu.Buffer import VimBuffer, TextBuffer from PySnipEmu.Geometry import Range, Position +from PySnipEmu.debug import debug + __all__ = [ "Mirror", "Transformation", "SnippetInstance" ] class TextObject(object): @@ -39,10 +41,36 @@ class TextObject(object): self._current_text = initial_text + # TODO: span or range. To use both is not clever def span(self): return Range(self._start, self._end) span = property(span) + def abs_start(self): + if self._parent: + ps = self._parent.abs_start + if self._start.line == 0: + return ps + self._start + else: + return Position(ps.line + self._start.line, self._start.col) + return self._start + abs_start = property(abs_start) + + def abs_end(self): + if self._parent: + ps = self._parent.abs_start + if self._end.line == 0: + return ps + self._end + else: + return Position(ps.line + self._end.line, self._start.col) + + return self._end + abs_end = property(abs_end) + + def abs_range(self): + return Range(self.abs_start, self.abs_end) + abs_range = property(abs_range) + def __cmp__(self, other): return cmp(self._start, other._start) @@ -341,40 +369,6 @@ class TabStop(ChangeableText): return "TabStop(%s -> %s, %s)" % (self._start, self._end, repr(self._current_text)) - def select(self, start): - lineno, col = start.line, start.col - - newline = lineno + self._start.line - newcol = self._start.col - - if newline == lineno: - newcol += col - - vim.current.window.cursor = newline + 1, newcol - - if len(self.current_text) == 0: - if newcol == 0: - vim.command(r'call feedkeys("\i")') - else: - vim.command(r'call feedkeys("\a")') - else: - # Select the word - # Depending on the current mode and position, we - # might need to move escape out of the mode and this - # will move our cursor one left - if newcol != 0 and vim.eval("mode()") == 'i': - move_one_right = "l" - else: - move_one_right = "" - - if len(self.current_text) <= 1: - do_select = "" - else: - do_select = "%il" % (len(self.current_text)-1) - - vim.command(r'call feedkeys("\%sv%s\")' % - (move_one_right, do_select)) - class SnippetInstance(TextObject): """ @@ -400,6 +394,12 @@ class SnippetInstance(TextObject): return self._tab_selected tab_selected = property(tab_selected) + def current_tab(self): + if self._cts in self._tabstops: + return self._tabstops[self._cts] + return None + current_tab = property(current_tab) + def update(self, buf, cur): TextObject.update(self, buf) @@ -419,7 +419,7 @@ class SnippetInstance(TextObject): def select_next_tab(self, backwards = False): if self._cts == 0: - return False + return None if backwards: cts_bf = self._cts @@ -440,14 +440,10 @@ class SnippetInstance(TextObject): if self._cts not in self._tabstops: self._cts = 0 if 0 not in self._tabstops: - return False - - ts = self._tabstops[self._cts] - - ts.select(self._start) + return None self._tab_selected = True - return self._cts + return self._tabstops[self._cts] def backspace(self,count, previous_cp): cts = self._tabstops[self._cts] @@ -458,11 +454,14 @@ class SnippetInstance(TextObject): def chars_entered(self, chars, cur): cts = self._tabstops[self._cts] + debug("chars_entered"); if self._tab_selected: cts.current_text = chars + debug("cts.current_text: %s" % (cts.current_text)) self._tab_selected = False else: cts.current_text += chars + debug("cts.current_text: %s" % (cts.current_text)) self.update(self._vb, cur) diff --git a/plugin/PySnipEmu/__init__.py b/plugin/PySnipEmu/__init__.py index ce153b4..0fcb0f3 100644 --- a/plugin/PySnipEmu/__init__.py +++ b/plugin/PySnipEmu/__init__.py @@ -7,8 +7,8 @@ import re import string import vim -from PySnipEmu.TextObjects import * from PySnipEmu.Geometry import Position +from PySnipEmu.TextObjects import * from PySnipEmu.debug import debug @@ -51,7 +51,6 @@ class Snippet(object): s = SnippetInstance(start, end, v, text_before, text_after) if s.has_tabs(): - s.select_next_tab() return s else: vim.current.window.cursor = s.end.line + 1, s.end.col @@ -104,6 +103,40 @@ class VimState(object): self._text_changed = self._lline != vim.current.buffer[line] self._lline = vim.current.buffer[line] + def select_range(self, r): + debug("r: %s" % (r)) + delta = r.end - r.start + debug("delta: %s" % (delta)) + lineno, col = r.start.line, r.start.col + + debug("lineno: %s, col: %s" % (lineno, col)) + + vim.current.window.cursor = lineno + 1, col + + if delta.col == 0: + if (col + delta.col) == 0: + vim.command(r'call feedkeys("\i")') + else: + vim.command(r'call feedkeys("\a")') + else: + # Select the word + # Depending on the current mode and position, we + # might need to move escape out of the mode and this + # will move our cursor one left + if col != 0 and vim.eval("mode()") == 'i': + move_one_right = "l" + else: + move_one_right = "" + + if delta.col <= 1: + do_select = "" + else: + do_select = "%il" % (delta.col-1) + + vim.command(r'call feedkeys("\%sv%s\")' % + (move_one_right, do_select)) + + def buf_changed(self): return self._text_changed buf_changed = property(buf_changed) @@ -204,8 +237,8 @@ class SnippetManager(object): if len(self._current_snippets): cs = self._current_snippets[-1] self._expect_move_wo_change = True - if not cs.select_next_tab(backwards): - + ts = cs.select_next_tab(backwards) + if ts is None: # HACK: only jump to end if there is no zero defined. This # TODO: this jump should be inside select_next_tab or even # better: when the snippet is launched and no parent snippet is @@ -219,6 +252,8 @@ class SnippetManager(object): self._current_snippets.pop() return True + else: + self._vstate.select_range(ts.abs_range) self._vstate.update() self._accept_input = True @@ -262,6 +297,11 @@ class SnippetManager(object): self._expect_move_wo_change = True s = snippet.launch(before.rstrip()[:-len(word)], after) + # TODO: this code is duplicated above + if s is not None: + ts = s.select_next_tab() + if ts is not None: + self._vstate.select_range(ts.abs_range) self._vstate.update() if s is not None: @@ -298,6 +338,7 @@ class SnippetManager(object): if not is_inside: self._current_snippets.pop() + debug("self._accept_input): %s" % (self._accept_input)) if not self._accept_input: return