1 /* vi_mode.c -- A vi emulation mode for Bash.
2 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
4 /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
6 This file is part of the GNU Readline Library (Readline), a library
7 for reading lines of text with interactive input and history editing.
9 Readline is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Readline is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Readline. If not, see <http://www.gnu.org/licenses/>.
23 #define READLINE_LIBRARY
25 /* **************************************************************** */
27 /* VI Emulation Mode */
29 /* **************************************************************** */
34 #if defined (HAVE_CONFIG_H)
38 #include <sys/types.h>
40 #if defined (HAVE_STDLIB_H)
43 # include "ansi_stdlib.h"
44 #endif /* HAVE_STDLIB_H */
46 #if defined (HAVE_UNISTD_H)
52 /* Some standard library routines. */
59 #include "rlprivate.h"
63 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
66 int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
68 /* Non-zero means enter insertion mode. */
69 static int _rl_vi_doing_insert;
71 /* Command keys which do movement for xxx_to commands. */
72 static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`";
74 /* Keymap used for vi replace characters. Created dynamically since
76 static Keymap vi_replace_map;
78 /* The number of characters inserted in the last replace operation. */
79 static int vi_replace_count;
81 /* If non-zero, we have text inserted after a c[motion] command that put
82 us implicitly into insert mode. Some people want this text to be
83 attached to the command so that it is `redoable' with `.'. */
84 static int vi_continued_command;
85 static char *vi_insert_buffer;
86 static int vi_insert_buffer_size;
88 static int _rl_vi_last_repeat = 1;
89 static int _rl_vi_last_arg_sign = 1;
90 static int _rl_vi_last_motion;
91 #if defined (HANDLE_MULTIBYTE)
92 static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
93 static int _rl_vi_last_search_mblen;
95 static int _rl_vi_last_search_char;
97 static int _rl_vi_last_replacement;
99 static int _rl_vi_last_key_before_insert;
101 static int vi_redoing;
103 /* Text modification commands. These are the `redoable' commands. */
104 static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
106 /* Arrays for the saved marks. */
107 static int vi_mark_chars['z' - 'a' + 1];
109 static void _rl_vi_stuff_insert PARAMS((int));
110 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
112 static void _rl_vi_backup PARAMS((void));
114 static int _rl_vi_arg_dispatch PARAMS((int));
115 static int rl_digit_loop1 PARAMS((void));
117 static int _rl_vi_set_mark PARAMS((void));
118 static int _rl_vi_goto_mark PARAMS((void));
120 static void _rl_vi_append_forward PARAMS((int));
122 static int _rl_vi_callback_getchar PARAMS((char *, int));
124 #if defined (READLINE_CALLBACKS)
125 static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
126 static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
127 static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
128 static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
132 _rl_vi_initialize_line ()
136 n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
137 for (i = 0; i < n; i++)
138 vi_mark_chars[i] = -1;
140 RL_UNSETSTATE(RL_STATE_VICMDONCE);
146 _rl_vi_last_command = 'i';
147 _rl_vi_last_repeat = 1;
148 _rl_vi_last_arg_sign = 1;
149 _rl_vi_last_motion = 0;
153 _rl_vi_set_last (key, repeat, sign)
154 int key, repeat, sign;
156 _rl_vi_last_command = key;
157 _rl_vi_last_repeat = repeat;
158 _rl_vi_last_arg_sign = sign;
161 /* A convenience function that calls _rl_vi_set_last to save the last command
162 information and enters insertion mode. */
164 rl_vi_start_inserting (key, repeat, sign)
165 int key, repeat, sign;
167 _rl_vi_set_last (key, repeat, sign);
168 rl_vi_insertion_mode (1, key);
171 /* Is the command C a VI mode text modification command? */
173 _rl_vi_textmod_command (c)
176 return (member (c, vi_textmod));
180 _rl_vi_stuff_insert (count)
183 rl_begin_undo_group ();
185 rl_insert_text (vi_insert_buffer);
186 rl_end_undo_group ();
189 /* Bound to `.'. Called from command mode, so we know that we have to
190 redo a text modification command. The default for _rl_vi_last_command
191 puts you back into insert mode. */
193 rl_vi_redo (count, c)
198 if (!rl_explicit_arg)
200 rl_numeric_arg = _rl_vi_last_repeat;
201 rl_arg_sign = _rl_vi_last_arg_sign;
206 /* If we're redoing an insert with `i', stuff in the inserted text
207 and do not go into insertion mode. */
208 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
210 _rl_vi_stuff_insert (count);
211 /* And back up point over the last character inserted. */
215 /* Ditto for redoing an insert with `I', but move to the beginning of the
216 line like the `I' command does. */
217 else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
219 rl_beg_of_line (1, 'I');
220 _rl_vi_stuff_insert (count);
224 /* Ditto for redoing an insert with `a', but move forward a character first
225 like the `a' command does. */
226 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
228 _rl_vi_append_forward ('a');
229 _rl_vi_stuff_insert (count);
233 /* Ditto for redoing an insert with `A', but move to the end of the line
234 like the `A' command does. */
235 else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
237 rl_end_of_line (1, 'A');
238 _rl_vi_stuff_insert (count);
243 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
249 /* A placeholder for further expansion. */
251 rl_vi_undo (count, key)
254 return (rl_undo_command (count, key));
257 /* Yank the nth arg from the previous line into this line at point. */
259 rl_vi_yank_arg (count, key)
262 /* Readline thinks that the first word on a line is the 0th, while vi
263 thinks the first word on a line is the 1st. Compensate. */
265 rl_yank_nth_arg (count - 1, 0);
267 rl_yank_nth_arg ('$', 0);
272 /* With an argument, move back that many history lines, else move to the
273 beginning of history. */
275 rl_vi_fetch_history (count, c)
280 /* Giving an argument of n means we want the nth command in the history
281 file. The command number is interpreted the same way that the bash
282 `history' command does it -- that is, giving an argument count of 450
283 to this command would get the command listed as number 450 in the
284 output of `history'. */
287 wanted = history_base + where_history () - count;
289 rl_beginning_of_history (0, 0);
291 rl_get_previous_history (wanted, c);
294 rl_beginning_of_history (count, 0);
298 /* Search again for the last thing searched for. */
300 rl_vi_search_again (count, key)
306 rl_noninc_reverse_search_again (count, key);
310 rl_noninc_forward_search_again (count, key);
316 /* Do a vi style search. */
318 rl_vi_search (count, key)
324 _rl_free_saved_history_line ();
325 rl_noninc_forward_search (count, key);
329 _rl_free_saved_history_line ();
330 rl_noninc_reverse_search (count, key);
340 /* Completion, from vi's point of view. */
342 rl_vi_complete (ignore, key)
345 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
347 if (!whitespace (rl_line_buffer[rl_point + 1]))
348 rl_vi_end_word (1, 'E');
353 rl_complete_internal ('*'); /* Expansion and replacement. */
355 rl_complete_internal ('?'); /* List possible completions. */
356 else if (key == '\\')
357 rl_complete_internal (TAB); /* Standard Readline completion. */
359 rl_complete (0, key);
361 if (key == '*' || key == '\\')
362 rl_vi_start_inserting (key, 1, rl_arg_sign);
367 /* Tilde expansion for vi mode. */
369 rl_vi_tilde_expand (ignore, key)
372 rl_tilde_expand (0, key);
373 rl_vi_start_inserting (key, 1, rl_arg_sign);
377 /* Previous word in vi mode. */
379 rl_vi_prev_word (count, key)
383 return (rl_vi_next_word (-count, key));
391 if (_rl_uppercase_p (key))
392 rl_vi_bWord (count, key);
394 rl_vi_bword (count, key);
399 /* Next word in vi mode. */
401 rl_vi_next_word (count, key)
405 return (rl_vi_prev_word (-count, key));
407 if (rl_point >= (rl_end - 1))
413 if (_rl_uppercase_p (key))
414 rl_vi_fWord (count, key);
416 rl_vi_fword (count, key);
420 /* Move to the end of the ?next? word. */
422 rl_vi_end_word (count, key)
431 if (_rl_uppercase_p (key))
432 rl_vi_eWord (count, key);
434 rl_vi_eword (count, key);
438 /* Move forward a word the way that 'W' does. */
440 rl_vi_fWord (count, ignore)
443 while (count-- && rl_point < (rl_end - 1))
445 /* Skip until whitespace. */
446 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
449 /* Now skip whitespace. */
450 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
457 rl_vi_bWord (count, ignore)
460 while (count-- && rl_point > 0)
462 /* If we are at the start of a word, move back to whitespace so
463 we will go back to the start of the previous word. */
464 if (!whitespace (rl_line_buffer[rl_point]) &&
465 whitespace (rl_line_buffer[rl_point - 1]))
468 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
473 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
481 rl_vi_eWord (count, ignore)
484 while (count-- && rl_point < (rl_end - 1))
486 if (!whitespace (rl_line_buffer[rl_point]))
489 /* Move to the next non-whitespace character (to the start of the
491 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
494 if (rl_point && rl_point < rl_end)
496 /* Skip whitespace. */
497 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
500 /* Skip until whitespace. */
501 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
504 /* Move back to the last character of the word. */
512 rl_vi_fword (count, ignore)
515 while (count-- && rl_point < (rl_end - 1))
517 /* Move to white space (really non-identifer). */
518 if (_rl_isident (rl_line_buffer[rl_point]))
520 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
523 else /* if (!whitespace (rl_line_buffer[rl_point])) */
525 while (!_rl_isident (rl_line_buffer[rl_point]) &&
526 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
530 /* Move past whitespace. */
531 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
538 rl_vi_bword (count, ignore)
541 while (count-- && rl_point > 0)
545 /* If we are at the start of a word, move back to whitespace
546 so we will go back to the start of the previous word. */
547 if (!whitespace (rl_line_buffer[rl_point]) &&
548 whitespace (rl_line_buffer[rl_point - 1]))
551 /* If this character and the previous character are `opposite', move
552 back so we don't get messed up by the rl_point++ down there in
553 the while loop. Without this code, words like `l;' screw up the
555 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
556 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
557 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
560 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
565 if (_rl_isident (rl_line_buffer[rl_point]))
566 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
568 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
569 !whitespace (rl_line_buffer[rl_point]));
577 rl_vi_eword (count, ignore)
580 while (count-- && rl_point < rl_end - 1)
582 if (!whitespace (rl_line_buffer[rl_point]))
585 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
588 if (rl_point < rl_end)
590 if (_rl_isident (rl_line_buffer[rl_point]))
591 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
593 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
594 && !whitespace (rl_line_buffer[rl_point]));
602 rl_vi_insert_beg (count, key)
605 rl_beg_of_line (1, key);
606 rl_vi_insert_mode (1, key);
611 _rl_vi_append_forward (key)
616 if (rl_point < rl_end)
618 if (MB_CUR_MAX == 1 || rl_byte_oriented)
623 rl_forward_char (1, key);
624 if (point == rl_point)
631 rl_vi_append_mode (count, key)
634 _rl_vi_append_forward (key);
635 rl_vi_start_inserting (key, 1, rl_arg_sign);
640 rl_vi_append_eol (count, key)
643 rl_end_of_line (1, key);
644 rl_vi_append_mode (1, key);
648 /* What to do in the case of C-d. */
650 rl_vi_eof_maybe (count, c)
653 return (rl_newline (1, '\n'));
656 /* Insertion mode stuff. */
658 /* Switching from one mode to the other really just involves
659 switching keymaps. */
661 rl_vi_insertion_mode (count, key)
664 _rl_keymap = vi_insertion_keymap;
665 _rl_vi_last_key_before_insert = key;
670 rl_vi_insert_mode (count, key)
673 rl_vi_start_inserting (key, 1, rl_arg_sign);
678 _rl_vi_save_insert (up)
683 if (up == 0 || up->what != UNDO_INSERT)
685 if (vi_insert_buffer_size >= 1)
686 vi_insert_buffer[0] = '\0';
692 len = end - start + 1;
693 if (len >= vi_insert_buffer_size)
695 vi_insert_buffer_size += (len + 32) - (len % 32);
696 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
698 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
699 vi_insert_buffer[len-1] = '\0';
703 _rl_vi_done_inserting ()
705 if (_rl_vi_doing_insert)
707 /* The `C', `s', and `S' commands set this. */
708 rl_end_undo_group ();
709 /* Now, the text between rl_undo_list->next->start and
710 rl_undo_list->next->end is what was inserted while in insert
711 mode. It gets copied to VI_INSERT_BUFFER because it depends
712 on absolute indices into the line which may change (though they
713 probably will not). */
714 _rl_vi_doing_insert = 0;
715 _rl_vi_save_insert (rl_undo_list->next);
716 vi_continued_command = 1;
720 if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
721 _rl_vi_last_key_before_insert == 'a' ||
722 _rl_vi_last_key_before_insert == 'I' ||
723 _rl_vi_last_key_before_insert == 'A'))
724 _rl_vi_save_insert (rl_undo_list);
725 /* XXX - Other keys probably need to be checked. */
726 else if (_rl_vi_last_key_before_insert == 'C')
727 rl_end_undo_group ();
728 while (_rl_undo_group_level > 0)
729 rl_end_undo_group ();
730 vi_continued_command = 0;
735 rl_vi_movement_mode (count, key)
739 rl_backward_char (1, key);
741 _rl_keymap = vi_movement_keymap;
742 _rl_vi_done_inserting ();
744 /* This is how POSIX.2 says `U' should behave -- everything up until the
745 first time you go into command mode should not be undone. */
746 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
747 rl_free_undo_list ();
749 RL_SETSTATE (RL_STATE_VICMDONCE);
754 rl_vi_arg_digit (count, c)
757 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
758 return (rl_beg_of_line (1, c));
760 return (rl_digit_argument (count, c));
763 /* Change the case of the next COUNT characters. */
764 #if defined (HANDLE_MULTIBYTE)
766 _rl_vi_change_mbchar_case (count)
770 char mb[MB_LEN_MAX+1];
775 memset (&ps, 0, sizeof (mbstate_t));
776 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
778 while (count-- && rl_point < rl_end)
780 m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
781 if (MB_INVALIDCH (m))
782 wc = (wchar_t)rl_line_buffer[rl_point];
783 else if (MB_NULLWCH (m))
787 else if (iswlower (wc))
791 /* Just skip over chars neither upper nor lower case */
792 rl_forward_char (1, 0);
796 /* Vi is kind of strange here. */
800 mlen = wcrtomb (mb, wc, &ps);
803 rl_begin_undo_group ();
805 if (rl_point < p) /* Did we retreat at EOL? */
806 rl_point++; /* XXX - should we advance more than 1 for mbchar? */
808 rl_end_undo_group ();
812 rl_forward_char (1, 0);
820 rl_vi_change_case (count, ignore)
825 /* Don't try this on an empty line. */
826 if (rl_point >= rl_end)
830 #if defined (HANDLE_MULTIBYTE)
831 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
832 return (_rl_vi_change_mbchar_case (count));
835 while (count-- && rl_point < rl_end)
837 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
838 c = _rl_to_lower (rl_line_buffer[rl_point]);
839 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
840 c = _rl_to_upper (rl_line_buffer[rl_point]);
843 /* Just skip over characters neither upper nor lower case. */
844 rl_forward_char (1, c);
848 /* Vi is kind of strange here. */
852 rl_begin_undo_group ();
854 if (rl_point < p) /* Did we retreat at EOL? */
856 _rl_insert_char (1, c);
857 rl_end_undo_group ();
861 rl_forward_char (1, c);
867 rl_vi_put (count, key)
870 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
871 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
876 rl_backward_char (1, key);
883 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
884 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
892 if (rl_point && rl_point == rl_end)
894 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
895 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
903 rl_vi_column (count, key)
907 rl_end_of_line (1, key);
909 rl_point = count - 1;
914 rl_vi_domove (key, nextkey)
921 RL_SETSTATE(RL_STATE_MOREINPUT);
923 RL_UNSETSTATE(RL_STATE_MOREINPUT);
933 if (!member (c, vi_motion))
937 save = rl_numeric_arg;
938 rl_numeric_arg = _rl_digit_value (c);
940 RL_SETSTATE (RL_STATE_NUMERICARG|RL_STATE_VIMOTION);
942 RL_UNSETSTATE (RL_STATE_VIMOTION);
943 rl_numeric_arg *= save;
944 RL_SETSTATE(RL_STATE_MOREINPUT);
945 c = rl_read_key (); /* real command */
946 RL_UNSETSTATE(RL_STATE_MOREINPUT);
954 else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
957 rl_beg_of_line (1, c);
958 _rl_vi_last_motion = c;
965 _rl_vi_last_motion = c;
967 /* Append a blank character temporarily so that the motion routines
968 work right at the end of the line. */
970 rl_line_buffer[rl_end++] = ' ';
971 rl_line_buffer[rl_end] = '\0';
973 _rl_dispatch (c, _rl_keymap);
975 /* Remove the blank that we added. */
977 rl_line_buffer[rl_end] = '\0';
978 if (rl_point > rl_end)
981 /* No change in position means the command failed. */
982 if (rl_mark == rl_point)
985 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
986 word. If we are not at the end of the line, and we are on a
987 non-whitespace character, move back one (presumably to whitespace). */
988 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
989 !whitespace (rl_line_buffer[rl_point]))
992 /* If cw or cW, back up to the end of a word, so the behaviour of ce
993 or cE is the actual result. Brute-force, no subtlety. */
994 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
996 /* Don't move farther back than where we started. */
997 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
1000 /* Posix.2 says that if cw or cW moves the cursor towards the end of
1001 the line, the character under the cursor should be deleted. */
1002 if (rl_point == rl_mark)
1006 /* Move past the end of the word so that the kill doesn't
1007 remove the last letter of the previous word. Only do this
1008 if we are not at the end of the line. */
1009 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
1014 if (rl_mark < rl_point)
1015 SWAP (rl_point, rl_mark);
1020 /* Process C as part of the current numeric argument. Return -1 if the
1021 argument should be aborted, 0 if we should not read any more chars, and
1022 1 if we should continue to read chars. */
1024 _rl_vi_arg_dispatch (c)
1030 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
1032 rl_numeric_arg *= 4;
1038 if (_rl_digit_p (c))
1040 if (rl_explicit_arg)
1041 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
1043 rl_numeric_arg = _rl_digit_value (c);
1044 rl_explicit_arg = 1;
1049 rl_clear_message ();
1050 rl_stuff_char (key);
1055 /* A simplified loop for vi. Don't dispatch key at end.
1056 Don't recognize minus sign?
1057 Should this do rl_save_prompt/rl_restore_prompt? */
1065 if (_rl_arg_overflow ())
1068 c = _rl_arg_getchar ();
1070 r = _rl_vi_arg_dispatch (c);
1075 RL_UNSETSTATE(RL_STATE_NUMERICARG);
1080 rl_vi_delete_to (count, key)
1085 if (_rl_uppercase_p (key))
1086 rl_stuff_char ('$');
1087 else if (vi_redoing)
1088 rl_stuff_char (_rl_vi_last_motion);
1090 start_pos = rl_point;
1092 if (rl_vi_domove (key, &c))
1098 /* These are the motion commands that do not require adjusting the
1100 if (((strchr (" l|h^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
1104 rl_kill_text (rl_point, rl_mark);
1109 rl_vi_change_to (count, key)
1114 if (_rl_uppercase_p (key))
1115 rl_stuff_char ('$');
1116 else if (vi_redoing)
1117 rl_stuff_char (_rl_vi_last_motion);
1119 start_pos = rl_point;
1121 if (rl_vi_domove (key, &c))
1127 /* These are the motion commands that do not require adjusting the
1128 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1129 and already leave the mark at the correct location. */
1130 if (((strchr (" l|hwW^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
1134 /* The cursor never moves with c[wW]. */
1135 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
1136 rl_point = start_pos;
1140 if (vi_insert_buffer && *vi_insert_buffer)
1141 rl_begin_undo_group ();
1142 rl_delete_text (rl_point, rl_mark);
1143 if (vi_insert_buffer && *vi_insert_buffer)
1145 rl_insert_text (vi_insert_buffer);
1146 rl_end_undo_group ();
1151 rl_begin_undo_group (); /* to make the `u' command work */
1152 rl_kill_text (rl_point, rl_mark);
1153 /* `C' does not save the text inserted for undoing or redoing. */
1154 if (_rl_uppercase_p (key) == 0)
1155 _rl_vi_doing_insert = 1;
1156 rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
1163 rl_vi_yank_to (count, key)
1168 if (_rl_uppercase_p (key))
1169 rl_stuff_char ('$');
1171 start_pos = rl_point;
1173 if (rl_vi_domove (key, &c))
1179 /* These are the motion commands that do not require adjusting the
1181 if (((strchr (" l|h^0%bBFT`", c) == 0) && (rl_point >= start_pos)) &&
1185 rl_begin_undo_group ();
1186 rl_kill_text (rl_point, rl_mark);
1187 rl_end_undo_group ();
1189 rl_point = start_pos;
1195 rl_vi_rubout (count, key)
1201 return (rl_vi_delete (-count, key));
1210 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1211 rl_backward_char (count, key);
1212 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1213 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1220 rl_kill_text (rl_point, opoint);
1226 rl_vi_delete (count, key)
1232 return (rl_vi_rubout (-count, key));
1240 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1241 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1243 end = rl_point + count;
1248 rl_kill_text (rl_point, end);
1250 if (rl_point > 0 && rl_point == rl_end)
1251 rl_backward_char (1, key);
1257 rl_vi_back_to_indent (count, key)
1260 rl_beg_of_line (1, key);
1261 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1267 rl_vi_first_print (count, key)
1270 return (rl_vi_back_to_indent (1, key));
1273 static int _rl_cs_dir, _rl_cs_orig_dir;
1275 #if defined (READLINE_CALLBACKS)
1277 _rl_vi_callback_char_search (data)
1278 _rl_callback_generic_arg *data;
1281 #if defined (HANDLE_MULTIBYTE)
1282 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1284 RL_SETSTATE(RL_STATE_MOREINPUT);
1286 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1292 #if !defined (HANDLE_MULTIBYTE)
1293 _rl_vi_last_search_char = c;
1296 _rl_callback_func = 0;
1297 _rl_want_redisplay = 1;
1299 #if defined (HANDLE_MULTIBYTE)
1300 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
1302 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
1308 rl_vi_char_search (count, key)
1312 #if defined (HANDLE_MULTIBYTE)
1313 static char *target;
1319 if (key == ';' || key == ',')
1320 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
1326 _rl_cs_orig_dir = _rl_cs_dir = FTO;
1330 _rl_cs_orig_dir = _rl_cs_dir = BTO;
1334 _rl_cs_orig_dir = _rl_cs_dir = FFIND;
1338 _rl_cs_orig_dir = _rl_cs_dir = BFIND;
1344 /* set target and tlen below */
1346 #if defined (READLINE_CALLBACKS)
1347 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1349 _rl_callback_data = _rl_callback_data_alloc (count);
1350 _rl_callback_data->i1 = _rl_cs_dir;
1351 _rl_callback_func = _rl_vi_callback_char_search;
1357 #if defined (HANDLE_MULTIBYTE)
1358 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1361 _rl_vi_last_search_mblen = c;
1363 RL_SETSTATE(RL_STATE_MOREINPUT);
1365 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1368 _rl_vi_last_search_char = c;
1373 #if defined (HANDLE_MULTIBYTE)
1374 target = _rl_vi_last_search_mbchar;
1375 tlen = _rl_vi_last_search_mblen;
1377 target = _rl_vi_last_search_char;
1380 #if defined (HANDLE_MULTIBYTE)
1381 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
1383 return (_rl_char_search_internal (count, _rl_cs_dir, target));
1387 /* Match brackets */
1389 rl_vi_match (ignore, key)
1392 int count = 1, brack, pos, tmp, pre;
1395 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1397 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1399 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1402 rl_forward_char (1, key);
1403 if (pre == rl_point)
1408 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1409 rl_point < rl_end - 1)
1410 rl_forward_char (1, key);
1427 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1431 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1437 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1440 else if (b == brack)
1454 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1457 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1461 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1464 else if (b == brack)
1485 case ')': return -1;
1487 case ']': return -2;
1489 case '}': return -3;
1495 _rl_vi_change_char (count, c, mb)
1501 if (c == '\033' || c == CTRL ('C'))
1504 rl_begin_undo_group ();
1505 while (count-- && rl_point < rl_end)
1508 rl_vi_delete (1, c);
1509 if (rl_point < p) /* Did we retreat at EOL? */
1511 #if defined (HANDLE_MULTIBYTE)
1512 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1513 rl_insert_text (mb);
1516 _rl_insert_char (1, c);
1519 /* The cursor shall be left on the last character changed. */
1520 rl_backward_char (1, c);
1522 rl_end_undo_group ();
1528 _rl_vi_callback_getchar (mb, mlen)
1534 RL_SETSTATE(RL_STATE_MOREINPUT);
1536 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1541 #if defined (HANDLE_MULTIBYTE)
1542 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1543 c = _rl_read_mbstring (c, mb, mlen);
1549 #if defined (READLINE_CALLBACKS)
1551 _rl_vi_callback_change_char (data)
1552 _rl_callback_generic_arg *data;
1555 char mb[MB_LEN_MAX];
1557 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1562 _rl_callback_func = 0;
1563 _rl_want_redisplay = 1;
1565 return (_rl_vi_change_char (data->count, c, mb));
1570 rl_vi_change_char (count, key)
1574 char mb[MB_LEN_MAX];
1578 c = _rl_vi_last_replacement;
1582 #if defined (READLINE_CALLBACKS)
1583 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1585 _rl_callback_data = _rl_callback_data_alloc (count);
1586 _rl_callback_func = _rl_vi_callback_change_char;
1591 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1596 return (_rl_vi_change_char (count, c, mb));
1600 rl_vi_subst (count, key)
1603 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1604 if (vi_redoing == 0)
1605 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1607 return (rl_vi_change_to (count, 'c'));
1611 rl_vi_overstrike (count, key)
1614 if (_rl_vi_doing_insert == 0)
1616 _rl_vi_doing_insert = 1;
1617 rl_begin_undo_group ();
1622 _rl_overwrite_char (count, key);
1623 vi_replace_count += count;
1630 rl_vi_overstrike_delete (count, key)
1635 for (i = 0; i < count; i++)
1637 if (vi_replace_count == 0)
1648 rl_backward_char (1, key);
1651 if (vi_replace_count == 0 && _rl_vi_doing_insert)
1653 rl_end_undo_group ();
1655 _rl_vi_doing_insert = 0;
1661 rl_vi_replace (count, key)
1666 vi_replace_count = 0;
1668 if (!vi_replace_map)
1670 vi_replace_map = rl_make_bare_keymap ();
1672 for (i = ' '; i < KEYMAP_SIZE; i++)
1673 vi_replace_map[i].function = rl_vi_overstrike;
1675 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1676 vi_replace_map[ESC].function = rl_vi_movement_mode;
1677 vi_replace_map[RETURN].function = rl_newline;
1678 vi_replace_map[NEWLINE].function = rl_newline;
1680 /* If the normal vi insertion keymap has ^H bound to erase, do the
1681 same here. Probably should remove the assignment to RUBOUT up
1682 there, but I don't think it will make a difference in real life. */
1683 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1684 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1685 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1688 _rl_keymap = vi_replace_map;
1693 /* Try to complete the word we are standing on or the word that ends with
1694 the previous character. A space matches everything. Word delimiters are
1697 rl_vi_possible_completions()
1699 int save_pos = rl_point;
1701 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1703 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1704 rl_line_buffer[rl_point] != ';')
1707 else if (rl_line_buffer[rl_point - 1] == ';')
1713 rl_possible_completions ();
1714 rl_point = save_pos;
1720 /* Functions to save and restore marks. */
1726 RL_SETSTATE(RL_STATE_MOREINPUT);
1727 ch = rl_read_key ();
1728 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1730 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
1736 vi_mark_chars[ch] = rl_point;
1740 #if defined (READLINE_CALLBACKS)
1742 _rl_vi_callback_set_mark (data)
1743 _rl_callback_generic_arg *data;
1745 _rl_callback_func = 0;
1746 _rl_want_redisplay = 1;
1748 return (_rl_vi_set_mark ());
1753 rl_vi_set_mark (count, key)
1756 #if defined (READLINE_CALLBACKS)
1757 if (RL_ISSTATE (RL_STATE_CALLBACK))
1759 _rl_callback_data = 0;
1760 _rl_callback_func = _rl_vi_callback_set_mark;
1765 return (_rl_vi_set_mark ());
1773 RL_SETSTATE(RL_STATE_MOREINPUT);
1774 ch = rl_read_key ();
1775 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1782 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
1789 if (vi_mark_chars[ch] == -1)
1794 rl_point = vi_mark_chars[ch];
1798 #if defined (READLINE_CALLBACKS)
1800 _rl_vi_callback_goto_mark (data)
1801 _rl_callback_generic_arg *data;
1803 _rl_callback_func = 0;
1804 _rl_want_redisplay = 1;
1806 return (_rl_vi_goto_mark ());
1811 rl_vi_goto_mark (count, key)
1814 #if defined (READLINE_CALLBACKS)
1815 if (RL_ISSTATE (RL_STATE_CALLBACK))
1817 _rl_callback_data = 0;
1818 _rl_callback_func = _rl_vi_callback_goto_mark;
1823 return (_rl_vi_goto_mark ());
1825 #endif /* VI_MODE */