Import GNU Readline 8.1
[deliverable/binutils-gdb.git] / readline / readline / vi_mode.c
index 836371c95fff755e5bb9fc2faf8998310ef286ae..742341e362836fb72f361465856992e586a0fb6a 100644 (file)
@@ -1,7 +1,7 @@
 /* vi_mode.c -- A vi emulation mode for Bash.
    Derived from code written by Jeff Sparkes (jsparkes@bnr.ca).  */
 
-/* Copyright (C) 1987-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library (Readline), a library
    for reading lines of text with interactive input and history editing.      
@@ -298,6 +298,11 @@ rl_vi_redo (int count, int c)
       if (rl_point > 0)
        _rl_vi_backup ();
     }
+  else if (_rl_vi_last_command == '.' && _rl_keymap == vi_movement_keymap)
+    {
+      rl_ding ();
+      r = 0;
+    }
   else
     r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
 
@@ -320,9 +325,9 @@ rl_vi_yank_arg (int count, int key)
   /* Readline thinks that the first word on a line is the 0th, while vi
      thinks the first word on a line is the 1st.  Compensate. */
   if (rl_explicit_arg)
-    rl_yank_nth_arg (count - 1, 0);
+    rl_yank_nth_arg (count - 1, key);
   else
-    rl_yank_nth_arg ('$', 0);
+    rl_yank_nth_arg ('$', key);
 
   return (0);
 }
@@ -837,6 +842,12 @@ _rl_vi_save_replace (void)
   start = end - vi_replace_count + 1;
   len = vi_replace_count + 1;
 
+  if (start < 0)
+    {
+      len = end + 1;
+      start = 0;
+    }
+
   vi_save_insert_buffer (start, len);  
 }
 
@@ -864,8 +875,8 @@ _rl_vi_done_inserting (void)
 {
   if (_rl_vi_doing_insert)
     {
-      /* The `C', `s', and `S' commands set this. */
-      rl_end_undo_group ();
+      /* The `c', `s', `S', and `R' commands set this. */
+      rl_end_undo_group ();    /* for the group in rl_vi_start_inserting */
       /* Now, the text between rl_undo_list->next->start and
         rl_undo_list->next->end is what was inserted while in insert
         mode.  It gets copied to VI_INSERT_BUFFER because it depends
@@ -876,7 +887,9 @@ _rl_vi_done_inserting (void)
        _rl_vi_save_replace ();         /* Half the battle */
       else
        _rl_vi_save_insert (rl_undo_list->next);
-      vi_continued_command = 1;
+      /* sanity check, should always be >= 1 here */
+      if (_rl_undo_group_level > 0)
+       rl_end_undo_group ();   /* for the group in the command (change or replace) */
     }
   else
     {
@@ -888,10 +901,12 @@ _rl_vi_done_inserting (void)
       /* XXX - Other keys probably need to be checked. */
       else if (_rl_vi_last_key_before_insert == 'C')
        rl_end_undo_group ();
-      while (_rl_undo_group_level > 0)
-       rl_end_undo_group ();
-      vi_continued_command = 0;
     }
+
+  /* Sanity check, make sure all the undo groups are closed before we leave
+     insert mode */
+  while (_rl_undo_group_level > 0)
+    rl_end_undo_group ();
 }
 
 int
@@ -1162,6 +1177,7 @@ rl_domove_motion_callback (_rl_vimotion_cxt *m)
   /* Append a blank character temporarily so that the motion routines
      work right at the end of the line.  Original value of rl_end is saved
      as m->end. */
+  rl_extend_line_buffer (rl_end + 1);
   rl_line_buffer[rl_end++] = ' ';
   rl_line_buffer[rl_end] = '\0';
 
@@ -1193,12 +1209,15 @@ _rl_vi_domove_motion_cleanup (int c, _rl_vimotion_cxt *m)
   /* Remove the blank that we added in rl_domove_motion_callback. */
   rl_end = m->end;
   rl_line_buffer[rl_end] = '\0';
-  if (rl_point > rl_end)
-    rl_point = rl_end;
+  _rl_fix_point (0);
 
   /* No change in position means the command failed. */
   if (rl_mark == rl_point)
     {
+      /* 'c' and 'C' enter insert mode after the delete even if the motion
+        didn't delete anything, as long as the motion command is valid. */
+      if (_rl_to_upper (m->key) == 'C' && _rl_vi_motion_command (c))
+       return (vidomove_dispatch (m));
       RL_UNSETSTATE (RL_STATE_VIMOTION);
       return (-1);
     }
@@ -1316,13 +1335,7 @@ rl_domove_read_callback (_rl_vimotion_cxt *m)
 static int
 rl_vi_domove_getchar (_rl_vimotion_cxt *m)
 {
-  int c;
-
-  RL_SETSTATE(RL_STATE_MOREINPUT);
-  c = rl_read_key ();
-  RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-  return c;
+  return (_rl_bracketed_read_key ());
 }
 
 #if defined (READLINE_CALLBACKS)
@@ -1377,7 +1390,11 @@ rl_vi_delete_to (int count, int key)
 {
   int c, r;
 
-  _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
+  if (_rl_vimvcxt)
+    _rl_mvcxt_init (_rl_vimvcxt, VIM_DELETE, key);
+  else
+    _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
+
   _rl_vimvcxt->start = rl_point;
 
   rl_mark = rl_point;
@@ -1465,7 +1482,10 @@ rl_vi_change_to (int count, int key)
 {
   int c, r;
 
-  _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
+  if (_rl_vimvcxt)
+    _rl_mvcxt_init (_rl_vimvcxt, VIM_CHANGE, key);
+  else
+    _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
   _rl_vimvcxt->start = rl_point;
 
   rl_mark = rl_point;
@@ -1524,6 +1544,8 @@ vi_yank_dispatch (_rl_vimotion_cxt *m)
   rl_do_undo ();
   rl_point = m->start;
 
+  _rl_fix_point (1);
+
   return (0);
 }
 
@@ -1532,7 +1554,10 @@ rl_vi_yank_to (int count, int key)
 {
   int c, r;
 
-  _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
+  if (_rl_vimvcxt)
+    _rl_mvcxt_init (_rl_vimvcxt, VIM_YANK, key);
+  else
+    _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
   _rl_vimvcxt->start = rl_point;
 
   rl_mark = rl_point;
@@ -2000,21 +2025,7 @@ _rl_vi_change_char (int count, int c, char *mb)
 static int
 _rl_vi_callback_getchar (char *mb, int mlen)
 {
-  int c;
-
-  RL_SETSTATE(RL_STATE_MOREINPUT);
-  c = rl_read_key ();
-  RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-  if (c < 0)
-    return -1;
-
-#if defined (HANDLE_MULTIBYTE)
-  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
-    c = _rl_read_mbstring (c, mb, mlen);
-#endif
-
-  return c;
+  return (_rl_bracketed_read_mbstring (mb, mlen));
 }
 
 #if defined (READLINE_CALLBACKS)
@@ -2026,10 +2037,11 @@ _rl_vi_callback_change_char (_rl_callback_generic_arg *data)
 
   c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
 #if defined (HANDLE_MULTIBYTE)
-  strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
-#else
-  _rl_vi_last_replacement[0] = c;
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
+  else
 #endif
+    _rl_vi_last_replacement[0] = c;
   _rl_vi_last_replacement[MB_LEN_MAX] = '\0';  /* XXX */
 
   if (c < 0)
@@ -2066,10 +2078,11 @@ rl_vi_change_char (int count, int key)
     {
       c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
 #ifdef HANDLE_MULTIBYTE
-      strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
-#else
-      _rl_vi_last_replacement[0] = c;
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
+      else
 #endif
+       _rl_vi_last_replacement[0] = c;
       _rl_vi_last_replacement[MB_LEN_MAX] = '\0';      /* just in case */      
     }
 
@@ -2122,7 +2135,7 @@ rl_vi_overstrike_delete (int count, int key)
       s = rl_point;
 
       if (rl_do_undo ())
-       vi_replace_count--;
+       vi_replace_count--;             /* XXX */
 
       if (rl_point == s)
        rl_backward_char (1, key);
@@ -2137,6 +2150,67 @@ rl_vi_overstrike_delete (int count, int key)
   return (0);
 }
 
+static int
+rl_vi_overstrike_kill_line (int count, int key)
+{
+  int r, end;
+
+  end = rl_end;
+  r = rl_unix_line_discard (count, key);
+  vi_replace_count -= end - rl_end;
+  return r;
+}
+
+static int
+rl_vi_overstrike_kill_word (int count, int key)
+{
+  int r, end;
+
+  end = rl_end;
+  r = rl_vi_unix_word_rubout (count, key);
+  vi_replace_count -= end - rl_end;
+  return r;
+}
+
+static int
+rl_vi_overstrike_yank (int count, int key)
+{
+  int r, end;
+
+  end = rl_end;
+  r = rl_yank (count, key);
+  vi_replace_count += rl_end - end;
+  return r;
+}
+
+/* Read bracketed paste mode pasted text and insert it in overwrite mode */
+static int
+rl_vi_overstrike_bracketed_paste (int count, int key)
+{
+  int r;
+  char *pbuf;
+  size_t pblen;
+
+  pbuf = _rl_bracketed_text (&pblen);
+  if (pblen == 0)
+    {
+      xfree (pbuf);
+      return 0;
+    }
+  r = pblen;
+  while (--r >= 0)
+    _rl_unget_char ((unsigned char)pbuf[r]);
+  xfree (pbuf);
+
+  while (_rl_pushed_input_available ())
+    {
+      key = rl_read_key ();
+      r = rl_vi_overstrike (1, key);
+    }
+
+  return r;
+}
+
 int
 rl_vi_replace (int count, int key)
 {
@@ -2169,6 +2243,21 @@ rl_vi_replace (int count, int key)
          vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
        vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
 
+      /* Same for ^U and unix-line-discard. */
+      if (vi_insertion_keymap[CTRL ('U')].type == ISFUNC &&
+         vi_insertion_keymap[CTRL ('U')].function == rl_unix_line_discard)
+       vi_replace_map[CTRL ('U')].function = rl_vi_overstrike_kill_line;
+
+      /* And for ^W and unix-word-rubout. */
+      if (vi_insertion_keymap[CTRL ('W')].type == ISFUNC &&
+         vi_insertion_keymap[CTRL ('W')].function == rl_vi_unix_word_rubout)
+       vi_replace_map[CTRL ('W')].function = rl_vi_overstrike_kill_word;
+
+      /* And finally for ^Y and yank. */
+      if (vi_insertion_keymap[CTRL ('Y')].type == ISFUNC &&
+         vi_insertion_keymap[CTRL ('Y')].function == rl_yank)
+       vi_replace_map[CTRL ('Y')].function = rl_vi_overstrike_yank;
+
       /* Make sure this is the value we need. */
       vi_replace_map[ANYOTHERKEY].type = ISFUNC;
       vi_replace_map[ANYOTHERKEY].function = (rl_command_func_t *)NULL;
@@ -2176,9 +2265,12 @@ rl_vi_replace (int count, int key)
 
   rl_vi_start_inserting (key, 1, rl_arg_sign);
 
-  _rl_vi_last_key_before_insert = key;
+  _rl_vi_last_key_before_insert = 'R'; /* in case someone rebinds it */
   _rl_keymap = vi_replace_map;
 
+  if (_rl_enable_bracketed_paste)
+    rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_vi_overstrike_bracketed_paste);
+
   return (0);
 }
 
@@ -2268,6 +2360,7 @@ _rl_vi_goto_mark (void)
   if (ch == '`')
     {
       rl_point = rl_mark;
+      _rl_fix_point (1);
       return 0;
     }
   else if (ch < 0 || ch < 'a' || ch > 'z')     /* make test against 0 explicit */
@@ -2283,6 +2376,7 @@ _rl_vi_goto_mark (void)
       return 1;
     }
   rl_point = vi_mark_chars[ch];
+  _rl_fix_point (1);
   return 0;
 }
 
This page took 0.027831 seconds and 4 git commands to generate.