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-2012 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 _rl_vimotion_cxt *_rl_vimvcxt = 0;
70 /* Non-zero means enter insertion mode. */
71 static int _rl_vi_doing_insert;
73 /* Command keys which do movement for xxx_to commands. */
74 static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`";
76 /* Keymap used for vi replace characters. Created dynamically since
78 static Keymap vi_replace_map;
80 /* The number of characters inserted in the last replace operation. */
81 static int vi_replace_count;
83 /* If non-zero, we have text inserted after a c[motion] command that put
84 us implicitly into insert mode. Some people want this text to be
85 attached to the command so that it is `redoable' with `.'. */
86 static int vi_continued_command;
87 static char *vi_insert_buffer;
88 static int vi_insert_buffer_size;
90 static int _rl_vi_last_repeat = 1;
91 static int _rl_vi_last_arg_sign = 1;
92 static int _rl_vi_last_motion;
93 #if defined (HANDLE_MULTIBYTE)
94 static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
95 static int _rl_vi_last_search_mblen;
97 static int _rl_vi_last_search_char;
99 static int _rl_vi_last_replacement;
101 static int _rl_vi_last_key_before_insert;
103 static int vi_redoing;
105 /* Text modification commands. These are the `redoable' commands. */
106 static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
108 /* Arrays for the saved marks. */
109 static int vi_mark_chars['z' - 'a' + 1];
111 static void _rl_vi_replace_insert PARAMS((int));
112 static void _rl_vi_save_replace PARAMS((void));
113 static void _rl_vi_stuff_insert PARAMS((int));
114 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
116 static void vi_save_insert_buffer PARAMS ((int, int));
118 static void _rl_vi_backup PARAMS((void));
120 static int _rl_vi_arg_dispatch PARAMS((int));
121 static int rl_digit_loop1 PARAMS((void));
123 static int _rl_vi_set_mark PARAMS((void));
124 static int _rl_vi_goto_mark PARAMS((void));
126 static void _rl_vi_append_forward PARAMS((int));
128 static int _rl_vi_callback_getchar PARAMS((char *, int));
130 #if defined (READLINE_CALLBACKS)
131 static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
132 static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
133 static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
134 static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
137 static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *));
138 static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *));
139 static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *));
141 static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
142 static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
143 static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
145 static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
148 _rl_vi_initialize_line ()
152 n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
153 for (i = 0; i < n; i++)
154 vi_mark_chars[i] = -1;
156 RL_UNSETSTATE(RL_STATE_VICMDONCE);
162 _rl_vi_last_command = 'i';
163 _rl_vi_last_repeat = 1;
164 _rl_vi_last_arg_sign = 1;
165 _rl_vi_last_motion = 0;
169 _rl_vi_set_last (key, repeat, sign)
170 int key, repeat, sign;
172 _rl_vi_last_command = key;
173 _rl_vi_last_repeat = repeat;
174 _rl_vi_last_arg_sign = sign;
177 /* A convenience function that calls _rl_vi_set_last to save the last command
178 information and enters insertion mode. */
180 rl_vi_start_inserting (key, repeat, sign)
181 int key, repeat, sign;
183 _rl_vi_set_last (key, repeat, sign);
184 rl_vi_insertion_mode (1, key);
187 /* Is the command C a VI mode text modification command? */
189 _rl_vi_textmod_command (c)
192 return (member (c, vi_textmod));
196 _rl_vi_motion_command (c)
199 return (member (c, vi_motion));
203 _rl_vi_replace_insert (count)
208 nchars = strlen (vi_insert_buffer);
210 rl_begin_undo_group ();
212 /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
214 _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
215 rl_end_undo_group ();
219 _rl_vi_stuff_insert (count)
222 rl_begin_undo_group ();
224 rl_insert_text (vi_insert_buffer);
225 rl_end_undo_group ();
228 /* Bound to `.'. Called from command mode, so we know that we have to
229 redo a text modification command. The default for _rl_vi_last_command
230 puts you back into insert mode. */
232 rl_vi_redo (count, c)
237 if (rl_explicit_arg == 0)
239 rl_numeric_arg = _rl_vi_last_repeat;
240 rl_arg_sign = _rl_vi_last_arg_sign;
245 /* If we're redoing an insert with `i', stuff in the inserted text
246 and do not go into insertion mode. */
247 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
249 _rl_vi_stuff_insert (count);
250 /* And back up point over the last character inserted. */
254 else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
256 _rl_vi_replace_insert (count);
257 /* And back up point over the last character inserted. */
261 /* Ditto for redoing an insert with `I', but move to the beginning of the
262 line like the `I' command does. */
263 else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
265 rl_beg_of_line (1, 'I');
266 _rl_vi_stuff_insert (count);
270 /* Ditto for redoing an insert with `a', but move forward a character first
271 like the `a' command does. */
272 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
274 _rl_vi_append_forward ('a');
275 _rl_vi_stuff_insert (count);
279 /* Ditto for redoing an insert with `A', but move to the end of the line
280 like the `A' command does. */
281 else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
283 rl_end_of_line (1, 'A');
284 _rl_vi_stuff_insert (count);
289 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
295 /* A placeholder for further expansion. */
297 rl_vi_undo (count, key)
300 return (rl_undo_command (count, key));
303 /* Yank the nth arg from the previous line into this line at point. */
305 rl_vi_yank_arg (count, key)
308 /* Readline thinks that the first word on a line is the 0th, while vi
309 thinks the first word on a line is the 1st. Compensate. */
311 rl_yank_nth_arg (count - 1, 0);
313 rl_yank_nth_arg ('$', 0);
318 /* With an argument, move back that many history lines, else move to the
319 beginning of history. */
321 rl_vi_fetch_history (count, c)
326 /* Giving an argument of n means we want the nth command in the history
327 file. The command number is interpreted the same way that the bash
328 `history' command does it -- that is, giving an argument count of 450
329 to this command would get the command listed as number 450 in the
330 output of `history'. */
333 wanted = history_base + where_history () - count;
335 rl_beginning_of_history (0, 0);
337 rl_get_previous_history (wanted, c);
340 rl_beginning_of_history (count, 0);
344 /* Search again for the last thing searched for. */
346 rl_vi_search_again (count, key)
352 rl_noninc_reverse_search_again (count, key);
356 rl_noninc_forward_search_again (count, key);
362 /* Do a vi style search. */
364 rl_vi_search (count, key)
370 _rl_free_saved_history_line ();
371 rl_noninc_forward_search (count, key);
375 _rl_free_saved_history_line ();
376 rl_noninc_reverse_search (count, key);
386 /* Completion, from vi's point of view. */
388 rl_vi_complete (ignore, key)
391 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
393 if (!whitespace (rl_line_buffer[rl_point + 1]))
394 rl_vi_end_word (1, 'E');
399 rl_complete_internal ('*'); /* Expansion and replacement. */
401 rl_complete_internal ('?'); /* List possible completions. */
402 else if (key == '\\')
403 rl_complete_internal (TAB); /* Standard Readline completion. */
405 rl_complete (0, key);
407 if (key == '*' || key == '\\')
408 rl_vi_start_inserting (key, 1, rl_arg_sign);
413 /* Tilde expansion for vi mode. */
415 rl_vi_tilde_expand (ignore, key)
418 rl_tilde_expand (0, key);
419 rl_vi_start_inserting (key, 1, rl_arg_sign);
423 /* Previous word in vi mode. */
425 rl_vi_prev_word (count, key)
429 return (rl_vi_next_word (-count, key));
437 if (_rl_uppercase_p (key))
438 rl_vi_bWord (count, key);
440 rl_vi_bword (count, key);
445 /* Next word in vi mode. */
447 rl_vi_next_word (count, key)
451 return (rl_vi_prev_word (-count, key));
453 if (rl_point >= (rl_end - 1))
459 if (_rl_uppercase_p (key))
460 rl_vi_fWord (count, key);
462 rl_vi_fword (count, key);
466 /* Move to the end of the ?next? word. */
468 rl_vi_end_word (count, key)
477 if (_rl_uppercase_p (key))
478 rl_vi_eWord (count, key);
480 rl_vi_eword (count, key);
484 /* Move forward a word the way that 'W' does. */
486 rl_vi_fWord (count, ignore)
489 while (count-- && rl_point < (rl_end - 1))
491 /* Skip until whitespace. */
492 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
495 /* Now skip whitespace. */
496 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
503 rl_vi_bWord (count, ignore)
506 while (count-- && rl_point > 0)
508 /* If we are at the start of a word, move back to whitespace so
509 we will go back to the start of the previous word. */
510 if (!whitespace (rl_line_buffer[rl_point]) &&
511 whitespace (rl_line_buffer[rl_point - 1]))
514 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
519 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
527 rl_vi_eWord (count, ignore)
530 while (count-- && rl_point < (rl_end - 1))
532 if (!whitespace (rl_line_buffer[rl_point]))
535 /* Move to the next non-whitespace character (to the start of the
537 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
540 if (rl_point && rl_point < rl_end)
542 /* Skip whitespace. */
543 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
546 /* Skip until whitespace. */
547 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
550 /* Move back to the last character of the word. */
558 rl_vi_fword (count, ignore)
561 while (count-- && rl_point < (rl_end - 1))
563 /* Move to white space (really non-identifer). */
564 if (_rl_isident (rl_line_buffer[rl_point]))
566 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
569 else /* if (!whitespace (rl_line_buffer[rl_point])) */
571 while (!_rl_isident (rl_line_buffer[rl_point]) &&
572 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
576 /* Move past whitespace. */
577 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
584 rl_vi_bword (count, ignore)
587 while (count-- && rl_point > 0)
591 /* If we are at the start of a word, move back to whitespace
592 so we will go back to the start of the previous word. */
593 if (!whitespace (rl_line_buffer[rl_point]) &&
594 whitespace (rl_line_buffer[rl_point - 1]))
597 /* If this character and the previous character are `opposite', move
598 back so we don't get messed up by the rl_point++ down there in
599 the while loop. Without this code, words like `l;' screw up the
601 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
602 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
603 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
606 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
611 if (_rl_isident (rl_line_buffer[rl_point]))
612 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
614 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
615 !whitespace (rl_line_buffer[rl_point]));
623 rl_vi_eword (count, ignore)
626 while (count-- && rl_point < rl_end - 1)
628 if (!whitespace (rl_line_buffer[rl_point]))
631 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
634 if (rl_point < rl_end)
636 if (_rl_isident (rl_line_buffer[rl_point]))
637 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
639 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
640 && !whitespace (rl_line_buffer[rl_point]));
648 rl_vi_insert_beg (count, key)
651 rl_beg_of_line (1, key);
652 rl_vi_insert_mode (1, key);
657 _rl_vi_append_forward (key)
662 if (rl_point < rl_end)
664 if (MB_CUR_MAX == 1 || rl_byte_oriented)
670 rl_forward_char (1, key);
672 rl_point = _rl_forward_char_internal (1);
674 if (point == rl_point)
681 rl_vi_append_mode (count, key)
684 _rl_vi_append_forward (key);
685 rl_vi_start_inserting (key, 1, rl_arg_sign);
690 rl_vi_append_eol (count, key)
693 rl_end_of_line (1, key);
694 rl_vi_append_mode (1, key);
698 /* What to do in the case of C-d. */
700 rl_vi_eof_maybe (count, c)
703 return (rl_newline (1, '\n'));
706 /* Insertion mode stuff. */
708 /* Switching from one mode to the other really just involves
709 switching keymaps. */
711 rl_vi_insertion_mode (count, key)
714 _rl_keymap = vi_insertion_keymap;
715 _rl_vi_last_key_before_insert = key;
716 if (_rl_show_mode_in_prompt)
722 rl_vi_insert_mode (count, key)
725 rl_vi_start_inserting (key, 1, rl_arg_sign);
730 vi_save_insert_buffer (start, len)
733 /* Same code as _rl_vi_save_insert below */
734 if (len >= vi_insert_buffer_size)
736 vi_insert_buffer_size += (len + 32) - (len % 32);
737 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
739 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
740 vi_insert_buffer[len-1] = '\0';
744 _rl_vi_save_replace ()
750 if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
752 if (vi_insert_buffer_size >= 1)
753 vi_insert_buffer[0] = '\0';
756 /* Let's try it the quick and easy way for now. This should essentially
757 accommodate every UNDO_INSERT and save the inserted text to
760 start = end - vi_replace_count + 1;
761 len = vi_replace_count + 1;
763 vi_save_insert_buffer (start, len);
767 _rl_vi_save_insert (up)
772 if (up == 0 || up->what != UNDO_INSERT)
774 if (vi_insert_buffer_size >= 1)
775 vi_insert_buffer[0] = '\0';
781 len = end - start + 1;
783 vi_save_insert_buffer (start, len);
787 _rl_vi_done_inserting ()
789 if (_rl_vi_doing_insert)
791 /* The `C', `s', and `S' commands set this. */
792 rl_end_undo_group ();
793 /* Now, the text between rl_undo_list->next->start and
794 rl_undo_list->next->end is what was inserted while in insert
795 mode. It gets copied to VI_INSERT_BUFFER because it depends
796 on absolute indices into the line which may change (though they
797 probably will not). */
798 _rl_vi_doing_insert = 0;
799 if (_rl_vi_last_key_before_insert == 'R')
800 _rl_vi_save_replace (); /* Half the battle */
802 _rl_vi_save_insert (rl_undo_list->next);
803 vi_continued_command = 1;
807 if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
808 _rl_vi_last_key_before_insert == 'a' ||
809 _rl_vi_last_key_before_insert == 'I' ||
810 _rl_vi_last_key_before_insert == 'A'))
811 _rl_vi_save_insert (rl_undo_list);
812 /* XXX - Other keys probably need to be checked. */
813 else if (_rl_vi_last_key_before_insert == 'C')
814 rl_end_undo_group ();
815 while (_rl_undo_group_level > 0)
816 rl_end_undo_group ();
817 vi_continued_command = 0;
822 rl_vi_movement_mode (count, key)
826 rl_backward_char (1, key);
828 _rl_keymap = vi_movement_keymap;
829 _rl_vi_done_inserting ();
831 /* This is how POSIX.2 says `U' should behave -- everything up until the
832 first time you go into command mode should not be undone. */
833 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
834 rl_free_undo_list ();
836 if (_rl_show_mode_in_prompt)
839 RL_SETSTATE (RL_STATE_VICMDONCE);
844 rl_vi_arg_digit (count, c)
847 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
848 return (rl_beg_of_line (1, c));
850 return (rl_digit_argument (count, c));
853 /* Change the case of the next COUNT characters. */
854 #if defined (HANDLE_MULTIBYTE)
856 _rl_vi_change_mbchar_case (count)
860 char mb[MB_LEN_MAX+1];
865 memset (&ps, 0, sizeof (mbstate_t));
866 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
868 while (count-- && rl_point < rl_end)
870 m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
871 if (MB_INVALIDCH (m))
872 wc = (wchar_t)rl_line_buffer[rl_point];
873 else if (MB_NULLWCH (m))
877 else if (iswlower (wc))
881 /* Just skip over chars neither upper nor lower case */
882 rl_forward_char (1, 0);
886 /* Vi is kind of strange here. */
890 mlen = wcrtomb (mb, wc, &ps);
893 rl_begin_undo_group ();
895 if (rl_point < p) /* Did we retreat at EOL? */
896 rl_point++; /* XXX - should we advance more than 1 for mbchar? */
898 rl_end_undo_group ();
902 rl_forward_char (1, 0);
910 rl_vi_change_case (count, ignore)
915 /* Don't try this on an empty line. */
916 if (rl_point >= rl_end)
920 #if defined (HANDLE_MULTIBYTE)
921 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
922 return (_rl_vi_change_mbchar_case (count));
925 while (count-- && rl_point < rl_end)
927 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
928 c = _rl_to_lower (rl_line_buffer[rl_point]);
929 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
930 c = _rl_to_upper (rl_line_buffer[rl_point]);
933 /* Just skip over characters neither upper nor lower case. */
934 rl_forward_char (1, c);
938 /* Vi is kind of strange here. */
942 rl_begin_undo_group ();
944 if (rl_point < p) /* Did we retreat at EOL? */
946 _rl_insert_char (1, c);
947 rl_end_undo_group ();
951 rl_forward_char (1, c);
957 rl_vi_put (count, key)
960 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
961 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
966 rl_backward_char (1, key);
973 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
974 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
982 if (rl_point && rl_point == rl_end)
984 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
985 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
993 rl_vi_column (count, key)
997 rl_end_of_line (1, key);
999 rl_point = count - 1;
1003 /* Process C as part of the current numeric argument. Return -1 if the
1004 argument should be aborted, 0 if we should not read any more chars, and
1005 1 if we should continue to read chars. */
1007 _rl_vi_arg_dispatch (c)
1013 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
1015 rl_numeric_arg *= 4;
1021 if (_rl_digit_p (c))
1023 if (rl_explicit_arg)
1024 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
1026 rl_numeric_arg = _rl_digit_value (c);
1027 rl_explicit_arg = 1;
1028 return 1; /* keep going */
1032 rl_clear_message ();
1033 rl_stuff_char (key);
1034 return 0; /* done */
1038 /* A simplified loop for vi. Don't dispatch key at end.
1039 Don't recognize minus sign?
1040 Should this do rl_save_prompt/rl_restore_prompt? */
1048 if (_rl_arg_overflow ())
1051 c = _rl_arg_getchar ();
1053 r = _rl_vi_arg_dispatch (c);
1058 RL_UNSETSTATE(RL_STATE_NUMERICARG);
1063 _rl_mvcxt_init (m, op, key)
1064 _rl_vimotion_cxt *m;
1068 m->state = m->flags = 0;
1070 m->numeric_arg = -1;
1071 m->start = rl_point;
1077 static _rl_vimotion_cxt *
1078 _rl_mvcxt_alloc (op, key)
1081 _rl_vimotion_cxt *m;
1083 m = xmalloc (sizeof (_rl_vimotion_cxt));
1084 _rl_mvcxt_init (m, op, key);
1089 _rl_mvcxt_dispose (m)
1090 _rl_vimotion_cxt *m;
1096 rl_domove_motion_callback (m)
1097 _rl_vimotion_cxt *m;
1102 _rl_vi_last_motion = c = m->motion;
1104 /* Append a blank character temporarily so that the motion routines
1105 work right at the end of the line. */
1107 rl_line_buffer[rl_end++] = ' ';
1108 rl_line_buffer[rl_end] = '\0';
1110 _rl_dispatch (c, _rl_keymap);
1112 /* Remove the blank that we added. */
1114 rl_line_buffer[rl_end] = '\0';
1115 if (rl_point > rl_end)
1118 /* No change in position means the command failed. */
1119 if (rl_mark == rl_point)
1122 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
1123 word. If we are not at the end of the line, and we are on a
1124 non-whitespace character, move back one (presumably to whitespace). */
1125 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
1126 !whitespace (rl_line_buffer[rl_point]))
1129 /* If cw or cW, back up to the end of a word, so the behaviour of ce
1130 or cE is the actual result. Brute-force, no subtlety. */
1131 if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
1133 /* Don't move farther back than where we started. */
1134 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
1137 /* Posix.2 says that if cw or cW moves the cursor towards the end of
1138 the line, the character under the cursor should be deleted. */
1139 if (rl_point == rl_mark)
1143 /* Move past the end of the word so that the kill doesn't
1144 remove the last letter of the previous word. Only do this
1145 if we are not at the end of the line. */
1146 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
1151 if (rl_mark < rl_point)
1152 SWAP (rl_point, rl_mark);
1154 #if defined (READLINE_CALLBACKS)
1155 if (RL_ISSTATE (RL_STATE_CALLBACK))
1156 (*rl_redisplay_function)(); /* make sure motion is displayed */
1159 r = vidomove_dispatch (m);
1164 #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
1167 rl_domove_read_callback (m)
1168 _rl_vimotion_cxt *m;
1174 if (member (c, vi_motion))
1176 #if defined (READLINE_CALLBACKS)
1177 /* If we just read a vi-mode motion command numeric argument, turn off
1178 the `reading numeric arg' state */
1179 if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1180 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1182 /* Should do everything, including turning off RL_STATE_VIMOTION */
1183 return (rl_domove_motion_callback (m));
1185 else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c'))
1188 rl_beg_of_line (1, c);
1189 _rl_vi_last_motion = c;
1190 RL_UNSETSTATE (RL_STATE_VIMOTION);
1191 return (vidomove_dispatch (m));
1193 #if defined (READLINE_CALLBACKS)
1194 /* XXX - these need to handle rl_universal_argument bindings */
1195 /* Reading vi motion char continuing numeric argument */
1196 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1198 return (_rl_vi_arg_dispatch (c));
1200 /* Readine vi motion char starting numeric argument */
1201 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
1203 RL_SETSTATE (RL_STATE_NUMERICARG);
1204 return (_rl_vi_arg_dispatch (c));
1207 else if (_rl_digit_p (c))
1209 /* This code path taken when not in callback mode */
1210 save = rl_numeric_arg;
1211 rl_numeric_arg = _rl_digit_value (c);
1212 rl_explicit_arg = 1;
1213 RL_SETSTATE (RL_STATE_NUMERICARG);
1215 rl_numeric_arg *= save;
1216 c = rl_vi_domove_getchar (m);
1223 return (rl_domove_motion_callback (m));
1227 RL_UNSETSTATE (RL_STATE_VIMOTION);
1228 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1234 rl_vi_domove_getchar (m)
1235 _rl_vimotion_cxt *m;
1239 RL_SETSTATE(RL_STATE_MOREINPUT);
1241 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1246 #if defined (READLINE_CALLBACKS)
1248 _rl_vi_domove_callback (m)
1249 _rl_vimotion_cxt *m;
1253 m->motion = c = rl_vi_domove_getchar (m);
1254 /* XXX - what to do if this returns -1? Should we return 1 for eof to
1256 r = rl_domove_read_callback (m);
1258 return ((r == 0) ? r : 1); /* normalize return values */
1262 /* This code path taken when not in callback mode. */
1264 rl_vi_domove (x, ignore)
1268 _rl_vimotion_cxt *m;
1271 *ignore = m->motion = rl_vi_domove_getchar (m);
1279 return (rl_domove_read_callback (m));
1283 vi_delete_dispatch (m)
1284 _rl_vimotion_cxt *m;
1286 /* These are the motion commands that do not require adjusting the
1288 if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1292 rl_kill_text (rl_point, rl_mark);
1297 rl_vi_delete_to (count, key)
1302 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
1303 _rl_vimvcxt->start = rl_point;
1306 if (_rl_uppercase_p (key))
1308 _rl_vimvcxt->motion = '$';
1309 r = rl_domove_motion_callback (_rl_vimvcxt);
1311 else if (vi_redoing && _rl_vi_last_motion != 'd') /* `dd' is special */
1313 _rl_vimvcxt->motion = _rl_vi_last_motion;
1314 r = rl_domove_motion_callback (_rl_vimvcxt);
1316 else if (vi_redoing) /* handle redoing `dd' here */
1318 _rl_vimvcxt->motion = _rl_vi_last_motion;
1320 rl_beg_of_line (1, key);
1321 RL_UNSETSTATE (RL_STATE_VIMOTION);
1322 r = vidomove_dispatch (_rl_vimvcxt);
1324 #if defined (READLINE_CALLBACKS)
1325 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1327 RL_SETSTATE (RL_STATE_VIMOTION);
1332 r = rl_vi_domove (key, &c);
1340 _rl_mvcxt_dispose (_rl_vimvcxt);
1347 vi_change_dispatch (m)
1348 _rl_vimotion_cxt *m;
1350 /* These are the motion commands that do not require adjusting the
1351 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1352 and already leave the mark at the correct location. */
1353 if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1357 /* The cursor never moves with c[wW]. */
1358 if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
1359 rl_point = m->start;
1363 if (vi_insert_buffer && *vi_insert_buffer)
1364 rl_begin_undo_group ();
1365 rl_delete_text (rl_point, rl_mark);
1366 if (vi_insert_buffer && *vi_insert_buffer)
1368 rl_insert_text (vi_insert_buffer);
1369 rl_end_undo_group ();
1374 rl_begin_undo_group (); /* to make the `u' command work */
1375 rl_kill_text (rl_point, rl_mark);
1376 /* `C' does not save the text inserted for undoing or redoing. */
1377 if (_rl_uppercase_p (m->key) == 0)
1378 _rl_vi_doing_insert = 1;
1379 /* XXX -- TODO -- use m->numericarg? */
1380 rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
1387 rl_vi_change_to (count, key)
1392 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
1393 _rl_vimvcxt->start = rl_point;
1396 if (_rl_uppercase_p (key))
1398 _rl_vimvcxt->motion = '$';
1399 r = rl_domove_motion_callback (_rl_vimvcxt);
1401 else if (vi_redoing && _rl_vi_last_motion != 'c') /* `cc' is special */
1403 _rl_vimvcxt->motion = _rl_vi_last_motion;
1404 r = rl_domove_motion_callback (_rl_vimvcxt);
1406 else if (vi_redoing) /* handle redoing `cc' here */
1408 _rl_vimvcxt->motion = _rl_vi_last_motion;
1410 rl_beg_of_line (1, key);
1411 RL_UNSETSTATE (RL_STATE_VIMOTION);
1412 r = vidomove_dispatch (_rl_vimvcxt);
1414 #if defined (READLINE_CALLBACKS)
1415 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1417 RL_SETSTATE (RL_STATE_VIMOTION);
1422 r = rl_vi_domove (key, &c);
1427 r = -1; /* normalize return value */
1430 _rl_mvcxt_dispose (_rl_vimvcxt);
1437 vi_yank_dispatch (m)
1438 _rl_vimotion_cxt *m;
1440 /* These are the motion commands that do not require adjusting the
1442 if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1446 rl_begin_undo_group ();
1447 rl_kill_text (rl_point, rl_mark);
1448 rl_end_undo_group ();
1450 rl_point = m->start;
1456 rl_vi_yank_to (count, key)
1461 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
1462 _rl_vimvcxt->start = rl_point;
1465 if (_rl_uppercase_p (key))
1467 _rl_vimvcxt->motion = '$';
1468 r = rl_domove_motion_callback (_rl_vimvcxt);
1470 else if (vi_redoing && _rl_vi_last_motion != 'y') /* `yy' is special */
1472 _rl_vimvcxt->motion = _rl_vi_last_motion;
1473 r = rl_domove_motion_callback (_rl_vimvcxt);
1475 else if (vi_redoing) /* handle redoing `yy' here */
1477 _rl_vimvcxt->motion = _rl_vi_last_motion;
1479 rl_beg_of_line (1, key);
1480 RL_UNSETSTATE (RL_STATE_VIMOTION);
1481 r = vidomove_dispatch (_rl_vimvcxt);
1483 #if defined (READLINE_CALLBACKS)
1484 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1486 RL_SETSTATE (RL_STATE_VIMOTION);
1491 r = rl_vi_domove (key, &c);
1499 _rl_mvcxt_dispose (_rl_vimvcxt);
1506 vidomove_dispatch (m)
1507 _rl_vimotion_cxt *m;
1514 r = vi_delete_dispatch (m);
1517 r = vi_change_dispatch (m);
1520 r = vi_yank_dispatch (m);
1523 _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op);
1528 RL_UNSETSTATE (RL_STATE_VIMOTION);
1533 rl_vi_rubout (count, key)
1539 return (rl_vi_delete (-count, key));
1548 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1549 rl_backward_char (count, key);
1550 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1551 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1558 rl_kill_text (rl_point, opoint);
1564 rl_vi_delete (count, key)
1570 return (rl_vi_rubout (-count, key));
1578 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1579 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1581 end = rl_point + count;
1586 rl_kill_text (rl_point, end);
1588 if (rl_point > 0 && rl_point == rl_end)
1589 rl_backward_char (1, key);
1595 rl_vi_back_to_indent (count, key)
1598 rl_beg_of_line (1, key);
1599 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1605 rl_vi_first_print (count, key)
1608 return (rl_vi_back_to_indent (1, key));
1611 static int _rl_cs_dir, _rl_cs_orig_dir;
1613 #if defined (READLINE_CALLBACKS)
1615 _rl_vi_callback_char_search (data)
1616 _rl_callback_generic_arg *data;
1619 #if defined (HANDLE_MULTIBYTE)
1620 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1622 RL_SETSTATE(RL_STATE_MOREINPUT);
1624 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1630 #if !defined (HANDLE_MULTIBYTE)
1631 _rl_vi_last_search_char = c;
1634 _rl_callback_func = 0;
1635 _rl_want_redisplay = 1;
1637 #if defined (HANDLE_MULTIBYTE)
1638 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
1640 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
1646 rl_vi_char_search (count, key)
1650 #if defined (HANDLE_MULTIBYTE)
1651 static char *target;
1657 if (key == ';' || key == ',')
1659 if (_rl_cs_orig_dir == 0)
1661 #if defined (HANDLE_MULTIBYTE)
1662 if (_rl_vi_last_search_mblen == 0)
1665 if (_rl_vi_last_search_char == 0)
1668 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
1675 _rl_cs_orig_dir = _rl_cs_dir = FTO;
1679 _rl_cs_orig_dir = _rl_cs_dir = BTO;
1683 _rl_cs_orig_dir = _rl_cs_dir = FFIND;
1687 _rl_cs_orig_dir = _rl_cs_dir = BFIND;
1693 /* set target and tlen below */
1695 #if defined (READLINE_CALLBACKS)
1696 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1698 _rl_callback_data = _rl_callback_data_alloc (count);
1699 _rl_callback_data->i1 = _rl_cs_dir;
1700 _rl_callback_func = _rl_vi_callback_char_search;
1706 #if defined (HANDLE_MULTIBYTE)
1707 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1710 _rl_vi_last_search_mblen = c;
1712 RL_SETSTATE(RL_STATE_MOREINPUT);
1714 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1717 _rl_vi_last_search_char = c;
1722 #if defined (HANDLE_MULTIBYTE)
1723 target = _rl_vi_last_search_mbchar;
1724 tlen = _rl_vi_last_search_mblen;
1726 target = _rl_vi_last_search_char;
1729 #if defined (HANDLE_MULTIBYTE)
1730 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
1732 return (_rl_char_search_internal (count, _rl_cs_dir, target));
1736 /* Match brackets */
1738 rl_vi_match (ignore, key)
1741 int count = 1, brack, pos, tmp, pre;
1744 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1746 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1748 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1751 rl_forward_char (1, key);
1752 if (pre == rl_point)
1757 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1758 rl_point < rl_end - 1)
1759 rl_forward_char (1, key);
1776 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1780 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1786 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1789 else if (b == brack)
1803 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1806 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1810 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1813 else if (b == brack)
1834 case ')': return -1;
1836 case ']': return -2;
1838 case '}': return -3;
1844 _rl_vi_change_char (count, c, mb)
1850 if (c == '\033' || c == CTRL ('C'))
1853 rl_begin_undo_group ();
1854 while (count-- && rl_point < rl_end)
1857 rl_vi_delete (1, c);
1858 if (rl_point < p) /* Did we retreat at EOL? */
1860 #if defined (HANDLE_MULTIBYTE)
1861 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1862 rl_insert_text (mb);
1865 _rl_insert_char (1, c);
1868 /* The cursor shall be left on the last character changed. */
1869 rl_backward_char (1, c);
1871 rl_end_undo_group ();
1877 _rl_vi_callback_getchar (mb, mlen)
1883 RL_SETSTATE(RL_STATE_MOREINPUT);
1885 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1890 #if defined (HANDLE_MULTIBYTE)
1891 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1892 c = _rl_read_mbstring (c, mb, mlen);
1898 #if defined (READLINE_CALLBACKS)
1900 _rl_vi_callback_change_char (data)
1901 _rl_callback_generic_arg *data;
1904 char mb[MB_LEN_MAX];
1906 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1911 _rl_callback_func = 0;
1912 _rl_want_redisplay = 1;
1914 return (_rl_vi_change_char (data->count, c, mb));
1919 rl_vi_change_char (count, key)
1923 char mb[MB_LEN_MAX];
1927 c = _rl_vi_last_replacement;
1931 #if defined (READLINE_CALLBACKS)
1932 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1934 _rl_callback_data = _rl_callback_data_alloc (count);
1935 _rl_callback_func = _rl_vi_callback_change_char;
1940 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
1945 return (_rl_vi_change_char (count, c, mb));
1949 rl_vi_subst (count, key)
1952 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1953 if (vi_redoing == 0)
1954 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1956 return (rl_vi_change_to (count, 'c'));
1960 rl_vi_overstrike (count, key)
1963 if (_rl_vi_doing_insert == 0)
1965 _rl_vi_doing_insert = 1;
1966 rl_begin_undo_group ();
1971 _rl_overwrite_char (count, key);
1972 vi_replace_count += count;
1979 rl_vi_overstrike_delete (count, key)
1984 for (i = 0; i < count; i++)
1986 if (vi_replace_count == 0)
1997 rl_backward_char (1, key);
2000 if (vi_replace_count == 0 && _rl_vi_doing_insert)
2002 rl_end_undo_group ();
2004 _rl_vi_doing_insert = 0;
2010 rl_vi_replace (count, key)
2015 vi_replace_count = 0;
2017 if (vi_replace_map == 0)
2019 vi_replace_map = rl_make_bare_keymap ();
2021 for (i = 0; i < ' '; i++)
2022 if (vi_insertion_keymap[i].type == ISFUNC)
2023 vi_replace_map[i].function = vi_insertion_keymap[i].function;
2025 for (i = ' '; i < KEYMAP_SIZE; i++)
2026 vi_replace_map[i].function = rl_vi_overstrike;
2028 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
2030 /* Make sure these are what we want. */
2031 vi_replace_map[ESC].function = rl_vi_movement_mode;
2032 vi_replace_map[RETURN].function = rl_newline;
2033 vi_replace_map[NEWLINE].function = rl_newline;
2035 /* If the normal vi insertion keymap has ^H bound to erase, do the
2036 same here. Probably should remove the assignment to RUBOUT up
2037 there, but I don't think it will make a difference in real life. */
2038 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
2039 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
2040 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
2044 rl_vi_start_inserting (key, 1, rl_arg_sign);
2046 _rl_vi_last_key_before_insert = key;
2047 _rl_keymap = vi_replace_map;
2053 /* Try to complete the word we are standing on or the word that ends with
2054 the previous character. A space matches everything. Word delimiters are
2057 rl_vi_possible_completions()
2059 int save_pos = rl_point;
2061 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
2063 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
2064 rl_line_buffer[rl_point] != ';')
2067 else if (rl_line_buffer[rl_point - 1] == ';')
2073 rl_possible_completions ();
2074 rl_point = save_pos;
2080 /* Functions to save and restore marks. */
2086 RL_SETSTATE(RL_STATE_MOREINPUT);
2087 ch = rl_read_key ();
2088 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2090 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2096 vi_mark_chars[ch] = rl_point;
2100 #if defined (READLINE_CALLBACKS)
2102 _rl_vi_callback_set_mark (data)
2103 _rl_callback_generic_arg *data;
2105 _rl_callback_func = 0;
2106 _rl_want_redisplay = 1;
2108 return (_rl_vi_set_mark ());
2113 rl_vi_set_mark (count, key)
2116 #if defined (READLINE_CALLBACKS)
2117 if (RL_ISSTATE (RL_STATE_CALLBACK))
2119 _rl_callback_data = 0;
2120 _rl_callback_func = _rl_vi_callback_set_mark;
2125 return (_rl_vi_set_mark ());
2133 RL_SETSTATE(RL_STATE_MOREINPUT);
2134 ch = rl_read_key ();
2135 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2142 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2149 if (vi_mark_chars[ch] == -1)
2154 rl_point = vi_mark_chars[ch];
2158 #if defined (READLINE_CALLBACKS)
2160 _rl_vi_callback_goto_mark (data)
2161 _rl_callback_generic_arg *data;
2163 _rl_callback_func = 0;
2164 _rl_want_redisplay = 1;
2166 return (_rl_vi_goto_mark ());
2171 rl_vi_goto_mark (count, key)
2174 #if defined (READLINE_CALLBACKS)
2175 if (RL_ISSTATE (RL_STATE_CALLBACK))
2177 _rl_callback_data = 0;
2178 _rl_callback_func = _rl_vi_callback_goto_mark;
2183 return (_rl_vi_goto_mark ());
2185 #endif /* VI_MODE */