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, 1989, 1992 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 /* Non-zero means enter insertion mode. */
67 static int _rl_vi_doing_insert;
69 /* Command keys which do movement for xxx_to commands. */
70 static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|";
72 /* Keymap used for vi replace characters. Created dynamically since
74 static Keymap vi_replace_map;
76 /* The number of characters inserted in the last replace operation. */
77 static int vi_replace_count;
79 /* If non-zero, we have text inserted after a c[motion] command that put
80 us implicitly into insert mode. Some people want this text to be
81 attached to the command so that it is `redoable' with `.'. */
82 static int vi_continued_command;
83 static char *vi_insert_buffer;
84 static int vi_insert_buffer_size;
86 static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
87 static int _rl_vi_last_repeat = 1;
88 static int _rl_vi_last_arg_sign = 1;
89 static int _rl_vi_last_motion;
90 #if defined (HANDLE_MULTIBYTE)
91 static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
93 static int _rl_vi_last_search_char;
95 static int _rl_vi_last_replacement;
97 static int _rl_vi_last_key_before_insert;
99 static int vi_redoing;
101 /* Text modification commands. These are the `redoable' commands. */
102 static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
104 /* Arrays for the saved marks. */
105 static int vi_mark_chars['z' - 'a' + 1];
107 static void _rl_vi_stuff_insert PARAMS((int));
108 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
109 static int rl_digit_loop1 PARAMS((void));
112 _rl_vi_initialize_line ()
116 for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
117 vi_mark_chars[i] = -1;
123 _rl_vi_last_command = 'i';
124 _rl_vi_last_repeat = 1;
125 _rl_vi_last_arg_sign = 1;
126 _rl_vi_last_motion = 0;
130 _rl_vi_set_last (key, repeat, sign)
131 int key, repeat, sign;
133 _rl_vi_last_command = key;
134 _rl_vi_last_repeat = repeat;
135 _rl_vi_last_arg_sign = sign;
138 /* Is the command C a VI mode text modification command? */
140 _rl_vi_textmod_command (c)
143 return (member (c, vi_textmod));
147 _rl_vi_stuff_insert (count)
150 rl_begin_undo_group ();
152 rl_insert_text (vi_insert_buffer);
153 rl_end_undo_group ();
156 /* Bound to `.'. Called from command mode, so we know that we have to
157 redo a text modification command. The default for _rl_vi_last_command
158 puts you back into insert mode. */
160 rl_vi_redo (count, c)
165 if (!rl_explicit_arg)
167 rl_numeric_arg = _rl_vi_last_repeat;
168 rl_arg_sign = _rl_vi_last_arg_sign;
173 /* If we're redoing an insert with `i', stuff in the inserted text
174 and do not go into insertion mode. */
175 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
177 _rl_vi_stuff_insert (count);
178 /* And back up point over the last character inserted. */
183 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
189 /* A placeholder for further expansion. */
191 rl_vi_undo (count, key)
194 return (rl_undo_command (count, key));
197 /* Yank the nth arg from the previous line into this line at point. */
199 rl_vi_yank_arg (count, key)
202 /* Readline thinks that the first word on a line is the 0th, while vi
203 thinks the first word on a line is the 1st. Compensate. */
205 rl_yank_nth_arg (count - 1, 0);
207 rl_yank_nth_arg ('$', 0);
212 /* With an argument, move back that many history lines, else move to the
213 beginning of history. */
215 rl_vi_fetch_history (count, c)
220 /* Giving an argument of n means we want the nth command in the history
221 file. The command number is interpreted the same way that the bash
222 `history' command does it -- that is, giving an argument count of 450
223 to this command would get the command listed as number 450 in the
224 output of `history'. */
227 wanted = history_base + where_history () - count;
229 rl_beginning_of_history (0, 0);
231 rl_get_previous_history (wanted, c);
234 rl_beginning_of_history (count, 0);
238 /* Search again for the last thing searched for. */
240 rl_vi_search_again (count, key)
246 rl_noninc_reverse_search_again (count, key);
250 rl_noninc_forward_search_again (count, key);
256 /* Do a vi style search. */
258 rl_vi_search (count, key)
264 rl_noninc_forward_search (count, key);
268 rl_noninc_reverse_search (count, key);
278 /* Completion, from vi's point of view. */
280 rl_vi_complete (ignore, key)
283 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
285 if (!whitespace (rl_line_buffer[rl_point + 1]))
286 rl_vi_end_word (1, 'E');
291 rl_complete_internal ('*'); /* Expansion and replacement. */
293 rl_complete_internal ('?'); /* List possible completions. */
294 else if (key == '\\')
295 rl_complete_internal (TAB); /* Standard Readline completion. */
297 rl_complete (0, key);
299 if (key == '*' || key == '\\')
301 _rl_vi_set_last (key, 1, rl_arg_sign);
302 rl_vi_insertion_mode (1, key);
307 /* Tilde expansion for vi mode. */
309 rl_vi_tilde_expand (ignore, key)
312 rl_tilde_expand (0, key);
313 _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */
314 rl_vi_insertion_mode (1, key);
318 /* Previous word in vi mode. */
320 rl_vi_prev_word (count, key)
324 return (rl_vi_next_word (-count, key));
332 if (_rl_uppercase_p (key))
333 rl_vi_bWord (count, key);
335 rl_vi_bword (count, key);
340 /* Next word in vi mode. */
342 rl_vi_next_word (count, key)
346 return (rl_vi_prev_word (-count, key));
348 if (rl_point >= (rl_end - 1))
354 if (_rl_uppercase_p (key))
355 rl_vi_fWord (count, key);
357 rl_vi_fword (count, key);
361 /* Move to the end of the ?next? word. */
363 rl_vi_end_word (count, key)
372 if (_rl_uppercase_p (key))
373 rl_vi_eWord (count, key);
375 rl_vi_eword (count, key);
379 /* Move forward a word the way that 'W' does. */
381 rl_vi_fWord (count, ignore)
384 while (count-- && rl_point < (rl_end - 1))
386 /* Skip until whitespace. */
387 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
390 /* Now skip whitespace. */
391 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
398 rl_vi_bWord (count, ignore)
401 while (count-- && rl_point > 0)
403 /* If we are at the start of a word, move back to whitespace so
404 we will go back to the start of the previous word. */
405 if (!whitespace (rl_line_buffer[rl_point]) &&
406 whitespace (rl_line_buffer[rl_point - 1]))
409 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
414 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
422 rl_vi_eWord (count, ignore)
425 while (count-- && rl_point < (rl_end - 1))
427 if (!whitespace (rl_line_buffer[rl_point]))
430 /* Move to the next non-whitespace character (to the start of the
432 while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
434 if (rl_point && rl_point < rl_end)
436 /* Skip whitespace. */
437 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
440 /* Skip until whitespace. */
441 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
444 /* Move back to the last character of the word. */
452 rl_vi_fword (count, ignore)
455 while (count-- && rl_point < (rl_end - 1))
457 /* Move to white space (really non-identifer). */
458 if (_rl_isident (rl_line_buffer[rl_point]))
460 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
463 else /* if (!whitespace (rl_line_buffer[rl_point])) */
465 while (!_rl_isident (rl_line_buffer[rl_point]) &&
466 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
470 /* Move past whitespace. */
471 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
478 rl_vi_bword (count, ignore)
481 while (count-- && rl_point > 0)
485 /* If we are at the start of a word, move back to whitespace
486 so we will go back to the start of the previous word. */
487 if (!whitespace (rl_line_buffer[rl_point]) &&
488 whitespace (rl_line_buffer[rl_point - 1]))
491 /* If this character and the previous character are `opposite', move
492 back so we don't get messed up by the rl_point++ down there in
493 the while loop. Without this code, words like `l;' screw up the
495 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
496 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
497 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
500 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
505 if (_rl_isident (rl_line_buffer[rl_point]))
506 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
508 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
509 !whitespace (rl_line_buffer[rl_point]));
517 rl_vi_eword (count, ignore)
520 while (count-- && rl_point < rl_end - 1)
522 if (!whitespace (rl_line_buffer[rl_point]))
525 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
528 if (rl_point < rl_end)
530 if (_rl_isident (rl_line_buffer[rl_point]))
531 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
533 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
534 && !whitespace (rl_line_buffer[rl_point]));
542 rl_vi_insert_beg (count, key)
545 rl_beg_of_line (1, key);
546 rl_vi_insertion_mode (1, key);
551 rl_vi_append_mode (count, key)
554 if (rl_point < rl_end)
556 if (MB_CUR_MAX == 1 || rl_byte_oriented)
560 int point = rl_point;
561 rl_forward_char (1, key);
562 if (point == rl_point)
566 rl_vi_insertion_mode (1, key);
571 rl_vi_append_eol (count, key)
574 rl_end_of_line (1, key);
575 rl_vi_append_mode (1, key);
579 /* What to do in the case of C-d. */
581 rl_vi_eof_maybe (count, c)
584 return (rl_newline (1, '\n'));
587 /* Insertion mode stuff. */
589 /* Switching from one mode to the other really just involves
590 switching keymaps. */
592 rl_vi_insertion_mode (count, key)
595 _rl_keymap = vi_insertion_keymap;
596 _rl_vi_last_key_before_insert = key;
601 _rl_vi_save_insert (up)
608 if (vi_insert_buffer_size >= 1)
609 vi_insert_buffer[0] = '\0';
615 len = end - start + 1;
616 if (len >= vi_insert_buffer_size)
618 vi_insert_buffer_size += (len + 32) - (len % 32);
619 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
621 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
622 vi_insert_buffer[len-1] = '\0';
626 _rl_vi_done_inserting ()
628 if (_rl_vi_doing_insert)
630 /* The `C', `s', and `S' commands set this. */
631 rl_end_undo_group ();
632 /* Now, the text between rl_undo_list->next->start and
633 rl_undo_list->next->end is what was inserted while in insert
634 mode. It gets copied to VI_INSERT_BUFFER because it depends
635 on absolute indices into the line which may change (though they
636 probably will not). */
637 _rl_vi_doing_insert = 0;
638 _rl_vi_save_insert (rl_undo_list->next);
639 vi_continued_command = 1;
643 if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
644 _rl_vi_save_insert (rl_undo_list);
645 /* XXX - Other keys probably need to be checked. */
646 else if (_rl_vi_last_key_before_insert == 'C')
647 rl_end_undo_group ();
648 while (_rl_undo_group_level > 0)
649 rl_end_undo_group ();
650 vi_continued_command = 0;
655 rl_vi_movement_mode (count, key)
659 rl_backward_char (1, key);
661 _rl_keymap = vi_movement_keymap;
662 _rl_vi_done_inserting ();
667 rl_vi_arg_digit (count, c)
670 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
671 return (rl_beg_of_line (1, c));
673 return (rl_digit_argument (count, c));
676 /* Change the case of the next COUNT characters. */
677 #if defined (HANDLE_MULTIBYTE)
679 _rl_vi_change_mbchar_case (count)
683 char mb[MB_LEN_MAX+1];
687 memset (&ps, 0, sizeof (mbstate_t));
688 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
690 while (count-- && rl_point < rl_end)
692 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
695 else if (iswlower (wc))
699 /* Just skip over chars neither upper nor lower case */
700 rl_forward_char (1, 0);
704 /* Vi is kind of strange here. */
707 mblen = wctomb (mb, wc);
710 rl_begin_undo_group ();
713 rl_end_undo_group ();
717 rl_forward_char (1, 0);
725 rl_vi_change_case (count, ignore)
730 /* Don't try this on an empty line. */
731 if (rl_point >= rl_end)
734 #if defined (HANDLE_MULTIBYTE)
735 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
736 return (_rl_vi_change_mbchar_case (count));
739 while (count-- && rl_point < rl_end)
741 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
742 c = _rl_to_lower (rl_line_buffer[rl_point]);
743 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
744 c = _rl_to_upper (rl_line_buffer[rl_point]);
747 /* Just skip over characters neither upper nor lower case. */
748 rl_forward_char (1, c);
752 /* Vi is kind of strange here. */
755 rl_begin_undo_group ();
757 _rl_insert_char (1, c);
758 rl_end_undo_group ();
762 rl_forward_char (1, c);
768 rl_vi_put (count, key)
771 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
772 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
775 rl_backward_char (1, key);
782 if (rl_point && rl_point == rl_end)
784 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
785 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
793 rl_vi_column (count, key)
797 rl_end_of_line (1, key);
799 rl_point = count - 1;
804 rl_vi_domove (key, nextkey)
811 RL_SETSTATE(RL_STATE_MOREINPUT);
813 RL_UNSETSTATE(RL_STATE_MOREINPUT);
816 if (!member (c, vi_motion))
820 save = rl_numeric_arg;
821 rl_numeric_arg = _rl_digit_value (c);
823 rl_numeric_arg *= save;
824 RL_SETSTATE(RL_STATE_MOREINPUT);
825 c = rl_read_key (); /* real command */
826 RL_UNSETSTATE(RL_STATE_MOREINPUT);
829 else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
832 rl_beg_of_line (1, c);
833 _rl_vi_last_motion = c;
840 _rl_vi_last_motion = c;
842 /* Append a blank character temporarily so that the motion routines
843 work right at the end of the line. */
845 rl_line_buffer[rl_end++] = ' ';
846 rl_line_buffer[rl_end] = '\0';
848 _rl_dispatch (c, _rl_keymap);
850 /* Remove the blank that we added. */
852 rl_line_buffer[rl_end] = '\0';
853 if (rl_point > rl_end)
856 /* No change in position means the command failed. */
857 if (rl_mark == rl_point)
860 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
861 word. If we are not at the end of the line, and we are on a
862 non-whitespace character, move back one (presumably to whitespace). */
863 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
864 !whitespace (rl_line_buffer[rl_point]))
867 /* If cw or cW, back up to the end of a word, so the behaviour of ce
868 or cE is the actual result. Brute-force, no subtlety. */
869 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
871 /* Don't move farther back than where we started. */
872 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
875 /* Posix.2 says that if cw or cW moves the cursor towards the end of
876 the line, the character under the cursor should be deleted. */
877 if (rl_point == rl_mark)
881 /* Move past the end of the word so that the kill doesn't
882 remove the last letter of the previous word. Only do this
883 if we are not at the end of the line. */
884 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
889 if (rl_mark < rl_point)
890 SWAP (rl_point, rl_mark);
895 /* A simplified loop for vi. Don't dispatch key at end.
896 Don't recognize minus sign?
897 Should this do rl_save_prompt/rl_restore_prompt? */
903 RL_SETSTATE(RL_STATE_NUMERICARG);
906 if (rl_numeric_arg > 1000000)
908 rl_explicit_arg = rl_numeric_arg = 0;
911 RL_UNSETSTATE(RL_STATE_NUMERICARG);
914 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
915 RL_SETSTATE(RL_STATE_MOREINPUT);
916 key = c = rl_read_key ();
917 RL_UNSETSTATE(RL_STATE_MOREINPUT);
919 if (c >= 0 && _rl_keymap[c].type == ISFUNC &&
920 _rl_keymap[c].function == rl_universal_argument)
930 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
932 rl_numeric_arg = _rl_digit_value (c);
943 RL_UNSETSTATE(RL_STATE_NUMERICARG);
948 rl_vi_delete_to (count, key)
953 if (_rl_uppercase_p (key))
956 rl_stuff_char (_rl_vi_last_motion);
958 if (rl_vi_domove (key, &c))
964 /* These are the motion commands that do not require adjusting the
966 if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
969 rl_kill_text (rl_point, rl_mark);
974 rl_vi_change_to (count, key)
979 if (_rl_uppercase_p (key))
982 rl_stuff_char (_rl_vi_last_motion);
984 start_pos = rl_point;
986 if (rl_vi_domove (key, &c))
992 /* These are the motion commands that do not require adjusting the
993 mark. c[wW] are handled by special-case code in rl_vi_domove(),
994 and already leave the mark at the correct location. */
995 if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
998 /* The cursor never moves with c[wW]. */
999 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
1000 rl_point = start_pos;
1004 if (vi_insert_buffer && *vi_insert_buffer)
1005 rl_begin_undo_group ();
1006 rl_delete_text (rl_point, rl_mark);
1007 if (vi_insert_buffer && *vi_insert_buffer)
1009 rl_insert_text (vi_insert_buffer);
1010 rl_end_undo_group ();
1015 rl_begin_undo_group (); /* to make the `u' command work */
1016 rl_kill_text (rl_point, rl_mark);
1017 /* `C' does not save the text inserted for undoing or redoing. */
1018 if (_rl_uppercase_p (key) == 0)
1019 _rl_vi_doing_insert = 1;
1020 _rl_vi_set_last (key, count, rl_arg_sign);
1021 rl_vi_insertion_mode (1, key);
1028 rl_vi_yank_to (count, key)
1031 int c, save = rl_point;
1033 if (_rl_uppercase_p (key))
1034 rl_stuff_char ('$');
1036 if (rl_vi_domove (key, &c))
1042 /* These are the motion commands that do not require adjusting the
1044 if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
1047 rl_begin_undo_group ();
1048 rl_kill_text (rl_point, rl_mark);
1049 rl_end_undo_group ();
1057 rl_vi_delete (count, key)
1068 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1069 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1071 end = rl_point + count;
1076 rl_kill_text (rl_point, end);
1078 if (rl_point > 0 && rl_point == rl_end)
1079 rl_backward_char (1, key);
1084 rl_vi_back_to_indent (count, key)
1087 rl_beg_of_line (1, key);
1088 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1094 rl_vi_first_print (count, key)
1097 return (rl_vi_back_to_indent (1, key));
1101 rl_vi_char_search (count, key)
1104 #if defined (HANDLE_MULTIBYTE)
1105 static char *target;
1110 static int orig_dir, dir;
1112 if (key == ';' || key == ',')
1113 dir = key == ';' ? orig_dir : -orig_dir;
1117 #if defined (HANDLE_MULTIBYTE)
1118 target = _rl_vi_last_search_mbchar;
1120 target = _rl_vi_last_search_char;
1124 #if defined (HANDLE_MULTIBYTE)
1125 mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1126 target = _rl_vi_last_search_mbchar;
1128 RL_SETSTATE(RL_STATE_MOREINPUT);
1129 _rl_vi_last_search_char = target = rl_read_key ();
1130 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1137 orig_dir = dir = FTO;
1141 orig_dir = dir = BTO;
1145 orig_dir = dir = FFIND;
1149 orig_dir = dir = BFIND;
1154 #if defined (HANDLE_MULTIBYTE)
1155 return (_rl_char_search_internal (count, dir, target, mb_len));
1157 return (_rl_char_search_internal (count, dir, target));
1161 /* Match brackets */
1163 rl_vi_match (ignore, key)
1166 int count = 1, brack, pos, tmp, pre;
1169 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1171 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1173 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1176 rl_forward_char (1, key);
1177 if (pre == rl_point)
1182 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1183 rl_point < rl_end - 1)
1184 rl_forward_char (1, key);
1201 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1205 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1211 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1214 else if (b == brack)
1228 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1231 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1235 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1238 else if (b == brack)
1259 case ')': return -1;
1261 case ']': return -2;
1263 case '}': return -3;
1268 /* XXX - think about reading an entire mbchar with _rl_read_mbchar and
1269 inserting it in one bunch instead of the loop below (like in
1270 rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0]
1271 for test against 033 or ^C. Make sure that _rl_read_mbchar does
1274 rl_vi_change_char (count, key)
1280 c = _rl_vi_last_replacement;
1283 RL_SETSTATE(RL_STATE_MOREINPUT);
1284 _rl_vi_last_replacement = c = rl_read_key ();
1285 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1288 if (c == '\033' || c == CTRL ('C'))
1291 while (count-- && rl_point < rl_end)
1293 rl_begin_undo_group ();
1296 #if defined (HANDLE_MULTIBYTE)
1297 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1298 while (_rl_insert_char (1, c))
1300 RL_SETSTATE (RL_STATE_MOREINPUT);
1302 RL_UNSETSTATE (RL_STATE_MOREINPUT);
1306 _rl_insert_char (1, c);
1308 rl_backward_char (1, c);
1310 rl_end_undo_group ();
1316 rl_vi_subst (count, key)
1319 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1320 if (vi_redoing == 0)
1321 rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */
1323 return (rl_vi_change_to (count, 'c'));
1327 rl_vi_overstrike (count, key)
1330 if (_rl_vi_doing_insert == 0)
1332 _rl_vi_doing_insert = 1;
1333 rl_begin_undo_group ();
1338 _rl_overwrite_char (count, key);
1339 vi_replace_count += count;
1346 rl_vi_overstrike_delete (count, key)
1351 for (i = 0; i < count; i++)
1353 if (vi_replace_count == 0)
1364 rl_backward_char (1, key);
1367 if (vi_replace_count == 0 && _rl_vi_doing_insert)
1369 rl_end_undo_group ();
1371 _rl_vi_doing_insert = 0;
1377 rl_vi_replace (count, key)
1382 vi_replace_count = 0;
1384 if (!vi_replace_map)
1386 vi_replace_map = rl_make_bare_keymap ();
1388 for (i = ' '; i < KEYMAP_SIZE; i++)
1389 vi_replace_map[i].function = rl_vi_overstrike;
1391 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1392 vi_replace_map[ESC].function = rl_vi_movement_mode;
1393 vi_replace_map[RETURN].function = rl_newline;
1394 vi_replace_map[NEWLINE].function = rl_newline;
1396 /* If the normal vi insertion keymap has ^H bound to erase, do the
1397 same here. Probably should remove the assignment to RUBOUT up
1398 there, but I don't think it will make a difference in real life. */
1399 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1400 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1401 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1404 _rl_keymap = vi_replace_map;
1409 /* Try to complete the word we are standing on or the word that ends with
1410 the previous character. A space matches everything. Word delimiters are
1413 rl_vi_possible_completions()
1415 int save_pos = rl_point;
1417 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1419 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1420 rl_line_buffer[rl_point] != ';')
1423 else if (rl_line_buffer[rl_point - 1] == ';')
1429 rl_possible_completions ();
1430 rl_point = save_pos;
1436 /* Functions to save and restore marks. */
1438 rl_vi_set_mark (count, key)
1443 RL_SETSTATE(RL_STATE_MOREINPUT);
1444 ch = rl_read_key ();
1445 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1447 if (ch < 'a' || ch > 'z')
1453 vi_mark_chars[ch] = rl_point;
1458 rl_vi_goto_mark (count, key)
1463 RL_SETSTATE(RL_STATE_MOREINPUT);
1464 ch = rl_read_key ();
1465 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1472 else if (ch < 'a' || ch > 'z')
1479 if (vi_mark_chars[ch] == -1)
1484 rl_point = vi_mark_chars[ch];
1488 #endif /* VI_MODE */