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-2016 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 indicates we are redoing a vi-mode command with `.' */
73 /* Non-zero means enter insertion mode. */
74 static int _rl_vi_doing_insert;
76 /* Command keys which do movement for xxx_to commands. */
77 static const char * const vi_motion = " hl^$0ftFT;,%wbeWBE|`";
79 /* Keymap used for vi replace characters. Created dynamically since
81 static Keymap vi_replace_map;
83 /* The number of characters inserted in the last replace operation. */
84 static int vi_replace_count;
86 /* If non-zero, we have text inserted after a c[motion] command that put
87 us implicitly into insert mode. Some people want this text to be
88 attached to the command so that it is `redoable' with `.'. */
89 static int vi_continued_command;
90 static char *vi_insert_buffer;
91 static int vi_insert_buffer_size;
93 static int _rl_vi_last_repeat = 1;
94 static int _rl_vi_last_arg_sign = 1;
95 static int _rl_vi_last_motion;
96 #if defined (HANDLE_MULTIBYTE)
97 static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
98 static int _rl_vi_last_search_mblen;
100 static int _rl_vi_last_search_char;
102 static int _rl_vi_last_replacement;
104 static int _rl_vi_last_key_before_insert;
106 /* Text modification commands. These are the `redoable' commands. */
107 static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
109 /* Arrays for the saved marks. */
110 static int vi_mark_chars['z' - 'a' + 1];
112 static void _rl_vi_replace_insert PARAMS((int));
113 static void _rl_vi_save_replace PARAMS((void));
114 static void _rl_vi_stuff_insert PARAMS((int));
115 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
117 static void vi_save_insert_buffer PARAMS ((int, int));
119 static void _rl_vi_backup PARAMS((void));
121 static int _rl_vi_arg_dispatch PARAMS((int));
122 static int rl_digit_loop1 PARAMS((void));
124 static int _rl_vi_set_mark PARAMS((void));
125 static int _rl_vi_goto_mark PARAMS((void));
127 static void _rl_vi_append_forward PARAMS((int));
129 static int _rl_vi_callback_getchar PARAMS((char *, int));
131 #if defined (READLINE_CALLBACKS)
132 static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
133 static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
134 static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
135 static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
138 static int rl_domove_read_callback PARAMS((_rl_vimotion_cxt *));
139 static int rl_domove_motion_callback PARAMS((_rl_vimotion_cxt *));
140 static int rl_vi_domove_getchar PARAMS((_rl_vimotion_cxt *));
142 static int vi_change_dispatch PARAMS((_rl_vimotion_cxt *));
143 static int vi_delete_dispatch PARAMS((_rl_vimotion_cxt *));
144 static int vi_yank_dispatch PARAMS((_rl_vimotion_cxt *));
146 static int vidomove_dispatch PARAMS((_rl_vimotion_cxt *));
149 _rl_vi_initialize_line ()
153 n = sizeof (vi_mark_chars) / sizeof (vi_mark_chars[0]);
154 for (i = 0; i < n; i++)
155 vi_mark_chars[i] = -1;
157 RL_UNSETSTATE(RL_STATE_VICMDONCE);
163 _rl_vi_last_command = 'i';
164 _rl_vi_last_repeat = 1;
165 _rl_vi_last_arg_sign = 1;
166 _rl_vi_last_motion = 0;
170 _rl_vi_set_last (key, repeat, sign)
171 int key, repeat, sign;
173 _rl_vi_last_command = key;
174 _rl_vi_last_repeat = repeat;
175 _rl_vi_last_arg_sign = sign;
178 /* A convenience function that calls _rl_vi_set_last to save the last command
179 information and enters insertion mode. */
181 rl_vi_start_inserting (key, repeat, sign)
182 int key, repeat, sign;
184 _rl_vi_set_last (key, repeat, sign);
185 rl_vi_insertion_mode (1, key);
188 /* Is the command C a VI mode text modification command? */
190 _rl_vi_textmod_command (c)
193 return (member (c, vi_textmod));
197 _rl_vi_motion_command (c)
200 return (member (c, vi_motion));
204 _rl_vi_replace_insert (count)
209 nchars = strlen (vi_insert_buffer);
211 rl_begin_undo_group ();
213 /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
215 _rl_replace_text (vi_insert_buffer, rl_point, rl_point+nchars-1);
216 rl_end_undo_group ();
220 _rl_vi_stuff_insert (count)
223 rl_begin_undo_group ();
225 rl_insert_text (vi_insert_buffer);
226 rl_end_undo_group ();
229 /* Bound to `.'. Called from command mode, so we know that we have to
230 redo a text modification command. The default for _rl_vi_last_command
231 puts you back into insert mode. */
233 rl_vi_redo (count, c)
238 if (rl_explicit_arg == 0)
240 rl_numeric_arg = _rl_vi_last_repeat;
241 rl_arg_sign = _rl_vi_last_arg_sign;
246 /* If we're redoing an insert with `i', stuff in the inserted text
247 and do not go into insertion mode. */
248 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
250 _rl_vi_stuff_insert (count);
251 /* And back up point over the last character inserted. */
255 else if (_rl_vi_last_command == 'R' && vi_insert_buffer && *vi_insert_buffer)
257 _rl_vi_replace_insert (count);
258 /* And back up point over the last character inserted. */
262 /* Ditto for redoing an insert with `I', but move to the beginning of the
263 line like the `I' command does. */
264 else if (_rl_vi_last_command == 'I' && vi_insert_buffer && *vi_insert_buffer)
266 rl_beg_of_line (1, 'I');
267 _rl_vi_stuff_insert (count);
271 /* Ditto for redoing an insert with `a', but move forward a character first
272 like the `a' command does. */
273 else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
275 _rl_vi_append_forward ('a');
276 _rl_vi_stuff_insert (count);
280 /* Ditto for redoing an insert with `A', but move to the end of the line
281 like the `A' command does. */
282 else if (_rl_vi_last_command == 'A' && vi_insert_buffer && *vi_insert_buffer)
284 rl_end_of_line (1, 'A');
285 _rl_vi_stuff_insert (count);
290 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
297 /* A placeholder for further expansion. */
299 rl_vi_undo (count, key)
302 return (rl_undo_command (count, key));
305 /* Yank the nth arg from the previous line into this line at point. */
307 rl_vi_yank_arg (count, key)
310 /* Readline thinks that the first word on a line is the 0th, while vi
311 thinks the first word on a line is the 1st. Compensate. */
313 rl_yank_nth_arg (count - 1, 0);
315 rl_yank_nth_arg ('$', 0);
320 /* With an argument, move back that many history lines, else move to the
321 beginning of history. */
323 rl_vi_fetch_history (count, c)
328 /* Giving an argument of n means we want the nth command in the history
329 file. The command number is interpreted the same way that the bash
330 `history' command does it -- that is, giving an argument count of 450
331 to this command would get the command listed as number 450 in the
332 output of `history'. */
335 wanted = history_base + where_history () - count;
337 rl_beginning_of_history (0, 0);
339 rl_get_previous_history (wanted, c);
342 rl_beginning_of_history (count, 0);
346 /* Search again for the last thing searched for. */
348 rl_vi_search_again (count, key)
354 rl_noninc_reverse_search_again (count, key);
358 rl_noninc_forward_search_again (count, key);
364 /* Do a vi style search. */
366 rl_vi_search (count, key)
372 _rl_free_saved_history_line ();
373 rl_noninc_forward_search (count, key);
377 _rl_free_saved_history_line ();
378 rl_noninc_reverse_search (count, key);
388 /* Completion, from vi's point of view. */
390 rl_vi_complete (ignore, key)
393 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
395 if (!whitespace (rl_line_buffer[rl_point + 1]))
396 rl_vi_end_word (1, 'E');
401 rl_complete_internal ('*'); /* Expansion and replacement. */
403 rl_complete_internal ('?'); /* List possible completions. */
404 else if (key == '\\')
405 rl_complete_internal (TAB); /* Standard Readline completion. */
407 rl_complete (0, key);
409 if (key == '*' || key == '\\')
410 rl_vi_start_inserting (key, 1, rl_arg_sign);
415 /* Tilde expansion for vi mode. */
417 rl_vi_tilde_expand (ignore, key)
420 rl_tilde_expand (0, key);
421 rl_vi_start_inserting (key, 1, rl_arg_sign);
425 /* Previous word in vi mode. */
427 rl_vi_prev_word (count, key)
431 return (rl_vi_next_word (-count, key));
439 if (_rl_uppercase_p (key))
440 rl_vi_bWord (count, key);
442 rl_vi_bword (count, key);
447 /* Next word in vi mode. */
449 rl_vi_next_word (count, key)
453 return (rl_vi_prev_word (-count, key));
455 if (rl_point >= (rl_end - 1))
461 if (_rl_uppercase_p (key))
462 rl_vi_fWord (count, key);
464 rl_vi_fword (count, key);
468 /* Move to the end of the ?next? word. */
470 rl_vi_end_word (count, key)
479 if (_rl_uppercase_p (key))
480 rl_vi_eWord (count, key);
482 rl_vi_eword (count, key);
486 /* Move forward a word the way that 'W' does. */
488 rl_vi_fWord (count, ignore)
491 while (count-- && rl_point < (rl_end - 1))
493 /* Skip until whitespace. */
494 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
497 /* Now skip whitespace. */
498 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
505 rl_vi_bWord (count, ignore)
508 while (count-- && rl_point > 0)
510 /* If we are at the start of a word, move back to whitespace so
511 we will go back to the start of the previous word. */
512 if (!whitespace (rl_line_buffer[rl_point]) &&
513 whitespace (rl_line_buffer[rl_point - 1]))
516 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
521 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
529 rl_vi_eWord (count, ignore)
532 while (count-- && rl_point < (rl_end - 1))
534 if (!whitespace (rl_line_buffer[rl_point]))
537 /* Move to the next non-whitespace character (to the start of the
539 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
542 if (rl_point && rl_point < rl_end)
544 /* Skip whitespace. */
545 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
548 /* Skip until whitespace. */
549 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
552 /* Move back to the last character of the word. */
560 rl_vi_fword (count, ignore)
563 while (count-- && rl_point < (rl_end - 1))
565 /* Move to white space (really non-identifer). */
566 if (_rl_isident (rl_line_buffer[rl_point]))
568 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
571 else /* if (!whitespace (rl_line_buffer[rl_point])) */
573 while (!_rl_isident (rl_line_buffer[rl_point]) &&
574 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
578 /* Move past whitespace. */
579 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
586 rl_vi_bword (count, ignore)
589 while (count-- && rl_point > 0)
593 /* If we are at the start of a word, move back to whitespace
594 so we will go back to the start of the previous word. */
595 if (!whitespace (rl_line_buffer[rl_point]) &&
596 whitespace (rl_line_buffer[rl_point - 1]))
599 /* If this character and the previous character are `opposite', move
600 back so we don't get messed up by the rl_point++ down there in
601 the while loop. Without this code, words like `l;' screw up the
603 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
604 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
605 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
608 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
613 if (_rl_isident (rl_line_buffer[rl_point]))
614 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
616 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
617 !whitespace (rl_line_buffer[rl_point]));
625 rl_vi_eword (count, ignore)
628 while (count-- && rl_point < rl_end - 1)
630 if (!whitespace (rl_line_buffer[rl_point]))
633 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
636 if (rl_point < rl_end)
638 if (_rl_isident (rl_line_buffer[rl_point]))
639 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
641 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
642 && !whitespace (rl_line_buffer[rl_point]));
650 rl_vi_insert_beg (count, key)
653 rl_beg_of_line (1, key);
654 rl_vi_insert_mode (1, key);
659 _rl_vi_append_forward (key)
664 if (rl_point < rl_end)
666 if (MB_CUR_MAX == 1 || rl_byte_oriented)
672 rl_forward_char (1, key);
674 rl_point = _rl_forward_char_internal (1);
676 if (point == rl_point)
683 rl_vi_append_mode (count, key)
686 _rl_vi_append_forward (key);
687 rl_vi_start_inserting (key, 1, rl_arg_sign);
692 rl_vi_append_eol (count, key)
695 rl_end_of_line (1, key);
696 rl_vi_append_mode (1, key);
700 /* What to do in the case of C-d. */
702 rl_vi_eof_maybe (count, c)
705 return (rl_newline (1, '\n'));
708 /* Insertion mode stuff. */
710 /* Switching from one mode to the other really just involves
711 switching keymaps. */
713 rl_vi_insertion_mode (count, key)
716 _rl_keymap = vi_insertion_keymap;
717 _rl_vi_last_key_before_insert = key;
718 if (_rl_show_mode_in_prompt)
724 rl_vi_insert_mode (count, key)
727 rl_vi_start_inserting (key, 1, rl_arg_sign);
732 vi_save_insert_buffer (start, len)
735 /* Same code as _rl_vi_save_insert below */
736 if (len >= vi_insert_buffer_size)
738 vi_insert_buffer_size += (len + 32) - (len % 32);
739 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
741 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
742 vi_insert_buffer[len-1] = '\0';
746 _rl_vi_save_replace ()
752 if (up == 0 || up->what != UNDO_END || vi_replace_count <= 0)
754 if (vi_insert_buffer_size >= 1)
755 vi_insert_buffer[0] = '\0';
758 /* Let's try it the quick and easy way for now. This should essentially
759 accommodate every UNDO_INSERT and save the inserted text to
762 start = end - vi_replace_count + 1;
763 len = vi_replace_count + 1;
765 vi_save_insert_buffer (start, len);
769 _rl_vi_save_insert (up)
774 if (up == 0 || up->what != UNDO_INSERT)
776 if (vi_insert_buffer_size >= 1)
777 vi_insert_buffer[0] = '\0';
783 len = end - start + 1;
785 vi_save_insert_buffer (start, len);
789 _rl_vi_done_inserting ()
791 if (_rl_vi_doing_insert)
793 /* The `C', `s', and `S' commands set this. */
794 rl_end_undo_group ();
795 /* Now, the text between rl_undo_list->next->start and
796 rl_undo_list->next->end is what was inserted while in insert
797 mode. It gets copied to VI_INSERT_BUFFER because it depends
798 on absolute indices into the line which may change (though they
799 probably will not). */
800 _rl_vi_doing_insert = 0;
801 if (_rl_vi_last_key_before_insert == 'R')
802 _rl_vi_save_replace (); /* Half the battle */
804 _rl_vi_save_insert (rl_undo_list->next);
805 vi_continued_command = 1;
809 if (rl_undo_list && (_rl_vi_last_key_before_insert == 'i' ||
810 _rl_vi_last_key_before_insert == 'a' ||
811 _rl_vi_last_key_before_insert == 'I' ||
812 _rl_vi_last_key_before_insert == 'A'))
813 _rl_vi_save_insert (rl_undo_list);
814 /* XXX - Other keys probably need to be checked. */
815 else if (_rl_vi_last_key_before_insert == 'C')
816 rl_end_undo_group ();
817 while (_rl_undo_group_level > 0)
818 rl_end_undo_group ();
819 vi_continued_command = 0;
824 rl_vi_movement_mode (count, key)
828 rl_backward_char (1, key);
830 _rl_keymap = vi_movement_keymap;
831 _rl_vi_done_inserting ();
833 /* This is how POSIX.2 says `U' should behave -- everything up until the
834 first time you go into command mode should not be undone. */
835 if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
836 rl_free_undo_list ();
838 if (_rl_show_mode_in_prompt)
841 RL_SETSTATE (RL_STATE_VICMDONCE);
846 rl_vi_arg_digit (count, c)
849 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
850 return (rl_beg_of_line (1, c));
852 return (rl_digit_argument (count, c));
855 /* Change the case of the next COUNT characters. */
856 #if defined (HANDLE_MULTIBYTE)
858 _rl_vi_change_mbchar_case (count)
862 char mb[MB_LEN_MAX+1];
867 memset (&ps, 0, sizeof (mbstate_t));
868 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
870 while (count-- && rl_point < rl_end)
872 m = mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
873 if (MB_INVALIDCH (m))
874 wc = (wchar_t)rl_line_buffer[rl_point];
875 else if (MB_NULLWCH (m))
879 else if (iswlower (wc))
883 /* Just skip over chars neither upper nor lower case */
884 rl_forward_char (1, 0);
888 /* Vi is kind of strange here. */
892 mlen = wcrtomb (mb, wc, &ps);
895 rl_begin_undo_group ();
897 if (rl_point < p) /* Did we retreat at EOL? */
898 rl_point++; /* XXX - should we advance more than 1 for mbchar? */
900 rl_end_undo_group ();
904 rl_forward_char (1, 0);
912 rl_vi_change_case (count, ignore)
917 /* Don't try this on an empty line. */
918 if (rl_point >= rl_end)
922 #if defined (HANDLE_MULTIBYTE)
923 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
924 return (_rl_vi_change_mbchar_case (count));
927 while (count-- && rl_point < rl_end)
929 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
930 c = _rl_to_lower (rl_line_buffer[rl_point]);
931 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
932 c = _rl_to_upper (rl_line_buffer[rl_point]);
935 /* Just skip over characters neither upper nor lower case. */
936 rl_forward_char (1, c);
940 /* Vi is kind of strange here. */
944 rl_begin_undo_group ();
946 if (rl_point < p) /* Did we retreat at EOL? */
948 _rl_insert_char (1, c);
949 rl_end_undo_group ();
953 rl_forward_char (1, c);
959 rl_vi_put (count, key)
962 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
963 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
968 rl_backward_char (1, key);
975 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
976 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
984 if (rl_point && rl_point == rl_end)
986 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
987 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
995 rl_vi_column (count, key)
999 rl_end_of_line (1, key);
1001 rl_point = count - 1;
1005 /* Process C as part of the current numeric argument. Return -1 if the
1006 argument should be aborted, 0 if we should not read any more chars, and
1007 1 if we should continue to read chars. */
1009 _rl_vi_arg_dispatch (c)
1015 if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
1017 rl_numeric_arg *= 4;
1023 if (_rl_digit_p (c))
1025 if (rl_explicit_arg)
1026 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
1028 rl_numeric_arg = _rl_digit_value (c);
1029 rl_explicit_arg = 1;
1030 return 1; /* keep going */
1034 rl_clear_message ();
1035 rl_stuff_char (key);
1036 return 0; /* done */
1040 /* A simplified loop for vi. Don't dispatch key at end.
1041 Don't recognize minus sign?
1042 Should this do rl_save_prompt/rl_restore_prompt? */
1050 if (_rl_arg_overflow ())
1053 c = _rl_arg_getchar ();
1055 r = _rl_vi_arg_dispatch (c);
1060 RL_UNSETSTATE(RL_STATE_NUMERICARG);
1065 _rl_mvcxt_init (m, op, key)
1066 _rl_vimotion_cxt *m;
1070 m->state = m->flags = 0;
1072 m->numeric_arg = -1;
1073 m->start = rl_point;
1079 static _rl_vimotion_cxt *
1080 _rl_mvcxt_alloc (op, key)
1083 _rl_vimotion_cxt *m;
1085 m = xmalloc (sizeof (_rl_vimotion_cxt));
1086 _rl_mvcxt_init (m, op, key);
1091 _rl_mvcxt_dispose (m)
1092 _rl_vimotion_cxt *m;
1098 rl_domove_motion_callback (m)
1099 _rl_vimotion_cxt *m;
1103 _rl_vi_last_motion = c = m->motion;
1105 /* Append a blank character temporarily so that the motion routines
1106 work right at the end of the line. Original value of rl_end is saved
1108 rl_line_buffer[rl_end++] = ' ';
1109 rl_line_buffer[rl_end] = '\0';
1111 _rl_dispatch (c, _rl_keymap);
1113 #if defined (READLINE_CALLBACKS)
1114 if (RL_ISSTATE (RL_STATE_CALLBACK))
1116 /* Messy case where char search can be vi motion command; see rest of
1117 details in callback.c. vi_char_search and callback_char_search just
1118 set and unset the CHARSEARCH state. This is where any vi motion
1119 command that needs to set its own state should be handled, with any
1120 corresponding code to manage that state in callback.c */
1121 if (RL_ISSTATE (RL_STATE_CHARSEARCH))
1124 return (_rl_vi_domove_motion_cleanup (c, m));
1128 return (_rl_vi_domove_motion_cleanup (c, m));
1132 _rl_vi_domove_motion_cleanup (c, m)
1134 _rl_vimotion_cxt *m;
1138 /* Remove the blank that we added in rl_domove_motion_callback. */
1140 rl_line_buffer[rl_end] = '\0';
1141 if (rl_point > rl_end)
1144 /* No change in position means the command failed. */
1145 if (rl_mark == rl_point)
1147 RL_UNSETSTATE (RL_STATE_VIMOTION);
1151 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
1152 word. If we are not at the end of the line, and we are on a
1153 non-whitespace character, move back one (presumably to whitespace). */
1154 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
1155 !whitespace (rl_line_buffer[rl_point]))
1158 /* If cw or cW, back up to the end of a word, so the behaviour of ce
1159 or cE is the actual result. Brute-force, no subtlety. */
1160 if (m->key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
1162 /* Don't move farther back than where we started. */
1163 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
1166 /* Posix.2 says that if cw or cW moves the cursor towards the end of
1167 the line, the character under the cursor should be deleted. */
1168 if (rl_point == rl_mark)
1172 /* Move past the end of the word so that the kill doesn't
1173 remove the last letter of the previous word. Only do this
1174 if we are not at the end of the line. */
1175 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
1180 if (rl_mark < rl_point)
1181 SWAP (rl_point, rl_mark);
1183 #if defined (READLINE_CALLBACKS)
1184 if (RL_ISSTATE (RL_STATE_CALLBACK))
1185 (*rl_redisplay_function)(); /* make sure motion is displayed */
1188 r = vidomove_dispatch (m);
1193 #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
1196 rl_domove_read_callback (m)
1197 _rl_vimotion_cxt *m;
1203 if (member (c, vi_motion))
1205 #if defined (READLINE_CALLBACKS)
1206 /* If we just read a vi-mode motion command numeric argument, turn off
1207 the `reading numeric arg' state */
1208 if (RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1209 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1211 /* Should do everything, including turning off RL_STATE_VIMOTION */
1212 return (rl_domove_motion_callback (m));
1214 else if (m->key == c && (m->key == 'd' || m->key == 'y' || m->key == 'c'))
1217 rl_beg_of_line (1, c);
1218 _rl_vi_last_motion = c;
1219 RL_UNSETSTATE (RL_STATE_VIMOTION);
1220 return (vidomove_dispatch (m));
1222 #if defined (READLINE_CALLBACKS)
1223 /* XXX - these need to handle rl_universal_argument bindings */
1224 /* Reading vi motion char continuing numeric argument */
1225 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_VIMOVENUMARG())
1227 return (_rl_vi_arg_dispatch (c));
1229 /* Readine vi motion char starting numeric argument */
1230 else if (_rl_digit_p (c) && RL_ISSTATE (RL_STATE_CALLBACK) && RL_ISSTATE (RL_STATE_VIMOTION) && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
1232 RL_SETSTATE (RL_STATE_NUMERICARG);
1233 return (_rl_vi_arg_dispatch (c));
1236 else if (_rl_digit_p (c))
1238 /* This code path taken when not in callback mode */
1239 save = rl_numeric_arg;
1240 rl_numeric_arg = _rl_digit_value (c);
1241 rl_explicit_arg = 1;
1242 RL_SETSTATE (RL_STATE_NUMERICARG);
1244 rl_numeric_arg *= save;
1245 c = rl_vi_domove_getchar (m);
1252 return (rl_domove_motion_callback (m));
1256 RL_UNSETSTATE (RL_STATE_VIMOTION);
1257 RL_UNSETSTATE (RL_STATE_NUMERICARG);
1263 rl_vi_domove_getchar (m)
1264 _rl_vimotion_cxt *m;
1268 RL_SETSTATE(RL_STATE_MOREINPUT);
1270 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1275 #if defined (READLINE_CALLBACKS)
1277 _rl_vi_domove_callback (m)
1278 _rl_vimotion_cxt *m;
1282 m->motion = c = rl_vi_domove_getchar (m);
1285 r = rl_domove_read_callback (m);
1287 return ((r == 0) ? r : 1); /* normalize return values */
1291 /* This code path taken when not in callback mode. */
1293 rl_vi_domove (x, ignore)
1297 _rl_vimotion_cxt *m;
1300 *ignore = m->motion = rl_vi_domove_getchar (m);
1308 return (rl_domove_read_callback (m));
1312 vi_delete_dispatch (m)
1313 _rl_vimotion_cxt *m;
1315 /* These are the motion commands that do not require adjusting the
1317 if (((strchr (" l|h^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1321 rl_kill_text (rl_point, rl_mark);
1326 rl_vi_delete_to (count, key)
1331 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_DELETE, key);
1332 _rl_vimvcxt->start = rl_point;
1335 if (_rl_uppercase_p (key))
1337 _rl_vimvcxt->motion = '$';
1338 r = rl_domove_motion_callback (_rl_vimvcxt);
1340 else if (_rl_vi_redoing && _rl_vi_last_motion != 'd') /* `dd' is special */
1342 _rl_vimvcxt->motion = _rl_vi_last_motion;
1343 r = rl_domove_motion_callback (_rl_vimvcxt);
1345 else if (_rl_vi_redoing) /* handle redoing `dd' here */
1347 _rl_vimvcxt->motion = _rl_vi_last_motion;
1349 rl_beg_of_line (1, key);
1350 RL_UNSETSTATE (RL_STATE_VIMOTION);
1351 r = vidomove_dispatch (_rl_vimvcxt);
1353 #if defined (READLINE_CALLBACKS)
1354 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1356 RL_SETSTATE (RL_STATE_VIMOTION);
1361 r = rl_vi_domove (key, &c);
1369 _rl_mvcxt_dispose (_rl_vimvcxt);
1376 vi_change_dispatch (m)
1377 _rl_vimotion_cxt *m;
1379 /* These are the motion commands that do not require adjusting the
1380 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1381 and already leave the mark at the correct location. */
1382 if (((strchr (" l|hwW^0bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1386 /* The cursor never moves with c[wW]. */
1387 if ((_rl_to_upper (m->motion) == 'W') && rl_point < m->start)
1388 rl_point = m->start;
1392 if (vi_insert_buffer && *vi_insert_buffer)
1393 rl_begin_undo_group ();
1394 rl_delete_text (rl_point, rl_mark);
1395 if (vi_insert_buffer && *vi_insert_buffer)
1397 rl_insert_text (vi_insert_buffer);
1398 rl_end_undo_group ();
1403 rl_begin_undo_group (); /* to make the `u' command work */
1404 rl_kill_text (rl_point, rl_mark);
1405 /* `C' does not save the text inserted for undoing or redoing. */
1406 if (_rl_uppercase_p (m->key) == 0)
1407 _rl_vi_doing_insert = 1;
1408 /* XXX -- TODO -- use m->numericarg? */
1409 rl_vi_start_inserting (m->key, rl_numeric_arg, rl_arg_sign);
1416 rl_vi_change_to (count, key)
1421 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_CHANGE, key);
1422 _rl_vimvcxt->start = rl_point;
1425 if (_rl_uppercase_p (key))
1427 _rl_vimvcxt->motion = '$';
1428 r = rl_domove_motion_callback (_rl_vimvcxt);
1430 else if (_rl_vi_redoing && _rl_vi_last_motion != 'c') /* `cc' is special */
1432 _rl_vimvcxt->motion = _rl_vi_last_motion;
1433 r = rl_domove_motion_callback (_rl_vimvcxt);
1435 else if (_rl_vi_redoing) /* handle redoing `cc' here */
1437 _rl_vimvcxt->motion = _rl_vi_last_motion;
1439 rl_beg_of_line (1, key);
1440 RL_UNSETSTATE (RL_STATE_VIMOTION);
1441 r = vidomove_dispatch (_rl_vimvcxt);
1443 #if defined (READLINE_CALLBACKS)
1444 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1446 RL_SETSTATE (RL_STATE_VIMOTION);
1451 r = rl_vi_domove (key, &c);
1456 r = -1; /* normalize return value */
1459 _rl_mvcxt_dispose (_rl_vimvcxt);
1466 vi_yank_dispatch (m)
1467 _rl_vimotion_cxt *m;
1469 /* These are the motion commands that do not require adjusting the
1471 if (((strchr (" l|h^0%bBFT`", m->motion) == 0) && (rl_point >= m->start)) &&
1475 rl_begin_undo_group ();
1476 rl_kill_text (rl_point, rl_mark);
1477 rl_end_undo_group ();
1479 rl_point = m->start;
1485 rl_vi_yank_to (count, key)
1490 _rl_vimvcxt = _rl_mvcxt_alloc (VIM_YANK, key);
1491 _rl_vimvcxt->start = rl_point;
1494 if (_rl_uppercase_p (key))
1496 _rl_vimvcxt->motion = '$';
1497 r = rl_domove_motion_callback (_rl_vimvcxt);
1499 else if (_rl_vi_redoing && _rl_vi_last_motion != 'y') /* `yy' is special */
1501 _rl_vimvcxt->motion = _rl_vi_last_motion;
1502 r = rl_domove_motion_callback (_rl_vimvcxt);
1504 else if (_rl_vi_redoing) /* handle redoing `yy' here */
1506 _rl_vimvcxt->motion = _rl_vi_last_motion;
1508 rl_beg_of_line (1, key);
1509 RL_UNSETSTATE (RL_STATE_VIMOTION);
1510 r = vidomove_dispatch (_rl_vimvcxt);
1512 #if defined (READLINE_CALLBACKS)
1513 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1515 RL_SETSTATE (RL_STATE_VIMOTION);
1520 r = rl_vi_domove (key, &c);
1528 _rl_mvcxt_dispose (_rl_vimvcxt);
1535 vidomove_dispatch (m)
1536 _rl_vimotion_cxt *m;
1543 r = vi_delete_dispatch (m);
1546 r = vi_change_dispatch (m);
1549 r = vi_yank_dispatch (m);
1552 _rl_errmsg ("vidomove_dispatch: unknown operator %d", m->op);
1557 RL_UNSETSTATE (RL_STATE_VIMOTION);
1562 rl_vi_rubout (count, key)
1568 return (rl_vi_delete (-count, key));
1577 if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1578 rl_backward_char (count, key);
1579 else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1580 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
1587 rl_kill_text (rl_point, opoint);
1593 rl_vi_delete (count, key)
1599 return (rl_vi_rubout (-count, key));
1607 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1608 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1610 end = rl_point + count;
1615 rl_kill_text (rl_point, end);
1617 if (rl_point > 0 && rl_point == rl_end)
1618 rl_backward_char (1, key);
1623 /* This does what Posix specifies vi-mode C-w to do: using whitespace and
1624 punctuation characters as the word boundaries. */
1626 #define vi_unix_word_boundary(c) (whitespace(c) || ispunct(c))
1629 rl_vi_unix_word_rubout (count, key)
1638 orig_point = rl_point;
1644 /* This isn't quite what ksh93 does but it seems to match what the
1645 Posix description of sh specifies, with a few accommodations
1646 for sequences of whitespace characters between words and at
1647 the end of the line. */
1649 /* Skip over whitespace at the end of the line as a special case */
1650 if (rl_point > 0 && (rl_line_buffer[rl_point] == 0) &&
1651 whitespace (rl_line_buffer[rl_point - 1]))
1652 while (--rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
1655 /* If we're at the start of a word, move back to word boundary so we
1656 move back to the `preceding' word */
1657 if (rl_point > 0 && (vi_unix_word_boundary (rl_line_buffer[rl_point]) == 0) &&
1658 vi_unix_word_boundary (rl_line_buffer[rl_point - 1]))
1661 /* If we are at a word boundary (whitespace/punct), move backward
1662 past a sequence of word boundary characters. If we are at the
1663 end of a word (non-word boundary), move back to a word boundary */
1664 if (rl_point > 0 && vi_unix_word_boundary (rl_line_buffer[rl_point]))
1665 while (rl_point && vi_unix_word_boundary (rl_line_buffer[rl_point - 1]))
1667 else if (rl_point > 0 && vi_unix_word_boundary (rl_line_buffer[rl_point]) == 0)
1668 while (rl_point && (vi_unix_word_boundary (rl_line_buffer[rl_point - 1]) == 0))
1672 rl_kill_text (orig_point, rl_point);
1680 rl_vi_back_to_indent (count, key)
1683 rl_beg_of_line (1, key);
1684 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1690 rl_vi_first_print (count, key)
1693 return (rl_vi_back_to_indent (1, key));
1696 static int _rl_cs_dir, _rl_cs_orig_dir;
1698 #if defined (READLINE_CALLBACKS)
1700 _rl_vi_callback_char_search (data)
1701 _rl_callback_generic_arg *data;
1704 #if defined (HANDLE_MULTIBYTE)
1705 c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1707 RL_SETSTATE(RL_STATE_MOREINPUT);
1709 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1714 RL_UNSETSTATE (RL_STATE_CHARSEARCH);
1718 #if !defined (HANDLE_MULTIBYTE)
1719 _rl_vi_last_search_char = c;
1722 _rl_callback_func = 0;
1723 _rl_want_redisplay = 1;
1724 RL_UNSETSTATE (RL_STATE_CHARSEARCH);
1726 #if defined (HANDLE_MULTIBYTE)
1727 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
1729 return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
1735 rl_vi_char_search (count, key)
1739 #if defined (HANDLE_MULTIBYTE)
1740 static char *target;
1746 if (key == ';' || key == ',')
1748 if (_rl_cs_orig_dir == 0)
1750 #if defined (HANDLE_MULTIBYTE)
1751 if (_rl_vi_last_search_mblen == 0)
1754 if (_rl_vi_last_search_char == 0)
1757 _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
1764 _rl_cs_orig_dir = _rl_cs_dir = FTO;
1768 _rl_cs_orig_dir = _rl_cs_dir = BTO;
1772 _rl_cs_orig_dir = _rl_cs_dir = FFIND;
1776 _rl_cs_orig_dir = _rl_cs_dir = BFIND;
1782 /* set target and tlen below */
1784 #if defined (READLINE_CALLBACKS)
1785 else if (RL_ISSTATE (RL_STATE_CALLBACK))
1787 _rl_callback_data = _rl_callback_data_alloc (count);
1788 _rl_callback_data->i1 = _rl_cs_dir;
1789 _rl_callback_data->i2 = key;
1790 _rl_callback_func = _rl_vi_callback_char_search;
1791 RL_SETSTATE (RL_STATE_CHARSEARCH);
1797 #if defined (HANDLE_MULTIBYTE)
1798 c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1801 _rl_vi_last_search_mblen = c;
1803 RL_SETSTATE(RL_STATE_MOREINPUT);
1805 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1808 _rl_vi_last_search_char = c;
1813 #if defined (HANDLE_MULTIBYTE)
1814 target = _rl_vi_last_search_mbchar;
1815 tlen = _rl_vi_last_search_mblen;
1817 target = _rl_vi_last_search_char;
1820 #if defined (HANDLE_MULTIBYTE)
1821 return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
1823 return (_rl_char_search_internal (count, _rl_cs_dir, target));
1827 /* Match brackets */
1829 rl_vi_match (ignore, key)
1832 int count = 1, brack, pos, tmp, pre;
1835 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1837 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1839 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1842 rl_forward_char (1, key);
1843 if (pre == rl_point)
1848 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1849 rl_point < rl_end - 1)
1850 rl_forward_char (1, key);
1867 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1871 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1877 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1880 else if (b == brack)
1894 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1897 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1901 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1904 else if (b == brack)
1925 case ')': return -1;
1927 case ']': return -2;
1929 case '}': return -3;
1935 _rl_vi_change_char (count, c, mb)
1941 if (c == '\033' || c == CTRL ('C'))
1944 rl_begin_undo_group ();
1945 while (count-- && rl_point < rl_end)
1948 rl_vi_delete (1, c);
1949 if (rl_point < p) /* Did we retreat at EOL? */
1951 #if defined (HANDLE_MULTIBYTE)
1952 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1953 rl_insert_text (mb);
1956 _rl_insert_char (1, c);
1959 /* The cursor shall be left on the last character changed. */
1960 rl_backward_char (1, c);
1962 rl_end_undo_group ();
1968 _rl_vi_callback_getchar (mb, mlen)
1974 RL_SETSTATE(RL_STATE_MOREINPUT);
1976 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1981 #if defined (HANDLE_MULTIBYTE)
1982 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1983 c = _rl_read_mbstring (c, mb, mlen);
1989 #if defined (READLINE_CALLBACKS)
1991 _rl_vi_callback_change_char (data)
1992 _rl_callback_generic_arg *data;
1995 char mb[MB_LEN_MAX];
1997 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
2002 _rl_callback_func = 0;
2003 _rl_want_redisplay = 1;
2005 return (_rl_vi_change_char (data->count, c, mb));
2010 rl_vi_change_char (count, key)
2014 char mb[MB_LEN_MAX];
2018 c = _rl_vi_last_replacement;
2022 #if defined (READLINE_CALLBACKS)
2023 else if (RL_ISSTATE (RL_STATE_CALLBACK))
2025 _rl_callback_data = _rl_callback_data_alloc (count);
2026 _rl_callback_func = _rl_vi_callback_change_char;
2031 _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
2036 return (_rl_vi_change_char (count, c, mb));
2040 rl_vi_subst (count, key)
2043 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
2044 if (_rl_vi_redoing == 0)
2045 rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
2047 return (rl_vi_change_to (count, 'c'));
2051 rl_vi_overstrike (count, key)
2054 if (_rl_vi_doing_insert == 0)
2056 _rl_vi_doing_insert = 1;
2057 rl_begin_undo_group ();
2062 _rl_overwrite_char (count, key);
2063 vi_replace_count += count;
2070 rl_vi_overstrike_delete (count, key)
2075 for (i = 0; i < count; i++)
2077 if (vi_replace_count == 0)
2088 rl_backward_char (1, key);
2091 if (vi_replace_count == 0 && _rl_vi_doing_insert)
2093 rl_end_undo_group ();
2095 _rl_vi_doing_insert = 0;
2101 rl_vi_replace (count, key)
2106 vi_replace_count = 0;
2108 if (vi_replace_map == 0)
2110 vi_replace_map = rl_make_bare_keymap ();
2112 for (i = 0; i < ' '; i++)
2113 if (vi_insertion_keymap[i].type == ISFUNC)
2114 vi_replace_map[i].function = vi_insertion_keymap[i].function;
2116 for (i = ' '; i < KEYMAP_SIZE; i++)
2117 vi_replace_map[i].function = rl_vi_overstrike;
2119 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
2121 /* Make sure these are what we want. */
2122 vi_replace_map[ESC].function = rl_vi_movement_mode;
2123 vi_replace_map[RETURN].function = rl_newline;
2124 vi_replace_map[NEWLINE].function = rl_newline;
2126 /* If the normal vi insertion keymap has ^H bound to erase, do the
2127 same here. Probably should remove the assignment to RUBOUT up
2128 there, but I don't think it will make a difference in real life. */
2129 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
2130 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
2131 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
2135 rl_vi_start_inserting (key, 1, rl_arg_sign);
2137 _rl_vi_last_key_before_insert = key;
2138 _rl_keymap = vi_replace_map;
2144 /* Try to complete the word we are standing on or the word that ends with
2145 the previous character. A space matches everything. Word delimiters are
2148 rl_vi_possible_completions()
2150 int save_pos = rl_point;
2152 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
2154 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
2155 rl_line_buffer[rl_point] != ';')
2158 else if (rl_line_buffer[rl_point - 1] == ';')
2164 rl_possible_completions ();
2165 rl_point = save_pos;
2171 /* Functions to save and restore marks. */
2177 RL_SETSTATE(RL_STATE_MOREINPUT);
2178 ch = rl_read_key ();
2179 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2181 if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2187 vi_mark_chars[ch] = rl_point;
2191 #if defined (READLINE_CALLBACKS)
2193 _rl_vi_callback_set_mark (data)
2194 _rl_callback_generic_arg *data;
2196 _rl_callback_func = 0;
2197 _rl_want_redisplay = 1;
2199 return (_rl_vi_set_mark ());
2204 rl_vi_set_mark (count, key)
2207 #if defined (READLINE_CALLBACKS)
2208 if (RL_ISSTATE (RL_STATE_CALLBACK))
2210 _rl_callback_data = 0;
2211 _rl_callback_func = _rl_vi_callback_set_mark;
2216 return (_rl_vi_set_mark ());
2224 RL_SETSTATE(RL_STATE_MOREINPUT);
2225 ch = rl_read_key ();
2226 RL_UNSETSTATE(RL_STATE_MOREINPUT);
2233 else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
2240 if (vi_mark_chars[ch] == -1)
2245 rl_point = vi_mark_chars[ch];
2249 #if defined (READLINE_CALLBACKS)
2251 _rl_vi_callback_goto_mark (data)
2252 _rl_callback_generic_arg *data;
2254 _rl_callback_func = 0;
2255 _rl_want_redisplay = 1;
2257 return (_rl_vi_goto_mark ());
2262 rl_vi_goto_mark (count, key)
2265 #if defined (READLINE_CALLBACKS)
2266 if (RL_ISSTATE (RL_STATE_CALLBACK))
2268 _rl_callback_data = 0;
2269 _rl_callback_func = _rl_vi_callback_goto_mark;
2274 return (_rl_vi_goto_mark ());
2276 #endif /* VI_MODE */