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. */
57 #include "rlprivate.h"
61 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
65 #define exchange(x, y) do {int temp = x; x = y; y = temp;} while (0)
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_command = 'i'; /* default `.' puts you in insert mode */
89 static int _rl_vi_last_repeat = 1;
90 static int _rl_vi_last_arg_sign = 1;
91 static int _rl_vi_last_motion;
92 static int _rl_vi_last_search_char;
93 static int _rl_vi_last_replacement;
95 static int _rl_vi_last_key_before_insert;
97 static int vi_redoing;
99 /* Text modification commands. These are the `redoable' commands. */
100 static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
102 /* Arrays for the saved marks. */
103 static int vi_mark_chars['z' - 'a' + 1];
105 static void _rl_vi_stuff_insert PARAMS((int));
106 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
107 static int rl_digit_loop1 PARAMS((void));
110 _rl_vi_initialize_line ()
114 for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
115 vi_mark_chars[i] = -1;
121 _rl_vi_last_command = 'i';
122 _rl_vi_last_repeat = 1;
123 _rl_vi_last_arg_sign = 1;
124 _rl_vi_last_motion = 0;
128 _rl_vi_set_last (key, repeat, sign)
129 int key, repeat, sign;
131 _rl_vi_last_command = key;
132 _rl_vi_last_repeat = repeat;
133 _rl_vi_last_arg_sign = sign;
136 /* Is the command C a VI mode text modification command? */
138 _rl_vi_textmod_command (c)
141 return (member (c, vi_textmod));
145 _rl_vi_stuff_insert (count)
148 rl_begin_undo_group ();
150 rl_insert_text (vi_insert_buffer);
151 rl_end_undo_group ();
154 /* Bound to `.'. Called from command mode, so we know that we have to
155 redo a text modification command. The default for _rl_vi_last_command
156 puts you back into insert mode. */
158 rl_vi_redo (count, c)
161 if (!rl_explicit_arg)
163 rl_numeric_arg = _rl_vi_last_repeat;
164 rl_arg_sign = _rl_vi_last_arg_sign;
168 /* If we're redoing an insert with `i', stuff in the inserted text
169 and do not go into insertion mode. */
170 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
172 _rl_vi_stuff_insert (count);
173 /* And back up point over the last character inserted. */
178 _rl_dispatch (_rl_vi_last_command, _rl_keymap);
184 /* A placeholder for further expansion. */
186 rl_vi_undo (count, key)
189 return (rl_undo_command (count, key));
192 /* Yank the nth arg from the previous line into this line at point. */
194 rl_vi_yank_arg (count, key)
197 /* Readline thinks that the first word on a line is the 0th, while vi
198 thinks the first word on a line is the 1st. Compensate. */
200 rl_yank_nth_arg (count - 1, 0);
202 rl_yank_nth_arg ('$', 0);
207 /* With an argument, move back that many history lines, else move to the
208 beginning of history. */
210 rl_vi_fetch_history (count, c)
215 /* Giving an argument of n means we want the nth command in the history
216 file. The command number is interpreted the same way that the bash
217 `history' command does it -- that is, giving an argument count of 450
218 to this command would get the command listed as number 450 in the
219 output of `history'. */
222 wanted = history_base + where_history () - count;
224 rl_beginning_of_history (0, 0);
226 rl_get_previous_history (wanted, c);
229 rl_beginning_of_history (count, 0);
233 /* Search again for the last thing searched for. */
235 rl_vi_search_again (count, key)
241 rl_noninc_reverse_search_again (count, key);
245 rl_noninc_forward_search_again (count, key);
251 /* Do a vi style search. */
253 rl_vi_search (count, key)
259 rl_noninc_forward_search (count, key);
263 rl_noninc_reverse_search (count, key);
273 /* Completion, from vi's point of view. */
275 rl_vi_complete (ignore, key)
278 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
280 if (!whitespace (rl_line_buffer[rl_point + 1]))
281 rl_vi_end_word (1, 'E');
286 rl_complete_internal ('*'); /* Expansion and replacement. */
288 rl_complete_internal ('?'); /* List possible completions. */
289 else if (key == '\\')
290 rl_complete_internal (TAB); /* Standard Readline completion. */
292 rl_complete (0, key);
294 if (key == '*' || key == '\\')
296 _rl_vi_set_last (key, 1, rl_arg_sign);
297 rl_vi_insertion_mode (1, key);
302 /* Tilde expansion for vi mode. */
304 rl_vi_tilde_expand (ignore, key)
307 rl_tilde_expand (0, key);
308 _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */
309 rl_vi_insertion_mode (1, key);
313 /* Previous word in vi mode. */
315 rl_vi_prev_word (count, key)
319 return (rl_vi_next_word (-count, key));
327 if (_rl_uppercase_p (key))
328 rl_vi_bWord (count, key);
330 rl_vi_bword (count, key);
335 /* Next word in vi mode. */
337 rl_vi_next_word (count, key)
341 return (rl_vi_prev_word (-count, key));
343 if (rl_point >= (rl_end - 1))
349 if (_rl_uppercase_p (key))
350 rl_vi_fWord (count, key);
352 rl_vi_fword (count, key);
356 /* Move to the end of the ?next? word. */
358 rl_vi_end_word (count, key)
367 if (_rl_uppercase_p (key))
368 rl_vi_eWord (count, key);
370 rl_vi_eword (count, key);
374 /* Move forward a word the way that 'W' does. */
376 rl_vi_fWord (count, ignore)
379 while (count-- && rl_point < (rl_end - 1))
381 /* Skip until whitespace. */
382 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
385 /* Now skip whitespace. */
386 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
393 rl_vi_bWord (count, ignore)
396 while (count-- && rl_point > 0)
398 /* If we are at the start of a word, move back to whitespace so
399 we will go back to the start of the previous word. */
400 if (!whitespace (rl_line_buffer[rl_point]) &&
401 whitespace (rl_line_buffer[rl_point - 1]))
404 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
409 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
417 rl_vi_eWord (count, ignore)
420 while (count-- && rl_point < (rl_end - 1))
422 if (!whitespace (rl_line_buffer[rl_point]))
425 /* Move to the next non-whitespace character (to the start of the
427 while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
429 if (rl_point && rl_point < rl_end)
431 /* Skip whitespace. */
432 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
435 /* Skip until whitespace. */
436 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
439 /* Move back to the last character of the word. */
447 rl_vi_fword (count, ignore)
450 while (count-- && rl_point < (rl_end - 1))
452 /* Move to white space (really non-identifer). */
453 if (_rl_isident (rl_line_buffer[rl_point]))
455 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
458 else /* if (!whitespace (rl_line_buffer[rl_point])) */
460 while (!_rl_isident (rl_line_buffer[rl_point]) &&
461 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
465 /* Move past whitespace. */
466 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
473 rl_vi_bword (count, ignore)
476 while (count-- && rl_point > 0)
480 /* If we are at the start of a word, move back to whitespace
481 so we will go back to the start of the previous word. */
482 if (!whitespace (rl_line_buffer[rl_point]) &&
483 whitespace (rl_line_buffer[rl_point - 1]))
486 /* If this character and the previous character are `opposite', move
487 back so we don't get messed up by the rl_point++ down there in
488 the while loop. Without this code, words like `l;' screw up the
490 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
491 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
492 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
495 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
500 if (_rl_isident (rl_line_buffer[rl_point]))
501 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
503 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
504 !whitespace (rl_line_buffer[rl_point]));
512 rl_vi_eword (count, ignore)
515 while (count-- && rl_point < rl_end - 1)
517 if (!whitespace (rl_line_buffer[rl_point]))
520 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
523 if (rl_point < rl_end)
525 if (_rl_isident (rl_line_buffer[rl_point]))
526 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
528 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
529 && !whitespace (rl_line_buffer[rl_point]));
537 rl_vi_insert_beg (count, key)
540 rl_beg_of_line (1, key);
541 rl_vi_insertion_mode (1, key);
546 rl_vi_append_mode (count, key)
549 if (rl_point < rl_end)
551 rl_vi_insertion_mode (1, key);
556 rl_vi_append_eol (count, key)
559 rl_end_of_line (1, key);
560 rl_vi_append_mode (1, key);
564 /* What to do in the case of C-d. */
566 rl_vi_eof_maybe (count, c)
569 return (rl_newline (1, '\n'));
572 /* Insertion mode stuff. */
574 /* Switching from one mode to the other really just involves
575 switching keymaps. */
577 rl_vi_insertion_mode (count, key)
580 _rl_keymap = vi_insertion_keymap;
581 _rl_vi_last_key_before_insert = key;
586 _rl_vi_save_insert (up)
593 if (vi_insert_buffer_size >= 1)
594 vi_insert_buffer[0] = '\0';
600 len = end - start + 1;
601 if (len >= vi_insert_buffer_size)
603 vi_insert_buffer_size += (len + 32) - (len % 32);
604 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
606 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
607 vi_insert_buffer[len-1] = '\0';
611 _rl_vi_done_inserting ()
613 if (_rl_vi_doing_insert)
615 rl_end_undo_group ();
616 /* Now, the text between rl_undo_list->next->start and
617 rl_undo_list->next->end is what was inserted while in insert
618 mode. It gets copied to VI_INSERT_BUFFER because it depends
619 on absolute indices into the line which may change (though they
620 probably will not). */
621 _rl_vi_doing_insert = 0;
622 _rl_vi_save_insert (rl_undo_list->next);
623 vi_continued_command = 1;
627 if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
628 _rl_vi_save_insert (rl_undo_list);
629 /* XXX - Other keys probably need to be checked. */
630 else if (_rl_vi_last_key_before_insert == 'C')
631 rl_end_undo_group ();
632 while (_rl_undo_group_level > 0)
633 rl_end_undo_group ();
634 vi_continued_command = 0;
639 rl_vi_movement_mode (count, key)
643 rl_backward (1, key);
645 _rl_keymap = vi_movement_keymap;
646 _rl_vi_done_inserting ();
651 rl_vi_arg_digit (count, c)
654 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
655 return (rl_beg_of_line (1, c));
657 return (rl_digit_argument (count, c));
661 rl_vi_change_case (count, ignore)
666 /* Don't try this on an empty line. */
667 if (rl_point >= rl_end)
670 while (count-- && rl_point < rl_end)
672 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
673 c = _rl_to_lower (rl_line_buffer[rl_point]);
674 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
675 c = _rl_to_upper (rl_line_buffer[rl_point]);
678 /* Just skip over characters neither upper nor lower case. */
683 /* Vi is kind of strange here. */
686 rl_begin_undo_group ();
689 rl_end_undo_group ();
699 rl_vi_put (count, key)
702 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
706 rl_backward (1, key);
713 if (rl_point && rl_point == rl_end)
719 rl_vi_column (count, key)
723 rl_end_of_line (1, key);
725 rl_point = count - 1;
730 rl_vi_domove (key, nextkey)
737 RL_SETSTATE(RL_STATE_MOREINPUT);
739 RL_UNSETSTATE(RL_STATE_MOREINPUT);
742 if (!member (c, vi_motion))
746 save = rl_numeric_arg;
747 rl_numeric_arg = _rl_digit_value (c);
749 rl_numeric_arg *= save;
750 RL_SETSTATE(RL_STATE_MOREINPUT);
751 c = rl_read_key (); /* real command */
752 RL_UNSETSTATE(RL_STATE_MOREINPUT);
755 else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
758 rl_beg_of_line (1, c);
759 _rl_vi_last_motion = c;
766 _rl_vi_last_motion = c;
768 /* Append a blank character temporarily so that the motion routines
769 work right at the end of the line. */
771 rl_line_buffer[rl_end++] = ' ';
772 rl_line_buffer[rl_end] = '\0';
774 _rl_dispatch (c, _rl_keymap);
776 /* Remove the blank that we added. */
778 rl_line_buffer[rl_end] = '\0';
779 if (rl_point > rl_end)
782 /* No change in position means the command failed. */
783 if (rl_mark == rl_point)
786 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
787 word. If we are not at the end of the line, and we are on a
788 non-whitespace character, move back one (presumably to whitespace). */
789 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
790 !whitespace (rl_line_buffer[rl_point]))
793 /* If cw or cW, back up to the end of a word, so the behaviour of ce
794 or cE is the actual result. Brute-force, no subtlety. */
795 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
797 /* Don't move farther back than where we started. */
798 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
801 /* Posix.2 says that if cw or cW moves the cursor towards the end of
802 the line, the character under the cursor should be deleted. */
803 if (rl_point == rl_mark)
807 /* Move past the end of the word so that the kill doesn't
808 remove the last letter of the previous word. Only do this
809 if we are not at the end of the line. */
810 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
815 if (rl_mark < rl_point)
816 exchange (rl_point, rl_mark);
821 /* A simplified loop for vi. Don't dispatch key at end.
822 Don't recognize minus sign?
823 Should this do rl_save_prompt/rl_restore_prompt? */
829 RL_SETSTATE(RL_STATE_NUMERICARG);
832 if (rl_numeric_arg > 1000000)
834 rl_explicit_arg = rl_numeric_arg = 0;
837 RL_UNSETSTATE(RL_STATE_NUMERICARG);
840 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
841 RL_SETSTATE(RL_STATE_MOREINPUT);
842 key = c = rl_read_key ();
843 RL_UNSETSTATE(RL_STATE_MOREINPUT);
845 if (c >= 0 && _rl_keymap[c].type == ISFUNC &&
846 _rl_keymap[c].function == rl_universal_argument)
856 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
858 rl_numeric_arg = _rl_digit_value (c);
869 RL_UNSETSTATE(RL_STATE_NUMERICARG);
874 rl_vi_delete_to (count, key)
879 if (_rl_uppercase_p (key))
882 rl_stuff_char (_rl_vi_last_motion);
884 if (rl_vi_domove (key, &c))
890 /* These are the motion commands that do not require adjusting the
892 if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
895 rl_kill_text (rl_point, rl_mark);
900 rl_vi_change_to (count, key)
905 if (_rl_uppercase_p (key))
908 rl_stuff_char (_rl_vi_last_motion);
910 start_pos = rl_point;
912 if (rl_vi_domove (key, &c))
918 /* These are the motion commands that do not require adjusting the
919 mark. c[wW] are handled by special-case code in rl_vi_domove(),
920 and already leave the mark at the correct location. */
921 if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
924 /* The cursor never moves with c[wW]. */
925 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
926 rl_point = start_pos;
930 if (vi_insert_buffer && *vi_insert_buffer)
931 rl_begin_undo_group ();
932 rl_delete_text (rl_point, rl_mark);
933 if (vi_insert_buffer && *vi_insert_buffer)
935 rl_insert_text (vi_insert_buffer);
936 rl_end_undo_group ();
941 rl_begin_undo_group (); /* to make the `u' command work */
942 rl_kill_text (rl_point, rl_mark);
943 /* `C' does not save the text inserted for undoing or redoing. */
944 if (_rl_uppercase_p (key) == 0)
945 _rl_vi_doing_insert = 1;
946 _rl_vi_set_last (key, count, rl_arg_sign);
947 rl_vi_insertion_mode (1, key);
954 rl_vi_yank_to (count, key)
957 int c, save = rl_point;
959 if (_rl_uppercase_p (key))
962 if (rl_vi_domove (key, &c))
968 /* These are the motion commands that do not require adjusting the
970 if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
973 rl_begin_undo_group ();
974 rl_kill_text (rl_point, rl_mark);
975 rl_end_undo_group ();
983 rl_vi_delete (count, key)
994 end = rl_point + count;
999 rl_kill_text (rl_point, end);
1001 if (rl_point > 0 && rl_point == rl_end)
1002 rl_backward (1, key);
1007 rl_vi_back_to_indent (count, key)
1010 rl_beg_of_line (1, key);
1011 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1017 rl_vi_first_print (count, key)
1020 return (rl_vi_back_to_indent (1, key));
1024 rl_vi_char_search (count, key)
1028 static int orig_dir, dir;
1030 if (key == ';' || key == ',')
1031 dir = key == ';' ? orig_dir : -orig_dir;
1035 target = _rl_vi_last_search_char;
1038 RL_SETSTATE(RL_STATE_MOREINPUT);
1039 _rl_vi_last_search_char = target = rl_read_key ();
1040 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1046 orig_dir = dir = FTO;
1050 orig_dir = dir = BTO;
1054 orig_dir = dir = FFIND;
1058 orig_dir = dir = BFIND;
1063 return (_rl_char_search_internal (count, dir, target));
1066 /* Match brackets */
1068 rl_vi_match (ignore, key)
1071 int count = 1, brack, pos;
1074 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1076 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1077 rl_point < rl_end - 1)
1078 rl_forward (1, key);
1096 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1099 else if (b == brack)
1115 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1118 else if (b == brack)
1139 case ')': return -1;
1141 case ']': return -2;
1143 case '}': return -3;
1149 rl_vi_change_char (count, key)
1155 c = _rl_vi_last_replacement;
1158 RL_SETSTATE(RL_STATE_MOREINPUT);
1159 _rl_vi_last_replacement = c = rl_read_key ();
1160 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1163 if (c == '\033' || c == CTRL ('C'))
1166 while (count-- && rl_point < rl_end)
1168 rl_begin_undo_group ();
1175 rl_end_undo_group ();
1181 rl_vi_subst (count, key)
1184 rl_begin_undo_group ();
1186 if (_rl_uppercase_p (key))
1188 rl_beg_of_line (1, key);
1189 rl_kill_line (1, key);
1192 rl_delete_text (rl_point, rl_point+count);
1194 rl_end_undo_group ();
1196 _rl_vi_set_last (key, count, rl_arg_sign);
1200 int o = _rl_doing_an_undo;
1202 _rl_doing_an_undo = 1;
1203 if (vi_insert_buffer && *vi_insert_buffer)
1204 rl_insert_text (vi_insert_buffer);
1205 _rl_doing_an_undo = o;
1209 rl_begin_undo_group ();
1210 _rl_vi_doing_insert = 1;
1211 rl_vi_insertion_mode (1, key);
1218 rl_vi_overstrike (count, key)
1223 if (_rl_vi_doing_insert == 0)
1225 _rl_vi_doing_insert = 1;
1226 rl_begin_undo_group ();
1229 for (i = 0; i < count; i++)
1232 rl_begin_undo_group ();
1234 if (rl_point < rl_end)
1242 rl_end_undo_group ();
1248 rl_vi_overstrike_delete (count, key)
1253 for (i = 0; i < count; i++)
1255 if (vi_replace_count == 0)
1266 rl_backward (1, key);
1269 if (vi_replace_count == 0 && _rl_vi_doing_insert)
1271 rl_end_undo_group ();
1273 _rl_vi_doing_insert = 0;
1279 rl_vi_replace (count, key)
1284 vi_replace_count = 0;
1286 if (!vi_replace_map)
1288 vi_replace_map = rl_make_bare_keymap ();
1290 for (i = ' '; i < KEYMAP_SIZE; i++)
1291 vi_replace_map[i].function = rl_vi_overstrike;
1293 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1294 vi_replace_map[ESC].function = rl_vi_movement_mode;
1295 vi_replace_map[RETURN].function = rl_newline;
1296 vi_replace_map[NEWLINE].function = rl_newline;
1298 /* If the normal vi insertion keymap has ^H bound to erase, do the
1299 same here. Probably should remove the assignment to RUBOUT up
1300 there, but I don't think it will make a difference in real life. */
1301 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1302 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1303 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1306 _rl_keymap = vi_replace_map;
1311 /* Try to complete the word we are standing on or the word that ends with
1312 the previous character. A space matches everything. Word delimiters are
1315 rl_vi_possible_completions()
1317 int save_pos = rl_point;
1319 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1321 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1322 rl_line_buffer[rl_point] != ';')
1325 else if (rl_line_buffer[rl_point - 1] == ';')
1331 rl_possible_completions ();
1332 rl_point = save_pos;
1338 /* Functions to save and restore marks. */
1340 rl_vi_set_mark (count, key)
1345 RL_SETSTATE(RL_STATE_MOREINPUT);
1346 ch = rl_read_key ();
1347 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1349 if (ch < 'a' || ch > 'z')
1355 vi_mark_chars[ch] = rl_point;
1360 rl_vi_goto_mark (count, key)
1365 RL_SETSTATE(RL_STATE_MOREINPUT);
1366 ch = rl_read_key ();
1367 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1374 else if (ch < 'a' || ch > 'z')
1381 if (vi_mark_chars[ch] == -1)
1386 rl_point = vi_mark_chars[ch];
1390 #endif /* VI_MODE */