From f58ae8869cea73adeeb71624f247cb52ed1569c0 Mon Sep 17 00:00:00 2001 From: jstenar <> Date: Fri, 31 Mar 2006 20:40:05 +0000 Subject: [PATCH] pyreadline-refactor: Merged patch for vi-mode from Michael Graz --- doc/ChangeLog | 4 + pyreadline/configuration/pyreadlineconfig.ini | 2 + pyreadline/configuration/startup.py | 10 +- pyreadline/lineeditor/lineobj.py | 13 +- pyreadline/modes/basemode.py | 13 +- pyreadline/modes/vi.py | 221 +- pyreadline/rlmain.py | 12 +- pyreadline/test/vi_test.py | 2168 +++++++++++++++++ 8 files changed, 2320 insertions(+), 123 deletions(-) create mode 100644 pyreadline/test/vi_test.py diff --git a/doc/ChangeLog b/doc/ChangeLog index aadbabf..265acc6 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2006-03-31 Jörgen Stenarson + * Merged patch from Michael Graz for the vi mode + * test directory now have a vi_test, should add more tests + 2006-03-16 Jörgen Stenarson * Added vi patch * Added visible selection mode to emacs mode diff --git a/pyreadline/configuration/pyreadlineconfig.ini b/pyreadline/configuration/pyreadlineconfig.ini index 0c5cc67..dacdc27 100644 --- a/pyreadline/configuration/pyreadlineconfig.ini +++ b/pyreadline/configuration/pyreadlineconfig.ini @@ -79,3 +79,5 @@ debug_output("off") history_filename("~/.pythonhistory") history_length(200) #value of -1 means no limit + +#set_mode("vi") #will cause following bind_keys to bind to vi mode as well as activate vi mode diff --git a/pyreadline/configuration/startup.py b/pyreadline/configuration/startup.py index 47770a8..a52dacf 100644 --- a/pyreadline/configuration/startup.py +++ b/pyreadline/configuration/startup.py @@ -1,14 +1,14 @@ # -*- coding: UTF-8 -*- # Example snippet to use in a PYTHONSTARTUP file try: - import pyreadline,atexit + import readline,atexit except ImportError: print "Module readline not available." else: #import tab completion functionality import rlcompleter #activate tab completion - pyreadline.parse_and_bind("tab: complete") - pyreadline.rl.read_history_file() - atexit.register(pyreadline.rl.write_history_file) - del pyreadline,rlcompleter,atexit + readline.parse_and_bind("tab: complete") + readline.read_history_file() + atexit.register(pyreadline.write_history_file) + del readline,rlcompleter,atexit diff --git a/pyreadline/lineeditor/lineobj.py b/pyreadline/lineeditor/lineobj.py index 1da1556..49e5ac1 100644 --- a/pyreadline/lineeditor/lineobj.py +++ b/pyreadline/lineeditor/lineobj.py @@ -210,9 +210,10 @@ class TextLine(object): def set_point(self,value): if isinstance(value,LinePositioner): - self._point=value(self) - else: - self._point=value + value=value(self) + if value>len(self.line_buffer): + value=len(self.line_buffer) + self._point=value def get_point(self): return self._point point=property(get_point,set_point) @@ -241,6 +242,9 @@ class TextLine(object): self.line_buffer = [] self.point = 0 + def end_of_line(self): + self.point = len(self.line_buffer) + def _insert_text(self, text): if self.overwrite: for c in text: @@ -280,7 +284,8 @@ class TextLine(object): elif isinstance(key,tuple): raise IndexError("Cannot use step in line buffer indexing") #Multiple slice not allowed else: - return TextLine(self.line_buffer[key]) + # return TextLine(self.line_buffer[key]) + return self.line_buffer[key] def __delitem__(self,key): if isinstance(key,LineSlice): diff --git a/pyreadline/modes/basemode.py b/pyreadline/modes/basemode.py index 3330e2c..c120d79 100644 --- a/pyreadline/modes/basemode.py +++ b/pyreadline/modes/basemode.py @@ -6,7 +6,7 @@ # Distributed under the terms of the BSD License. The full license is in # the file COPYING, distributed as part of this software. #***************************************************************************** -import os,re +import os,re,math import pyreadline.logger as logger from pyreadline.logger import log from pyreadline.keysyms import key_text_to_keyinfo @@ -352,3 +352,14 @@ class BaseMode(object): '''Copy the text in the region to the windows clipboard.''' self.l_buffer.cut_selection_to_clipboard() +def commonprefix(m): + "Given a list of pathnames, returns the longest common leading component" + if not m: return '' + prefix = m[0] + for item in m: + for i in range(len(prefix)): + if prefix[:i+1].lower() != item[:i+1].lower(): + prefix = prefix[:i] + if i == 0: return '' + break + return prefix diff --git a/pyreadline/modes/vi.py b/pyreadline/modes/vi.py index 75653d1..103e65f 100644 --- a/pyreadline/modes/vi.py +++ b/pyreadline/modes/vi.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- #***************************************************************************** # Copyright (C) 2003-2006 Gary Bishop. +# Copyright (C) 2006 Michael Graz. # Copyright (C) 2006 Jorgen Stenarson. # # Distributed under the terms of the BSD License. The full license is in @@ -92,7 +93,6 @@ class ViMode(basemode.BaseMode): ### Methods below here are bindable emacs functions - def init_editing_mode(self, e): # (M-C-j) '''Initialize vi editingmode''' self.show_all_if_ambiguous = 'on' @@ -117,13 +117,13 @@ class ViMode(basemode.BaseMode): self._bind_key('BackSpace', self.vi_backspace) self._bind_key('Escape', self.vi_escape) self._bind_key('Return', self.vi_accept_line) - + self._bind_key('Left', self.backward_char) self._bind_key('Right', self.forward_char) self._bind_key('Home', self.beginning_of_line) self._bind_key('End', self.end_of_line) self._bind_key('Delete', self.delete_char) - + self._bind_key('Control-d', self.vi_eof) self._bind_key('Control-z', self.vi_eof) self._bind_key('Control-r', self.vi_redo) @@ -178,12 +178,12 @@ class ViMode(basemode.BaseMode): if self.l_buffer.overwrite: try: prev = self._vi_undo_stack [self._vi_undo_cursor][1][self.l_buffer.point ] - self.l_buffer [self.l_buffer.point] = prev + self.l_buffer.line_buffer [self.l_buffer.point] = prev except IndexError: - del self.l_buffer[self.l_buffer.point ] + del self.l_buffer.line_buffer [self.l_buffer.point ] else: self.vi_save_line () - del self.l_buffer[self.l_buffer.point ] + del self.l_buffer.line_buffer [self.l_buffer.point ] def vi_accept_line (self, e): if self._vi_command and self._vi_command.is_search: @@ -210,15 +210,15 @@ class ViMode(basemode.BaseMode): self.console.cursor (size=100) def vi_undo_restart (self): - tpl_undo = (self.line_cursor, self.line_buffer[:], ) + tpl_undo = (self.l_buffer.point, self.l_buffer.line_buffer[:], ) self._vi_undo_stack = [tpl_undo] self._vi_undo_cursor = 0 def vi_save_line (self): - return if self._vi_undo_stack and self._vi_undo_cursor >= 0: del self._vi_undo_stack [self._vi_undo_cursor + 1 : ] - tpl_undo = (self.line_cursor, self.line_buffer[:], ) + # tpl_undo = (self.l_buffer.point, self.l_buffer[:], ) + tpl_undo = (self.l_buffer.point, self.l_buffer.line_buffer[:], ) if not self._vi_undo_stack or self._vi_undo_stack[self._vi_undo_cursor][1] != tpl_undo[1]: self._vi_undo_stack.append (tpl_undo) self._vi_undo_cursor += 1 @@ -245,8 +245,8 @@ class ViMode(basemode.BaseMode): def vi_undo_assign (self): tpl_undo = self._vi_undo_stack [self._vi_undo_cursor] - self.line_cursor = tpl_undo [0] - self.line_buffer = tpl_undo [1][:] + self.l_buffer.point = tpl_undo [0] + self.l_buffer.line_buffer = tpl_undo [1][:] def vi_redo (self, e): if self._vi_undo_cursor >= len(self._vi_undo_stack)-1: @@ -257,24 +257,24 @@ class ViMode(basemode.BaseMode): def vi_search (self, rng): for i in rng: - line_history = self.history [i] - pos = line_history.find (self._vi_search_text) + line_history = self._history.history [i] + pos = line_history.get_line_text().find (self._vi_search_text) if pos >= 0: - self.history_cursor = i - self.line_buffer = list (line_history) - self.line_cursor = pos + self._history.history_cursor = i + self.l_buffer.line_buffer = list (line_history.line_buffer) + self.l_buffer.point = pos self.vi_undo_restart () return True self._bell () return False def vi_search_first (self): - text = ''.join (self.line_buffer [1:]) + text = ''.join (self.l_buffer.line_buffer [1:]) if text: self._vi_search_text = text - position = len (self.history) - 1 + position = len (self._history.history) - 1 elif self._vi_search_text: - position = self.history_cursor - 1 + position = self._history.history_cursor - 1 else: self.vi_error () self.vi_undo () @@ -284,15 +284,16 @@ class ViMode(basemode.BaseMode): self.vi_undo () def vi_search_again_backward (self): - self.vi_search (range (self.history_cursor-1, -1, -1)) + self.vi_search (range (self._history.history_cursor-1, -1, -1)) def vi_search_again_forward (self): - self.vi_search (range (self.history_cursor+1, len(self.history))) + self.vi_search (range (self._history.history_cursor+1, len(self._history.history))) def vi_up (self, e): - if self.history_cursor == len(self.history): - self._vi_current = self.line_buffer [:] - self.previous_history (e) + if self._history.history_cursor == len(self._history.history): + self._vi_current = self.l_buffer.line_buffer [:] + # self._history.previous_history (e) + self._history.previous_history (self.l_buffer) if self.vi_is_insert_mode: self.end_of_line (e) else: @@ -300,22 +301,23 @@ class ViMode(basemode.BaseMode): self.vi_undo_restart () def vi_down (self, e): - if self.history_cursor >= len(self.history): + if self._history.history_cursor >= len(self._history.history): self.vi_error () return - if self.history_cursor < len(self.history) - 1: - self.next_history (e) + if self._history.history_cursor < len(self._history.history) - 1: + # self._history.next_history (e) + self._history.next_history (self.l_buffer) if self.vi_is_insert_mode: self.end_of_line (e) else: self.beginning_of_line (e) self.vi_undo_restart () elif self._vi_current is not None: - self.history_cursor = len(self.history) - self.line_buffer = self._vi_current + self._history.history_cursor = len(self._history.history) + self.l_buffer.line_buffer = self._vi_current self.end_of_line (e) - if not self.vi_is_insert_mode and self.line_cursor > 0: - self.line_cursor -= 1 + if not self.vi_is_insert_mode and self.l_buffer.point > 0: + self.l_buffer.point -= 1 self._vi_current = None else: self.vi_error () @@ -332,7 +334,7 @@ class ViMode(basemode.BaseMode): self.vi_save_line () def vi_complete (self, e): - text = ''.join (self.line_buffer) + text = self.l_buffer.get_line_text () if text and not text.isspace (): return self.complete (e) else: @@ -363,7 +365,7 @@ class ViCommand: self.text = None self.pos_motion = None self.is_edit = False -# self.is_overwrite = False + self.is_overwrite = False self.is_error = False self.is_star = False self.delete_left = 0 @@ -402,7 +404,7 @@ class ViCommand: self.escape (char) elif char == '\x09': # tab ts = self.readline.tabstop - ws = ' ' * (ts - (self.readline.line_cursor%ts)) + ws = ' ' * (ts - (self.readline.l_buffer.point%ts)) self.set_text (ws) elif char == '\x08': # backspace self.key_backspace (char) @@ -439,20 +441,20 @@ class ViCommand: for char in text: if not self.char_isprint (char): continue - self.readline.l_buffer.insert_text(char) - return - #overwrite in l_buffer obj +# self.readline.l_buffer.insert_text(char) +# continue +# #overwrite in l_buffer obj if self.is_overwrite: - if self.readline.line_cursor < len (self.readline.l_buffer): - self.readline.l_buffer[self.l_buffer.point]=char - #self.readline.line_buffer [self.readline.line_cursor] = char + if self.readline.l_buffer.point < len (self.readline.l_buffer.line_buffer): + # self.readline.l_buffer[self.l_buffer.point]=char + self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] = char else: - self.readline.l_buffer.insert_text(char) - #self.readline.line_buffer.append (char) + # self.readline.l_buffer.insert_text(char) + self.readline.l_buffer.line_buffer.append (char) else: - self.readline.l_buffer.insert_text(char) - #self.readline.line_buffer.insert (self.readline.line_cursor, char) - #self.readline.line_cursor += 1 + # self.readline.l_buffer.insert_text(char) + self.readline.l_buffer.line_buffer.insert (self.readline.l_buffer.point, char) + self.readline.l_buffer.point += 1 def replace_one (self, char): if char == '\x1b': # escape @@ -461,10 +463,10 @@ class ViCommand: self.is_edit = True self.readline.vi_save_line () times = self.get_multiplier () - cursor = self.readline.line_cursor - self.readline.line_buffer [cursor : cursor + times] = char * times + cursor = self.readline.l_buffer.point + self.readline.l_buffer.line_buffer [cursor : cursor + times] = char * times if times > 1: - self.readline.line_cursor += (times - 1) + self.readline.l_buffer.point += (times - 1) self.end () def char_isprint (self, char): @@ -611,14 +613,14 @@ class ViCommand: vi_cmd.set_override_multiplier (vi_cmd_edit.override_multiplier) for char in vi_cmd_edit.lst_char: vi_cmd.add_char (char) - if vi_cmd_edit.is_overwrite and self.readline.line_cursor > 0: - self.readline.line_cursor -= 1 + if vi_cmd_edit.is_overwrite and self.readline.l_buffer.point > 0: + self.readline.l_buffer.point -= 1 self.readline.vi_set_insert_mode (False) self.end () def key_slash (self, char): self.readline.vi_save_line () - self.readline.line_cursor, self.readline.line_buffer = 1, ['/'] + self.readline.l_buffer.point, self.readline.l_buffer.line_buffer = 1, ['/'] self.state = _VI_SEARCH def key_star (self, char): @@ -628,9 +630,9 @@ class ViCommand: completions = self.readline._get_completions() if completions: text = ' '.join (completions) + ' ' - self.readline.line_buffer [self.readline.begidx : self.readline.endidx + 1] = list (text) + self.readline.l_buffer.line_buffer [self.readline.begidx : self.readline.endidx + 1] = list (text) prefix_len = self.readline.endidx - self.readline.begidx - self.readline.line_cursor += len(text) - prefix_len + self.readline.l_buffer.point += len(text) - prefix_len self.readline.vi_set_insert_mode (True) else: self.error () @@ -646,12 +648,12 @@ class ViCommand: self.readline.vi_save_line () for i in range (self.get_multiplier()): try: - c = self.readline.line_buffer [self.readline.line_cursor] + c = self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] if c.isupper (): - self.readline.line_buffer [self.readline.line_cursor] = c.lower() + self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] = c.lower() elif c.islower (): - self.readline.line_buffer [self.readline.line_cursor] = c.upper() - self.readline.line_cursor += 1 + self.readline.l_buffer.line_buffer [self.readline.l_buffer.point] = c.upper() + self.readline.l_buffer.point += 1 except IndexError: break self.end () @@ -674,7 +676,7 @@ class ViCommand: else: self.key_h (char) self.readline._vi_do_backspace (self) - if self.state == _VI_SEARCH and not (self.readline.line_buffer): + if self.state == _VI_SEARCH and not (self.readline.l_buffer.line_buffer): self.state = _VI_BEGIN def key_l (self, char): @@ -691,20 +693,20 @@ class ViCommand: self.is_edit = True self.state = _VI_TEXT self.readline.vi_set_insert_mode (True) - self.readline.line_cursor = 0 + self.readline.l_buffer.point = 0 def key_a (self, char): self.is_edit = True self.state = _VI_TEXT self.readline.vi_set_insert_mode (True) - if len (self.readline.line_buffer): - self.readline.line_cursor += 1 + if len (self.readline.l_buffer.line_buffer): + self.readline.l_buffer.point += 1 def key_A (self, char): self.is_edit = True self.state = _VI_TEXT self.readline.vi_set_insert_mode (True) - self.readline.line_cursor = len (self.readline.line_buffer) + self.readline.l_buffer.point = len (self.readline.l_buffer.line_buffer) def key_d (self, char): self.is_edit = True @@ -731,18 +733,18 @@ class ViCommand: def key_s (self, char): self.is_edit = True - i1 = self.readline.line_cursor - i2 = self.readline.line_cursor + self.get_multiplier () + i1 = self.readline.l_buffer.point + i2 = self.readline.l_buffer.point + self.get_multiplier () self.skip_multipler = True self.readline.vi_set_insert_mode (True) - del self.readline.line_buffer [i1 : i2] + del self.readline.l_buffer.line_buffer [i1 : i2] self.state = _VI_TEXT def key_S (self, char): self.is_edit = True self.readline.vi_set_insert_mode (True) - self.readline.line_buffer = [] - self.readline.line_cursor = 0 + self.readline.l_buffer.line_buffer = [] + self.readline.l_buffer.point = 0 self.state = _VI_TEXT def key_c (self, char): @@ -753,7 +755,7 @@ class ViCommand: def key_C (self, char): self.is_edit = True self.readline.vi_set_insert_mode (True) - del self.readline.line_buffer [self.readline.line_cursor : ] + del self.readline.l_buffer.line_buffer [self.readline.l_buffer.point : ] self.state = _VI_TEXT def key_r (self, char): @@ -771,7 +773,7 @@ class ViCommand: self.action = self.yank def key_Y (self, char): - self.readline._vi_yank_buffer = ''.join (self.readline.line_buffer) + self.readline._vi_yank_buffer = self.readline.l_buffer.get_line_text() self.end () def key_p (self, char): @@ -779,9 +781,9 @@ class ViCommand: return self.is_edit = True self.readline.vi_save_line () - self.readline.line_cursor += 1 - self.readline.insert_text (self.readline._vi_yank_buffer * self.get_multiplier ()) - self.readline.line_cursor -= 1 + self.readline.l_buffer.point += 1 + self.readline.l_buffer.insert_text (self.readline._vi_yank_buffer * self.get_multiplier ()) + self.readline.l_buffer.point -= 1 self.state = _VI_END def key_P (self, char): @@ -789,8 +791,8 @@ class ViCommand: return self.is_edit = True self.readline.vi_save_line () - self.readline.insert_text (self.readline._vi_yank_buffer * self.get_multiplier ()) - self.readline.line_cursor -= 1 + self.readline.l_buffer.insert_text (self.readline._vi_yank_buffer * self.get_multiplier ()) + self.readline.l_buffer.point -= 1 self.state = _VI_END def key_u (self, char): @@ -802,9 +804,9 @@ class ViCommand: self.state = _VI_END def key_v (self, char): - editor = ViExternalEditor (self.readline.line_buffer) - self.readline.line_buffer = list (editor.result) - self.readline.line_cursor = 0 + editor = ViExternalEditor (self.readline.l_buffer.line_buffer) + self.readline.l_buffer.line_buffer = list (editor.result) + self.readline.l_buffer.point = 0 self.is_edit = True self.state = _VI_END @@ -840,7 +842,7 @@ class ViCommand: return 0 def motion_end_in_line (self, line, index=0, count=1, **kw): - return max (0, len (self.readline.line_buffer)-1) + return max (0, len (self.readline.l_buffer.line_buffer)-1) def motion_word_short (self, line, index=0, count=1, **kw): return vi_pos_word_short (line, index, count) @@ -903,7 +905,7 @@ class ViCommand: def apply (self): if self.motion: - self.pos_motion = self.motion (self.readline.l_buffer, self.readline.l_buffer.point, + self.pos_motion = self.motion (self.readline.l_buffer.line_buffer, self.readline.l_buffer.point, self.get_multiplier(), char=self.motion_argument) if self.pos_motion < 0: self.error () @@ -913,54 +915,56 @@ class ViCommand: self.end () def movement (self): - if self.pos_motion <= len(self.readline.l_buffer): + if self.pos_motion <= len(self.readline.l_buffer.line_buffer): self.readline.l_buffer.point = self.pos_motion else: - self.readline.l_buffer.point = len(self.readline.l_buffer) - 1 + self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer) - 1 def yank (self): - if self.pos_motion > self.readline.line_cursor: - s = self.readline.line_buffer [self.readline.line_cursor : self.pos_motion + self.delete_right] + if self.pos_motion > self.readline.l_buffer.point: + s = self.readline.l_buffer.line_buffer [self.readline.l_buffer.point : self.pos_motion + self.delete_right] else: index = max (0, self.pos_motion - self.delete_left) - s = self.readline.line_buffer [index : self.readline.line_cursor + self.delete_right] + s = self.readline.l_buffer.line_buffer [index : self.readline.l_buffer.point + self.delete_right] self.readline._vi_yank_buffer = s def delete (self): self.readline.vi_save_line () self.yank () - point=lineobj.Point(self.readline.l_buffer) - pm=self.pos_motion - del self.readline.l_buffer[point:pm] - - return - if self.pos_motion > self.readline.line_cursor: - del self.readline.line_buffer [self.readline.line_cursor : self.pos_motion + self.delete_right] - if self.readline.line_cursor > len (self.readline.line_buffer): - self.readline.line_cursor = len (self.readline.line_buffer) +# point=lineobj.Point(self.readline.l_buffer) +# pm=self.pos_motion +# del self.readline.l_buffer[point:pm] +# return + if self.pos_motion > self.readline.l_buffer.point: + del self.readline.l_buffer.line_buffer [self.readline.l_buffer.point : self.pos_motion + self.delete_right] + if self.readline.l_buffer.point > len (self.readline.l_buffer.line_buffer): + self.readline.l_buffer.point = len (self.readline.l_buffer.line_buffer) else: index = max (0, self.pos_motion - self.delete_left) - del self.readline.line_buffer [index : self.readline.line_cursor + self.delete_right] - self.readline.line_cursor = index + del self.readline.l_buffer.line_buffer [index : self.readline.l_buffer.point + self.delete_right] + self.readline.l_buffer.point = index def delete_end_of_line (self): self.readline.vi_save_line () - del self.readline.line_buffer [self.readline.line_cursor : ] - if self.readline.line_cursor > 0: - self.readline.line_cursor -= 1 + # del self.readline.l_buffer [self.readline.l_buffer.point : ] + line_text = self.readline.l_buffer.get_line_text () + line_text = line_text [ : self.readline.l_buffer.point] + self.readline.l_buffer.set_line (line_text) + if self.readline.l_buffer.point > 0: + self.readline.l_buffer.point -= 1 def delete_char (self): - point=lineobj.Point(self.readline.l_buffer) - del self.readline.l_buffer[point:point+self.get_multiplier ()] - return - self.pos_motion = self.readline.line_cursor + self.get_multiplier () +# point=lineobj.Point(self.readline.l_buffer) +# del self.readline.l_buffer[point:point+self.get_multiplier ()] +# return + self.pos_motion = self.readline.l_buffer.point + self.get_multiplier () self.delete () - end = max (0, len (self.readline.line_buffer) - 1) - if self.readline.line_cursor > end: - self.readline.line_cursor = end + end = max (0, len (self.readline.l_buffer) - 1) + if self.readline.l_buffer.point > end: + self.readline.l_buffer.point = end def delete_prev_char (self): - self.pos_motion = self.readline.line_cursor - self.get_multiplier () + self.pos_motion = self.readline.l_buffer.point - self.get_multiplier () self.delete () def change (self): @@ -984,8 +988,8 @@ class ViCommand: def end (self): self.state = _VI_END - #if self.readline.line_cursor >= len(self.readline.line_buffer): - # self.readline.line_cursor = max (0, len(self.readline.line_buffer) - 1) + if self.readline.l_buffer.point >= len(self.readline.l_buffer.line_buffer): + self.readline.l_buffer.point = max (0, len(self.readline.l_buffer.line_buffer) - 1) class ViExternalEditor: def __init__ (self, line): @@ -1030,6 +1034,7 @@ class ViEvent: # vi standalone functions def vi_is_word (char): + log ('xx vi_is_word: type(%s), %s' % (type(char), char, )) return char.isalpha() or char.isdigit() or char == '_' def vi_is_space (char): diff --git a/pyreadline/rlmain.py b/pyreadline/rlmain.py index 8bc3305..7f23794 100644 --- a/pyreadline/rlmain.py +++ b/pyreadline/rlmain.py @@ -60,11 +60,6 @@ class Readline(object): self.next_meta = False # True to force meta on next character self.tabstop = 4 - self.editingmodes=[mode(self) for mode in editingmodes] - for mode in self.editingmodes: - mode.init_editing_mode(None) - self.mode=self.editingmodes[0] - self.begidx = 0 self.endidx = 0 @@ -75,6 +70,13 @@ class Readline(object): self.mark=-1 self.l_buffer=lineobj.ReadLineTextBuffer("") self._history=history.LineHistory() + + # this code needs to follow l_buffer and history creation + self.editingmodes=[mode(self) for mode in editingmodes] + for mode in self.editingmodes: + mode.init_editing_mode(None) + self.mode=self.editingmodes[0] + self.read_inputrc() log("\n".join(self.rl_settings_to_string())) diff --git a/pyreadline/test/vi_test.py b/pyreadline/test/vi_test.py new file mode 100644 index 0000000..848354d --- /dev/null +++ b/pyreadline/test/vi_test.py @@ -0,0 +1,2168 @@ +# -*- coding: utf-8 -*- +#***************************************************************************** +# Copyright (C) 2006 Michael Graz. +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#***************************************************************************** + +import sys, unittest +sys.path.append ('../..') +from pyreadline.modes.vi import * +from pyreadline import keysyms +from pyreadline.lineeditor import lineobj + +#---------------------------------------------------------------------- + +class ViModeTest (ViMode): + def __init__ (self): + ViMode.__init__ (self, MockReadline()) + self.mock_console = MockConsole () + self.init_editing_mode (None) + self.vi_set_insert_mode (True) + self.lst_completions = [] + self.completer = self.mock_completer + self.completer_delims = ' ' + self.tabstop = 4 + + def get_mock_console (self): + return self.mock_console + console = property (get_mock_console) + + def _set_line (self, text): + self.l_buffer.set_line (text) + + def get_line (self): + return self.l_buffer.get_line_text () + line = property (get_line) + + def get_line_cursor (self): + return self.l_buffer.point + line_cursor = property (get_line_cursor) + + def input (self, keytext): + if keytext[0] == '"' and keytext[-1] == '"': + lst_key = ['"%s"' % c for c in keytext[1:-1]] + else: + lst_key = [keytext] + for key in lst_key: + keyinfo, event = keytext_to_keyinfo_and_event (key) + dispatch_func = self.key_dispatch [keyinfo] + dispatch_func (event) + + def vi_accept_line (self, e): + if ViMode.vi_accept_line (self, e): + # simulate return + # self.add_history (self.line) + self.l_buffer.reset_line () + + def mock_completer (self, text, state): + return self.lst_completions [state] + +class MockReadline: + def __init__ (self): + self.l_buffer=lineobj.ReadLineTextBuffer("") + self._history=history.LineHistory() + + def add_history (self, line): + self._history.add_history (lineobj.TextLine (line)) + + def _print_prompt (self): + pass + + def _bell (self): + pass + +class MockConsole: + def __init__ (self): + self.bell_count = 0 + self.text = '' + + def size (self): + return (1, 1) + + def cursor(self, visible=None, size=None): + pass + + def bell (self): + self.bell_count += 1 + + def write (self, text): + self.text += text + +class ViExternalEditorTest (ViExternalEditor): + def __init__ (self, line): + import StringIO + self.sio_write = StringIO.StringIO () + self.sio_read = StringIO.StringIO ('qwerty after') + ViExternalEditor.__init__ (self, line) + + def get_tempfile (self): + return 'temp.py' + + def get_editor (self): + return 'vim.exe' + + def file_open (self, filename, mode): + if mode == 'w': + return self.sio_write + else: + return self.sio_read + + def file_remove (self, filename): + self.remove = filename + + def run_command (self, command): + self.command = command + +#---------------------------------------------------------------------- + +class Tests (unittest.TestCase): + + def test_keyinfo (self): + keyinfo, event = keytext_to_keyinfo_and_event ('"d"') + self.assertEqual ('d', event.char) + keyinfo, event = keytext_to_keyinfo_and_event ('"D"') + self.assertEqual ('D', event.char) + keyinfo, event = keytext_to_keyinfo_and_event ('"$"') + self.assertEqual ('$', event.char) + keyinfo, event = keytext_to_keyinfo_and_event ('Escape') + self.assertEqual ('\x1b', event.char) + + def test_simple (self): + r = ViModeTest () + r._set_line ('abc') + self.assert_ (r.vi_is_insert_mode) + r.input ('"d"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual ('abcd', r.line) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual ('abcd', r.line) + r.input ('"i"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual ('abcd', r.line) + r.input ('"x"') + self.assertEqual ('abcxd', r.line) + r.input ('"y"') + self.assertEqual ('abcxyd', r.line) + + def test_begin_and_end (self): + r = ViModeTest () + r._set_line ('abc') + self.assertEqual (3, r.line_cursor) + r.input ('Escape') + self.assertEqual (2, r.line_cursor) + r.input ('"0"') + self.assertEqual (0, r.line_cursor) + r.input ('"$"') + self.assertEqual (2, r.line_cursor) + r.input ('"^"') + self.assertEqual (0, r.line_cursor) + + def test_history_alpha (self): + r = ViModeTest () + r.add_history ('abc') + r.add_history ('def') + r._set_line ('ghi') + r.input ('Escape') + r.input ('"k"') + self.assertEqual (0, r.line_cursor) + self.assertEqual ('def', r.line) + r.input ('"k"') + self.assertEqual ('abc', r.line) + self.assertEqual (0, r.console.bell_count) + r.input ('"k"') + self.assertEqual ('abc', r.line) + # TODO up history with no more -> error ? + # self.assertEqual (1, r.console.bell_count) + r.input ('"j"') + self.assertEqual ('def', r.line) + self.assertEqual (0, r.line_cursor) + r.input ('"j"') + self.assertEqual ('ghi', r.line) + # TODO returning to original line loses cursor pos? + # self.assertEqual (2, r.line_cursor) + r.input ('"j"') + self.assertEqual ('ghi', r.line) + self.assertEqual (2, r.line_cursor) + + def test_history_arrow (self): + r = ViModeTest () + r.add_history ('abc') + r.add_history ('def') + r.input ('"ghi"') + self.assertEqual (3, r.line_cursor) + r.input ('Up') + self.assertEqual (3, r.line_cursor) + self.assertEqual ('def', r.line) + r.input ('Up') + self.assertEqual (3, r.line_cursor) + self.assertEqual ('abc', r.line) + self.assertEqual (0, r.console.bell_count) + r.input ('Up') + self.assertEqual ('abc', r.line) + # TODO up history with no more -> error ? + # self.assertEqual (1, r.console.bell_count) + r.input ('Down') + self.assertEqual ('def', r.line) + self.assertEqual (3, r.line_cursor) + r.input ('Down') + self.assertEqual ('ghi', r.line) + self.assertEqual (3, r.line_cursor) + r.input ('Down') + self.assertEqual ('ghi', r.line) + self.assertEqual (3, r.line_cursor) + + def test_history_arrow_after_undo (self): + r = ViModeTest () + r.input ('"aaa"') + r.input ('Return') + r.input ('"bbb ccc"') + r.input ('Escape') + r.input ('"F D"') + self.assertEqual (r.line, 'bbb') + r.input ('"u"') + self.assertEqual (r.line, 'bbb ccc') + r.input ('Return') + self.assertEqual (r.console.bell_count, 0) + r.input ('"ddd"') + r.input ('Down') + self.assertEqual (r.line, 'ddd') + # TODO down history with no more -> error ? + # self.assertEqual (r.console.bell_count, 1) + + def test_vi_is_word (self): + self.assert_ (vi_is_word ('a')) + self.assert_ (not vi_is_word (' ')) + + def test_pos_word_short (self): + self.assertEqual (0, vi_pos_word_short ('')) + self.assertEqual (4, vi_pos_word_short ('abc def ')) + self.assertEqual (4, vi_pos_word_short ('abc def ', 2)) + self.assertEqual (4, vi_pos_word_short ('abc def ', 3)) + self.assertEqual (8, vi_pos_word_short ('abc def ', 4)) + self.assertEqual (3, vi_pos_word_short ('abc.def ')) + self.assertEqual (5, vi_pos_word_short ('abc..def ', 3)) + self.assertEqual (8, vi_pos_word_short ('ab cd ef gh', count=2)) + self.assertEqual (8, vi_pos_word_short ('ab cd ef gh', 1, 2)) + self.assertEqual (8, vi_pos_word_short ('ab cd ef gh', 3, 2)) + self.assertEqual (14, vi_pos_word_short ('ab cd ef gh', count=10)) + + def test_pos_word_long (self): + self.assertEqual (0, vi_pos_word_long ('')) + self.assertEqual (4, vi_pos_word_long ('abc def ')) + self.assertEqual (4, vi_pos_word_long ('abc def ', 2)) + self.assertEqual (4, vi_pos_word_long ('abc def ', 3)) + self.assertEqual (8, vi_pos_word_long ('abc def ', 4)) + self.assertEqual (8, vi_pos_word_long ('abc.def ')) + self.assertEqual (9, vi_pos_word_long ('abc..def ', 3)) + self.assertEqual (10, vi_pos_word_long ('a.b c.d e.f g.h', count=2)) + self.assertEqual (10, vi_pos_word_long ('a.b c.d e.f g.h', 2, 2)) + self.assertEqual (10, vi_pos_word_long ('a.b c.d e.f g.h', 4, 2)) + + def test_pos_end_short (self): + self.assertEqual (0, vi_pos_end_short ('')) + self.assertEqual (2, vi_pos_end_short ('abc def ')) + self.assertEqual (6, vi_pos_end_short ('abc def ', 2)) + self.assertEqual (6, vi_pos_end_short ('abc def ', 3)) + self.assertEqual (6, vi_pos_end_short ('abc def ', 4)) + self.assertEqual (2, vi_pos_end_short ('abc.def ')) + self.assertEqual (7, vi_pos_end_short ('abc ... def ', 3)) + self.assertEqual (7, vi_pos_end_short ('abc ... def ', 5)) + self.assertEqual (12, vi_pos_end_short ('abc ... def ', 8)) + self.assertEqual (5, vi_pos_end_short ('ab cd ef gh', count=2)) + self.assertEqual (9, vi_pos_end_short ('ab cd ef gh', 1, 2)) + self.assertEqual (9, vi_pos_end_short ('ab cd ef gh', 3, 2)) + + def test_pos_end_long (self): + self.assertEqual (0, vi_pos_end_long ('')) + self.assertEqual (2, vi_pos_end_long ('abc def ')) + self.assertEqual (6, vi_pos_end_long ('abc def ', 2)) + self.assertEqual (6, vi_pos_end_long ('abc def ', 3)) + self.assertEqual (6, vi_pos_end_long ('abc def ', 4)) + self.assertEqual (6, vi_pos_end_long ('abc.def ')) + self.assertEqual (10, vi_pos_end_long (' abc...def ')) + self.assertEqual (10, vi_pos_end_long ('abc ...def ', 5)) + self.assertEqual (7, vi_pos_end_long ('a.b c.d e.f g.h', count=2)) + self.assertEqual (12, vi_pos_end_long ('a.b c.d e.f g.h', 2, 2)) + self.assertEqual (12, vi_pos_end_long ('a.b c.d e.f g.h', 4, 2)) + + def test_pos_back_short (self): + self.assertEqual (0, vi_pos_back_short ('')) + self.assertEqual (4, vi_pos_back_short ('abc def', 6)) + self.assertEqual (4, vi_pos_back_short ('abc def', 5)) + self.assertEqual (0, vi_pos_back_short ('abc def', 4)) + self.assertEqual (0, vi_pos_back_short ('abc def', 3)) + self.assertEqual (8, vi_pos_back_short ('abc ...def ', 11)) + self.assertEqual (5, vi_pos_back_short ('abc ...def ', 8)) + self.assertEqual (0, vi_pos_back_short ('abc ...def ', 5)) + self.assertEqual (0, vi_pos_back_short ('abc ...def ')) + self.assertEqual (8, vi_pos_back_short ('abc def... ', 11)) + self.assertEqual (5, vi_pos_back_short ('abc def... ', 8)) + self.assertEqual (0, vi_pos_back_short ('abc def... ', 5)) + self.assertEqual (11, vi_pos_back_short ('abc def... ghi...', 16, count=2)) + self.assertEqual (0, vi_pos_back_short ('abc def... ghi...', 11, count=3)) + + def test_pos_back_long (self): + self.assertEqual (0, vi_pos_back_long ('')) + self.assertEqual (4, vi_pos_back_long ('abc def', 6)) + self.assertEqual (4, vi_pos_back_long ('abc def', 5)) + self.assertEqual (0, vi_pos_back_long ('abc def', 4)) + self.assertEqual (0, vi_pos_back_long ('abc def', 3)) + self.assertEqual (5, vi_pos_back_long ('abc ...def ', 11)) + self.assertEqual (0, vi_pos_back_long ('abc ...def ', 5)) + self.assertEqual (0, vi_pos_back_long ('abc ...def ')) + self.assertEqual (5, vi_pos_back_long ('abc def... ', 11)) + self.assertEqual (0, vi_pos_back_long ('abc def... ', 5)) + self.assertEqual (4, vi_pos_back_long ('abc def... ghi...', 16, count=2)) + + def test_pos_find_char_forward (self): + self.assertEqual (-1, vi_pos_find_char_forward ('', 'x')) + self.assertEqual (-1, vi_pos_find_char_forward ('abc def', 'x')) + self.assertEqual (4, vi_pos_find_char_forward ('abc def', 'd')) + self.assertEqual (4, vi_pos_find_char_forward ('abc def', 'd', 3)) + self.assertEqual (-1, vi_pos_find_char_forward ('abc def', 'd', 4)) + self.assertEqual (-1, vi_pos_find_char_forward ('abc def', 'd', count=2)) + self.assertEqual (12, vi_pos_find_char_forward ('abc def abc def', 'd', count=2)) + + def test_pos_find_char_backward (self): + self.assertEqual (-1, vi_pos_find_char_backward ('', 'x')) + self.assertEqual (-1, vi_pos_find_char_backward ('abc def', 'x', 6)) + self.assertEqual (4, vi_pos_find_char_backward ('abc def', 'd', 6)) + self.assertEqual (4, vi_pos_find_char_backward ('abc def', 'd', 5)) + self.assertEqual (-1, vi_pos_find_char_backward ('abc def', 'd', 4)) + self.assertEqual (-1, vi_pos_find_char_backward ('abc def', 'd', 6, count=2)) + self.assertEqual (4, vi_pos_find_char_backward ('abc def abc def', 'd', 14, count=2)) + + def test_pos_to_char_forward (self): + self.assertEqual (-1, vi_pos_to_char_forward ('', 'x')) + self.assertEqual (-1, vi_pos_to_char_forward ('abc def', 'x')) + self.assertEqual (3, vi_pos_to_char_forward ('abc def', 'd')) + self.assertEqual (3, vi_pos_to_char_forward ('abc def', 'd', 2)) + self.assertEqual (-1, vi_pos_to_char_forward ('abc def', 'd', 4)) + self.assertEqual (-1, vi_pos_to_char_forward ('abc def', 'd', count=2)) + self.assertEqual (11, vi_pos_to_char_forward ('abc def abc def', 'd', count=2)) + + def test_pos_to_char_backward (self): + self.assertEqual (-1, vi_pos_to_char_backward ('', 'x')) + self.assertEqual (-1, vi_pos_to_char_backward ('abc def', 'x', 6)) + self.assertEqual (5, vi_pos_to_char_backward ('abc def', 'd', 6)) + self.assertEqual (5, vi_pos_to_char_backward ('abc def', 'd', 5)) + self.assertEqual (-1, vi_pos_to_char_backward ('abc def', 'd', 4)) + self.assertEqual (-1, vi_pos_to_char_backward ('abc def', 'd', 6, count=2)) + self.assertEqual (5, vi_pos_to_char_backward ('abc def abc def', 'd', 14, count=2)) + + def test_motion_word (self): + '''motions: lowercase mode is alpha, digit and _, uppercase is delim by spaces + w/W: forward short/long word''' + r = ViModeTest () + r._set_line ('abc_123 def--456.789 x') + r.input ('Escape') + r.input ('"0"') + r.input ('"w"') + self.assertEqual (9, r.line_cursor) + r.input ('"w"') + self.assertEqual (12, r.line_cursor) + r.input ('"w"') + self.assertEqual (14, r.line_cursor) + r.input ('"W"') + self.assertEqual (23, r.line_cursor) + + def test_motion_word_multiplier (self): + r = ViModeTest () + r._set_line ('a b c d e f g h i j k l m n o p q r s t u v w x y z') + r.input ('Escape') + r.input ('"0"') + r.input ('"2"') + self.assertEqual (0, r.line_cursor) + r.input ('"w"') + self.assertEqual (4, r.line_cursor) + r.input ('"2"') + r.input ('"0"') + r.input ('"w"') + self.assertEqual (44, r.line_cursor) + r.input ('"2"') + r.input ('"W"') + self.assertEqual (48, r.line_cursor) + + def test_motion_end (self): + '''motions: lowercase mode is alpha, digit and _, uppercase is delim by spaces + e/E: to end of short/long word''' + r = ViModeTest () + r._set_line (' abc_123 --def--456.789 x') + r.input ('Escape') + r.input ('"0"') + r.input ('"e"') + self.assertEqual (8, r.line_cursor) + r.input ('"e"') + self.assertEqual (12, r.line_cursor) + r.input ('"e"') + self.assertEqual (15, r.line_cursor) + r.input ('"E"') + self.assertEqual (24, r.line_cursor) + + def test_motion_end_multiplier (self): + r = ViModeTest () + r._set_line ('ab cd ef gh ij kl mn op qr st uv wx yz') + r.input ('Escape') + r.input ('"0"') + r.input ('"3"') + r.input ('"e"') + self.assertEqual (7, r.line_cursor) + r.input ('"4"') + r.input ('"E"') + self.assertEqual (19, r.line_cursor) + + def test_motion_backward (self): + '''motions: lowercase mode is alpha, digit and _, uppercase is delim by spaces + b/B: backward short/long word''' + r = ViModeTest () + r._set_line ('abc_123 def--456.789 x') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (23, r.line_cursor) + r.input ('"b"') + self.assertEqual (18, r.line_cursor) + r.input ('"b"') + self.assertEqual (17, r.line_cursor) + r.input ('"B"') + self.assertEqual (9, r.line_cursor) + r.input ('"B"') + self.assertEqual (0, r.line_cursor) + + def test_motion_backward_multiplier (self): + r = ViModeTest () + r._set_line ('ab cd ef gh ij kl mn op qr st uv wx yz') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (37, r.line_cursor) + r.input ('"3"') + r.input ('"b"') + self.assertEqual (30, r.line_cursor) + r.input ('"5"') + r.input ('"b"') + self.assertEqual (15, r.line_cursor) + + def test_motion_find_char_forward (self): + r = ViModeTest () + r._set_line ('abc_123 def--456.789 x') + r.input ('Escape') + r.input ('"0"') + r.input ('"f"') + self.assertEqual (0, r.line_cursor) + r.input ('"c"') + self.assertEqual (2, r.line_cursor) + + def test_motion_find_char_backward (self): + r = ViModeTest () + r._set_line ('abc_123 def--456.789 x') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (23, r.line_cursor) + r.input ('"F"') + self.assertEqual (23, r.line_cursor) + r.input ('"c"') + self.assertEqual (2, r.line_cursor) + + def test_motion_find_char_forward_multiplier (self): + r = ViModeTest () + r._set_line ('ab cd ef 01 23 45 ab cd ef 01 23 45 ab cd ef 01 23 45') + r.input ('Escape') + r.input ('"0"') + r.input ('"2"') + r.input ('"f"') + r.input ('"0"') + self.assertEqual (27, r.line_cursor) + + def test_motion_find_char_backward_multiplier (self): + r = ViModeTest () + r._set_line ('ab cd ef 01 23 45 ab cd ef 01 23 45 ab cd ef 01 23 45') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (52, r.line_cursor) + r.input ('"2"') + r.input ('"F"') + r.input ('"0"') + self.assertEqual (27, r.line_cursor) + + def test_motion_find_char_again (self): + r = ViModeTest () + r._set_line ('1234512345123451234512345') + r.input ('Escape') + r.input ('"0"') + r.input ('"2"') + r.input ('"f"') + r.input ('"3"') + self.assertEqual (7, r.line_cursor) + r.input ('";"') + self.assertEqual (12, r.line_cursor) + r.input ('"2"') + r.input ('";"') + self.assertEqual (22, r.line_cursor) + r.input ('","') + self.assertEqual (17, r.line_cursor) + r.input ('"2"') + r.input ('","') + self.assertEqual (7, r.line_cursor) + + def test_motion_find_char_opposite (self): + r = ViModeTest () + r._set_line ('1234512345123451234512345') + r.input ('Escape') + r.input ('"$"') + r.input ('"2"') + r.input ('"F"') + r.input ('"3"') + self.assertEqual (17, r.line_cursor) + r.input ('";"') + self.assertEqual (12, r.line_cursor) + r.input ('"2"') + r.input ('";"') + self.assertEqual (2, r.line_cursor) + r.input ('","') + self.assertEqual (7, r.line_cursor) + r.input ('"2"') + r.input ('","') + self.assertEqual (17, r.line_cursor) + r.input ('"2"') + r.input ('","') + self.assertEqual (17, r.line_cursor) + + def test_motion_to_char_forward (self): + r = ViModeTest () + r._set_line ('abc_123 def--456.789 x') + r.input ('Escape') + r.input ('"0"') + r.input ('"t"') + self.assertEqual (0, r.line_cursor) + r.input ('"c"') + self.assertEqual (1, r.line_cursor) + + def test_motion_to_char_backward (self): + r = ViModeTest () + r._set_line ('abc_123 def--456.789 x') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (23, r.line_cursor) + r.input ('"T"') + self.assertEqual (23, r.line_cursor) + r.input ('"c"') + self.assertEqual (3, r.line_cursor) + + def test_motion_to_char_forward_multiplier (self): + r = ViModeTest () + r._set_line ('ab cd ef 01 23 45 ab cd ef 01 23 45 ab cd ef 01 23 45') + r.input ('Escape') + r.input ('"0"') + r.input ('"2"') + r.input ('"t"') + r.input ('"0"') + self.assertEqual (26, r.line_cursor) + + def test_motion_to_char_backward_multiplier (self): + r = ViModeTest () + r._set_line ('ab cd ef 01 23 45 ab cd ef 01 23 45 ab cd ef 01 23 45') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (52, r.line_cursor) + r.input ('"2"') + r.input ('"T"') + r.input ('"0"') + self.assertEqual (28, r.line_cursor) + + def test_delete_word (self): + r = ViModeTest () + r._set_line ('abc de fghi jkl mnopq rst') + r.input ('Escape') + r.input ('"0"') + r.input ('"d"') + r.input ('"w"') + self.assertEqual (0, r.line_cursor) + self.assertEqual (r.line, 'de fghi jkl mnopq rst') + r.input ('"d"') + r.input ('"2"') + r.input ('"w"') + self.assertEqual (0, r.line_cursor) + self.assertEqual (r.line, 'jkl mnopq rst') + r.input ('"2"') + r.input ('"d"') + r.input ('"w"') + self.assertEqual (0, r.line_cursor) + self.assertEqual (r.line, 'rst') + + def test_delete_word_two_multipliers (self): + r = ViModeTest () + r._set_line ('abc de fghi jkl mnopq rst uv wx yz') + r.input ('Escape') + r.input ('"0w"') + r.input ('"2d3w"') + self.assertEqual (4, r.line_cursor) + self.assertEqual (r.line, 'abc wx yz') + + def test_delete_find_char_forward_two_multipliers (self): + r = ViModeTest () + r._set_line ('0123456789012345678901234567890123456789012345678901234567890123456789') + r.input ('Escape') + r.input ('"0"') + r.input ('"2d3f4"') + self.assertEqual (r.line, '567890123456789') + + def test_delete_end_of_line (self): + r = ViModeTest () + r._set_line ('abc de fghi jkl mnopq rst uv wx yz') + r.input ('Escape') + r.input ('"0w"') + r.input ('"D"') + self.assertEqual (r.line, 'abc ') + + def test_two_lines (self): + r = ViModeTest () + r.input ('"abcdef"') + self.assertEqual (r.line, 'abcdef') + r.input ('Escape') + r.input ('"0iqq"') + self.assertEqual (r.line, 'qqabcdef') + r.input ('Return') + self.assertEqual (r.line, '') + r.input ('"xyz"') + self.assertEqual (r.line, 'xyz') + + def test_delete_word_short_to_end_of_line (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"03dw"') + self.assertEqual ('', r.line) + r._set_line ('abc def ghi ') + r.input ('Escape') + r.input ('"03dw"') + self.assertEqual ('', r.line) + + def test_delete_word_long_to_end_of_line (self): + r = ViModeTest () + r._set_line ('a.c d.f g.i') + r.input ('Escape') + r.input ('"03dW"') + self.assertEqual ('', r.line) + r._set_line ('a.c d.f g.i ') + r.input ('Escape') + r.input ('"03dW"') + self.assertEqual ('', r.line) + + def test_delete_end_short_to_end_of_line (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"03de"') + self.assertEqual ('', r.line) + r._set_line ('abc def ghi ') + r.input ('Escape') + r.input ('"03de"') + self.assertEqual (' ', r.line) + + def test_delete_end_long_to_end_of_line (self): + r = ViModeTest () + r._set_line ('a.c d.f g.i') + r.input ('Escape') + r.input ('"03dE"') + self.assertEqual ('', r.line) + r._set_line ('a.c d.f g.i ') + r.input ('Escape') + r.input ('"03dE"') + self.assertEqual (' ', r.line) + + def test_delete_back_short_to_begining_of_line (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"$3db"') + self.assertEqual ('i', r.line) + r._set_line ('abc def ghi ') + r.input ('Escape') + r.input ('"$3db"') + self.assertEqual (' ', r.line) + + def test_delete_back_long_to_begining_of_line (self): + r = ViModeTest () + r._set_line ('a.c d.f g.i') + r.input ('Escape') + r.input ('"$3dB"') + self.assertEqual ('i', r.line) + r._set_line ('a.c d.f g.i ') + r.input ('Escape') + r.input ('"$3dB"') + self.assertEqual (' ', r.line) + + def test_delete_dollar (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0ld$"') + self.assertEqual (r.line, 'a') + self.assertEqual (r.line_cursor, 0) + + def test_motion_left (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (10, r.line_cursor) + r.input ('"h"') + self.assertEqual (9, r.line_cursor) + r.input ('"2h"') + self.assertEqual (7, r.line_cursor) + r.input ('"2d3h"') + self.assertEqual (1, r.line_cursor) + self.assertEqual ('a ghi', r.line) + r.input ('"4dh"') + self.assertEqual (0, r.line_cursor) + self.assertEqual (' ghi', r.line) + + def test_motion_right (self): + r = ViModeTest () + r.input ('Escape') + self.assertEqual (r.line, '') + self.assertEqual (r.line_cursor, 0) + r.input ('"a"') + self.assertEqual (r.line, '') + self.assertEqual (r.line_cursor, 0) + r.input ('"abc"') + self.assertEqual (r.line, 'abc') + self.assertEqual (r.line_cursor, 3) + r.input ('Escape') + self.assertEqual (r.line, 'abc') + self.assertEqual (r.line_cursor, 2) + r.input ('"l"') + self.assertEqual (r.line, 'abc') + self.assertEqual (r.line_cursor, 2) + r.input ('Left') + self.assertEqual (r.line, 'abc') + self.assertEqual (r.line_cursor, 1) + r.input ('"l"') + self.assertEqual (r.line, 'abc') + self.assertEqual (r.line_cursor, 2) + r.input ('"l"') + self.assertEqual (r.line, 'abc') + self.assertEqual (r.line_cursor, 2) + + def test_motion_right_delete (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0"') + self.assertEqual (0, r.line_cursor) + r.input ('"l"') + self.assertEqual (1, r.line_cursor) + r.input ('"2l"') + self.assertEqual (3, r.line_cursor) + r.input ('"2d3l"') + self.assertEqual (3, r.line_cursor) + self.assertEqual ('abchi', r.line) + r.input ('"4dl"') + self.assertEqual (2, r.line_cursor) + self.assertEqual ('abc', r.line) + + def test_backspace_motion (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (10, r.line_cursor) + r.input ('BackSpace') + self.assertEqual (9, r.line_cursor) + r.input ('"2"') + r.input ('BackSpace') + self.assertEqual (7, r.line_cursor) + r.input ('"2d3"') + r.input ('BackSpace') + self.assertEqual (1, r.line_cursor) + self.assertEqual ('a ghi', r.line) + r.input ('"4d"') + r.input ('BackSpace') + self.assertEqual (0, r.line_cursor) + self.assertEqual (' ghi', r.line) + + def test_backspace_insert (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"$"') + self.assertEqual (10, r.line_cursor) + r.input ('"i"') + self.assertEqual (10, r.line_cursor) + r.input ('BackSpace') + self.assertEqual (9, r.line_cursor) + self.assertEqual ('abc def gi', r.line) + + def test_insert_lower_i (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0w"') + r.input ('"i"') + r.input ('"zz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'abc zzdef ghi') + r.input ('Escape') + r.input ('"w"') + r.input ('"2iyy"') + r.input ('Escape') + self.assertEqual (r.line, 'abc zzdef yyyyghi') + + def test_insert_upper_i (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0w"') + r.input ('"I"') + r.input ('"zz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'zzabc def ghi') + r.input ('Escape') + r.input ('"w"') + r.input ('"2Iyy"') + r.input ('Escape') + self.assertEqual (r.line, 'yyyyzzabc def ghi') + + def test_append_lower_a (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0"') + r.input ('"a"') + r.input ('"zz"') + self.assertEqual (r.line, 'azzbc def ghi') + self.assert_ (r.vi_is_insert_mode) + r.input ('Escape') + r.input ('"w"') + r.input ('"2ayy"') + r.input ('Escape') + self.assertEqual (r.line, 'azzbc dyyyyef ghi') + + def test_append_upper_a_simple (self): + r = ViModeTest () + r._set_line ('') + r.input ('Escape') + r.input ('"2A"') + r.input ('"jj"') + r.input ('Escape') + self.assertEqual (r.line, 'jjjj') + self.assert_ (not r.vi_is_insert_mode) + + def test_append_upper_a (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0"') + r.input ('"A"') + r.input ('"zz"') + self.assertEqual (r.line, 'abc def ghizz') + self.assert_ (r.vi_is_insert_mode) + r.input ('Escape') + r.input ('"0w"') + r.input ('"2Ayy"') + r.input ('Escape') + self.assertEqual (r.line, 'abc def ghizzyyyy') + + def test_delete_lower_x (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0w"') + r.input ('"x"') + self.assertEqual (r.line, 'abc ef') + r.input ('"4x"') + self.assertEqual (r.line, 'abc ') + self.assertEqual (r.line_cursor, 3) + r.input ('"x"') + self.assertEqual (r.line, 'abc') + self.assertEqual (r.line_cursor, 2) + r.input ('"x"') + self.assertEqual (r.line, 'ab') + self.assertEqual (r.line_cursor, 1) + r.input ('"x"') + self.assertEqual (r.line, 'a') + self.assertEqual (r.line_cursor, 0) + r.input ('"x"') + self.assertEqual (r.line, '') + self.assertEqual (r.line_cursor, 0) + r.input ('"x"') + self.assertEqual (r.line, '') + self.assertEqual (r.line_cursor, 0) + + def test_delete_upper_x (self): + r = ViModeTest () + r._set_line ('abc def') + self.assertEqual (r.line_cursor, 7) + r.input ('Escape') + self.assertEqual (r.line_cursor, 6) + r.input ('"$"') + self.assertEqual (r.line_cursor, 6) + r.input ('"X"') + self.assertEqual (r.line, 'abc df') + self.assertEqual (r.line_cursor, 5) + r.input ('"4X"') + self.assertEqual (r.line, 'af') + self.assertEqual (r.line_cursor, 1) + r.input ('"2X"') + self.assertEqual (r.line, 'f') + self.assertEqual (r.line_cursor, 0) + r.input ('"X"') + self.assertEqual (r.line, 'f') + self.assertEqual (r.line_cursor, 0) + + def test_substitute_lower_s (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0"') + r.input ('"s"') + r.input ('"qq"') + r.input ('Escape') + self.assertEqual (r.line, 'qqbc def') + self.assertEqual (r.line_cursor, 1) + r.input ('"3s"') + r.input ('"yyy"') + r.input ('Escape') + self.assertEqual (r.line, 'qyyy def') + self.assertEqual (r.line_cursor, 3) + r.input ('"w"') + r.input ('"5"') + r.input ('"s"') + r.input ('"zz"') + r.input ('Escape') + self.assertEqual (r.line, 'qyyy zz') + self.assertEqual (r.line_cursor, 6) + + def test_change_to_end_of_line (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0w"') + r.input ('"C"') + self.assert_ (r.vi_is_insert_mode) + r.input ('"123"') + self.assertEqual (r.line, 'abc 123') + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + + def test_change_whole_line (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0w"') + r.input ('"S"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, '') + r.input ('"123"') + self.assertEqual (r.line, '123') + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + + def test_change_word_short (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0cwzzz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'zzz def ghi') + self.assertEqual (r.line_cursor, 3) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 2) + r.input ('"w"') + self.assertEqual (r.line_cursor, 4) + r.input ('"2cwyyy"') + self.assertEqual (r.line, 'zzz yyy') + r.input ('Escape') + self.assertEqual (r.line, 'zzz yyy') + + def test_change_word_long (self): + r = ViModeTest () + r._set_line ('abc.def ghi.jkl mno.pqr') + r.input ('Escape') + r.input ('"0cWss"') + self.assertEqual (r.line, 'ss ghi.jkl mno.pqr') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 2) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 1) + r.input ('"w2."') + self.assertEqual (r.line, 'ss ss') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 4) + + def test_change_end_short (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0cezzz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'zzz def ghi') + self.assertEqual (r.line_cursor, 3) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 2) + r.input ('"w2."') + self.assertEqual (r.line, 'zzz zzz') + + def test_change_end_long (self): + r = ViModeTest () + r._set_line ('abc.def ghi jkl.mno pqr stu.vwx') + r.input ('Escape') + r.input ('"02cEzz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'zz jkl.mno pqr stu.vwx') + self.assertEqual (r.line_cursor, 2) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 1) + r.input ('"w2."') + self.assertEqual (r.line, 'zz zz stu.vwx') + self.assertEqual (r.line_cursor, 5) + + def test_change_back_short (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"$cbzz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'abc def zzi') + self.assertEqual (r.line_cursor, 10) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 9) + r.input ('"b2."') + self.assertEqual (r.line, 'zzzzi') + self.assertEqual (r.line_cursor, 2) + + def test_change_back_long (self): + r = ViModeTest () + r._set_line ('abc.def ghi jkl.mno pqr stu.vwx') + r.input ('Escape') + r.input ('"$2cBzz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'abc.def ghi jkl.mno zzx') + self.assertEqual (r.line_cursor, 22) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 21) + r.input ('"5."') + self.assertEqual (r.line, 'zzzx') + self.assertEqual (r.line_cursor, 2) + self.assert_ (not r.vi_is_insert_mode) + + def test_change_find_lower (self): + r = ViModeTest () + r._set_line ('aa bb cc dd ee aa bb cc dd ee') + r.input ('Escape') + r.input ('"0cfbzz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'zzb cc dd ee aa bb cc dd ee') + self.assertEqual (r.line_cursor, 2) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 1) + r.input ('"c2fcyy"') + self.assertEqual (r.line, 'zyy dd ee aa bb cc dd ee') + r.input ('Escape') + r.input ('"."') + self.assertEqual (r.line, 'zyyy dd ee') + + def test_change_find_upper (self): + r = ViModeTest () + r._set_line ('aa bb cc aa bb cc') + r.input ('Escape') + r.input ('"$2c2Fazz"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'zzc') + self.assertEqual (r.line_cursor, 2) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 1) + r.input ('"."') + self.assertEqual (r.line, 'zzc') + + def test_change_to_lower (self): + r = ViModeTest () + r._set_line ('aa bb cc aa bb cc aa bb cc') + r.input ('Escape') + r.input ('"02c2ta"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'aa bb cc') + self.assertEqual (r.line_cursor, 0) + r.input ('"zz "') + self.assertEqual (r.line, 'zz aa bb cc') + self.assertEqual (r.line_cursor, 3) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 2) + + def test_change_to_upper (self): + r = ViModeTest () + r._set_line ('aa bb cc aa bb cc aa bb cc') + r.input ('Escape') + r.input ('"$2c2Ta"') + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.line, 'aa bb cc ac') + self.assertEqual (r.line_cursor, 10) + r.input ('"zz"') + self.assertEqual (r.line, 'aa bb cc azzc') + self.assertEqual (r.line_cursor, 12) + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 11) + r.input ('"3."') + self.assertEqual (r.line, 'azzzc') + # The following fails but it does not seem that important + # self.assertEqual (r.line_cursor, 2) + self.assert_ (not r.vi_is_insert_mode) + + def test_pos_matching (self): + self.assertEqual (6, vi_pos_matching ('aa (bb)')) + self.assertEqual (6, vi_pos_matching ('aa (bb)', 3)) + self.assertEqual (3, vi_pos_matching ('aa (bb)', 6)) + self.assertEqual (11, vi_pos_matching ('aa (bb (cc))')) + self.assertEqual (3, vi_pos_matching ('aa (bb (cc))', 11)) + self.assertEqual (10, vi_pos_matching ('aa (bb (cc))', 4)) + self.assertEqual (7, vi_pos_matching ('aa (bb (cc))', 10)) + self.assertEqual (7, vi_pos_matching ('aa (bb (cc))', 8)) + self.assertEqual (3, vi_pos_matching ('aa (bb (cc) dd)', 12)) + self.assertEqual (3, vi_pos_matching ('aa (bb (cc) dd)', 14)) + self.assertEqual (-1, vi_pos_matching ('aa ((bb (cc) dd)', 3)) + self.assertEqual (-1, vi_pos_matching ('aa (bb (cc) dd) ee)', 16)) + self.assertEqual (-1, vi_pos_matching ('aa (bb (cc) dd) ee)', 18)) + self.assertEqual (6, vi_pos_matching ('aa ')) + self.assertEqual (11, vi_pos_matching ('aa >')) + self.assertEqual (10, vi_pos_matching ('aa >', 4)) + self.assertEqual (6, vi_pos_matching ('aa {bb}')) + self.assertEqual (11, vi_pos_matching ('aa {bb {cc}}')) + self.assertEqual (10, vi_pos_matching ('aa {bb {cc}}', 4)) + self.assertEqual (6, vi_pos_matching ('aa [bb]')) + self.assertEqual (11, vi_pos_matching ('aa [bb [cc]]')) + self.assertEqual (10, vi_pos_matching ('aa [bb [cc]]', 4)) + + def test_matching_paren_forward (self): + r = ViModeTest () + r._set_line ('abc (def (ghi)) jkl') + r.input ('Escape') + r.input ('"0w"') + r.input ('"d"') + r.input ('"%"') + self.assertEqual (r.line, 'abc jkl') + self.assertEqual (r.line_cursor, 4) + + def test_matching_paren_backward (self): + r = ViModeTest () + r._set_line ('abc (def (ghi)) jkl') + r.input ('Escape') + r.input ('"0w"') + r.input ('"%"') + self.assertEqual (r.line_cursor, 14) + r.input ('"d"') + r.input ('"%"') + self.assertEqual (r.line, 'abc jkl') + self.assertEqual (r.line_cursor, 4) + + def test_yank_and_put (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0"') + self.assert_ (not r.vi_is_insert_mode) + r.input ('"yw"') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line, 'abc def') + self.assertEqual (r.line_cursor, 0) + r.input ('"P"') + self.assertEqual (r.line, 'abc abc def') + self.assertEqual (r.line_cursor, 3) + r.input ('"p"') + self.assertEqual (r.line, 'abc abc abc def') + self.assertEqual (r.line_cursor, 7) + + def test_put_multiple (self): + r = ViModeTest () + r._set_line ('001122') + r.input ('Escape') + r.input ('"0"') + r.input ('"y3l"') + self.assert_ (not r.vi_is_insert_mode) + self.assertEqual (r.line_cursor, 0) + r.input ('"2P"') + self.assertEqual (r.line, '001001001122') + self.assertEqual (r.line_cursor, 5) + r.input ('"f2"') + r.input ('"3p"') + self.assertEqual (r.line, '001001001120010010012') + self.assertEqual (r.line_cursor, 19) + + def test_put_undo (self): + r = ViModeTest () + r._set_line ('aaa b ccc') + r.input ('Escape') + r.input ('"0ywwp"') + self.assertEqual (r.line, 'aaa baaa ccc') + r.input ('"u"') + self.assertEqual (r.line, 'aaa b ccc') + r.input ('"P"') + self.assertEqual (r.line, 'aaa aaa b ccc') + r.input ('"u"') + self.assertEqual (r.line, 'aaa b ccc') + + def test_x_and_p (self): + r = ViModeTest () + r._set_line ('abc') + r.input ('Escape') + r.input ('"0xp"') + self.assertEqual (r.line, 'bac') + + def test_delete_and_put (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0dwep"') + self.assertEqual (r.line, 'defabc ') + r.input ('"0xp"') + self.assertEqual (r.line, 'edfabc ') + r.input ('"p"') + self.assertEqual (r.line, 'eddfabc ') + + def test_dot_simple (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0x"') + self.assertEqual (r.line, 'bc def') + r.input ('"."') + self.assertEqual (r.line, 'c def') + r.input ('"3."') + self.assertEqual (r.line, 'ef') + + def test_dot_movement_not_repeated_one (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0x"') + self.assertEqual (r.line, 'bc def') + r.input ('"$."') + self.assertEqual (r.line, 'bc de') + r.input ('"0."') + self.assertEqual (r.line, 'c de') + r.input ('"$."') + self.assertEqual (r.line, 'c d') + r.input ('"^."') + self.assertEqual (r.line, ' d') + + def test_dot_movement_not_repeated_two (self): + r = ViModeTest () + r._set_line ('abc def ghi jkl mno pqr') + r.input ('Escape') + r.input ('"0x"') + self.assertEqual (r.line, 'bc def ghi jkl mno pqr') + r.input ('"w."') + self.assertEqual (r.line, 'bc ef ghi jkl mno pqr') + r.input ('"fg."') + self.assertEqual (r.line, 'bc ef hi jkl mno pqr') + r.input ('"2b."') + self.assertEqual (r.line, 'c ef hi jkl mno pqr') + r.input ('"3e."') + self.assertEqual (r.line, 'c ef hi jk mno pqr') + r.input ('"Fh."') + self.assertEqual (r.line, 'c ef i jk mno pqr') + r.input ('"tn."') + self.assertEqual (r.line, 'c ef i jk no pqr') + r.input ('"3h."') + self.assertEqual (r.line, 'c ef i k no pqr') + r.input ('"5l."') + self.assertEqual (r.line, 'c ef i k no qr') + + def test_dot_insert (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0"') + r.input ('"2izz "') + r.input ('Escape') + self.assertEqual (r.line, 'zz zz abc def') + r.input ('"2w."') + self.assertEqual (r.line, 'zz zz abc zz zz def') + + def test_dot_delete_word (self): + r = ViModeTest () + r._set_line ('0 1 2 3 4 5 6 7 8 9') + r.input ('Escape') + r.input ('"02dw"') + self.assertEqual (r.line, '2 3 4 5 6 7 8 9') + r.input ('"."') + self.assertEqual (r.line, '4 5 6 7 8 9') + r.input ('"1."') + self.assertEqual (r.line, '5 6 7 8 9') + + def test_dot_override_multiplier (self): + r = ViModeTest () + r._set_line ('ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab') + r.input ('Escape') + r.input ('"02d2fb"') + self.assertEqual (r.line, ' ab ab ab ab ab ab ab ab ab ab ab ab') + r.input ('"."') + self.assertEqual (r.line, ' ab ab ab ab ab ab ab ab') + r.input ('"3."') + self.assertEqual (r.line, ' ab ab ab ab ab') + r.input ('"."') + self.assertEqual (r.line, ' ab ab') + + def test_dot_yank_and_put (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0ywP"') + self.assertEqual (r.line, 'abc abc def') + r.input ('"."') + self.assertEqual (r.line, 'abcabc abc def') + r.input ('"p"') + self.assertEqual (r.line, 'abcabc abc abc def') + r.input ('"2."') + self.assertEqual (r.line, 'abcabc abc abc abc abc def') + + def test_dot_insert_begin (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"Izz "') + r.input ('Escape') + self.assertEqual (r.line, 'zz abc def') + r.input ('"."') + self.assertEqual (r.line, 'zz zz abc def') + r.input ('"2."') + self.assertEqual (r.line, 'zz zz zz zz abc def') + + def test_dot_append_end (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"A yy"') + r.input ('Escape') + self.assertEqual (r.line, 'abc def yy') + r.input ('"."') + self.assertEqual (r.line, 'abc def yy yy') + r.input ('"2."') + self.assertEqual (r.line, 'abc def yy yy yy yy') + + def test_dot_insert_lower (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"b2izz "') + r.input ('Escape') + self.assertEqual (r.line, 'abc zz zz def') + r.input ('"3."') + self.assertEqual (r.line, 'abc zz zzzz zz zz def') + + def test_dot_append_lower (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"0e2a zz"') + r.input ('Escape') + self.assertEqual (r.line, 'abc zz zz def') + r.input ('"1."') + self.assertEqual (r.line, 'abc zz zz zz def') + + def test_dot_substitute_lower (self): + r = ViModeTest () + r._set_line ('abc def') + r.input ('Escape') + r.input ('"03sqq"') + r.input ('Escape') + self.assertEqual (r.line, 'qq def') + r.input ('"2."') + self.assertEqual (r.line, 'qqqdef') + + def test_undo (self): + r = ViModeTest () + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"0wdw"') + self.assertEqual (r.line, 'abc ghi') + self.assertEqual (r.line_cursor, 4) + r.input ('"u"') + self.assertEqual (r.line, 'abc def ghi') + self.assertEqual (r.line_cursor, 4) + + def test_undo_line (self): + r = ViModeTest () + r._set_line ('') + r.input ('"abc def ghi"') + r.input ('Escape') + r.input ('"0dwdw"') + self.assertEqual (r.line, 'ghi') + r.input ('"U"') + self.assertEqual (r.line, '') + + def test_undo_line_with_history (self): + r = ViModeTest () + r.add_history ('abc 123') + r._set_line ('') + r.input ('"abc def ghi"') + r.input ('Escape') + r.input ('"0dwdw"') + self.assertEqual (r.line, 'ghi') + r.input ('"U"') + self.assertEqual (r.line, '') + + def test_history_no_match (self): + r = ViModeTest () + r.add_history ('abc 123') + r.add_history ('def 456') + r.add_history ('ghi 789') + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"/"') + self.assertEqual (r.line, '/') + self.assertEqual (r.line_cursor, 1) + r.input ('"zz"') + self.assertEqual (r.line, '/zz') + self.assertEqual (r.line_cursor, 3) + self.assertEqual (r.console.bell_count, 0) + r.input ('Return') + # TODO should bell be rung here? + # self.assertEqual (r.console.bell_count, 1) + self.assertEqual (r.line, 'abc def ghi') + self.assertEqual (r.line_cursor, 10) + + def test_history_found_match (self): + r = ViModeTest () + r.add_history ('abc 123') + r.add_history ('def 456') + r.add_history ('ghi 789') + r._set_line ('abc def ghi') + r.input ('Escape') + r.input ('"/"') + self.assertEqual (r.line, '/') + self.assertEqual (r.line_cursor, 1) + r.input ('"de"') + self.assertEqual (r.line, '/de') + self.assertEqual (r.line_cursor, 3) + r.input ('Return') + self.assertEqual (r.line, 'def 456') + self.assertEqual (r.line_cursor, 0) + + def test_history_multi_match (self): + r = ViModeTest () + r.add_history ('xyz 123') + r.add_history ('xyz 456') + r.add_history ('xyz 789') + r._set_line ('abc def') + r.input ('Escape') + r.input ('"/xyz"') + r.input ('Return') + self.assertEqual (r.line, 'xyz 789') + r.input ('"n"') + self.assertEqual (r.line, 'xyz 456') + r.input ('"n"') + self.assertEqual (r.line, 'xyz 123') + self.assertEqual (r.console.bell_count, 0) + r.input ('"n"') + # TODO check bell ringing + # self.assertEqual (r.console.bell_count, 1) + self.assertEqual (r.line, 'xyz 123') + r.input ('"N"') + self.assertEqual (r.line, 'xyz 456') + r.input ('"N"') + self.assertEqual (r.line, 'xyz 789') + # TODO check bell ringing + # self.assertEqual (r.console.bell_count, 1) + r.input ('"N"') + # TODO check bell ringing + # self.assertEqual (r.console.bell_count, 2) + self.assertEqual (r.line, 'xyz 789') + + def test_history_search_empty_string (self): + r = ViModeTest () + r.add_history ('xyz 123') + r.add_history ('xyz 456') + r.add_history ('xyz 789') + r.input ('Escape') + r.input ('"/"') + r.input ('Return') + self.assertEqual (r.line, '') + # TODO check bell ringing + # self.assertEqual (r.console.bell_count, 1) + r.input ('"/"') + r.input ('Return') + self.assertEqual (r.line, '') + # TODO check bell ringing + # self.assertEqual (r.console.bell_count, 2) + r.input ('"/x"') + r.input ('Return') + self.assertEqual (r.line, 'xyz 789') + r.input ('"/"') + r.input ('Return') + self.assertEqual (r.line, 'xyz 456') + + def test_history_search_again_after_return (self): + r = ViModeTest () + r.add_history ('xyz 123') + r.add_history ('xyz 456') + r.add_history ('xyz 789') + r._set_line ('abc def') + r.input ('Escape') + r.input ('"/xyz"') + r.input ('Return') + self.assertEqual (r.line, 'xyz 789') + r.input ('"n"') + self.assertEqual (r.line, 'xyz 456') + r.input ('Return') + self.assertEqual (r.line, '') + r.input ('Escape') + r.input ('"n"') + self.assertEqual (r.line, 'xyz 123') + r.input ('Return') + r.input ('Escape') + r.input ('"N"') + self.assertEqual (r.line, 'xyz 456') + + def test_history_search_again_after_search_failed (self): + r = ViModeTest () + r.add_history ('xyz 123') + r.add_history ('xyz 456') + r.add_history ('xyz 789') + r._set_line ('abc def') + r.input ('Escape') + r.input ('"/xyz"') + r.input ('Return') + self.assertEqual (r.line, 'xyz 789') + r.input ('"C"') + self.assertEqual (r.line, '') + r.input ('Escape') + self.assertEqual (r.console.bell_count, 0) + r.input ('"/abc"') + r.input ('Return') + # TODO check bell ringing + # self.assertEqual (r.console.bell_count, 1) + self.assertEqual (r.line, '') + r.input ('Escape') + r.input ('"n"') + self.assertEqual (r.line, '') + + def test_history_search_and_backspace (self): + r = ViModeTest () + r.add_history ('aaa') + r.add_history ('bbb') + r._set_line ('') + r.input ('Escape') + r.input ('"/aaz"') + self.assertEqual (r.line, '/aaz') + r.input ('BackSpace') + self.assertEqual (r.line, '/aa') + r.input ('Return') + self.assertEqual (r.line, 'aaa') + r.input ('Escape') + r.input ('"/z"') + r.input ('BackSpace') + r.input ('BackSpace') + self.assertEqual (r.line, '') + r.input ('"j"') + self.assertEqual (r.line, 'bbb') + r.input ('"k"') + self.assertEqual (r.line, 'aaa') + + def test_history_insert_mode (self): + r = ViModeTest () + r.add_history ('aaa') + r.add_history ('bbb') + r.add_history ('ccc') + r.input ('Up') + self.assertEqual (r.line, 'ccc') + self.assert_ (r.vi_is_insert_mode) + r.input ('"z"') + self.assertEqual (r.line, 'cccz') + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + r.input ('Up') + self.assertEqual (r.line, 'bbb') + self.assert_ (r.vi_is_insert_mode) + r.input ('"z"') + self.assertEqual (r.line, 'bbbz') + r.input ('Escape') + r.input ('"k"') + self.assertEqual (r.line, 'aaa') + self.assert_ (not r.vi_is_insert_mode) + r.input ('"iz"') + self.assertEqual (r.line, 'zaaa') + r.input ('Down') + self.assertEqual (r.line, 'bbb') + self.assert_ (r.vi_is_insert_mode) + r.input ('"y"') + self.assertEqual (r.line, 'bbby') + r.input ('Escape') + r.input ('"j"') + self.assertEqual (r.line, 'ccc') + self.assert_ (not r.vi_is_insert_mode) + r.input ('"iy"') + self.assertEqual (r.line, 'yccc') + self.assert_ (r.vi_is_insert_mode) + + def test_history_cursor_arrow (self): + r = ViModeTest () + self.assertEqual (r._history.history_cursor, 0) + r.add_history ('aaa') + self.assertEqual (r._history.history_cursor, 1) + r.add_history ('bbb') + self.assertEqual (r._history.history_cursor, 2) + self.assertEqual (r.line, '') + r.input ('Up') + self.assertEqual (r._history.history_cursor, 1) + self.assertEqual (r.line, 'bbb') + r.input ('Up') + self.assertEqual (r._history.history_cursor, 0) + self.assertEqual (r.line, 'aaa') + r.input ('Down') + self.assertEqual (r._history.history_cursor, 1) + self.assertEqual (r.line, 'bbb') + r.input ('Down') + self.assertEqual (r._history.history_cursor, 2) + self.assertEqual (r.line, '') + r.input ('Up') + self.assertEqual (r._history.history_cursor, 1) + self.assertEqual (r.line, 'bbb') + + def test_history_control_n_and_p (self): + r = ViModeTest () + r.add_history ('aa') + r.add_history ('bbb') + self.assertEqual (r.line, '') + r.input ('Control-p') + self.assertEqual (r.line, 'bbb') + self.assertEqual (r.line_cursor, 3) + self.assert_ (r.vi_is_insert_mode) + r.input ('Control-p') + self.assertEqual (r.line, 'aa') + self.assertEqual (r.line_cursor, 2) + self.assert_ (r.vi_is_insert_mode) + r.input ('Control-n') + self.assertEqual (r.line, 'bbb') + self.assertEqual (r.line_cursor, 3) + self.assert_ (r.vi_is_insert_mode) + r.input ('Control-n') + self.assertEqual (r.line, '') + self.assertEqual (r.line_cursor, 0) + self.assert_ (r.vi_is_insert_mode) + r.input ('Control-p') + self.assertEqual (r.line, 'bbb') + self.assertEqual (r.line_cursor, 3) + self.assert_ (r.vi_is_insert_mode) + r.input ('Escape') + self.assertEqual (r.line, 'bbb') + self.assertEqual (r.line_cursor, 2) + self.assert_ (not r.vi_is_insert_mode) + r.input ('Control-p') + self.assertEqual (r.line, 'aa') + self.assertEqual (r.line_cursor, 0) + self.assert_ (not r.vi_is_insert_mode) + r.input ('Control-n') + self.assertEqual (r.line, 'bbb') + self.assertEqual (r.line_cursor, 0) + self.assert_ (not r.vi_is_insert_mode) + r.input ('Control-n') + self.assertEqual (r.line, '') + self.assertEqual (r.line_cursor, 0) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"/a"') + r.input ('Return') + self.assertEqual (r.line, 'aa') + self.assertEqual (r.line_cursor, 0) + self.assert_ (not r.vi_is_insert_mode) + r.input ('Control-n') + self.assertEqual (r.line, 'bbb') + self.assertEqual (r.line_cursor, 0) + self.assert_ (not r.vi_is_insert_mode) + + def test_history_cursor_j_and_k (self): + r = ViModeTest () + r.add_history ('aaa') + r.input ('Escape') + r.input ('"kiz"') + self.assertEqual (r.line, 'zaaa') + r.input ('Escape') + r.input ('"j"') + self.assertEqual (r.line, '') + + def test_history_input_j_and_k (self): + r = ViModeTest () + r.add_history ('aaa') + r.input ('Escape') + r.input ('"kAjk"') + self.assertEqual (r.line, 'aaajk') + + def test_history_cursor_search (self): + r = ViModeTest () + r.add_history ('aaa') + r.input ('Escape') + r.input ('"/a"') + r.input ('Return') + self.assertEqual (r.line, 'aaa') + r.input ('"iz"') + self.assertEqual (r.line, 'zaaa') + self.assertEqual (r.console.bell_count, 0) + r.input ('Escape') + r.input ('"j"') + self.assertEqual (r.line, 'zaaa') + # TODO check bell ringing + # self.assertEqual (r.console.bell_count, 1) + + def test_history_undo (self): + r = ViModeTest () + r.add_history ('aaa') + r.input ('Escape') + r.input ('"k"') + r.input ('"A b"') + r.input ('Escape') + r.input ('"A c"') + r.input ('Escape') + self.assertEqual (r.line, 'aaa b c') + r.input ('"U"') + self.assertEqual (r.line, 'aaa') + + def test_history_arrow_undo (self): + r = ViModeTest () + r.add_history ('aaa') + r.input ('Up') + r.input ('" zz"') + self.assertEqual (r.line, 'aaa zz') + r.input ('Escape') + r.input ('"u"') + self.assertEqual (r.line, 'aaa') + +# TODO: mode support? +# def test_mode (self): +# r = ViModeTest () +# self.assertEqual (r.editing_mode, Readline.mode_vi) +# self.assertEqual (r.mode (verbose=False), Readline.mode_vi) +# self.assertEqual (r.count_vi_editing_mode, 1) +# self.assertEqual (r.count_emacs_editing_mode, 0) +# r.vi () +# self.assertEqual (r.editing_mode, Readline.mode_vi) +# self.assertEqual (r.mode (verbose=False), Readline.mode_vi) +# self.assertEqual (r.count_vi_editing_mode, 1) +# self.assertEqual (r.count_emacs_editing_mode, 0) +# r.emacs () +# self.assertEqual (r.editing_mode, Readline.mode_emacs) +# self.assertEqual (r.mode (verbose=False), Readline.mode_emacs) +# self.assertEqual (r.count_vi_editing_mode, 1) +# self.assertEqual (r.count_emacs_editing_mode, 1) +# r.emacs () +# self.assertEqual (r.editing_mode, Readline.mode_emacs) +# self.assertEqual (r.mode (verbose=False), Readline.mode_emacs) +# self.assertEqual (r.count_vi_editing_mode, 1) +# self.assertEqual (r.count_emacs_editing_mode, 1) +# r.vi () +# self.assertEqual (r.editing_mode, Readline.mode_vi) +# self.assertEqual (r.mode (verbose=False), Readline.mode_vi) +# self.assertEqual (r.count_vi_editing_mode, 2) +# self.assertEqual (r.count_emacs_editing_mode, 1) +# +# def test_switch_mode (self): +# r = ViModeTest () +# r._set_line ('') +# r.input ('Escape') +# self.assertEqual (r.editing_mode, Readline.mode_vi) +# self.assertEqual (r.count_vi_editing_mode, 1) +# self.assertEqual (r.count_emacs_editing_mode, 0) +# r.input ('"abc"') +# r.input ('Control-e') +# self.assertEqual (r.editing_mode, Readline.mode_emacs) +# self.assertEqual (r.count_vi_editing_mode, 1) +# self.assertEqual (r.count_emacs_editing_mode, 1) +# r.input ('Meta-Control-j') +# self.assertEqual (r.editing_mode, Readline.mode_vi) +# self.assertEqual (r.count_vi_editing_mode, 2) +# self.assertEqual (r.count_emacs_editing_mode, 1) + +# TODO: show history support? +# def test_history_output (self): +# import StringIO +# sio = StringIO.StringIO () +# r = ViModeTest () +# r.add_history ('abc') +# r.add_history ('def') +# r.add_history ('ghi') +# r.show_history (sio) +# sio.seek (0) +# self.assertEqual (sio.read(), ' 1 abc\n 2 def\n 3 ghi\n') + + def test_editor (self): + vee = ViExternalEditorTest ('qwerty before') + self.assert_ (vee.sio_write.closed) + self.assertEqual (vee.command, 'vim.exe temp.py') + self.assert_ (vee.sio_read.closed) + self.assertEqual (vee.remove, 'temp.py') + self.assertEqual (vee.result, 'qwerty after') + + def test_completer (self): + r = ViModeTest () + r.lst_completions = ['aab', 'aac', 'aad', ] + r.input ('"aa"') + r.input ('Tab') + self.assertEqual (r.line, 'aa') + self.assertEqual (r.console.text, '\naab \naac \naad \n') + + def test_completer_star (self): + r = ViModeTest () + r.lst_completions = ['bbc', 'bbd', 'bbe', ] + r.input ('"aa bb"') + r.input ('Escape') + self.assert_ (not r.vi_is_insert_mode) + r.input ('"*"') + self.assertEqual (r.line, 'aa bbc bbd bbe ') + self.assertEqual (r.line_cursor, 15) + self.assert_ (r.vi_is_insert_mode) + self.assertEqual (r.console.text, '') + r.input ('" "') + r.input ('Escape') + self.assertEqual (r.line, 'aa bbc bbd bbe ') + self.assertEqual (r.line_cursor, 15) + r.input ('"."') + self.assertEqual (r.line, 'aa bbc bbd bbe bbc bbd bbe ') + self.assertEqual (r.line_cursor, 27) + + def test_completer_beginning_of_line (self): + r = ViModeTest () + r.input ('Tab') + self.assertEqual (r.line, ' ') + self.assertEqual (r.line_cursor, 4) + r.input ('Space') + self.assertEqual (r.line, ' ') + self.assertEqual (r.line_cursor, 5) + r.input ('Tab') + self.assertEqual (r.line, ' ') + self.assertEqual (r.line_cursor, 8) + r.input ('Space') + r.input ('Space') + r.input ('Space') + self.assertEqual (r.line, ' ') + self.assertEqual (r.line_cursor, 11) + r.input ('Tab') + self.assertEqual (r.line, ' ') + self.assertEqual (r.line_cursor, 12) + r.input ('Tab') + self.assertEqual (r.line, ' ') + self.assertEqual (r.line_cursor, 16) + + def test_replace_lower (self): + r = ViModeTest () + r._set_line ('aaa bbb ccc') + r.input ('Escape') + r.input ('"0ry"') + self.assertEqual (r.line, 'yaa bbb ccc') + self.assertEqual (r.line_cursor, 0) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"i"') + self.assertEqual (r.line, 'yaa bbb ccc') + self.assertEqual (r.line_cursor, 0) + self.assert_ (r.vi_is_insert_mode) + r.input ('"x"') + self.assertEqual (r.line, 'xyaa bbb ccc') + self.assertEqual (r.line_cursor, 1) + self.assert_ (r.vi_is_insert_mode) + r.input ('Escape') + self.assertEqual (r.line, 'xyaa bbb ccc') + self.assertEqual (r.line_cursor, 0) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"ll"') + r.input ('"2rz"') + self.assertEqual (r.line, 'xyzz bbb ccc') + self.assertEqual (r.line_cursor, 3) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"w7."') + self.assertEqual (r.line, 'xyzz zzzzzzz') + self.assertEqual (r.line_cursor, 11) + self.assert_ (not r.vi_is_insert_mode) + + def test_replace_lower_undo (self): + r = ViModeTest () + r._set_line ('aaa') + r.input ('Escape') + # print 'xx', sys._getframe().f_lineno, r._vi_undo_cursor, r._vi_undo_stack + r.input ('"0rz"') + self.assertEqual (r.line, 'zaa') + r.input ('"u"') + self.assertEqual (r.line, 'aaa') + r.input ('"2."') + self.assertEqual (r.line, 'zza') + r.input ('"u"') + self.assertEqual (r.line, 'aaa') + + def test_replace_lower_escape (self): + r = ViModeTest () + r._set_line ('aaa') + r.input ('Escape') + r.input ('"0r"') + self.assertEqual (r.line, 'aaa') + r.input ('Escape') + self.assertEqual (r.line, 'aaa') + r.input ('"r"') + self.assertEqual (r.line, 'aaa') + r.input ('"z"') + self.assertEqual (r.line, 'zaa') + + def test_replace_lower_escape_undo (self): + r = ViModeTest () + r._set_line ('aa bb cc') + r.input ('Escape') + r.input ('"0cwdd"') + r.input ('Escape') + self.assertEqual (r.line, 'dd bb cc') + r.input ('"wr"') + r.input ('Escape') + self.assertEqual (r.line, 'dd bb cc') + r.input ('"."') + self.assertEqual (r.line, 'dd dd cc') + r.input ('"u"') + self.assertEqual (r.line, 'dd bb cc') + r.input ('"u"') + self.assertEqual (r.line, 'aa bb cc') + + def test_replace_dot (self): + r = ViModeTest () + r._set_line ('ab') + r.input ('Escape') + r.input ('"0rzl"') + self.assertEqual (r.line, 'zb') + self.assertEqual (r.line_cursor, 1) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"r."') + self.assertEqual (r.line, 'z.') + self.assertEqual (r.line_cursor, 1) + self.assert_ (not r.vi_is_insert_mode) + + def test_replace_upper (self): + r = ViModeTest () + r._set_line ('aaa bbb') + r.input ('Escape') + r.input ('"0wR"') + self.assertEqual (r.line, 'aaa bbb') + self.assertEqual (r.line_cursor, 4) + self.assert_ (r.vi_is_insert_mode) + r.input ('"z"') + self.assertEqual (r.line, 'aaa zbb') + self.assertEqual (r.line_cursor, 5) + self.assert_ (r.vi_is_insert_mode) + r.input ('"zzz"') + self.assertEqual (r.line, 'aaa zzzz') + self.assertEqual (r.line_cursor, 8) + self.assert_ (r.vi_is_insert_mode) + r.input ('Escape') + self.assertEqual (r.line_cursor, 7) + self.assert_ (not r.vi_is_insert_mode) + + def test_replace_upper_dot (self): + r = ViModeTest () + r._set_line ('aaa bbb ccc ddd') + r.input ('Escape') + r.input ('"02Rz"') + r.input ('Escape') + self.assertEqual (r.line, 'zza bbb ccc ddd') + self.assertEqual (r.line_cursor, 1) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"w."') + self.assertEqual (r.line, 'zza zzb ccc ddd') + self.assertEqual (r.line_cursor, 5) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"w6."') + self.assertEqual (r.line, 'zza zzb zzzzzzd') + self.assertEqual (r.line_cursor, 13) + self.assert_ (not r.vi_is_insert_mode) + + def test_replace_upper_undo (self): + r = ViModeTest () + r._set_line ('aaa bbb ccc') + r.input ('Escape') + r.input ('"0Rzz"') + r.input ('Escape') + self.assertEqual (r.line, 'zza bbb ccc') + r.input ('"w3."') + self.assertEqual (r.line, 'zza zzzzzzc') + r.input ('"u"') + self.assertEqual (r.line, 'zza bbb ccc') + r.input ('"u"') + self.assertEqual (r.line, 'aaa bbb ccc') + + def test_replace_backspace_and_dot (self): + r = ViModeTest () + r._set_line ('aa bb') + r.input ('Escape') + r.input ('"0wRc"') + self.assertEqual (r.line, 'aa cb') + self.assertEqual (r.line_cursor, 4) + self.assert_ (r.vi_is_insert_mode) + r.input ('"c"') + self.assertEqual (r.line, 'aa cc') + self.assertEqual (r.line_cursor, 5) + r.input ('"c"') + self.assertEqual (r.line, 'aa ccc') + self.assertEqual (r.line_cursor, 6) + r.input ('BackSpace') + self.assertEqual (r.line, 'aa cc') + self.assertEqual (r.line_cursor, 5) + self.assert_ (r.vi_is_insert_mode) + r.input ('BackSpace') + self.assertEqual (r.line, 'aa cb') + self.assertEqual (r.line_cursor, 4) + self.assert_ (r.vi_is_insert_mode) + r.input ('BackSpace') + self.assertEqual (r.line, 'aa bb') + self.assertEqual (r.line_cursor, 3) + self.assert_ (r.vi_is_insert_mode) + r.input ('BackSpace') + self.assertEqual (r.line, 'aa bb') + self.assertEqual (r.line_cursor, 2) + self.assert_ (r.vi_is_insert_mode) + r.input ('"d"') + self.assertEqual (r.line, 'aadbb') + self.assertEqual (r.line_cursor, 3) + self.assert_ (r.vi_is_insert_mode) + r.input ('Escape') + self.assertEqual (r.line, 'aadbb') + self.assertEqual (r.line_cursor, 2) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"u"') + self.assertEqual (r.line, 'aa bb') + self.assertEqual (r.line_cursor, 3) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"hh"') + r.input ('"."') + self.assertEqual (r.line, 'da bb') + self.assert_ (not r.vi_is_insert_mode) + + def test_yank_line (self): + r = ViModeTest () + r._set_line ('aa bb') + r.input ('Escape') + r.input ('"0wY"') + self.assertEqual (r.line, 'aa bb') + self.assert_ (not r.vi_is_insert_mode) + r.input ('"P"') + self.assertEqual (r.line, 'aa aa bbbb') + self.assert_ (not r.vi_is_insert_mode) + r.input ('"u"') + self.assertEqual (r.line, 'aa bb') + self.assert_ (not r.vi_is_insert_mode) + + def test_column (self): + r = ViModeTest () + r._set_line ('aaa bbb') + r.input ('Escape') + r.input ('"099|"') + self.assertEqual (r.line, 'aaa bbb') + self.assertEqual (r.line_cursor, 6) + r.input ('"4|"') + self.assertEqual (r.line, 'aaa bbb') + self.assertEqual (r.line_cursor, 3) + r.input ('"d1|"') + self.assertEqual (r.line, ' bbb') + self.assertEqual (r.line_cursor, 0) + r.input ('"u"') + self.assertEqual (r.line, 'aaa bbb') + self.assertEqual (r.line_cursor, 3) + r.input ('"d7|"') + self.assertEqual (r.line, 'aaab') + self.assertEqual (r.line_cursor, 3) + + def test_change_case (self): + r = ViModeTest () + r._set_line ('aaa B7B ccc') + r.input ('Escape') + r.input ('"0~"') + self.assertEqual (r.line, 'Aaa B7B ccc') + self.assertEqual (r.line_cursor, 1) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"h."') + self.assertEqual (r.line, 'aaa B7B ccc') + self.assertEqual (r.line_cursor, 1) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"9~"') + self.assertEqual (r.line, 'aAA b7b CCc') + self.assertEqual (r.line_cursor, 10) + self.assert_ (not r.vi_is_insert_mode) + r.input ('"u"') + self.assertEqual (r.line, 'aaa B7B ccc') + self.assertEqual (r.line_cursor, 1) + self.assert_ (not r.vi_is_insert_mode) + + def test_redo (self): + r = ViModeTest () + r._set_line ('') + r.input ('Escape') + r.input ('"Saaa"') + self.assertEqual (r.line, 'aaa') + r.input ('Escape') + r.input ('"Sbbb"') + self.assertEqual (r.line, 'bbb') + r.input ('Escape') + r.input ('"Sccc"') + r.input ('Escape') + self.assertEqual (r.line, 'ccc') + r.input ('"u"') + self.assertEqual (r.line, 'bbb') + r.input ('Control-r') + self.assertEqual (r.line, 'ccc') + r.input ('"u"') + self.assertEqual (r.line, 'bbb') + r.input ('"u"') + self.assertEqual (r.line, 'aaa') + r.input ('"u"') + self.assertEqual (r.line, '') + r.input ('"u"') + self.assertEqual (r.line, '') + r.input ('Control-r') + self.assertEqual (r.line, 'aaa') + r.input ('Control-r') + self.assertEqual (r.line, 'bbb') + r.input ('Control-r') + self.assertEqual (r.line, 'ccc') + r.input ('Control-r') + self.assertEqual (r.line, 'ccc') + r.input ('"u"') + self.assertEqual (r.line, 'bbb') + r.input ('"Szzz"') + r.input ('Escape') + self.assertEqual (r.line, 'zzz') + r.input ('"u"') + self.assertEqual (r.line, 'bbb') + r.input ('Control-r') + self.assertEqual (r.line, 'zzz') + r.input ('"U"') + self.assertEqual (r.line, '') + r.input ('Control-r') + self.assertEqual (r.line, 'aaa') + r.input ('Control-r') + self.assertEqual (r.line, 'bbb') + r.input ('Control-r') + self.assertEqual (r.line, 'zzz') + r.input ('Control-r') + self.assertEqual (r.line, 'zzz') + +#---------------------------------------------------------------------- +# utility functions + +class Event: + def __init__ (self, char): + self.char = char + +def keytext_to_keyinfo_and_event (keytext): + keyinfo = keysyms.key_text_to_keyinfo (keytext) + if len(keytext) == 3 and keytext[0] == '"' and keytext[2] == '"': + event = Event (keytext[1]) + else: + event = Event (chr (keyinfo [3])) + return keyinfo, event + +#---------------------------------------------------------------------- + +if __name__ == '__main__': + unittest.main() +