Blob Blame History Raw
#190350: vi mode glitch

Whenever you do some non-inserting edit command, like 'x' or 'd',
that becomes the command-to-repeat and no further insertions may be repeated.

1. Start a new bash shell
2. 'set -o vi'
2. Type 'kekepop<esc>hxi\<esc>.'
3. You end up with 'kekepp' instead of 'kekep\\p'.

This patch fixes it and tries to fix redoing the 'I' command as well.
I'm not sure about 'c', though.

Signed-off-by: Tomas Janousek <tomi@nomi.cz>
---
 lib/readline/misc.c      |    2 +-
 lib/readline/readline.c  |    2 +-
 lib/readline/readline.h  |    1 +
 lib/readline/vi_keymap.c |    2 +-
 lib/readline/vi_mode.c   |   21 +++++++++++++++++++--
 5 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/lib/readline/misc.c b/lib/readline/misc.c
index e9c72c5..35d6348 100644
--- a/lib/readline/misc.c
+++ b/lib/readline/misc.c
@@ -560,7 +560,7 @@ rl_vi_editing_mode (count, key)
 #if defined (VI_MODE)
   _rl_set_insert_mode (RL_IM_INSERT, 1);	/* vi mode ignores insert mode */
   rl_editing_mode = vi_mode;
-  rl_vi_insertion_mode (1, key);
+  rl_vi_insert_mode (1, key);
 #endif /* VI_MODE */
 
   return 0;
diff --git a/lib/readline/readline.c b/lib/readline/readline.c
index bd4d263..4b3d91b 100644
--- a/lib/readline/readline.c
+++ b/lib/readline/readline.c
@@ -370,7 +370,7 @@ readline_internal_setup ()
 
 #if defined (VI_MODE)
   if (rl_editing_mode == vi_mode)
-    rl_vi_insertion_mode (1, 'i');
+    rl_vi_insert_mode (1, 'i');
 #endif /* VI_MODE */
 
   if (rl_pre_input_hook)
diff --git a/lib/readline/readline.h b/lib/readline/readline.h
index b71bf98..8527ebf 100644
--- a/lib/readline/readline.h
+++ b/lib/readline/readline.h
@@ -230,6 +230,7 @@ extern int rl_vi_next_word PARAMS((int, int));
 extern int rl_vi_end_word PARAMS((int, int));
 extern int rl_vi_insert_beg PARAMS((int, int));
 extern int rl_vi_append_mode PARAMS((int, int));
+extern int rl_vi_insert_mode PARAMS((int, int));
 extern int rl_vi_append_eol PARAMS((int, int));
 extern int rl_vi_eof_maybe PARAMS((int, int));
 extern int rl_vi_insertion_mode PARAMS((int, int));
diff --git a/lib/readline/vi_keymap.c b/lib/readline/vi_keymap.c
index 4b48c75..3a017cc 100644
--- a/lib/readline/vi_keymap.c
+++ b/lib/readline/vi_keymap.c
@@ -151,7 +151,7 @@ KEYMAP_ENTRY_ARRAY vi_movement_keymap = {
   { ISFUNC, rl_vi_char_search },		/* f */
   { ISFUNC, (rl_command_func_t *)0x0 },		/* g */
   { ISFUNC, rl_backward_char },			/* h */
-  { ISFUNC, rl_vi_insertion_mode },		/* i */
+  { ISFUNC, rl_vi_insert_mode },		/* i */
   { ISFUNC, rl_get_next_history },		/* j */
   { ISFUNC, rl_get_previous_history },		/* k */
   { ISFUNC, rl_forward_char },			/* l */
diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c
index b0da0ab..e859062 100644
--- a/lib/readline/vi_mode.c
+++ b/lib/readline/vi_mode.c
@@ -220,6 +220,15 @@ rl_vi_redo (count, c)
       if (rl_point > 0)
 	_rl_vi_backup ();
     }
+  /* Ditto for redoing an insert with `I', but move to the beginning of line
+     like the `I' command does. */
+  else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
+    {
+      rl_beg_of_line (1, 'I');
+      _rl_vi_stuff_insert (count);
+      if (rl_point > 0)
+	_rl_vi_backup ();
+    }
   else
     r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
   vi_redoing = 0;
@@ -584,7 +593,7 @@ rl_vi_insert_beg (count, key)
      int count, key;
 {
   rl_beg_of_line (1, key);
-  rl_vi_insertion_mode (1, key);
+  rl_vi_insert_mode (1, key);
   return (0);
 }
 
@@ -618,6 +627,14 @@ rl_vi_append_mode (count, key)
 }
 
 int
+rl_vi_insert_mode (count, key)
+     int count, key;
+{
+  rl_vi_start_inserting (key, 1, rl_arg_sign);
+  return (0);
+}
+
+int
 rl_vi_append_eol (count, key)
      int count, key;
 {
@@ -690,7 +707,7 @@ _rl_vi_done_inserting ()
     }
   else
     {
-      if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list)
+      if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a' || _rl_vi_last_key_before_insert == 'I') && rl_undo_list)
         _rl_vi_save_insert (rl_undo_list);
       /* XXX - Other keys probably need to be checked. */
       else if (_rl_vi_last_key_before_insert == 'C')
-- 
1.5.3.7


-- 
Tomas Janousek, SW Engineer, Red Hat, Inc.