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-2018 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 /* Increment START to the next character in RL_LINE_BUFFER, handling multibyte chars */
67 #if defined (HANDLE_MULTIBYTE)
68 #define INCREMENT_POS(start) \
70 if (MB_CUR_MAX == 1 || rl_byte_oriented) \
73 start = _rl_find_next_mbchar (rl_line_buffer, start, 1, MB_FIND_ANY); \
75 #else /* !HANDLE_MULTIBYTE */
76 #define INCREMENT_POS(start) (start)++
77 #endif /* !HANDLE_MULTIBYTE */
79 /* This is global so other parts of the code can check whether the last
80 command was a text modification command. */
81 int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
83 _rl_vimotion_cxt *_rl_vimvcxt = 0;
85 /* Non-zero indicates we are redoing a vi-mode command with `.' */
88 /* Non-zero means enter insertion mode. */
89 static int _rl_vi_doing_insert;
91 /* Command keys which do movement for xxx_to commands. */
92 static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`";
94 /* Keymap used for vi replace characters. Created dynamically since
96 static Keymap vi_replace_map;
98 /* The number of characters inserted in the last replace operation. */
99 static int vi_replace_count;
101 /* If non-zero, we have text inserted after a c[motion] command that put
102 us implicitly into insert mode. Some people want this text to be
103 attached to the command so that it is `redoable' with `.'. */
104 static int vi_continued_command;
105 static char *vi_insert_buffer;
106 static int vi_insert_buffer_size;
108 static int _rl_vi_last_repeat = 1;
109 static int _rl_vi_last_arg_sign = 1;
110 static int _rl_vi_last_motion;
111 #if defined (HANDLE_MULTIBYTE)
112 static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
113 static int _rl_vi_last_search_mblen;
115 static int _rl_vi_last_search_char;
117 static char _rl_vi_last_replacement[MB_LEN_MAX+1]; /* reserve for trailing NULL */
119 static int _rl_vi_last_key_before_insert;
121 /* Text modification commands. These are the `redoable' commands. */
122 static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
124 /* Arrays for the saved marks. */
125 static int vi_mark_chars['z' - 'a' + 1];
127 static void _rl_vi_replace_insert PARAMS((int));
128 static void _rl_vi_save_replace PARAMS((void));
129 static void _rl_vi_stuff_insert PARAMS((int));
130 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
132 static void vi_save_insert_buffer PARAMS ((int, int));
134 static inline void _rl_vi_backup PARAMS((void));
136 static int _rl_vi_arg_dispatch PARAMS((int));
137 static int rl_digit_loop1 PARAMS((void));
139 static int _rl_vi_set_mark PARAMS((void));
140 static int _rl_vi_goto_mark PARAMS((void));
142 static inline int _rl_vi_advance_point PARAMS((void));
143 static inline int _rl_vi_backup_point PARAMS((void));
145 static void _rl_vi_append_forward PARAMS((int));
147 static int _rl_vi_callback_getchar PARAMS((char *, int));
149 #if defined (READLINE_CALLBACKS)
150 static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
151 static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
152 static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
153 static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
156 static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *));
157 static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *));
158 static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *));
160 static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
161 static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
162 static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
164 static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
167 _rl_vi_initialize_line (void)
171 n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
172 for (i = 0; i < n; i++)
173 vi_mark_chars[i] = -1;
175 RL_UNSETSTATE(RL_STATE_VICMDONCE);
179 _rl_vi_reset_last (void)
181 _rl_vi_last_command = 'i';
182 _rl_vi_last_repeat = 1;
183 _rl_vi_last_arg_sign = 1;
184 _rl_vi_last_motion = 0;
188 _rl_vi_set_last (int key, int repeat, int sign)
190 _rl_vi_last_command = key;
191 _rl_vi_last_repeat = repeat;
192 _rl_vi_last_arg_sign = sign;
195 /* A convenience function that calls _rl_vi_set_last to save the last command
196 information and enters insertion mode. */
198 rl_vi_start_inserting (int key, int repeat, int sign)
200 _rl_vi_set_last (key, repeat, sign);
201 rl_begin_undo_group (); /* ensure inserts aren't concatenated */
202 rl_vi_insertion_mode (1, key);
205 /* Is the command C a VI mode text modification command? */
207 _rl_vi_textmod_command (int c)
209 return (member (c, vi_textmod));
213 _rl_vi_motion_command (int c)
215 return (member (c, vi_motion));
219 _rl_vi_replace_insert (int count)
223 nchars = strlen (vi_insert_buffer);
225 rl_begin_undo_group ();
227 /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
229 _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
230 rl_end_undo_group ();
234 _rl_vi_stuff_insert (int count)
236 rl_begin_undo_group ();
238 rl_insert_text (vi_insert_buffer);
239 rl_end_undo_group ();
242 /* Bound to `.'. Called from command mode, so we know that we have to
243 redo a text modification command. The default for _rl_vi_last_command
244 puts you back into insert mode. */
246 rl_vi_redo (int count, int c)
250 if (rl_explicit_arg == 0)
252 rl_numeric_arg = _rl_vi_last_repeat;
253 rl_arg_sign = _rl_vi_last_arg_sign;
258 /* If we're redoing an insert with `i', stuff in the inserted text
259 and do not go into insertion mode. */
260 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
262 _rl_vi_stuff_insert (count);
263 /* And back up point over the last character inserted. */
267 else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
269 _rl_vi_replace_insert (count);
270 /* And back up point over the last character inserted. */
274 /* Ditto for redoing an insert with `I', but move to the beginning of the
275 line like the `I' command does. */
276 else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
278 rl_beg_of_line (1, 'I');
279 _rl_vi_stuff_insert (count);
283 /* Ditto for redoing an insert with `a', but move forward a character first
284 like the `a' command does. */
285 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
287 _rl_vi_append_forward ('a');
288 _rl_vi_stuff_insert (count);
292 /* Ditto for redoing an insert with `A', but move to the end of the line
293 like the `A' command does. */
294 else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
296 rl_end_of_line (1, 'A');
297 _rl_vi_stuff_insert (count);
302 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
309 /* A placeholder for further expansion. */
311 rl_vi_undo (int count, int key)
313 return (rl_undo_command (count, key));
316 /* Yank the nth arg from the previous line into this line at point. */
318 rl_vi_yank_arg (int count, int key)
320 /* Readline thinks that the first word on a line is the 0th, while vi
321 thinks the first word on a line is the 1st. Compensate. */
323 rl_yank_nth_arg (count - 1, 0);
325 rl_yank_nth_arg ('$', 0);
330 /* With an argument, move back that many history lines, else move to the
331 beginning of history. */
333 rl_vi_fetch_history (int count, int c)
337 /* Giving an argument of n means we want the nth command in the history
338 file. The command number is interpreted the same way that the bash
339 `history' command does it -- that is, giving an argument count of 450
340 to this command would get the command listed as number 450 in the
341 output of `history'. */
344 wanted = history_base + where_history () - count;
346 rl_beginning_of_history (0, 0);
348 rl_get_previous_history (wanted, c);
351 rl_beginning_of_history (count, 0);
355 /* Search again for the last thing searched for. */
357 rl_vi_search_again (int count, int key)
362 rl_noninc_reverse_search_again (count, key);
366 rl_noninc_forward_search_again (count, key);
372 /* Do a vi style search. */
374 rl_vi_search (int count, int key)
379 _rl_free_saved_history_line ();
380 rl_noninc_forward_search (count, key);
384 _rl_free_saved_history_line ();
385 rl_noninc_reverse_search (count, key);
395 /* Completion, from vi's point of view. */
397 rl_vi_complete (int ignore, int key)
399 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
401 if (!whitespace (rl_line_buffer[rl_point + 1]))
402 rl_vi_end_word (1, 'E');
403 _rl_vi_advance_point ();
407 rl_complete_internal ('*'); /* Expansion and replacement. */
409 rl_complete_internal ('?'); /* List possible completions. */
410 else if (key == '\\')
411 rl_complete_internal (TAB); /* Standard Readline completion. */
413 rl_complete (0, key);
415 if (key == '*' || key == '\\')
416 rl_vi_start_inserting (key, 1, rl_arg_sign);
421 /* Tilde expansion for vi mode. */
423 rl_vi_tilde_expand (int ignore, int key)
425 rl_tilde_expand (0, key);
426 rl_vi_start_inserting (key, 1, rl_arg_sign);
430 /* Previous word in vi mode. */
432 rl_vi_prev_word (int count, int key)
435 return (rl_vi_next_word (-count, key));
443 if (_rl_uppercase_p (key))
444 rl_vi_bWord (count, key);
446 rl_vi_bword (count, key);
451 /* Next word in vi mode. */
453 rl_vi_next_word (int count, int key)
456 return (rl_vi_prev_word (-count, key));
458 if (rl_point >= (rl_end - 1))
464 if (_rl_uppercase_p (key))
465 rl_vi_fWord (count, key);
467 rl_vi_fword (count, key);
472 _rl_vi_advance_point (void)
477 if (rl_point < rl_end)
478 #if defined (HANDLE_MULTIBYTE)
480 if (MB_CUR_MAX == 1 || rl_byte_oriented)
485 rl_point = _rl_forward_char_internal (1);
486 if (point == rl_point || rl_point > rl_end)
497 /* Move the cursor back one character. */
501 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
502 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
507 /* Move the point back one character, returning the starting value and not
508 doing anything at the beginning of the line */
510 _rl_vi_backup_point (void)
516 #if defined (HANDLE_MULTIBYTE)
518 if (MB_CUR_MAX == 1 || rl_byte_oriented)
523 rl_point = _rl_backward_char_internal (1);
525 rl_point = 0; /* XXX - not really necessary */
534 /* Move to the end of the ?next? word. */
536 rl_vi_end_word (int count, int key)
544 if (_rl_uppercase_p (key))
545 rl_vi_eWord (count, key);
547 rl_vi_eword (count, key);
551 /* Move forward a word the way that 'W' does. */
553 rl_vi_fWord (int count, int ignore)
555 while (count-- && rl_point < (rl_end - 1))
557 /* Skip until whitespace. */
558 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
559 _rl_vi_advance_point ();
561 /* Now skip whitespace. */
562 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
563 _rl_vi_advance_point ();
569 rl_vi_bWord (int count, int ignore)
571 while (count-- && rl_point > 0)
573 /* If we are at the start of a word, move back to whitespace so
574 we will go back to the start of the previous word. */
575 if (!whitespace (rl_line_buffer[rl_point]) &&
576 whitespace (rl_line_buffer[rl_point - 1]))
579 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
580 _rl_vi_backup_point ();
585 _rl_vi_backup_point ();
586 while (rl_point > 0 && !whitespace (rl_line_buffer[rl_point]));
587 if (rl_point > 0) /* hit whitespace */
598 rl_vi_eWord (int count, int ignore)
602 while (count-- && rl_point < (rl_end - 1))
604 if (whitespace (rl_line_buffer[rl_point]) == 0)
605 _rl_vi_advance_point ();
607 /* Move to the next non-whitespace character (to the start of the
609 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
610 _rl_vi_advance_point ();
612 if (rl_point && rl_point < rl_end)
616 /* Skip whitespace. */
617 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
618 opoint = _rl_vi_advance_point (); /* XXX - why? */
620 /* Skip until whitespace. */
621 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
622 opoint = _rl_vi_advance_point ();
624 /* Move back to the last character of the word. */
632 rl_vi_fword (int count, int ignore)
636 while (count-- && rl_point < (rl_end - 1))
638 /* Move to white space (really non-identifer). */
639 if (_rl_isident (rl_line_buffer[rl_point]))
641 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
642 _rl_vi_advance_point ();
644 else /* if (!whitespace (rl_line_buffer[rl_point])) */
646 while (!_rl_isident (rl_line_buffer[rl_point]) &&
647 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
648 _rl_vi_advance_point ();
653 /* Move past whitespace. */
654 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
655 opoint = _rl_vi_advance_point ();
661 rl_vi_bword (int count, int ignore)
665 while (count-- && rl_point > 0)
667 int prev_is_ident, cur_is_ident;
669 /* If we are at the start of a word, move back to whitespace
670 so we will go back to the start of the previous word. */
671 if (!whitespace (rl_line_buffer[rl_point]) &&
672 whitespace (rl_line_buffer[rl_point - 1]))
676 /* If this character and the previous character are `opposite', move
677 back so we don't get messed up by the rl_point++ down there in
678 the while loop. Without this code, words like `l;' screw up the
680 cur_is_ident = _rl_isident (rl_line_buffer[rl_point]);
681 opoint = _rl_vi_backup_point ();
682 prev_is_ident = _rl_isident (rl_line_buffer[rl_point]);
683 if ((cur_is_ident && !prev_is_ident) || (!cur_is_ident && prev_is_ident))
684 ; /* leave point alone, we backed it up one character */
688 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
689 _rl_vi_backup_point ();
694 if (_rl_isident (rl_line_buffer[rl_point]))
696 opoint = _rl_vi_backup_point ();
697 while (rl_point > 0 && _rl_isident (rl_line_buffer[rl_point]));
700 opoint = _rl_vi_backup_point ();
701 while (rl_point > 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
702 !whitespace (rl_line_buffer[rl_point]));
715 rl_vi_eword (int count, int ignore)
719 while (count-- && rl_point < (rl_end - 1))
721 if (whitespace (rl_line_buffer[rl_point]) == 0)
722 _rl_vi_advance_point ();
724 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
725 _rl_vi_advance_point ();
728 if (rl_point < rl_end)
730 if (_rl_isident (rl_line_buffer[rl_point]))
733 opoint = _rl_vi_advance_point ();
735 while (rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
739 opoint = _rl_vi_advance_point ();
741 while (rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
742 && !whitespace (rl_line_buffer[rl_point]));
750 rl_vi_insert_beg (int count, int key)
752 rl_beg_of_line (1, key);
753 rl_vi_insert_mode (1, key);
758 _rl_vi_append_forward (int key)
760 _rl_vi_advance_point ();
764 rl_vi_append_mode (int count, int key)
766 _rl_vi_append_forward (key);
767 rl_vi_start_inserting (key, 1, rl_arg_sign);
772 rl_vi_append_eol (int count, int key)
774 rl_end_of_line (1, key);
775 rl_vi_append_mode (1, key);
779 /* What to do in the case of C-d. */
781 rl_vi_eof_maybe (int count, int c)
783 return (rl_newline (1, '\n'));
786 /* Insertion mode stuff. */
788 /* Switching from one mode to the other really just involves
789 switching keymaps. */
791 rl_vi_insertion_mode (int count, int key)
793 _rl_keymap = vi_insertion_keymap;
794 _rl_vi_last_key_before_insert = key;
795 if (_rl_show_mode_in_prompt)
801 rl_vi_insert_mode (int count, int key)
803 rl_vi_start_inserting (key, 1, rl_arg_sign);
808 vi_save_insert_buffer (int start, int len)
810 /* Same code as _rl_vi_save_insert below */
811 if (len >= vi_insert_buffer_size)
813 vi_insert_buffer_size += (len + 32) - (len % 32);
814 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
816 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
817 vi_insert_buffer[len-1] = '\0';
821 _rl_vi_save_replace (void)
827 if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
829 if (vi_insert_buffer_size >= 1)
830 vi_insert_buffer[0] = '\0';
833 /* Let's try it the quick and easy way for now. This should essentially
834 accommodate every UNDO_INSERT and save the inserted text to
837 start = end - vi_replace_count + 1;
838 len = vi_replace_count + 1;
840 vi_save_insert_buffer (start, len);
844 _rl_vi_save_insert (UNDO_LIST *up)
848 if (up == 0 || up->what != UNDO_INSERT)
850 if (vi_insert_buffer_size >= 1)
851 vi_insert_buffer[0] = '\0';
857 len = end - start + 1;
859 vi_save_insert_buffer (start, len);
863 _rl_vi_done_inserting (void)
865 if (_rl_vi_doing_insert)
867 /* The `C', `s', and `S' commands set this. */
868 rl_end_undo_group ();
869 /* Now, the text between rl_undo_list->next->start and
870 rl_undo_list->next->end is what was inserted while in insert
871 mode. It gets copied to VI_INSERT_BUFFER because it depends
872 on absolute indices into the line which may change (though they
873 probably will not). */
874 _rl_vi_doing_insert = 0;
875 if (_rl_vi_last_key_before_insert == 'R')
876 _rl_vi_save_replace (); /* Half the battle */
878 _rl_vi_save_insert (rl_undo_list->next);
879 vi_continued_command = 1;
883 if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
884 _rl_vi_last_key_before_insert == 'a' ||
885 _rl_vi_last_key_before_insert == 'I' ||
886 _rl_vi_last_key_before_insert == 'A'))
887 _rl_vi_save_insert (rl_undo_list);
888 /* XXX - Other keys probably need to be checked. */
889 else if (_rl_vi_last_key_before_insert == 'C')
890 rl_end_undo_group ();
891 while (_rl_undo_group_level > 0)
892 rl_end_undo_group ();
893 vi_continued_command = 0;
898 rl_vi_movement_mode (int count, int key)
901 rl_backward_char (1, key);
903 _rl_keymap = vi_movement_keymap;
904 _rl_vi_done_inserting ();
906 /* This is how POSIX.2 says `U' should behave -- everything up until the
907 first time you go into command mode should not be undone. */
908 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
909 rl_free_undo_list ();
911 if (_rl_show_mode_in_prompt)
914 RL_SETSTATE (RL_STATE_VICMDONCE);
919 rl_vi_arg_digit (int count, int c)
921 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
922 return (rl_beg_of_line (1, c));
924 return (rl_digit_argument (count, c));
927 /* Change the case of the next COUNT characters. */
928 #if defined (HANDLE_MULTIBYTE)
930 _rl_vi_change_mbchar_case (int count)
933 char mb[MB_LEN_MAX+1];
938 memset (&ps, 0, sizeof (mbstate_t));
939 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
941 while (count-- && rl_point < rl_end)
943 m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
944 if (MB_INVALIDCH (m))
945 wc = (wchar_t)rl_line_buffer[rl_point];
946 else if (MB_NULLWCH (m))
950 else if (iswlower (wc))
954 /* Just skip over chars neither upper nor lower case */
955 rl_forward_char (1, 0);
959 /* Vi is kind of strange here. */
963 mlen = wcrtomb (mb, wc, &ps);
966 rl_begin_undo_group ();
968 if (rl_point < p) /* Did we retreat at EOL? */
969 _rl_vi_advance_point ();
971 rl_end_undo_group ();
975 rl_forward_char (1, 0);
983 rl_vi_change_case (int count, int ignore)
987 /* Don't try this on an empty line. */
988 if (rl_point >= rl_end)
992 #if defined (HANDLE_MULTIBYTE)
993 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
994 return (_rl_vi_change_mbchar_case (count));
997 while (count-- && rl_point < rl_end)
999 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
1000 c = _rl_to_lower (rl_line_buffer[rl_point]);
1001 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
1002 c = _rl_to_upper (rl_line_buffer[rl_point]);
1005 /* Just skip over characters neither upper nor lower case. */
1006 rl_forward_char (1, c);
1010 /* Vi is kind of strange here. */
1014 rl_begin_undo_group ();
1015 rl_vi_delete (1, c);
1016 if (rl_point < p) /* Did we retreat at EOL? */
1018 _rl_insert_char (1, c);
1019 rl_end_undo_group ();
1023 rl_forward_char (1, c);
1029 rl_vi_put (int count, int key)
1031 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
1032 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
1037 rl_backward_char (1, key);
1041 /* Move the cursor back one character if you're at the end of the line */
1045 if (rl_point && rl_point == rl_end)
1050 /* Move to the character position specified by COUNT */
1052 rl_vi_column (int count, int key)
1055 rl_end_of_line (1, key);
1059 rl_point = _rl_forward_char_internal (count - 1);
1064 /* Process C as part of the current numeric argument. Return -1 if the
1065 argument should be aborted, 0 if we should not read any more chars, and
1066 1 if we should continue to read chars. */
1068 _rl_vi_arg_dispatch (int c)
1073 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
1075 rl_numeric_arg *= 4;
1081 if (_rl_digit_p (c))
1083 if (rl_explicit_arg)
1084 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
1086 rl_numeric_arg = _rl_digit_value (c);
1087 rl_explicit_arg = 1;
1088 return 1; /* keep going */
1092 rl_clear_message ();
1093 rl_stuff_char (key);
1094 return 0; /* done */
1098 /* A simplified loop for vi. Don't dispatch key at end.
1099 Don't recognize minus sign?
1100 Should this do rl_save_prompt/rl_restore_prompt? */
1102 rl_digit_loop1 (void)
1108 if (_rl_arg_overflow ())
1111 c = _rl_arg_getchar ();
1113 r = _rl_vi_arg_dispatch (c);
1118 RL_UNSETSTATE(RL_STATE_NUMERICARG);
1122 /* This set of functions is basically to handle the commands that take a
1123 motion argument while in callback mode: read the command, read the motion
1124 command modifier, find the extent of the text to affect, and dispatch the
1125 command for execution. */
1127 _rl_mvcxt_init (_rl_vimotion_cxt *m, int op, int key)
1130 m->state = m->flags = 0;
1132 m->numeric_arg = -1;
1133 m->start = rl_point;
1139 static _rl_vimotion_cxt *
1140 _rl_mvcxt_alloc (int op, int key)
1142 _rl_vimotion_cxt *m;
1144 m = xmalloc (sizeof (_rl_vimotion_cxt));
1145 _rl_mvcxt_init (m, op, key);
1150 _rl_mvcxt_dispose (_rl_vimotion_cxt *m)
1156 rl_domove_motion_callback (_rl_vimotion_cxt *m)
1160 _rl_vi_last_motion = c = m->motion;
1162 /* Append a blank character temporarily so that the motion routines
1163 work right at the end of the line. Original value of rl_end is saved
1165 rl_line_buffer[rl_end++] = ' ';
1166 rl_line_buffer[rl_end] = '\0';
1168 _rl_dispatch (c, _rl_keymap);
1170 #if defined (READLINE_CALLBACKS)
1171 if (RL_ISSTATE (RL_STATE_CALLBACK))
1173 /* Messy case where char search can be vi motion command; see rest of
1174 details in callback.c. vi_char_search and callback_char_search just
1175 set and unset the CHARSEARCH state. This is where any vi motion
1176 command that needs to set its own state should be handled, with any
1177 corresponding code to manage that state in callback.c */
1178 if (RL_ISSTATE (RL_STATE_CHARSEARCH))
1181 return (_rl_vi_domove_motion_cleanup (c, m));
1185 return (_rl_vi_domove_motion_cleanup (c, m));
1189 _rl_vi_domove_motion_cleanup (int c, _rl_vimotion_cxt *m)
1193 /* Remove the blank that we added in rl_domove_motion_callback. */
1195 rl_line_buffer[rl_end] = '\0';
1196 if (rl_point > rl_end)
1199 /* No change in position means the command failed. */
1200 if (rl_mark == rl_point)
1202 RL_UNSETSTATE (RL_STATE_VIMOTION);
1206 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
1207 word. If we are not at the end of the line, and we are on a
1208 non-whitespace character, move back one (presumably to whitespace). */
1209 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
1210 !whitespace (rl_line_buffer[rl_point]))
1211 rl_point--; /* XXX */
1213 /* If cw or cW, back up to the end of a word, so the behaviour of ce
1214 or cE is the actual result. Brute-force, no subtlety. */
1215 if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
1217 /* Don't move farther back than where we started. */
1218 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
1221 /* Posix.2 says that if cw or cW moves the cursor towards the end of
1222 the line, the character under the cursor should be deleted. */
1223 if (rl_point == rl_mark)
1224 _rl_vi_advance_point ();
1227 /* Move past the end of the word so that the kill doesn't
1228 remove the last letter of the previous word. Only do this
1229 if we are not at the end of the line. */
1230 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
1231 _rl_vi_advance_point ();
1235 if (rl_mark < rl_point)
1236 SWAP (rl_point, rl_mark);
1238 #if defined (READLINE_CALLBACKS)
1239 if (RL_ISSTATE (RL_STATE_CALLBACK))
1240 (*rl_redisplay_function)(); /* make sure motion is displayed */
1243 r = vidomove_dispatch (m);
1248 #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
1251 rl_domove_read_callback (_rl_vimotion_cxt *m)
1257 if (member (c, vi_motion))
1259 #if defined (READLINE_CALLBACKS)
1260 /* If we just read a vi-mode motion command numeric argument, turn off
1261 the `reading numeric arg' state */
1262 if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1263 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1265 /* Should do everything, including turning off RL_STATE_VIMOTION */
1266 return (rl_domove_motion_callback (m));
1268 else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c'))
1271 rl_beg_of_line (1, c);
1272 _rl_vi_last_motion = c;
1273 RL_UNSETSTATE (RL_STATE_VIMOTION);
1274 return (vidomove_dispatch (m));
1276 #if defined (READLINE_CALLBACKS)
1277 /* XXX - these need to handle rl_universal_argument bindings */
1278 /* Reading vi motion char continuing numeric argument */
1279 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1281 return (_rl_vi_arg_dispatch (c));
1283 /* Readine vi motion char starting numeric argument */
1284 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
1286 RL_SETSTATE (RL_STATE_NUMERICARG);
1287 return (_rl_vi_arg_dispatch (c));
1290 else if (_rl_digit_p (c))
1292 /* This code path taken when not in callback mode */
1293 save = rl_numeric_arg;
1294 rl_numeric_arg = _rl_digit_value (c);
1295 rl_explicit_arg = 1;
1296 RL_SETSTATE (RL_STATE_NUMERICARG);
1298 rl_numeric_arg *= save;
1299 c = rl_vi_domove_getchar (m);
1306 return (rl_domove_motion_callback (m));
1310 RL_UNSETSTATE (RL_STATE_VIMOTION);
1311 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1317 rl_vi_domove_getchar (_rl_vimotion_cxt *m)
1321 RL_SETSTATE(RL_STATE_MOREINPUT);
1323 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1328 #if defined (READLINE_CALLBACKS)
1330 _rl_vi_domove_callback (_rl_vimotion_cxt *m)
1334 m->motion = c = rl_vi_domove_getchar (m);
1337 r = rl_domove_read_callback (m);
1339 return ((r == 0) ? r : 1); /* normalize return values */
1343 /* This code path is taken when not in callback mode. */
1345 rl_vi_domove (int x, int *ignore)
1348 _rl_vimotion_cxt *m;
1351 *ignore = m->motion = rl_vi_domove_getchar (m);
1359 return (rl_domove_read_callback (m));
1363 vi_delete_dispatch (_rl_vimotion_cxt *m)
1365 /* These are the motion commands that do not require adjusting the
1367 if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1369 INCREMENT_POS (rl_mark);
1371 rl_kill_text (rl_point, rl_mark);
1376 rl_vi_delete_to (int count, int key)
1380 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
1381 _rl_vimvcxt->start = rl_point;
1384 if (_rl_uppercase_p (key))
1386 _rl_vimvcxt->motion = '$';
1387 r = rl_domove_motion_callback (_rl_vimvcxt);
1389 else if (_rl_vi_redoing && _rl_vi_last_motion != 'd') /* `dd' is special */
1391 _rl_vimvcxt->motion = _rl_vi_last_motion;
1392 r = rl_domove_motion_callback (_rl_vimvcxt);
1394 else if (_rl_vi_redoing) /* handle redoing `dd' here */
1396 _rl_vimvcxt->motion = _rl_vi_last_motion;
1398 rl_beg_of_line (1, key);
1399 RL_UNSETSTATE (RL_STATE_VIMOTION);
1400 r = vidomove_dispatch (_rl_vimvcxt);
1402 #if defined (READLINE_CALLBACKS)
1403 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1405 RL_SETSTATE (RL_STATE_VIMOTION);
1410 r = rl_vi_domove (key, &c);
1418 _rl_mvcxt_dispose (_rl_vimvcxt);
1425 vi_change_dispatch (_rl_vimotion_cxt *m)
1427 /* These are the motion commands that do not require adjusting the
1428 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1429 and already leave the mark at the correct location. */
1430 if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1432 INCREMENT_POS (rl_mark);
1434 /* The cursor never moves with c[wW]. */
1435 if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
1436 rl_point = m->start;
1440 if (vi_insert_buffer && *vi_insert_buffer)
1441 rl_begin_undo_group ();
1442 rl_delete_text (rl_point, rl_mark);
1443 if (vi_insert_buffer && *vi_insert_buffer)
1445 rl_insert_text (vi_insert_buffer);
1446 rl_end_undo_group ();
1451 rl_begin_undo_group (); /* to make the `u' command work */
1452 rl_kill_text (rl_point, rl_mark);
1453 /* `C' does not save the text inserted for undoing or redoing. */
1454 if (_rl_uppercase_p (m->key) == 0)
1455 _rl_vi_doing_insert = 1;
1456 /* XXX -- TODO -- use m->numericarg? */
1457 rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
1464 rl_vi_change_to (int count, int key)
1468 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
1469 _rl_vimvcxt->start = rl_point;
1472 if (_rl_uppercase_p (key))
1474 _rl_vimvcxt->motion = '$';
1475 r = rl_domove_motion_callback (_rl_vimvcxt);
1477 else if (_rl_vi_redoing && _rl_vi_last_motion != 'c') /* `cc' is special */
1479 _rl_vimvcxt->motion = _rl_vi_last_motion;
1480 r = rl_domove_motion_callback (_rl_vimvcxt);
1482 else if (_rl_vi_redoing) /* handle redoing `cc' here */
1484 _rl_vimvcxt->motion = _rl_vi_last_motion;
1486 rl_beg_of_line (1, key);
1487 RL_UNSETSTATE (RL_STATE_VIMOTION);
1488 r = vidomove_dispatch (_rl_vimvcxt);
1490 #if defined (READLINE_CALLBACKS)
1491 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1493 RL_SETSTATE (RL_STATE_VIMOTION);
1498 r = rl_vi_domove (key, &c);
1503 r = -1; /* normalize return value */
1506 _rl_mvcxt_dispose (_rl_vimvcxt);
1513 vi_yank_dispatch (_rl_vimotion_cxt *m)
1515 /* These are the motion commands that do not require adjusting the
1517 if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1519 INCREMENT_POS (rl_mark);
1521 rl_begin_undo_group ();
1522 rl_kill_text (rl_point, rl_mark);
1523 rl_end_undo_group ();
1525 rl_point = m->start;
1531 rl_vi_yank_to (int count, int key)
1535 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
1536 _rl_vimvcxt->start = rl_point;
1539 if (_rl_uppercase_p (key))
1541 _rl_vimvcxt->motion = '$';
1542 r = rl_domove_motion_callback (_rl_vimvcxt);
1544 else if (_rl_vi_redoing && _rl_vi_last_motion != 'y') /* `yy' is special */
1546 _rl_vimvcxt->motion = _rl_vi_last_motion;
1547 r = rl_domove_motion_callback (_rl_vimvcxt);
1549 else if (_rl_vi_redoing) /* handle redoing `yy' here */
1551 _rl_vimvcxt->motion = _rl_vi_last_motion;
1553 rl_beg_of_line (1, key);
1554 RL_UNSETSTATE (RL_STATE_VIMOTION);
1555 r = vidomove_dispatch (_rl_vimvcxt);
1557 #if defined (READLINE_CALLBACKS)
1558 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1560 RL_SETSTATE (RL_STATE_VIMOTION);
1565 r = rl_vi_domove (key, &c);
1573 _rl_mvcxt_dispose (_rl_vimvcxt);
1580 vidomove_dispatch (_rl_vimotion_cxt *m)
1587 r = vi_delete_dispatch (m);
1590 r = vi_change_dispatch (m);
1593 r = vi_yank_dispatch (m);
1596 _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op);
1601 RL_UNSETSTATE (RL_STATE_VIMOTION);
1606 rl_vi_rubout (int count, int key)
1611 return (rl_vi_delete (-count, key));
1620 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1621 rl_backward_char (count, key);
1622 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1623 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1630 rl_kill_text (rl_point, opoint);
1636 rl_vi_delete (int count, int key)
1641 return (rl_vi_rubout (-count, key));
1649 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1650 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1652 end = rl_point + count;
1657 rl_kill_text (rl_point, end);
1659 if (rl_point > 0 && rl_point == rl_end)
1660 rl_backward_char (1, key);
1665 /* This does what Posix specifies vi-mode C-w to do: using whitespace and
1666 punctuation characters as the word boundaries. */
1668 #define vi_unix_word_boundary(c) (whitespace(c) || ispunct(c))
1671 rl_vi_unix_word_rubout (int count, int key)
1679 orig_point = rl_point;
1685 /* This isn't quite what ksh93 does but it seems to match what the
1686 Posix description of sh specifies, with a few accommodations
1687 for sequences of whitespace characters between words and at
1688 the end of the line. */
1690 /* Skip over whitespace at the end of the line as a special case */
1691 if (rl_point > 0 && (rl_line_buffer[rl_point] == 0) &&
1692 whitespace (rl_line_buffer[rl_point - 1]))
1693 while (--rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
1696 /* If we're at the start of a word, move back to word boundary so we
1697 move back to the `preceding' word */
1698 if (rl_point > 0 && (vi_unix_word_boundary (rl_line_buffer[rl_point]) == 0) &&
1699 vi_unix_word_boundary (rl_line_buffer[rl_point - 1]))
1702 /* If we are at a word boundary (whitespace/punct), move backward
1703 past a sequence of word boundary characters. If we are at the
1704 end of a word (non-word boundary), move back to a word boundary */
1705 if (rl_point > 0 && vi_unix_word_boundary (rl_line_buffer[rl_point]))
1706 while (rl_point && vi_unix_word_boundary (rl_line_buffer[rl_point - 1]))
1708 else if (rl_point > 0 && vi_unix_word_boundary (rl_line_buffer[rl_point]) == 0)
1709 while (rl_point > 0 && (vi_unix_word_boundary (rl_line_buffer[rl_point - 1]) == 0))
1710 _rl_vi_backup_point ();
1713 rl_kill_text (orig_point, rl_point);
1721 rl_vi_back_to_indent (int count, int key)
1723 rl_beg_of_line (1, key);
1724 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1730 rl_vi_first_print (int count, int key)
1732 return (rl_vi_back_to_indent (1, key));
1735 static int _rl_cs_dir, _rl_cs_orig_dir;
1737 #if defined (READLINE_CALLBACKS)
1739 _rl_vi_callback_char_search (_rl_callback_generic_arg *data)
1742 #if defined (HANDLE_MULTIBYTE)
1743 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1745 RL_SETSTATE(RL_STATE_MOREINPUT);
1747 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1752 RL_UNSETSTATE (RL_STATE_CHARSEARCH);
1756 #if !defined (HANDLE_MULTIBYTE)
1757 _rl_vi_last_search_char = c;
1760 _rl_callback_func = 0;
1761 _rl_want_redisplay = 1;
1762 RL_UNSETSTATE (RL_STATE_CHARSEARCH);
1764 #if defined (HANDLE_MULTIBYTE)
1765 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
1767 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
1773 rl_vi_char_search (int count, int key)
1776 #if defined (HANDLE_MULTIBYTE)
1777 static char *target;
1783 if (key == ';' || key == ',')
1785 if (_rl_cs_orig_dir == 0)
1787 #if defined (HANDLE_MULTIBYTE)
1788 if (_rl_vi_last_search_mblen == 0)
1791 if (_rl_vi_last_search_char == 0)
1794 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
1801 _rl_cs_orig_dir = _rl_cs_dir = FTO;
1805 _rl_cs_orig_dir = _rl_cs_dir = BTO;
1809 _rl_cs_orig_dir = _rl_cs_dir = FFIND;
1813 _rl_cs_orig_dir = _rl_cs_dir = BFIND;
1819 /* set target and tlen below */
1821 #if defined (READLINE_CALLBACKS)
1822 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1824 _rl_callback_data = _rl_callback_data_alloc (count);
1825 _rl_callback_data->i1 = _rl_cs_dir;
1826 _rl_callback_data->i2 = key;
1827 _rl_callback_func = _rl_vi_callback_char_search;
1828 RL_SETSTATE (RL_STATE_CHARSEARCH);
1834 #if defined (HANDLE_MULTIBYTE)
1835 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1838 _rl_vi_last_search_mblen = c;
1840 RL_SETSTATE(RL_STATE_MOREINPUT);
1842 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1845 _rl_vi_last_search_char = c;
1850 #if defined (HANDLE_MULTIBYTE)
1851 target = _rl_vi_last_search_mbchar;
1852 tlen = _rl_vi_last_search_mblen;
1854 target = _rl_vi_last_search_char;
1857 #if defined (HANDLE_MULTIBYTE)
1858 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
1860 return (_rl_char_search_internal (count, _rl_cs_dir, target));
1864 /* Match brackets */
1866 rl_vi_match (int ignore, int key)
1868 int count = 1, brack, pos, tmp, pre;
1871 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1873 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1875 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1878 rl_forward_char (1, key);
1879 if (pre == rl_point)
1884 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1885 rl_point < rl_end - 1)
1886 rl_forward_char (1, key);
1903 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1907 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1913 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1916 else if (b == brack)
1930 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1933 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1937 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1940 else if (b == brack)
1955 rl_vi_bracktype (int c)
1960 case ')': return -1;
1962 case ']': return -2;
1964 case '}': return -3;
1970 _rl_vi_change_char (int count, int c, char *mb)
1974 if (c == '\033' || c == CTRL ('C'))
1977 rl_begin_undo_group ();
1978 while (count-- && rl_point < rl_end)
1981 rl_vi_delete (1, c);
1982 if (rl_point < p) /* Did we retreat at EOL? */
1983 _rl_vi_append_forward (c);
1984 #if defined (HANDLE_MULTIBYTE)
1985 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1986 rl_insert_text (mb);
1989 _rl_insert_char (1, c);
1992 /* The cursor shall be left on the last character changed. */
1993 rl_backward_char (1, c);
1995 rl_end_undo_group ();
2001 _rl_vi_callback_getchar (char *mb, int mlen)
2005 RL_SETSTATE(RL_STATE_MOREINPUT);
2007 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2012 #if defined (HANDLE_MULTIBYTE)
2013 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
2014 c = _rl_read_mbstring (c, mb, mlen);
2020 #if defined (READLINE_CALLBACKS)
2022 _rl_vi_callback_change_char (_rl_callback_generic_arg *data)
2025 char mb[MB_LEN_MAX+1];
2027 c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
2028 #if defined (HANDLE_MULTIBYTE)
2029 strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
2031 _rl_vi_last_replacement[0] = c;
2033 _rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* XXX */
2038 _rl_callback_func = 0;
2039 _rl_want_redisplay = 1;
2041 return (_rl_vi_change_char (data->count, c, mb));
2046 rl_vi_change_char (int count, int key)
2049 char mb[MB_LEN_MAX+1];
2053 strncpy (mb, _rl_vi_last_replacement, MB_LEN_MAX);
2054 c = (unsigned char)_rl_vi_last_replacement[0]; /* XXX */
2055 mb[MB_LEN_MAX] = '\0';
2057 #if defined (READLINE_CALLBACKS)
2058 else if (RL_ISSTATE (RL_STATE_CALLBACK))
2060 _rl_callback_data = _rl_callback_data_alloc (count);
2061 _rl_callback_func = _rl_vi_callback_change_char;
2067 c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
2068 #ifdef HANDLE_MULTIBYTE
2069 strncpy (_rl_vi_last_replacement, mb, MB_LEN_MAX);
2071 _rl_vi_last_replacement[0] = c;
2073 _rl_vi_last_replacement[MB_LEN_MAX] = '\0'; /* just in case */
2079 return (_rl_vi_change_char (count, c, mb));
2083 rl_vi_subst (int count, int key)
2085 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
2086 if (_rl_vi_redoing == 0)
2087 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
2089 return (rl_vi_change_to (count, 'c'));
2093 rl_vi_overstrike (int count, int key)
2095 if (_rl_vi_doing_insert == 0)
2097 _rl_vi_doing_insert = 1;
2098 rl_begin_undo_group ();
2103 _rl_overwrite_char (count, key);
2104 vi_replace_count += count;
2111 rl_vi_overstrike_delete (int count, int key)
2115 for (i = 0; i < count; i++)
2117 if (vi_replace_count == 0)
2128 rl_backward_char (1, key);
2131 if (vi_replace_count == 0 && _rl_vi_doing_insert)
2133 rl_end_undo_group ();
2135 _rl_vi_doing_insert = 0;
2141 rl_vi_replace (int count, int key)
2145 vi_replace_count = 0;
2147 if (vi_replace_map == 0)
2149 vi_replace_map = rl_make_bare_keymap ();
2151 for (i = 0; i < ' '; i++)
2152 if (vi_insertion_keymap[i].type == ISFUNC)
2153 vi_replace_map[i].function = vi_insertion_keymap[i].function;
2155 for (i = ' '; i < KEYMAP_SIZE; i++)
2156 vi_replace_map[i].function = rl_vi_overstrike;
2158 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
2160 /* Make sure these are what we want. */
2161 vi_replace_map[ESC].function = rl_vi_movement_mode;
2162 vi_replace_map[RETURN].function = rl_newline;
2163 vi_replace_map[NEWLINE].function = rl_newline;
2165 /* If the normal vi insertion keymap has ^H bound to erase, do the
2166 same here. Probably should remove the assignment to RUBOUT up
2167 there, but I don't think it will make a difference in real life. */
2168 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
2169 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
2170 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
2172 /* Make sure this is the value we need. */
2173 vi_replace_map[ANYOTHERKEY].type = ISFUNC;
2174 vi_replace_map[ANYOTHERKEY].function = (rl_command_func_t *)NULL;
2177 rl_vi_start_inserting (key, 1, rl_arg_sign);
2179 _rl_vi_last_key_before_insert = key;
2180 _rl_keymap = vi_replace_map;
2186 /* Try to complete the word we are standing on or the word that ends with
2187 the previous character. A space matches everything. Word delimiters are
2190 rl_vi_possible_completions (void)
2192 int save_pos = rl_point;
2194 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
2196 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
2197 rl_line_buffer[rl_point] != ';')
2198 _rl_vi_advance_point ();
2200 else if (rl_line_buffer[rl_point - 1] == ';')
2206 rl_possible_completions ();
2207 rl_point = save_pos;
2213 /* Functions to save and restore marks. */
2215 _rl_vi_set_mark (void)
2219 RL_SETSTATE(RL_STATE_MOREINPUT);
2220 ch = rl_read_key ();
2221 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2223 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2229 vi_mark_chars[ch] = rl_point;
2233 #if defined (READLINE_CALLBACKS)
2235 _rl_vi_callback_set_mark (_rl_callback_generic_arg *data)
2237 _rl_callback_func = 0;
2238 _rl_want_redisplay = 1;
2240 return (_rl_vi_set_mark ());
2245 rl_vi_set_mark (int count, int key)
2247 #if defined (READLINE_CALLBACKS)
2248 if (RL_ISSTATE (RL_STATE_CALLBACK))
2250 _rl_callback_data = 0;
2251 _rl_callback_func = _rl_vi_callback_set_mark;
2256 return (_rl_vi_set_mark ());
2260 _rl_vi_goto_mark (void)
2264 RL_SETSTATE(RL_STATE_MOREINPUT);
2265 ch = rl_read_key ();
2266 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2273 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2280 if (vi_mark_chars[ch] == -1)
2285 rl_point = vi_mark_chars[ch];
2289 #if defined (READLINE_CALLBACKS)
2291 _rl_vi_callback_goto_mark (_rl_callback_generic_arg *data)
2293 _rl_callback_func = 0;
2294 _rl_want_redisplay = 1;
2296 return (_rl_vi_goto_mark ());
2301 rl_vi_goto_mark (int count, int key)
2303 #if defined (READLINE_CALLBACKS)
2304 if (RL_ISSTATE (RL_STATE_CALLBACK))
2306 _rl_callback_data = 0;
2307 _rl_callback_func = _rl_vi_callback_goto_mark;
2312 return (_rl_vi_goto_mark ());
2314 #endif /* VI_MODE */