summaryrefslogtreecommitdiff
path: root/vi_mode.c
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2021-01-18 13:42:55 -0500
committerChet Ramey <chet.ramey@case.edu>2021-01-18 13:42:55 -0500
commitcf3c762ecfff5b2f445647a0f1543693984a5540 (patch)
treee21eb36970a06b1d8a2df6a97a161da43410e136 /vi_mode.c
parentc5ad6be530f5c1daf64a2d20df4baba9f6b57aa4 (diff)
downloadreadline-cf3c762ecfff5b2f445647a0f1543693984a5540.tar.gz
Readline-8.1 distribution sources and documentationreadline-8.1
Diffstat (limited to 'vi_mode.c')
-rw-r--r--vi_mode.c182
1 files changed, 138 insertions, 44 deletions
diff --git a/vi_mode.c b/vi_mode.c
index 836371c..742341e 100644
--- a/vi_mode.c
+++ b/vi_mode.c
@@ -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;
}