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-2004 Free Software Foundation, Inc.
6 This file is part of the GNU Readline Library, a library for
7 reading lines of text with interactive input and history editing.
9 The GNU Readline Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2, or
12 (at your option) any later version.
14 The GNU Readline Library is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 The GNU General Public License is often shipped with GNU software, and
20 is generally kept in a file called COPYING or LICENSE. If you do not
21 have a copy of the license, write to the Free Software Foundation,
22 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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 *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];
94 static int _rl_vi_last_search_char;
96 static int _rl_vi_last_replacement;
98 static int _rl_vi_last_key_before_insert;
100 static int vi_redoing;
102 /* Text modification commands. These are the `redoable' commands. */
103 static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
105 /* Arrays for the saved marks. */
106 static int vi_mark_chars['z' - 'a' + 1];
108 static void _rl_vi_stuff_insert PARAMS((int));
109 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
110 static int rl_digit_loop1 PARAMS((void));
113 _rl_vi_initialize_line ()
117 for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
118 vi_mark_chars[i] = -1;
124 _rl_vi_last_command = 'i';
125 _rl_vi_last_repeat = 1;
126 _rl_vi_last_arg_sign = 1;
127 _rl_vi_last_motion = 0;
131 _rl_vi_set_last (key, repeat, sign)
132 int key, repeat, sign;
134 _rl_vi_last_command = key;
135 _rl_vi_last_repeat = repeat;
136 _rl_vi_last_arg_sign = sign;
139 /* A convenience function that calls _rl_vi_set_last to save the last command
140 information and enters insertion mode. */
142 rl_vi_start_inserting (key, repeat, sign)
143 int key, repeat, sign;
145 _rl_vi_set_last (key, repeat, sign);
146 rl_vi_insertion_mode (1, key);
149 /* Is the command C a VI mode text modification command? */
151 _rl_vi_textmod_command (c)
154 return (member (c, vi_textmod));
158 _rl_vi_stuff_insert (count)
161 rl_begin_undo_group ();
163 rl_insert_text (vi_insert_buffer);
164 rl_end_undo_group ();
167 /* Bound to `.'. Called from command mode, so we know that we have to
168 redo a text modification command. The default for _rl_vi_last_command
169 puts you back into insert mode. */
171 rl_vi_redo (count, c)
176 if (!rl_explicit_arg)
178 rl_numeric_arg = _rl_vi_last_repeat;
179 rl_arg_sign = _rl_vi_last_arg_sign;
184 /* If we're redoing an insert with `i', stuff in the inserted text
185 and do not go into insertion mode. */
186 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
188 _rl_vi_stuff_insert (count);
189 /* And back up point over the last character inserted. */
194 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
200 /* A placeholder for further expansion. */
202 rl_vi_undo (count, key)
205 return (rl_undo_command (count, key));
208 /* Yank the nth arg from the previous line into this line at point. */
210 rl_vi_yank_arg (count, key)
213 /* Readline thinks that the first word on a line is the 0th, while vi
214 thinks the first word on a line is the 1st. Compensate. */
216 rl_yank_nth_arg (count - 1, 0);
218 rl_yank_nth_arg ('$', 0);
223 /* With an argument, move back that many history lines, else move to the
224 beginning of history. */
226 rl_vi_fetch_history (count, c)
231 /* Giving an argument of n means we want the nth command in the history
232 file. The command number is interpreted the same way that the bash
233 `history' command does it -- that is, giving an argument count of 450
234 to this command would get the command listed as number 450 in the
235 output of `history'. */
238 wanted = history_base + where_history () - count;
240 rl_beginning_of_history (0, 0);
242 rl_get_previous_history (wanted, c);
245 rl_beginning_of_history (count, 0);
249 /* Search again for the last thing searched for. */
251 rl_vi_search_again (count, key)
257 rl_noninc_reverse_search_again (count, key);
261 rl_noninc_forward_search_again (count, key);
267 /* Do a vi style search. */
269 rl_vi_search (count, key)
275 _rl_free_saved_history_line ();
276 rl_noninc_forward_search (count, key);
280 _rl_free_saved_history_line ();
281 rl_noninc_reverse_search (count, key);
291 /* Completion, from vi's point of view. */
293 rl_vi_complete (ignore, key)
296 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
298 if (!whitespace (rl_line_buffer[rl_point + 1]))
299 rl_vi_end_word (1, 'E');
304 rl_complete_internal ('*'); /* Expansion and replacement. */
306 rl_complete_internal ('?'); /* List possible completions. */
307 else if (key == '\\')
308 rl_complete_internal (TAB); /* Standard Readline completion. */
310 rl_complete (0, key);
312 if (key == '*' || key == '\\')
313 rl_vi_start_inserting (key, 1, rl_arg_sign);
318 /* Tilde expansion for vi mode. */
320 rl_vi_tilde_expand (ignore, key)
323 rl_tilde_expand (0, key);
324 rl_vi_start_inserting (key, 1, rl_arg_sign);
328 /* Previous word in vi mode. */
330 rl_vi_prev_word (count, key)
334 return (rl_vi_next_word (-count, key));
342 if (_rl_uppercase_p (key))
343 rl_vi_bWord (count, key);
345 rl_vi_bword (count, key);
350 /* Next word in vi mode. */
352 rl_vi_next_word (count, key)
356 return (rl_vi_prev_word (-count, key));
358 if (rl_point >= (rl_end - 1))
364 if (_rl_uppercase_p (key))
365 rl_vi_fWord (count, key);
367 rl_vi_fword (count, key);
371 /* Move to the end of the ?next? word. */
373 rl_vi_end_word (count, key)
382 if (_rl_uppercase_p (key))
383 rl_vi_eWord (count, key);
385 rl_vi_eword (count, key);
389 /* Move forward a word the way that 'W' does. */
391 rl_vi_fWord (count, ignore)
394 while (count-- && rl_point < (rl_end - 1))
396 /* Skip until whitespace. */
397 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
400 /* Now skip whitespace. */
401 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
408 rl_vi_bWord (count, ignore)
411 while (count-- && rl_point > 0)
413 /* If we are at the start of a word, move back to whitespace so
414 we will go back to the start of the previous word. */
415 if (!whitespace (rl_line_buffer[rl_point]) &&
416 whitespace (rl_line_buffer[rl_point - 1]))
419 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
424 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
432 rl_vi_eWord (count, ignore)
435 while (count-- && rl_point < (rl_end - 1))
437 if (!whitespace (rl_line_buffer[rl_point]))
440 /* Move to the next non-whitespace character (to the start of the
442 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
445 if (rl_point && rl_point < rl_end)
447 /* Skip whitespace. */
448 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
451 /* Skip until whitespace. */
452 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
455 /* Move back to the last character of the word. */
463 rl_vi_fword (count, ignore)
466 while (count-- && rl_point < (rl_end - 1))
468 /* Move to white space (really non-identifer). */
469 if (_rl_isident (rl_line_buffer[rl_point]))
471 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
474 else /* if (!whitespace (rl_line_buffer[rl_point])) */
476 while (!_rl_isident (rl_line_buffer[rl_point]) &&
477 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
481 /* Move past whitespace. */
482 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
489 rl_vi_bword (count, ignore)
492 while (count-- && rl_point > 0)
496 /* If we are at the start of a word, move back to whitespace
497 so we will go back to the start of the previous word. */
498 if (!whitespace (rl_line_buffer[rl_point]) &&
499 whitespace (rl_line_buffer[rl_point - 1]))
502 /* If this character and the previous character are `opposite', move
503 back so we don't get messed up by the rl_point++ down there in
504 the while loop. Without this code, words like `l;' screw up the
506 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
507 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
508 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
511 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
516 if (_rl_isident (rl_line_buffer[rl_point]))
517 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
519 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
520 !whitespace (rl_line_buffer[rl_point]));
528 rl_vi_eword (count, ignore)
531 while (count-- && rl_point < rl_end - 1)
533 if (!whitespace (rl_line_buffer[rl_point]))
536 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
539 if (rl_point < rl_end)
541 if (_rl_isident (rl_line_buffer[rl_point]))
542 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
544 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
545 && !whitespace (rl_line_buffer[rl_point]));
553 rl_vi_insert_beg (count, key)
556 rl_beg_of_line (1, key);
557 rl_vi_insertion_mode (1, key);
562 rl_vi_append_mode (count, key)
565 if (rl_point < rl_end)
567 if (MB_CUR_MAX == 1 || rl_byte_oriented)
571 int point = rl_point;
572 rl_forward_char (1, key);
573 if (point == rl_point)
577 rl_vi_insertion_mode (1, key);
582 rl_vi_append_eol (count, key)
585 rl_end_of_line (1, key);
586 rl_vi_append_mode (1, key);
590 /* What to do in the case of C-d. */
592 rl_vi_eof_maybe (count, c)
595 return (rl_newline (1, '\n'));
598 /* Insertion mode stuff. */
600 /* Switching from one mode to the other really just involves
601 switching keymaps. */
603 rl_vi_insertion_mode (count, key)
606 _rl_keymap = vi_insertion_keymap;
607 _rl_vi_last_key_before_insert = key;
612 _rl_vi_save_insert (up)
619 if (vi_insert_buffer_size >= 1)
620 vi_insert_buffer[0] = '\0';
626 len = end - start + 1;
627 if (len >= vi_insert_buffer_size)
629 vi_insert_buffer_size += (len + 32) - (len % 32);
630 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
632 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
633 vi_insert_buffer[len-1] = '\0';
637 _rl_vi_done_inserting ()
639 if (_rl_vi_doing_insert)
641 /* The `C', `s', and `S' commands set this. */
642 rl_end_undo_group ();
643 /* Now, the text between rl_undo_list->next->start and
644 rl_undo_list->next->end is what was inserted while in insert
645 mode. It gets copied to VI_INSERT_BUFFER because it depends
646 on absolute indices into the line which may change (though they
647 probably will not). */
648 _rl_vi_doing_insert = 0;
649 _rl_vi_save_insert (rl_undo_list->next);
650 vi_continued_command = 1;
654 if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list)
655 _rl_vi_save_insert (rl_undo_list);
656 /* XXX - Other keys probably need to be checked. */
657 else if (_rl_vi_last_key_before_insert == 'C')
658 rl_end_undo_group ();
659 while (_rl_undo_group_level > 0)
660 rl_end_undo_group ();
661 vi_continued_command = 0;
666 rl_vi_movement_mode (count, key)
670 rl_backward_char (1, key);
672 _rl_keymap = vi_movement_keymap;
673 _rl_vi_done_inserting ();
678 rl_vi_arg_digit (count, c)
681 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
682 return (rl_beg_of_line (1, c));
684 return (rl_digit_argument (count, c));
687 /* Change the case of the next COUNT characters. */
688 #if defined (HANDLE_MULTIBYTE)
690 _rl_vi_change_mbchar_case (count)
694 char mb[MB_LEN_MAX+1];
698 memset (&ps, 0, sizeof (mbstate_t));
699 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
701 while (count-- && rl_point < rl_end)
703 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
706 else if (iswlower (wc))
710 /* Just skip over chars neither upper nor lower case */
711 rl_forward_char (1, 0);
715 /* Vi is kind of strange here. */
719 mblen = wcrtomb (mb, wc, &ps);
722 rl_begin_undo_group ();
724 if (rl_point < p) /* Did we retreat at EOL? */
725 rl_point++; /* XXX - should we advance more than 1 for mbchar? */
727 rl_end_undo_group ();
731 rl_forward_char (1, 0);
739 rl_vi_change_case (count, ignore)
744 /* Don't try this on an empty line. */
745 if (rl_point >= rl_end)
749 #if defined (HANDLE_MULTIBYTE)
750 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
751 return (_rl_vi_change_mbchar_case (count));
754 while (count-- && rl_point < rl_end)
756 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
757 c = _rl_to_lower (rl_line_buffer[rl_point]);
758 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
759 c = _rl_to_upper (rl_line_buffer[rl_point]);
762 /* Just skip over characters neither upper nor lower case. */
763 rl_forward_char (1, c);
767 /* Vi is kind of strange here. */
771 rl_begin_undo_group ();
773 if (rl_point < p) /* Did we retreat at EOL? */
775 _rl_insert_char (1, c);
776 rl_end_undo_group ();
780 rl_forward_char (1, c);
786 rl_vi_put (count, key)
789 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
790 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
795 rl_backward_char (1, key);
802 if (rl_point && rl_point == rl_end)
804 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
805 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
813 rl_vi_column (count, key)
817 rl_end_of_line (1, key);
819 rl_point = count - 1;
824 rl_vi_domove (key, nextkey)
831 RL_SETSTATE(RL_STATE_MOREINPUT);
833 RL_UNSETSTATE(RL_STATE_MOREINPUT);
836 if (!member (c, vi_motion))
840 save = rl_numeric_arg;
841 rl_numeric_arg = _rl_digit_value (c);
844 rl_numeric_arg *= save;
845 RL_SETSTATE(RL_STATE_MOREINPUT);
846 c = rl_read_key (); /* real command */
847 RL_UNSETSTATE(RL_STATE_MOREINPUT);
850 else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
853 rl_beg_of_line (1, c);
854 _rl_vi_last_motion = c;
861 _rl_vi_last_motion = c;
863 /* Append a blank character temporarily so that the motion routines
864 work right at the end of the line. */
866 rl_line_buffer[rl_end++] = ' ';
867 rl_line_buffer[rl_end] = '\0';
869 _rl_dispatch (c, _rl_keymap);
871 /* Remove the blank that we added. */
873 rl_line_buffer[rl_end] = '\0';
874 if (rl_point > rl_end)
877 /* No change in position means the command failed. */
878 if (rl_mark == rl_point)
881 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
882 word. If we are not at the end of the line, and we are on a
883 non-whitespace character, move back one (presumably to whitespace). */
884 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
885 !whitespace (rl_line_buffer[rl_point]))
888 /* If cw or cW, back up to the end of a word, so the behaviour of ce
889 or cE is the actual result. Brute-force, no subtlety. */
890 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
892 /* Don't move farther back than where we started. */
893 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
896 /* Posix.2 says that if cw or cW moves the cursor towards the end of
897 the line, the character under the cursor should be deleted. */
898 if (rl_point == rl_mark)
902 /* Move past the end of the word so that the kill doesn't
903 remove the last letter of the previous word. Only do this
904 if we are not at the end of the line. */
905 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
910 if (rl_mark < rl_point)
911 SWAP (rl_point, rl_mark);
916 /* A simplified loop for vi. Don't dispatch key at end.
917 Don't recognize minus sign?
918 Should this do rl_save_prompt/rl_restore_prompt? */
924 RL_SETSTATE(RL_STATE_NUMERICARG);
927 if (rl_numeric_arg > 1000000)
929 rl_explicit_arg = rl_numeric_arg = 0;
932 RL_UNSETSTATE(RL_STATE_NUMERICARG);
935 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
936 RL_SETSTATE(RL_STATE_MOREINPUT);
937 key = c = rl_read_key ();
938 RL_UNSETSTATE(RL_STATE_MOREINPUT);
940 if (c >= 0 && _rl_keymap[c].type == ISFUNC &&
941 _rl_keymap[c].function == rl_universal_argument)
951 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
953 rl_numeric_arg = _rl_digit_value (c);
964 RL_UNSETSTATE(RL_STATE_NUMERICARG);
969 rl_vi_delete_to (count, key)
974 if (_rl_uppercase_p (key))
977 rl_stuff_char (_rl_vi_last_motion);
979 if (rl_vi_domove (key, &c))
985 /* These are the motion commands that do not require adjusting the
987 if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
990 rl_kill_text (rl_point, rl_mark);
995 rl_vi_change_to (count, key)
1000 if (_rl_uppercase_p (key))
1001 rl_stuff_char ('$');
1002 else if (vi_redoing)
1003 rl_stuff_char (_rl_vi_last_motion);
1005 start_pos = rl_point;
1007 if (rl_vi_domove (key, &c))
1013 /* These are the motion commands that do not require adjusting the
1014 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1015 and already leave the mark at the correct location. */
1016 if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
1019 /* The cursor never moves with c[wW]. */
1020 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
1021 rl_point = start_pos;
1025 if (vi_insert_buffer && *vi_insert_buffer)
1026 rl_begin_undo_group ();
1027 rl_delete_text (rl_point, rl_mark);
1028 if (vi_insert_buffer && *vi_insert_buffer)
1030 rl_insert_text (vi_insert_buffer);
1031 rl_end_undo_group ();
1036 rl_begin_undo_group (); /* to make the `u' command work */
1037 rl_kill_text (rl_point, rl_mark);
1038 /* `C' does not save the text inserted for undoing or redoing. */
1039 if (_rl_uppercase_p (key) == 0)
1040 _rl_vi_doing_insert = 1;
1041 rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
1048 rl_vi_yank_to (count, key)
1051 int c, save = rl_point;
1053 if (_rl_uppercase_p (key))
1054 rl_stuff_char ('$');
1056 if (rl_vi_domove (key, &c))
1062 /* These are the motion commands that do not require adjusting the
1064 if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
1067 rl_begin_undo_group ();
1068 rl_kill_text (rl_point, rl_mark);
1069 rl_end_undo_group ();
1077 rl_vi_delete (count, key)
1088 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1089 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1091 end = rl_point + count;
1096 rl_kill_text (rl_point, end);
1098 if (rl_point > 0 && rl_point == rl_end)
1099 rl_backward_char (1, key);
1104 rl_vi_back_to_indent (count, key)
1107 rl_beg_of_line (1, key);
1108 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1114 rl_vi_first_print (count, key)
1117 return (rl_vi_back_to_indent (1, key));
1121 rl_vi_char_search (count, key)
1124 #if defined (HANDLE_MULTIBYTE)
1125 static char *target;
1130 static int orig_dir, dir;
1132 if (key == ';' || key == ',')
1133 dir = key == ';' ? orig_dir : -orig_dir;
1137 #if defined (HANDLE_MULTIBYTE)
1138 target = _rl_vi_last_search_mbchar;
1140 target = _rl_vi_last_search_char;
1144 #if defined (HANDLE_MULTIBYTE)
1145 mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1146 target = _rl_vi_last_search_mbchar;
1148 RL_SETSTATE(RL_STATE_MOREINPUT);
1149 _rl_vi_last_search_char = target = rl_read_key ();
1150 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1157 orig_dir = dir = FTO;
1161 orig_dir = dir = BTO;
1165 orig_dir = dir = FFIND;
1169 orig_dir = dir = BFIND;
1174 #if defined (HANDLE_MULTIBYTE)
1175 return (_rl_char_search_internal (count, dir, target, mb_len));
1177 return (_rl_char_search_internal (count, dir, target));
1181 /* Match brackets */
1183 rl_vi_match (ignore, key)
1186 int count = 1, brack, pos, tmp, pre;
1189 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1191 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1193 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1196 rl_forward_char (1, key);
1197 if (pre == rl_point)
1202 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1203 rl_point < rl_end - 1)
1204 rl_forward_char (1, key);
1221 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1225 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1231 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1234 else if (b == brack)
1248 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1251 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1255 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1258 else if (b == brack)
1279 case ')': return -1;
1281 case ']': return -2;
1283 case '}': return -3;
1288 /* XXX - think about reading an entire mbchar with _rl_read_mbchar and
1289 inserting it in one bunch instead of the loop below (like in
1290 rl_vi_char_search or _rl_vi_change_mbchar_case). Set c to mbchar[0]
1291 for test against 033 or ^C. Make sure that _rl_read_mbchar does
1294 rl_vi_change_char (count, key)
1300 c = _rl_vi_last_replacement;
1303 RL_SETSTATE(RL_STATE_MOREINPUT);
1304 _rl_vi_last_replacement = c = rl_read_key ();
1305 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1308 if (c == '\033' || c == CTRL ('C'))
1311 rl_begin_undo_group ();
1312 while (count-- && rl_point < rl_end)
1315 rl_vi_delete (1, c);
1316 #if defined (HANDLE_MULTIBYTE)
1317 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1319 if (rl_point < p) /* Did we retreat at EOL? */
1321 while (_rl_insert_char (1, c))
1323 RL_SETSTATE (RL_STATE_MOREINPUT);
1325 RL_UNSETSTATE (RL_STATE_MOREINPUT);
1331 if (rl_point < p) /* Did we retreat at EOL? */
1333 _rl_insert_char (1, c);
1336 rl_end_undo_group ();
1342 rl_vi_subst (count, key)
1345 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1346 if (vi_redoing == 0)
1347 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1349 return (rl_vi_change_to (count, 'c'));
1353 rl_vi_overstrike (count, key)
1356 if (_rl_vi_doing_insert == 0)
1358 _rl_vi_doing_insert = 1;
1359 rl_begin_undo_group ();
1364 _rl_overwrite_char (count, key);
1365 vi_replace_count += count;
1372 rl_vi_overstrike_delete (count, key)
1377 for (i = 0; i < count; i++)
1379 if (vi_replace_count == 0)
1390 rl_backward_char (1, key);
1393 if (vi_replace_count == 0 && _rl_vi_doing_insert)
1395 rl_end_undo_group ();
1397 _rl_vi_doing_insert = 0;
1403 rl_vi_replace (count, key)
1408 vi_replace_count = 0;
1410 if (!vi_replace_map)
1412 vi_replace_map = rl_make_bare_keymap ();
1414 for (i = ' '; i < KEYMAP_SIZE; i++)
1415 vi_replace_map[i].function = rl_vi_overstrike;
1417 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1418 vi_replace_map[ESC].function = rl_vi_movement_mode;
1419 vi_replace_map[RETURN].function = rl_newline;
1420 vi_replace_map[NEWLINE].function = rl_newline;
1422 /* If the normal vi insertion keymap has ^H bound to erase, do the
1423 same here. Probably should remove the assignment to RUBOUT up
1424 there, but I don't think it will make a difference in real life. */
1425 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1426 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1427 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1430 _rl_keymap = vi_replace_map;
1435 /* Try to complete the word we are standing on or the word that ends with
1436 the previous character. A space matches everything. Word delimiters are
1439 rl_vi_possible_completions()
1441 int save_pos = rl_point;
1443 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1445 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1446 rl_line_buffer[rl_point] != ';')
1449 else if (rl_line_buffer[rl_point - 1] == ';')
1455 rl_possible_completions ();
1456 rl_point = save_pos;
1462 /* Functions to save and restore marks. */
1464 rl_vi_set_mark (count, key)
1469 RL_SETSTATE(RL_STATE_MOREINPUT);
1470 ch = rl_read_key ();
1471 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1473 if (ch < 'a' || ch > 'z')
1479 vi_mark_chars[ch] = rl_point;
1484 rl_vi_goto_mark (count, key)
1489 RL_SETSTATE(RL_STATE_MOREINPUT);
1490 ch = rl_read_key ();
1491 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1498 else if (ch < 'a' || ch > 'z')
1505 if (vi_mark_chars[ch] == -1)
1510 rl_point = vi_mark_chars[ch];
1514 #endif /* VI_MODE */