diff --git a/PySnipEmu.py b/PySnipEmu.py index 099ccbe..bc1c873 100644 --- a/PySnipEmu.py +++ b/PySnipEmu.py @@ -28,8 +28,51 @@ class TabStop(object): return self._no number = property(number) +class SnippetInstance(object): + def __init__(self,start,end, ts): + self._start = start + self._end = end + self._ts = ts + + self._cts = 1 + + def select_next_tab(self): + if self._cts not in self._ts: + if 0 in self._ts: + self._cts = 0 + else: + self._cts = 1 + + ts = self._ts[self._cts] + lineno, col = self._start + + newline = lineno + ts.line_idx + if newline == lineno: + newcol = col + ts.span[0] + endcol = col + ts.span[1] + else: + newcol = ts.span[0] + endcol = ts.span[1] + + self._cts += 1 + + vim.current.window.cursor = newline, newcol + + # 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 = "" + + vim.command(r'call feedkeys("\%sv%il\")' + % (move_one_right, endcol-newcol-1)) + class Snippet(object): - _TB_EXPR = re.compile(r'\$(?:(?:{(\d+):(.*)})|(\d+))') + _TB_EXPR = re.compile(r'\$(?:(?:{(\d+):(.*?)})|(\d+))') def __init__(self,trigger,value): self._t = trigger @@ -40,7 +83,7 @@ class Snippet(object): trigger = property(trigger) def _find_text_tabstops(self, lines): - tabstops = [] + tabstops = {} for idx in range(len(lines)): line = lines[idx] @@ -61,12 +104,10 @@ class Snippet(object): lines[idx] = line - tabstops.append( (ts.number, ts) ) + tabstops[ts.number] = ts m = self._TB_EXPR.search(line) - tabstops.sort() - return tabstops def _replace_tabstops(self): @@ -76,7 +117,7 @@ class Snippet(object): return ts, lines - def put(self, before, after): + def launch(self, before, after): lineno,col = vim.current.window.cursor col -= len(self._t) @@ -84,38 +125,37 @@ class Snippet(object): ts,lines = self._replace_tabstops() endcol = None - if len(ts): - zts = ts[0][1] - newline = lineno + zts.line_idx - if newline == lineno: - newcol = col + zts.span[0] - endcol = col + zts.span[1] - else: - newcol = zts.span[0] - endcol = zts.span[1] - else: + newline = 1 + newcol = 0 + if not len(ts): newline = lineno + len(lines) - 1 if len(lines) == 1: newcol = col + len(lines[-1]) else: newcol = len(lines[-1]) - - + lines[0] = before + lines[0] lines[-1] += after vim.current.buffer[lineno-1:lineno-1+len(lines)] = lines vim.current.window.cursor = newline, newcol - - # if endcol: - # # Select the word - # vim.command("insert PyVimSnips_SelectWord(%i)" % (endcol-newcol)) + + if len(ts): + s = SnippetInstance( (lineno,col), (newline,newcol), ts) + + s.select_next_tab() + + return s class SnippetManager(object): def __init__(self): + self.reset() + + def reset(self): self.clear_snippets() + self._current_snippets = [] def add_snippet(self,trigger,value): self._snippets[trigger] = Snippet(trigger,value) @@ -124,6 +164,10 @@ class SnippetManager(object): self._snippets = {} def try_expand(self): + if len(self._current_snippets): + self._current_snippets[-1].select_next_tab() + return + line = vim.current.line dummy,col = vim.current.window.cursor @@ -136,7 +180,14 @@ class SnippetManager(object): word = before.split()[-1] if word in self._snippets: - self._snippets[word].put(before.rstrip()[:-len(word)], after) + s = self._snippets[word].launch(before.rstrip()[:-len(word)], after) + if s is not None: + self._current_snippets.append(s) + + def cursor_moved(self): + pass + def entered_insert_mode(self): + pass PySnipSnippets = SnippetManager() diff --git a/PySnipEmu.vim b/PySnipEmu.vim index b9c94e3..603f29c 100644 --- a/PySnipEmu.vim +++ b/PySnipEmu.vim @@ -24,13 +24,22 @@ endfunction python from PySnipEmu import PySnipSnippets inoremap =PyVimSnips_ExpandSnippet() +snoremap :call PyVimSnips_ExpandSnippet() +python PySnipSnippets.add_snippet("echo","echo ${1:Hallo}") python PySnipSnippets.add_snippet("hello", "Hallo Welt!\nUnd Wie gehts?") -python PySnipSnippets.add_snippet("echo","$0 run") - - -python PySnipSnippets.add_snippet("if", "if(${1:/* condition */})\n{\n${0:/* code */}\n}") +python PySnipSnippets.add_snippet("hallo", "hallo ${0:End} ${1:Beginning}") +python << EOF +PySnipSnippets.add_snippet("if", +"""if(${1:/* condition */}) { + ${2:/* code */} +} +""") +EOF +au CursorMovedI * py PySnipSnippets.cursor_moved() +au InsertEnter * py PySnipSnippets.entered_insert_mode() + diff --git a/test.py b/test.py index a6ce4b4..22d05fd 100644 --- a/test.py +++ b/test.py @@ -10,16 +10,24 @@ from PySnipEmu import PySnipSnippets class _VimTest(unittest.TestCase): def setUp(self): + PySnipSnippets.reset() + + for sv,content in self.snippets: + PySnipSnippets.add_snippet(sv,content) + vim.command(":new") try: self.cmd() self.output = '\n'.join(vim.current.buffer[:]) finally: vim.command(":q!") - + def insert(self,string): """A helper function to type some text""" vim.command('normal i%s' % string) + def change(self,string): + """A helper function to type some text""" + vim.command('normal c%s' % string) def expand(self): vim.command("call PyVimSnips_ExpandSnippet()") @@ -36,10 +44,9 @@ class _VimTest(unittest.TestCase): # Simple Expands # ################## class _SimpleExpands(_VimTest): - def setUp(self): - PySnipSnippets.add_snippet("hallo","Hallo Welt!") - - _VimTest.setUp(self) + snippets = ( + ("hallo", "Hallo Welt!"), + ) class SimpleExpand_ExceptCorrectResult(_SimpleExpands): def cmd(self): @@ -85,8 +92,11 @@ class ExpandInTheMiddleOfLine_ExceptCorrectResult(_SimpleExpands): self.assertEqual(self.output,"Wie Hallo Welt! gehts?") class MultilineExpand_ExceptCorrectResult(_VimTest): + snippets = ( + ("hallo", "Hallo Welt!\nUnd Wie gehts?"), + ) + def cmd(self): - PySnipSnippets.add_snippet("hallo","Hallo Welt!\nUnd Wie gehts?") self.insert("Wie hallo gehts?") vim.command("normal 02f ") self.expand() @@ -94,8 +104,11 @@ class MultilineExpand_ExceptCorrectResult(_VimTest): def runTest(self): self.assertEqual(self.output, "Wie Hallo Welt!\nUnd Wie gehts? gehts?") class MultilineExpandTestTyping_ExceptCorrectResult(_VimTest): + snippets = ( + ("hallo", "Hallo Welt!\nUnd Wie gehts?"), + ) + def cmd(self): - PySnipSnippets.add_snippet("hallo","Hallo Welt!\nUnd Wie gehts?") self.insert("Wie hallo gehts?") vim.command("normal 02f ") self.expand() @@ -109,8 +122,11 @@ class MultilineExpandTestTyping_ExceptCorrectResult(_VimTest): # TabStops # ############ class ExitTabStop_ExceptCorrectResult(_VimTest): + snippets = ( + ("echo", "$0 run"), + ) + def cmd(self): - PySnipSnippets.add_snippet("echo","$0 run") self.insert("echo ") self.expand() self.insert("test") @@ -119,15 +135,30 @@ class ExitTabStop_ExceptCorrectResult(_VimTest): self.assertEqual(self.output,"test run ") class TextTabStopNoReplace_ExceptCorrectResult(_VimTest): + snippets = ( + ("echo", "echo ${1:Hallo}"), + ) + def cmd(self): - PySnipSnippets.add_snippet("echo","echo ${1:Hallo}") self.insert("echo ") self.expand() def runTest(self): self.assertEqual(self.output,"echo Hallo ") + +class TextTabStopSimpleReplace_ExceptCorrectResult(_VimTest): + snippets = ( + ("hallo", "hallo ${0:End} ${1:Beginning}"), + ) + + def cmd(self): + self.insert("hallo ") + self.expand() + vim.command(r'call feedkeys("na")') - + def runTest(self): + self.assertEqual(self.output,"hallo End na ") + if __name__ == '__main__': import sys from cStringIO import StringIO @@ -144,12 +175,13 @@ if __name__ == '__main__': MultilineExpandTestTyping_ExceptCorrectResult(), ExitTabStop_ExceptCorrectResult(), TextTabStopNoReplace_ExceptCorrectResult(), + TextTabStopSimpleReplace_ExceptCorrectResult(), ] # suite = unittest.TestLoader(.loadTestsFromModule(__import__("test")) suite = unittest.TestSuite() suite.addTests(tests) res = unittest.TextTestRunner(stream=s).run(suite) - + # if res.wasSuccessful(): # vim.command("qa!")