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 for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
137 vi_mark_chars[i] = -1;
139 RL_UNSETSTATE(RL_STATE_VICMDONCE);
145 _rl_vi_last_command = 'i';
146 _rl_vi_last_repeat = 1;
147 _rl_vi_last_arg_sign = 1;
148 _rl_vi_last_motion = 0;
152 _rl_vi_set_last (key, repeat, sign)
153 int key, repeat, sign;
155 _rl_vi_last_command = key;
156 _rl_vi_last_repeat = repeat;
157 _rl_vi_last_arg_sign = sign;
160 /* A convenience function that calls _rl_vi_set_last to save the last command
161 information and enters insertion mode. */
163 rl_vi_start_inserting (key, repeat, sign)
164 int key, repeat, sign;
166 _rl_vi_set_last (key, repeat, sign);
167 rl_vi_insertion_mode (1, key);
170 /* Is the command C a VI mode text modification command? */
172 _rl_vi_textmod_command (c)
175 return (member (c, vi_textmod));
179 _rl_vi_stuff_insert (count)
182 rl_begin_undo_group ();
184 rl_insert_text (vi_insert_buffer);
185 rl_end_undo_group ();
188 /* Bound to `.'. Called from command mode, so we know that we have to
189 redo a text modification command. The default for _rl_vi_last_command
190 puts you back into insert mode. */
192 rl_vi_redo (count, c)
197 if (!rl_explicit_arg)
199 rl_numeric_arg = _rl_vi_last_repeat;
200 rl_arg_sign = _rl_vi_last_arg_sign;
205 /* If we're redoing an insert with `i', stuff in the inserted text
206 and do not go into insertion mode. */
207 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
209 _rl_vi_stuff_insert (count);
210 /* And back up point over the last character inserted. */
214 /* Ditto for redoing an insert with `I', but move to the beginning of the
215 line like the `I' command does. */
216 else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
218 rl_beg_of_line (1, 'I');
219 _rl_vi_stuff_insert (count);
223 /* Ditto for redoing an insert with `a', but move forward a character first
224 like the `a' command does. */
225 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
227 _rl_vi_append_forward ('a');
228 _rl_vi_stuff_insert (count);
232 /* Ditto for redoing an insert with `A', but move to the end of the line
233 like the `A' command does. */
234 else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
236 rl_end_of_line (1, 'A');
237 _rl_vi_stuff_insert (count);
242 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
248 /* A placeholder for further expansion. */
250 rl_vi_undo (count, key)
253 return (rl_undo_command (count, key));
256 /* Yank the nth arg from the previous line into this line at point. */
258 rl_vi_yank_arg (count, key)
261 /* Readline thinks that the first word on a line is the 0th, while vi
262 thinks the first word on a line is the 1st. Compensate. */
264 rl_yank_nth_arg (count - 1, 0);
266 rl_yank_nth_arg ('$', 0);
271 /* With an argument, move back that many history lines, else move to the
272 beginning of history. */
274 rl_vi_fetch_history (count, c)
279 /* Giving an argument of n means we want the nth command in the history
280 file. The command number is interpreted the same way that the bash
281 `history' command does it -- that is, giving an argument count of 450
282 to this command would get the command listed as number 450 in the
283 output of `history'. */
286 wanted = history_base + where_history () - count;
288 rl_beginning_of_history (0, 0);
290 rl_get_previous_history (wanted, c);
293 rl_beginning_of_history (count, 0);
297 /* Search again for the last thing searched for. */
299 rl_vi_search_again (count, key)
305 rl_noninc_reverse_search_again (count, key);
309 rl_noninc_forward_search_again (count, key);
315 /* Do a vi style search. */
317 rl_vi_search (count, key)
323 _rl_free_saved_history_line ();
324 rl_noninc_forward_search (count, key);
328 _rl_free_saved_history_line ();
329 rl_noninc_reverse_search (count, key);
339 /* Completion, from vi's point of view. */
341 rl_vi_complete (ignore, key)
344 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
346 if (!whitespace (rl_line_buffer[rl_point + 1]))
347 rl_vi_end_word (1, 'E');
352 rl_complete_internal ('*'); /* Expansion and replacement. */
354 rl_complete_internal ('?'); /* List possible completions. */
355 else if (key == '\\')
356 rl_complete_internal (TAB); /* Standard Readline completion. */
358 rl_complete (0, key);
360 if (key == '*' || key == '\\')
361 rl_vi_start_inserting (key, 1, rl_arg_sign);
366 /* Tilde expansion for vi mode. */
368 rl_vi_tilde_expand (ignore, key)
371 rl_tilde_expand (0, key);
372 rl_vi_start_inserting (key, 1, rl_arg_sign);
376 /* Previous word in vi mode. */
378 rl_vi_prev_word (count, key)
382 return (rl_vi_next_word (-count, key));
390 if (_rl_uppercase_p (key))
391 rl_vi_bWord (count, key);
393 rl_vi_bword (count, key);
398 /* Next word in vi mode. */
400 rl_vi_next_word (count, key)
404 return (rl_vi_prev_word (-count, key));
406 if (rl_point >= (rl_end - 1))
412 if (_rl_uppercase_p (key))
413 rl_vi_fWord (count, key);
415 rl_vi_fword (count, key);
419 /* Move to the end of the ?next? word. */
421 rl_vi_end_word (count, key)
430 if (_rl_uppercase_p (key))
431 rl_vi_eWord (count, key);
433 rl_vi_eword (count, key);
437 /* Move forward a word the way that 'W' does. */
439 rl_vi_fWord (count, ignore)
442 while (count-- && rl_point < (rl_end - 1))
444 /* Skip until whitespace. */
445 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
448 /* Now skip whitespace. */
449 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
456 rl_vi_bWord (count, ignore)
459 while (count-- && rl_point > 0)
461 /* If we are at the start of a word, move back to whitespace so
462 we will go back to the start of the previous word. */
463 if (!whitespace (rl_line_buffer[rl_point]) &&
464 whitespace (rl_line_buffer[rl_point - 1]))
467 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
472 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
480 rl_vi_eWord (count, ignore)
483 while (count-- && rl_point < (rl_end - 1))
485 if (!whitespace (rl_line_buffer[rl_point]))
488 /* Move to the next non-whitespace character (to the start of the
490 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
493 if (rl_point && rl_point < rl_end)
495 /* Skip whitespace. */
496 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
499 /* Skip until whitespace. */
500 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
503 /* Move back to the last character of the word. */
511 rl_vi_fword (count, ignore)
514 while (count-- && rl_point < (rl_end - 1))
516 /* Move to white space (really non-identifer). */
517 if (_rl_isident (rl_line_buffer[rl_point]))
519 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
522 else /* if (!whitespace (rl_line_buffer[rl_point])) */
524 while (!_rl_isident (rl_line_buffer[rl_point]) &&
525 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
529 /* Move past whitespace. */
530 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
537 rl_vi_bword (count, ignore)
540 while (count-- && rl_point > 0)
544 /* If we are at the start of a word, move back to whitespace
545 so we will go back to the start of the previous word. */
546 if (!whitespace (rl_line_buffer[rl_point]) &&
547 whitespace (rl_line_buffer[rl_point - 1]))
550 /* If this character and the previous character are `opposite', move
551 back so we don't get messed up by the rl_point++ down there in
552 the while loop. Without this code, words like `l;' screw up the
554 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
555 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
556 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
559 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
564 if (_rl_isident (rl_line_buffer[rl_point]))
565 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
567 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
568 !whitespace (rl_line_buffer[rl_point]));
576 rl_vi_eword (count, ignore)
579 while (count-- && rl_point < rl_end - 1)
581 if (!whitespace (rl_line_buffer[rl_point]))
584 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
587 if (rl_point < rl_end)
589 if (_rl_isident (rl_line_buffer[rl_point]))
590 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
592 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
593 && !whitespace (rl_line_buffer[rl_point]));
601 rl_vi_insert_beg (count, key)
604 rl_beg_of_line (1, key);
605 rl_vi_insert_mode (1, key);
610 _rl_vi_append_forward (key)
615 if (rl_point < rl_end)
617 if (MB_CUR_MAX == 1 || rl_byte_oriented)
622 rl_forward_char (1, key);
623 if (point == rl_point)
630 rl_vi_append_mode (count, key)
633 _rl_vi_append_forward (key);
634 rl_vi_start_inserting (key, 1, rl_arg_sign);
639 rl_vi_append_eol (count, key)
642 rl_end_of_line (1, key);
643 rl_vi_append_mode (1, key);
647 /* What to do in the case of C-d. */
649 rl_vi_eof_maybe (count, c)
652 return (rl_newline (1, '\n'));
655 /* Insertion mode stuff. */
657 /* Switching from one mode to the other really just involves
658 switching keymaps. */
660 rl_vi_insertion_mode (count, key)
663 _rl_keymap = vi_insertion_keymap;
664 _rl_vi_last_key_before_insert = key;
669 rl_vi_insert_mode (count, key)
672 rl_vi_start_inserting (key, 1, rl_arg_sign);
677 _rl_vi_save_insert (up)
682 if (up == 0 || up->what != UNDO_INSERT)
684 if (vi_insert_buffer_size >= 1)
685 vi_insert_buffer[0] = '\0';
691 len = end - start + 1;
692 if (len >= vi_insert_buffer_size)
694 vi_insert_buffer_size += (len + 32) - (len % 32);
695 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
697 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
698 vi_insert_buffer[len-1] = '\0';
702 _rl_vi_done_inserting ()
704 if (_rl_vi_doing_insert)
706 /* The `C', `s', and `S' commands set this. */
707 rl_end_undo_group ();
708 /* Now, the text between rl_undo_list->next->start and
709 rl_undo_list->next->end is what was inserted while in insert
710 mode. It gets copied to VI_INSERT_BUFFER because it depends
711 on absolute indices into the line which may change (though they
712 probably will not). */
713 _rl_vi_doing_insert = 0;
714 _rl_vi_save_insert (rl_undo_list->next);
715 vi_continued_command = 1;
719 if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
720 _rl_vi_last_key_before_insert == 'a' ||
721 _rl_vi_last_key_before_insert == 'I' ||
722 _rl_vi_last_key_before_insert == 'A'))
723 _rl_vi_save_insert (rl_undo_list);
724 /* XXX - Other keys probably need to be checked. */
725 else if (_rl_vi_last_key_before_insert == 'C')
726 rl_end_undo_group ();
727 while (_rl_undo_group_level > 0)
728 rl_end_undo_group ();
729 vi_continued_command = 0;
734 rl_vi_movement_mode (count, key)
738 rl_backward_char (1, key);
740 _rl_keymap = vi_movement_keymap;
741 _rl_vi_done_inserting ();
743 /* This is how POSIX.2 says `U' should behave -- everything up until the
744 first time you go into command mode should not be undone. */
745 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
746 rl_free_undo_list ();
748 RL_SETSTATE (RL_STATE_VICMDONCE);
753 rl_vi_arg_digit (count, c)
756 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
757 return (rl_beg_of_line (1, c));
759 return (rl_digit_argument (count, c));
762 /* Change the case of the next COUNT characters. */
763 #if defined (HANDLE_MULTIBYTE)
765 _rl_vi_change_mbchar_case (count)
769 char mb[MB_LEN_MAX+1];
773 memset (&ps, 0, sizeof (mbstate_t));
774 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
776 while (count-- && rl_point < rl_end)
778 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
781 else if (iswlower (wc))
785 /* Just skip over chars neither upper nor lower case */
786 rl_forward_char (1, 0);
790 /* Vi is kind of strange here. */
794 mlen = wcrtomb (mb, wc, &ps);
797 rl_begin_undo_group ();
799 if (rl_point < p) /* Did we retreat at EOL? */
800 rl_point++; /* XXX - should we advance more than 1 for mbchar? */
802 rl_end_undo_group ();
806 rl_forward_char (1, 0);
814 rl_vi_change_case (count, ignore)
819 /* Don't try this on an empty line. */
820 if (rl_point >= rl_end)
824 #if defined (HANDLE_MULTIBYTE)
825 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
826 return (_rl_vi_change_mbchar_case (count));
829 while (count-- && rl_point < rl_end)
831 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
832 c = _rl_to_lower (rl_line_buffer[rl_point]);
833 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
834 c = _rl_to_upper (rl_line_buffer[rl_point]);
837 /* Just skip over characters neither upper nor lower case. */
838 rl_forward_char (1, c);
842 /* Vi is kind of strange here. */
846 rl_begin_undo_group ();
848 if (rl_point < p) /* Did we retreat at EOL? */
850 _rl_insert_char (1, c);
851 rl_end_undo_group ();
855 rl_forward_char (1, c);
861 rl_vi_put (count, key)
864 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
865 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
870 rl_backward_char (1, key);
877 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
878 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
886 if (rl_point && rl_point == rl_end)
888 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
889 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
897 rl_vi_column (count, key)
901 rl_end_of_line (1, key);
903 rl_point = count - 1;
908 rl_vi_domove (key, nextkey)
915 RL_SETSTATE(RL_STATE_MOREINPUT);
917 RL_UNSETSTATE(RL_STATE_MOREINPUT);
927 if (!member (c, vi_motion))
931 save = rl_numeric_arg;
932 rl_numeric_arg = _rl_digit_value (c);
934 RL_SETSTATE (RL_STATE_NUMERICARG|RL_STATE_VIMOTION);
936 RL_UNSETSTATE (RL_STATE_VIMOTION);
937 rl_numeric_arg *= save;
938 RL_SETSTATE(RL_STATE_MOREINPUT);
939 c = rl_read_key (); /* real command */
940 RL_UNSETSTATE(RL_STATE_MOREINPUT);
948 else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
951 rl_beg_of_line (1, c);
952 _rl_vi_last_motion = c;
959 _rl_vi_last_motion = c;
961 /* Append a blank character temporarily so that the motion routines
962 work right at the end of the line. */
964 rl_line_buffer[rl_end++] = ' ';
965 rl_line_buffer[rl_end] = '\0';
967 _rl_dispatch (c, _rl_keymap);
969 /* Remove the blank that we added. */
971 rl_line_buffer[rl_end] = '\0';
972 if (rl_point > rl_end)
975 /* No change in position means the command failed. */
976 if (rl_mark == rl_point)
979 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
980 word. If we are not at the end of the line, and we are on a
981 non-whitespace character, move back one (presumably to whitespace). */
982 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
983 !whitespace (rl_line_buffer[rl_point]))
986 /* If cw or cW, back up to the end of a word, so the behaviour of ce
987 or cE is the actual result. Brute-force, no subtlety. */
988 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
990 /* Don't move farther back than where we started. */
991 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
994 /* Posix.2 says that if cw or cW moves the cursor towards the end of
995 the line, the character under the cursor should be deleted. */
996 if (rl_point == rl_mark)
1000 /* Move past the end of the word so that the kill doesn't
1001 remove the last letter of the previous word. Only do this
1002 if we are not at the end of the line. */
1003 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
1008 if (rl_mark < rl_point)
1009 SWAP (rl_point, rl_mark);
1014 /* Process C as part of the current numeric argument. Return -1 if the
1015 argument should be aborted, 0 if we should not read any more chars, and
1016 1 if we should continue to read chars. */
1018 _rl_vi_arg_dispatch (c)
1024 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
1026 rl_numeric_arg *= 4;
1032 if (_rl_digit_p (c))
1034 if (rl_explicit_arg)
1035 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
1037 rl_numeric_arg = _rl_digit_value (c);
1038 rl_explicit_arg = 1;
1043 rl_clear_message ();
1044 rl_stuff_char (key);
1049 /* A simplified loop for vi. Don't dispatch key at end.
1050 Don't recognize minus sign?
1051 Should this do rl_save_prompt/rl_restore_prompt? */
1059 if (_rl_arg_overflow ())
1062 c = _rl_arg_getchar ();
1064 r = _rl_vi_arg_dispatch (c);
1069 RL_UNSETSTATE(RL_STATE_NUMERICARG);
1074 rl_vi_delete_to (count, key)
1079 if (_rl_uppercase_p (key))
1080 rl_stuff_char ('$');
1081 else if (vi_redoing)
1082 rl_stuff_char (_rl_vi_last_motion);
1084 start_pos = rl_point;
1086 if (rl_vi_domove (key, &c))
1092 /* These are the motion commands that do not require adjusting the
1094 if (((strchr (" l|h^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
1098 rl_kill_text (rl_point, rl_mark);
1103 rl_vi_change_to (count, key)
1108 if (_rl_uppercase_p (key))
1109 rl_stuff_char ('$');
1110 else if (vi_redoing)
1111 rl_stuff_char (_rl_vi_last_motion);
1113 start_pos = rl_point;
1115 if (rl_vi_domove (key, &c))
1121 /* These are the motion commands that do not require adjusting the
1122 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1123 and already leave the mark at the correct location. */
1124 if (((strchr (" l|hwW^0bBFT`", c) == 0) && (rl_point >= start_pos)) &&
1128 /* The cursor never moves with c[wW]. */
1129 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
1130 rl_point = start_pos;
1134 if (vi_insert_buffer && *vi_insert_buffer)
1135 rl_begin_undo_group ();
1136 rl_delete_text (rl_point, rl_mark);
1137 if (vi_insert_buffer && *vi_insert_buffer)
1139 rl_insert_text (vi_insert_buffer);
1140 rl_end_undo_group ();
1145 rl_begin_undo_group (); /* to make the `u' command work */
1146 rl_kill_text (rl_point, rl_mark);
1147 /* `C' does not save the text inserted for undoing or redoing. */
1148 if (_rl_uppercase_p (key) == 0)
1149 _rl_vi_doing_insert = 1;
1150 rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
1157 rl_vi_yank_to (count, key)
1162 if (_rl_uppercase_p (key))
1163 rl_stuff_char ('$');
1165 start_pos = rl_point;
1167 if (rl_vi_domove (key, &c))
1173 /* These are the motion commands that do not require adjusting the
1175 if (((strchr (" l|h^0%bBFT`", c) == 0) && (rl_point >= start_pos)) &&
1179 rl_begin_undo_group ();
1180 rl_kill_text (rl_point, rl_mark);
1181 rl_end_undo_group ();
1183 rl_point = start_pos;
1189 rl_vi_rubout (count, key)
1195 return (rl_vi_delete (-count, key));
1204 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1205 rl_backward_char (count, key);
1206 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1207 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1214 rl_kill_text (rl_point, opoint);
1220 rl_vi_delete (count, key)
1226 return (rl_vi_rubout (-count, key));
1234 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1235 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1237 end = rl_point + count;
1242 rl_kill_text (rl_point, end);
1244 if (rl_point > 0 && rl_point == rl_end)
1245 rl_backward_char (1, key);
1251 rl_vi_back_to_indent (count, key)
1254 rl_beg_of_line (1, key);
1255 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1261 rl_vi_first_print (count, key)
1264 return (rl_vi_back_to_indent (1, key));
1267 static int _rl_cs_dir, _rl_cs_orig_dir;
1269 #if defined (READLINE_CALLBACKS)
1271 _rl_vi_callback_char_search (data)
1272 _rl_callback_generic_arg *data;
1275 #if defined (HANDLE_MULTIBYTE)
1276 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1278 RL_SETSTATE(RL_STATE_MOREINPUT);
1280 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1286 #if !defined (HANDLE_MULTIBYTE)
1287 _rl_vi_last_search_char = c;
1290 _rl_callback_func = 0;
1291 _rl_want_redisplay = 1;
1293 #if defined (HANDLE_MULTIBYTE)
1294 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
1296 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
1302 rl_vi_char_search (count, key)
1306 #if defined (HANDLE_MULTIBYTE)
1307 static char *target;
1313 if (key == ';' || key == ',')
1314 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
1320 _rl_cs_orig_dir = _rl_cs_dir = FTO;
1324 _rl_cs_orig_dir = _rl_cs_dir = BTO;
1328 _rl_cs_orig_dir = _rl_cs_dir = FFIND;
1332 _rl_cs_orig_dir = _rl_cs_dir = BFIND;
1338 /* set target and tlen below */
1340 #if defined (READLINE_CALLBACKS)
1341 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1343 _rl_callback_data = _rl_callback_data_alloc (count);
1344 _rl_callback_data->i1 = _rl_cs_dir;
1345 _rl_callback_func = _rl_vi_callback_char_search;
1351 #if defined (HANDLE_MULTIBYTE)
1352 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1355 _rl_vi_last_search_mblen = c;
1357 RL_SETSTATE(RL_STATE_MOREINPUT);
1359 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1362 _rl_vi_last_search_char = c;
1367 #if defined (HANDLE_MULTIBYTE)
1368 target = _rl_vi_last_search_mbchar;
1369 tlen = _rl_vi_last_search_mblen;
1371 target = _rl_vi_last_search_char;
1374 #if defined (HANDLE_MULTIBYTE)
1375 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
1377 return (_rl_char_search_internal (count, _rl_cs_dir, target));
1381 /* Match brackets */
1383 rl_vi_match (ignore, key)
1386 int count = 1, brack, pos, tmp, pre;
1389 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1391 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1393 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1396 rl_forward_char (1, key);
1397 if (pre == rl_point)
1402 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1403 rl_point < rl_end - 1)
1404 rl_forward_char (1, key);
1421 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1425 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1431 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1434 else if (b == brack)
1448 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1451 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1455 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1458 else if (b == brack)
1479 case ')': return -1;
1481 case ']': return -2;
1483 case '}': return -3;
1489 _rl_vi_change_char (count, c, mb)
1495 if (c == '\033' || c == CTRL ('C'))
1498 rl_begin_undo_group ();
1499 while (count-- && rl_point < rl_end)
1502 rl_vi_delete (1, c);
1503 if (rl_point < p) /* Did we retreat at EOL? */
1505 #if defined (HANDLE_MULTIBYTE)
1506 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1507 rl_insert_text (mb);
1510 _rl_insert_char (1, c);
1513 /* The cursor shall be left on the last character changed. */
1514 rl_backward_char (1, c);
1516 rl_end_undo_group ();
1522 _rl_vi_callback_getchar (mb, mlen)
1528 RL_SETSTATE(RL_STATE_MOREINPUT);
1530 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1535 #if defined (HANDLE_MULTIBYTE)
1536 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1537 c = _rl_read_mbstring (c, mb, mlen);
1543 #if defined (READLINE_CALLBACKS)
1545 _rl_vi_callback_change_char (data)
1546 _rl_callback_generic_arg *data;
1549 char mb[MB_LEN_MAX];
1551 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1556 _rl_callback_func = 0;
1557 _rl_want_redisplay = 1;
1559 return (_rl_vi_change_char (data->count, c, mb));
1564 rl_vi_change_char (count, key)
1568 char mb[MB_LEN_MAX];
1572 c = _rl_vi_last_replacement;
1576 #if defined (READLINE_CALLBACKS)
1577 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1579 _rl_callback_data = _rl_callback_data_alloc (count);
1580 _rl_callback_func = _rl_vi_callback_change_char;
1585 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1590 return (_rl_vi_change_char (count, c, mb));
1594 rl_vi_subst (count, key)
1597 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1598 if (vi_redoing == 0)
1599 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1601 return (rl_vi_change_to (count, 'c'));
1605 rl_vi_overstrike (count, key)
1608 if (_rl_vi_doing_insert == 0)
1610 _rl_vi_doing_insert = 1;
1611 rl_begin_undo_group ();
1616 _rl_overwrite_char (count, key);
1617 vi_replace_count += count;
1624 rl_vi_overstrike_delete (count, key)
1629 for (i = 0; i < count; i++)
1631 if (vi_replace_count == 0)
1642 rl_backward_char (1, key);
1645 if (vi_replace_count == 0 && _rl_vi_doing_insert)
1647 rl_end_undo_group ();
1649 _rl_vi_doing_insert = 0;
1655 rl_vi_replace (count, key)
1660 vi_replace_count = 0;
1662 if (!vi_replace_map)
1664 vi_replace_map = rl_make_bare_keymap ();
1666 for (i = ' '; i < KEYMAP_SIZE; i++)
1667 vi_replace_map[i].function = rl_vi_overstrike;
1669 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1670 vi_replace_map[ESC].function = rl_vi_movement_mode;
1671 vi_replace_map[RETURN].function = rl_newline;
1672 vi_replace_map[NEWLINE].function = rl_newline;
1674 /* If the normal vi insertion keymap has ^H bound to erase, do the
1675 same here. Probably should remove the assignment to RUBOUT up
1676 there, but I don't think it will make a difference in real life. */
1677 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1678 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1679 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1682 _rl_keymap = vi_replace_map;
1687 /* Try to complete the word we are standing on or the word that ends with
1688 the previous character. A space matches everything. Word delimiters are
1691 rl_vi_possible_completions()
1693 int save_pos = rl_point;
1695 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1697 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1698 rl_line_buffer[rl_point] != ';')
1701 else if (rl_line_buffer[rl_point - 1] == ';')
1707 rl_possible_completions ();
1708 rl_point = save_pos;
1714 /* Functions to save and restore marks. */
1720 RL_SETSTATE(RL_STATE_MOREINPUT);
1721 ch = rl_read_key ();
1722 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1724 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
1730 vi_mark_chars[ch] = rl_point;
1734 #if defined (READLINE_CALLBACKS)
1736 _rl_vi_callback_set_mark (data)
1737 _rl_callback_generic_arg *data;
1739 _rl_callback_func = 0;
1740 _rl_want_redisplay = 1;
1742 return (_rl_vi_set_mark ());
1747 rl_vi_set_mark (count, key)
1750 #if defined (READLINE_CALLBACKS)
1751 if (RL_ISSTATE (RL_STATE_CALLBACK))
1753 _rl_callback_data = 0;
1754 _rl_callback_func = _rl_vi_callback_set_mark;
1759 return (_rl_vi_set_mark ());
1767 RL_SETSTATE(RL_STATE_MOREINPUT);
1768 ch = rl_read_key ();
1769 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1776 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
1783 if (vi_mark_chars[ch] == -1)
1788 rl_point = vi_mark_chars[ch];
1792 #if defined (READLINE_CALLBACKS)
1794 _rl_vi_callback_goto_mark (data)
1795 _rl_callback_generic_arg *data;
1797 _rl_callback_func = 0;
1798 _rl_want_redisplay = 1;
1800 return (_rl_vi_goto_mark ());
1805 rl_vi_goto_mark (count, key)
1808 #if defined (READLINE_CALLBACKS)
1809 if (RL_ISSTATE (RL_STATE_CALLBACK))
1811 _rl_callback_data = 0;
1812 _rl_callback_func = _rl_vi_callback_goto_mark;
1817 return (_rl_vi_goto_mark ());
1819 #endif /* VI_MODE */