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_replace_insert (count
)
201 nchars
= strlen (vi_insert_buffer
);
203 rl_begin_undo_group ();
205 /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
207 _rl_replace_text (vi_insert_buffer
, rl_point
, rl_point
+nchars
-1);
208 rl_end_undo_group ();
212 _rl_vi_stuff_insert (count
)
215 rl_begin_undo_group ();
217 rl_insert_text (vi_insert_buffer
);
218 rl_end_undo_group ();
221 /* Bound to `.'. Called from command mode, so we know that we have to
222 redo a text modification command. The default for _rl_vi_last_command
223 puts you back into insert mode. */
225 rl_vi_redo (count
, c
)
230 if (rl_explicit_arg
== 0)
232 rl_numeric_arg
= _rl_vi_last_repeat
;
233 rl_arg_sign
= _rl_vi_last_arg_sign
;
238 /* If we're redoing an insert with `i', stuff in the inserted text
239 and do not go into insertion mode. */
240 if (_rl_vi_last_command
== 'i' && vi_insert_buffer
&& *vi_insert_buffer
)
242 _rl_vi_stuff_insert (count
);
243 /* And back up point over the last character inserted. */
247 else if (_rl_vi_last_command
== 'R' && vi_insert_buffer
&& *vi_insert_buffer
)
249 _rl_vi_replace_insert (count
);
250 /* And back up point over the last character inserted. */
254 /* Ditto for redoing an insert with `I', but move to the beginning of the
255 line like the `I' command does. */
256 else if (_rl_vi_last_command
== 'I' && vi_insert_buffer
&& *vi_insert_buffer
)
258 rl_beg_of_line (1, 'I');
259 _rl_vi_stuff_insert (count
);
263 /* Ditto for redoing an insert with `a', but move forward a character first
264 like the `a' command does. */
265 else if (_rl_vi_last_command
== 'a' && vi_insert_buffer
&& *vi_insert_buffer
)
267 _rl_vi_append_forward ('a');
268 _rl_vi_stuff_insert (count
);
272 /* Ditto for redoing an insert with `A', but move to the end of the line
273 like the `A' command does. */
274 else if (_rl_vi_last_command
== 'A' && vi_insert_buffer
&& *vi_insert_buffer
)
276 rl_end_of_line (1, 'A');
277 _rl_vi_stuff_insert (count
);
282 r
= _rl_dispatch (_rl_vi_last_command
, _rl_keymap
);
288 /* A placeholder for further expansion. */
290 rl_vi_undo (count
, key
)
293 return (rl_undo_command (count
, key
));
296 /* Yank the nth arg from the previous line into this line at point. */
298 rl_vi_yank_arg (count
, key
)
301 /* Readline thinks that the first word on a line is the 0th, while vi
302 thinks the first word on a line is the 1st. Compensate. */
304 rl_yank_nth_arg (count
- 1, 0);
306 rl_yank_nth_arg ('$', 0);
311 /* With an argument, move back that many history lines, else move to the
312 beginning of history. */
314 rl_vi_fetch_history (count
, c
)
319 /* Giving an argument of n means we want the nth command in the history
320 file. The command number is interpreted the same way that the bash
321 `history' command does it -- that is, giving an argument count of 450
322 to this command would get the command listed as number 450 in the
323 output of `history'. */
326 wanted
= history_base
+ where_history () - count
;
328 rl_beginning_of_history (0, 0);
330 rl_get_previous_history (wanted
, c
);
333 rl_beginning_of_history (count
, 0);
337 /* Search again for the last thing searched for. */
339 rl_vi_search_again (count
, key
)
345 rl_noninc_reverse_search_again (count
, key
);
349 rl_noninc_forward_search_again (count
, key
);
355 /* Do a vi style search. */
357 rl_vi_search (count
, key
)
363 _rl_free_saved_history_line ();
364 rl_noninc_forward_search (count
, key
);
368 _rl_free_saved_history_line ();
369 rl_noninc_reverse_search (count
, key
);
379 /* Completion, from vi's point of view. */
381 rl_vi_complete (ignore
, key
)
384 if ((rl_point
< rl_end
) && (!whitespace (rl_line_buffer
[rl_point
])))
386 if (!whitespace (rl_line_buffer
[rl_point
+ 1]))
387 rl_vi_end_word (1, 'E');
392 rl_complete_internal ('*'); /* Expansion and replacement. */
394 rl_complete_internal ('?'); /* List possible completions. */
395 else if (key
== '\\')
396 rl_complete_internal (TAB
); /* Standard Readline completion. */
398 rl_complete (0, key
);
400 if (key
== '*' || key
== '\\')
401 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
406 /* Tilde expansion for vi mode. */
408 rl_vi_tilde_expand (ignore
, key
)
411 rl_tilde_expand (0, key
);
412 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
416 /* Previous word in vi mode. */
418 rl_vi_prev_word (count
, key
)
422 return (rl_vi_next_word (-count
, key
));
430 if (_rl_uppercase_p (key
))
431 rl_vi_bWord (count
, key
);
433 rl_vi_bword (count
, key
);
438 /* Next word in vi mode. */
440 rl_vi_next_word (count
, key
)
444 return (rl_vi_prev_word (-count
, key
));
446 if (rl_point
>= (rl_end
- 1))
452 if (_rl_uppercase_p (key
))
453 rl_vi_fWord (count
, key
);
455 rl_vi_fword (count
, key
);
459 /* Move to the end of the ?next? word. */
461 rl_vi_end_word (count
, key
)
470 if (_rl_uppercase_p (key
))
471 rl_vi_eWord (count
, key
);
473 rl_vi_eword (count
, key
);
477 /* Move forward a word the way that 'W' does. */
479 rl_vi_fWord (count
, ignore
)
482 while (count
-- && rl_point
< (rl_end
- 1))
484 /* Skip until whitespace. */
485 while (!whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
488 /* Now skip whitespace. */
489 while (whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
496 rl_vi_bWord (count
, ignore
)
499 while (count
-- && rl_point
> 0)
501 /* If we are at the start of a word, move back to whitespace so
502 we will go back to the start of the previous word. */
503 if (!whitespace (rl_line_buffer
[rl_point
]) &&
504 whitespace (rl_line_buffer
[rl_point
- 1]))
507 while (rl_point
> 0 && whitespace (rl_line_buffer
[rl_point
]))
512 while (--rl_point
>= 0 && !whitespace (rl_line_buffer
[rl_point
]));
520 rl_vi_eWord (count
, ignore
)
523 while (count
-- && rl_point
< (rl_end
- 1))
525 if (!whitespace (rl_line_buffer
[rl_point
]))
528 /* Move to the next non-whitespace character (to the start of the
530 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
533 if (rl_point
&& rl_point
< rl_end
)
535 /* Skip whitespace. */
536 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
539 /* Skip until whitespace. */
540 while (rl_point
< rl_end
&& !whitespace (rl_line_buffer
[rl_point
]))
543 /* Move back to the last character of the word. */
551 rl_vi_fword (count
, ignore
)
554 while (count
-- && rl_point
< (rl_end
- 1))
556 /* Move to white space (really non-identifer). */
557 if (_rl_isident (rl_line_buffer
[rl_point
]))
559 while (_rl_isident (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
562 else /* if (!whitespace (rl_line_buffer[rl_point])) */
564 while (!_rl_isident (rl_line_buffer
[rl_point
]) &&
565 !whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
569 /* Move past whitespace. */
570 while (whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
577 rl_vi_bword (count
, ignore
)
580 while (count
-- && rl_point
> 0)
584 /* If we are at the start of a word, move back to whitespace
585 so we will go back to the start of the previous word. */
586 if (!whitespace (rl_line_buffer
[rl_point
]) &&
587 whitespace (rl_line_buffer
[rl_point
- 1]))
590 /* If this character and the previous character are `opposite', move
591 back so we don't get messed up by the rl_point++ down there in
592 the while loop. Without this code, words like `l;' screw up the
594 last_is_ident
= _rl_isident (rl_line_buffer
[rl_point
- 1]);
595 if ((_rl_isident (rl_line_buffer
[rl_point
]) && !last_is_ident
) ||
596 (!_rl_isident (rl_line_buffer
[rl_point
]) && last_is_ident
))
599 while (rl_point
> 0 && whitespace (rl_line_buffer
[rl_point
]))
604 if (_rl_isident (rl_line_buffer
[rl_point
]))
605 while (--rl_point
>= 0 && _rl_isident (rl_line_buffer
[rl_point
]));
607 while (--rl_point
>= 0 && !_rl_isident (rl_line_buffer
[rl_point
]) &&
608 !whitespace (rl_line_buffer
[rl_point
]));
616 rl_vi_eword (count
, ignore
)
619 while (count
-- && rl_point
< rl_end
- 1)
621 if (!whitespace (rl_line_buffer
[rl_point
]))
624 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
627 if (rl_point
< rl_end
)
629 if (_rl_isident (rl_line_buffer
[rl_point
]))
630 while (++rl_point
< rl_end
&& _rl_isident (rl_line_buffer
[rl_point
]));
632 while (++rl_point
< rl_end
&& !_rl_isident (rl_line_buffer
[rl_point
])
633 && !whitespace (rl_line_buffer
[rl_point
]));
641 rl_vi_insert_beg (count
, key
)
644 rl_beg_of_line (1, key
);
645 rl_vi_insert_mode (1, key
);
650 _rl_vi_append_forward (key
)
655 if (rl_point
< rl_end
)
657 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
663 rl_forward_char (1, key
);
665 rl_point
= _rl_forward_char_internal (1);
667 if (point
== rl_point
)
674 rl_vi_append_mode (count
, key
)
677 _rl_vi_append_forward (key
);
678 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
683 rl_vi_append_eol (count
, key
)
686 rl_end_of_line (1, key
);
687 rl_vi_append_mode (1, key
);
691 /* What to do in the case of C-d. */
693 rl_vi_eof_maybe (count
, c
)
696 return (rl_newline (1, '\n'));
699 /* Insertion mode stuff. */
701 /* Switching from one mode to the other really just involves
702 switching keymaps. */
704 rl_vi_insertion_mode (count
, key
)
707 _rl_keymap
= vi_insertion_keymap
;
708 _rl_vi_last_key_before_insert
= key
;
709 if (_rl_show_mode_in_prompt
)
715 rl_vi_insert_mode (count
, key
)
718 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
723 vi_save_insert_buffer (start
, len
)
726 /* Same code as _rl_vi_save_insert below */
727 if (len
>= vi_insert_buffer_size
)
729 vi_insert_buffer_size
+= (len
+ 32) - (len
% 32);
730 vi_insert_buffer
= (char *)xrealloc (vi_insert_buffer
, vi_insert_buffer_size
);
732 strncpy (vi_insert_buffer
, rl_line_buffer
+ start
, len
- 1);
733 vi_insert_buffer
[len
-1] = '\0';
737 _rl_vi_save_replace ()
743 if (up
== 0 || up
->what
!= UNDO_END
|| vi_replace_count
<= 0)
745 if (vi_insert_buffer_size
>= 1)
746 vi_insert_buffer
[0] = '\0';
749 /* Let's try it the quick and easy way for now. This should essentially
750 accommodate every UNDO_INSERT and save the inserted text to
753 start
= end
- vi_replace_count
+ 1;
754 len
= vi_replace_count
+ 1;
756 vi_save_insert_buffer (start
, len
);
760 _rl_vi_save_insert (up
)
765 if (up
== 0 || up
->what
!= UNDO_INSERT
)
767 if (vi_insert_buffer_size
>= 1)
768 vi_insert_buffer
[0] = '\0';
774 len
= end
- start
+ 1;
776 vi_save_insert_buffer (start
, len
);
780 _rl_vi_done_inserting ()
782 if (_rl_vi_doing_insert
)
784 /* The `C', `s', and `S' commands set this. */
785 rl_end_undo_group ();
786 /* Now, the text between rl_undo_list->next->start and
787 rl_undo_list->next->end is what was inserted while in insert
788 mode. It gets copied to VI_INSERT_BUFFER because it depends
789 on absolute indices into the line which may change (though they
790 probably will not). */
791 _rl_vi_doing_insert
= 0;
792 if (_rl_vi_last_key_before_insert
== 'R')
793 _rl_vi_save_replace (); /* Half the battle */
795 _rl_vi_save_insert (rl_undo_list
->next
);
796 vi_continued_command
= 1;
800 if (rl_undo_list
&& (_rl_vi_last_key_before_insert
== 'i' ||
801 _rl_vi_last_key_before_insert
== 'a' ||
802 _rl_vi_last_key_before_insert
== 'I' ||
803 _rl_vi_last_key_before_insert
== 'A'))
804 _rl_vi_save_insert (rl_undo_list
);
805 /* XXX - Other keys probably need to be checked. */
806 else if (_rl_vi_last_key_before_insert
== 'C')
807 rl_end_undo_group ();
808 while (_rl_undo_group_level
> 0)
809 rl_end_undo_group ();
810 vi_continued_command
= 0;
815 rl_vi_movement_mode (count
, key
)
819 rl_backward_char (1, key
);
821 _rl_keymap
= vi_movement_keymap
;
822 _rl_vi_done_inserting ();
824 /* This is how POSIX.2 says `U' should behave -- everything up until the
825 first time you go into command mode should not be undone. */
826 if (RL_ISSTATE (RL_STATE_VICMDONCE
) == 0)
827 rl_free_undo_list ();
829 if (_rl_show_mode_in_prompt
)
832 RL_SETSTATE (RL_STATE_VICMDONCE
);
837 rl_vi_arg_digit (count
, c
)
840 if (c
== '0' && rl_numeric_arg
== 1 && !rl_explicit_arg
)
841 return (rl_beg_of_line (1, c
));
843 return (rl_digit_argument (count
, c
));
846 /* Change the case of the next COUNT characters. */
847 #if defined (HANDLE_MULTIBYTE)
849 _rl_vi_change_mbchar_case (count
)
853 char mb
[MB_LEN_MAX
+1];
858 memset (&ps
, 0, sizeof (mbstate_t));
859 if (_rl_adjust_point (rl_line_buffer
, rl_point
, &ps
) > 0)
861 while (count
-- && rl_point
< rl_end
)
863 m
= mbrtowc (&wc
, rl_line_buffer
+ rl_point
, rl_end
- rl_point
, &ps
);
864 if (MB_INVALIDCH (m
))
865 wc
= (wchar_t)rl_line_buffer
[rl_point
];
866 else if (MB_NULLWCH (m
))
870 else if (iswlower (wc
))
874 /* Just skip over chars neither upper nor lower case */
875 rl_forward_char (1, 0);
879 /* Vi is kind of strange here. */
883 mlen
= wcrtomb (mb
, wc
, &ps
);
886 rl_begin_undo_group ();
888 if (rl_point
< p
) /* Did we retreat at EOL? */
889 rl_point
++; /* XXX - should we advance more than 1 for mbchar? */
891 rl_end_undo_group ();
895 rl_forward_char (1, 0);
903 rl_vi_change_case (count
, ignore
)
908 /* Don't try this on an empty line. */
909 if (rl_point
>= rl_end
)
913 #if defined (HANDLE_MULTIBYTE)
914 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
915 return (_rl_vi_change_mbchar_case (count
));
918 while (count
-- && rl_point
< rl_end
)
920 if (_rl_uppercase_p (rl_line_buffer
[rl_point
]))
921 c
= _rl_to_lower (rl_line_buffer
[rl_point
]);
922 else if (_rl_lowercase_p (rl_line_buffer
[rl_point
]))
923 c
= _rl_to_upper (rl_line_buffer
[rl_point
]);
926 /* Just skip over characters neither upper nor lower case. */
927 rl_forward_char (1, c
);
931 /* Vi is kind of strange here. */
935 rl_begin_undo_group ();
937 if (rl_point
< p
) /* Did we retreat at EOL? */
939 _rl_insert_char (1, c
);
940 rl_end_undo_group ();
944 rl_forward_char (1, c
);
950 rl_vi_put (count
, key
)
953 if (!_rl_uppercase_p (key
) && (rl_point
+ 1 <= rl_end
))
954 rl_point
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, 1, MB_FIND_NONZERO
);
959 rl_backward_char (1, key
);
966 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
967 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
975 if (rl_point
&& rl_point
== rl_end
)
977 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
978 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
986 rl_vi_column (count
, key
)
990 rl_end_of_line (1, key
);
992 rl_point
= count
- 1;
996 /* Process C as part of the current numeric argument. Return -1 if the
997 argument should be aborted, 0 if we should not read any more chars, and
998 1 if we should continue to read chars. */
1000 _rl_vi_arg_dispatch (c
)
1006 if (c
>= 0 && _rl_keymap
[c
].type
== ISFUNC
&& _rl_keymap
[c
].function
== rl_universal_argument
)
1008 rl_numeric_arg
*= 4;
1014 if (_rl_digit_p (c
))
1016 if (rl_explicit_arg
)
1017 rl_numeric_arg
= (rl_numeric_arg
* 10) + _rl_digit_value (c
);
1019 rl_numeric_arg
= _rl_digit_value (c
);
1020 rl_explicit_arg
= 1;
1021 return 1; /* keep going */
1025 rl_clear_message ();
1026 rl_stuff_char (key
);
1027 return 0; /* done */
1031 /* A simplified loop for vi. Don't dispatch key at end.
1032 Don't recognize minus sign?
1033 Should this do rl_save_prompt/rl_restore_prompt? */
1041 if (_rl_arg_overflow ())
1044 c
= _rl_arg_getchar ();
1046 r
= _rl_vi_arg_dispatch (c
);
1051 RL_UNSETSTATE(RL_STATE_NUMERICARG
);
1056 _rl_mvcxt_init (m
, op
, key
)
1057 _rl_vimotion_cxt
*m
;
1061 m
->state
= m
->flags
= 0;
1063 m
->numeric_arg
= -1;
1064 m
->start
= rl_point
;
1070 static _rl_vimotion_cxt
*
1071 _rl_mvcxt_alloc (op
, key
)
1074 _rl_vimotion_cxt
*m
;
1076 m
= xmalloc (sizeof (_rl_vimotion_cxt
));
1077 _rl_mvcxt_init (m
, op
, key
);
1082 _rl_mvcxt_dispose (m
)
1083 _rl_vimotion_cxt
*m
;
1089 rl_domove_motion_callback (m
)
1090 _rl_vimotion_cxt
*m
;
1095 _rl_vi_last_motion
= c
= m
->motion
;
1097 /* Append a blank character temporarily so that the motion routines
1098 work right at the end of the line. */
1100 rl_line_buffer
[rl_end
++] = ' ';
1101 rl_line_buffer
[rl_end
] = '\0';
1103 _rl_dispatch (c
, _rl_keymap
);
1105 /* Remove the blank that we added. */
1107 rl_line_buffer
[rl_end
] = '\0';
1108 if (rl_point
> rl_end
)
1111 /* No change in position means the command failed. */
1112 if (rl_mark
== rl_point
)
1115 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
1116 word. If we are not at the end of the line, and we are on a
1117 non-whitespace character, move back one (presumably to whitespace). */
1118 if ((_rl_to_upper (c
) == 'W') && rl_point
< rl_end
&& rl_point
> rl_mark
&&
1119 !whitespace (rl_line_buffer
[rl_point
]))
1122 /* If cw or cW, back up to the end of a word, so the behaviour of ce
1123 or cE is the actual result. Brute-force, no subtlety. */
1124 if (m
->key
== 'c' && rl_point
>= rl_mark
&& (_rl_to_upper (c
) == 'W'))
1126 /* Don't move farther back than where we started. */
1127 while (rl_point
> rl_mark
&& whitespace (rl_line_buffer
[rl_point
]))
1130 /* Posix.2 says that if cw or cW moves the cursor towards the end of
1131 the line, the character under the cursor should be deleted. */
1132 if (rl_point
== rl_mark
)
1136 /* Move past the end of the word so that the kill doesn't
1137 remove the last letter of the previous word. Only do this
1138 if we are not at the end of the line. */
1139 if (rl_point
>= 0 && rl_point
< (rl_end
- 1) && !whitespace (rl_line_buffer
[rl_point
]))
1144 if (rl_mark
< rl_point
)
1145 SWAP (rl_point
, rl_mark
);
1147 #if defined (READLINE_CALLBACKS)
1148 if (RL_ISSTATE (RL_STATE_CALLBACK
))
1149 (*rl_redisplay_function
)(); /* make sure motion is displayed */
1152 r
= vidomove_dispatch (m
);
1157 #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
1160 rl_domove_read_callback (m
)
1161 _rl_vimotion_cxt
*m
;
1167 if (member (c
, vi_motion
))
1169 #if defined (READLINE_CALLBACKS)
1170 /* If we just read a vi-mode motion command numeric argument, turn off
1171 the `reading numeric arg' state */
1172 if (RL_ISSTATE (RL_STATE_CALLBACK
) && RL_VIMOVENUMARG())
1173 RL_UNSETSTATE (RL_STATE_NUMERICARG
);
1175 /* Should do everything, including turning off RL_STATE_VIMOTION */
1176 return (rl_domove_motion_callback (m
));
1178 else if (m
->key
== c
&& (m
->key
== 'd' || m
->key
== 'y' || m
->key
== 'c'))
1181 rl_beg_of_line (1, c
);
1182 _rl_vi_last_motion
= c
;
1183 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1184 return (vidomove_dispatch (m
));
1186 #if defined (READLINE_CALLBACKS)
1187 /* XXX - these need to handle rl_universal_argument bindings */
1188 /* Reading vi motion char continuing numeric argument */
1189 else if (_rl_digit_p (c
) && RL_ISSTATE (RL_STATE_CALLBACK
) && RL_VIMOVENUMARG())
1191 return (_rl_vi_arg_dispatch (c
));
1193 /* Readine vi motion char starting numeric argument */
1194 else if (_rl_digit_p (c
) && RL_ISSTATE (RL_STATE_CALLBACK
) && RL_ISSTATE (RL_STATE_VIMOTION
) && (RL_ISSTATE (RL_STATE_NUMERICARG
) == 0))
1196 RL_SETSTATE (RL_STATE_NUMERICARG
);
1197 return (_rl_vi_arg_dispatch (c
));
1200 else if (_rl_digit_p (c
))
1202 /* This code path taken when not in callback mode */
1203 save
= rl_numeric_arg
;
1204 rl_numeric_arg
= _rl_digit_value (c
);
1205 rl_explicit_arg
= 1;
1206 RL_SETSTATE (RL_STATE_NUMERICARG
);
1208 rl_numeric_arg
*= save
;
1209 c
= rl_vi_domove_getchar (m
);
1216 return (rl_domove_motion_callback (m
));
1220 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1221 RL_UNSETSTATE (RL_STATE_NUMERICARG
);
1227 rl_vi_domove_getchar (m
)
1228 _rl_vimotion_cxt
*m
;
1232 RL_SETSTATE(RL_STATE_MOREINPUT
);
1234 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1239 #if defined (READLINE_CALLBACKS)
1241 _rl_vi_domove_callback (m
)
1242 _rl_vimotion_cxt
*m
;
1246 m
->motion
= c
= rl_vi_domove_getchar (m
);
1247 /* XXX - what to do if this returns -1? Should we return 1 for eof to
1249 r
= rl_domove_read_callback (m
);
1251 return ((r
== 0) ? r
: 1); /* normalize return values */
1255 /* This code path taken when not in callback mode. */
1257 rl_vi_domove (x
, ignore
)
1261 _rl_vimotion_cxt
*m
;
1264 *ignore
= m
->motion
= rl_vi_domove_getchar (m
);
1272 return (rl_domove_read_callback (m
));
1276 vi_delete_dispatch (m
)
1277 _rl_vimotion_cxt
*m
;
1279 /* These are the motion commands that do not require adjusting the
1281 if (((strchr (" l|h^0bBFT`", m
->motion
) == 0) && (rl_point
>= m
->start
)) &&
1285 rl_kill_text (rl_point
, rl_mark
);
1290 rl_vi_delete_to (count
, key
)
1295 _rl_vimvcxt
= _rl_mvcxt_alloc (VIM_DELETE
, key
);
1296 _rl_vimvcxt
->start
= rl_point
;
1299 if (_rl_uppercase_p (key
))
1301 _rl_vimvcxt
->motion
= '$';
1302 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1304 else if (vi_redoing
&& _rl_vi_last_motion
!= 'd') /* `dd' is special */
1306 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1307 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1309 else if (vi_redoing
) /* handle redoing `dd' here */
1311 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1313 rl_beg_of_line (1, key
);
1314 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1315 r
= vidomove_dispatch (_rl_vimvcxt
);
1317 #if defined (READLINE_CALLBACKS)
1318 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1320 RL_SETSTATE (RL_STATE_VIMOTION
);
1325 r
= rl_vi_domove (key
, &c
);
1333 _rl_mvcxt_dispose (_rl_vimvcxt
);
1340 vi_change_dispatch (m
)
1341 _rl_vimotion_cxt
*m
;
1343 /* These are the motion commands that do not require adjusting the
1344 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1345 and already leave the mark at the correct location. */
1346 if (((strchr (" l|hwW^0bBFT`", m
->motion
) == 0) && (rl_point
>= m
->start
)) &&
1350 /* The cursor never moves with c[wW]. */
1351 if ((_rl_to_upper (m
->motion
) == 'W') && rl_point
< m
->start
)
1352 rl_point
= m
->start
;
1356 if (vi_insert_buffer
&& *vi_insert_buffer
)
1357 rl_begin_undo_group ();
1358 rl_delete_text (rl_point
, rl_mark
);
1359 if (vi_insert_buffer
&& *vi_insert_buffer
)
1361 rl_insert_text (vi_insert_buffer
);
1362 rl_end_undo_group ();
1367 rl_begin_undo_group (); /* to make the `u' command work */
1368 rl_kill_text (rl_point
, rl_mark
);
1369 /* `C' does not save the text inserted for undoing or redoing. */
1370 if (_rl_uppercase_p (m
->key
) == 0)
1371 _rl_vi_doing_insert
= 1;
1372 /* XXX -- TODO -- use m->numericarg? */
1373 rl_vi_start_inserting (m
->key
, rl_numeric_arg
, rl_arg_sign
);
1380 rl_vi_change_to (count
, key
)
1385 _rl_vimvcxt
= _rl_mvcxt_alloc (VIM_CHANGE
, key
);
1386 _rl_vimvcxt
->start
= rl_point
;
1389 if (_rl_uppercase_p (key
))
1391 _rl_vimvcxt
->motion
= '$';
1392 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1394 else if (vi_redoing
&& _rl_vi_last_motion
!= 'c') /* `cc' is special */
1396 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1397 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1399 else if (vi_redoing
) /* handle redoing `cc' here */
1401 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1403 rl_beg_of_line (1, key
);
1404 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1405 r
= vidomove_dispatch (_rl_vimvcxt
);
1407 #if defined (READLINE_CALLBACKS)
1408 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1410 RL_SETSTATE (RL_STATE_VIMOTION
);
1415 r
= rl_vi_domove (key
, &c
);
1420 r
= -1; /* normalize return value */
1423 _rl_mvcxt_dispose (_rl_vimvcxt
);
1430 vi_yank_dispatch (m
)
1431 _rl_vimotion_cxt
*m
;
1433 /* These are the motion commands that do not require adjusting the
1435 if (((strchr (" l|h^0%bBFT`", m
->motion
) == 0) && (rl_point
>= m
->start
)) &&
1439 rl_begin_undo_group ();
1440 rl_kill_text (rl_point
, rl_mark
);
1441 rl_end_undo_group ();
1443 rl_point
= m
->start
;
1449 rl_vi_yank_to (count
, key
)
1454 _rl_vimvcxt
= _rl_mvcxt_alloc (VIM_YANK
, key
);
1455 _rl_vimvcxt
->start
= rl_point
;
1458 if (_rl_uppercase_p (key
))
1460 _rl_vimvcxt
->motion
= '$';
1461 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1463 else if (vi_redoing
&& _rl_vi_last_motion
!= 'y') /* `yy' is special */
1465 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1466 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1468 else if (vi_redoing
) /* handle redoing `yy' here */
1470 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1472 rl_beg_of_line (1, key
);
1473 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1474 r
= vidomove_dispatch (_rl_vimvcxt
);
1476 #if defined (READLINE_CALLBACKS)
1477 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1479 RL_SETSTATE (RL_STATE_VIMOTION
);
1484 r
= rl_vi_domove (key
, &c
);
1492 _rl_mvcxt_dispose (_rl_vimvcxt
);
1499 vidomove_dispatch (m
)
1500 _rl_vimotion_cxt
*m
;
1507 r
= vi_delete_dispatch (m
);
1510 r
= vi_change_dispatch (m
);
1513 r
= vi_yank_dispatch (m
);
1516 _rl_errmsg ("vidomove_dispatch: unknown operator %d", m
->op
);
1521 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1526 rl_vi_rubout (count
, key
)
1532 return (rl_vi_delete (-count
, key
));
1541 if (count
> 1 && MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1542 rl_backward_char (count
, key
);
1543 else if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1544 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
1551 rl_kill_text (rl_point
, opoint
);
1557 rl_vi_delete (count
, key
)
1563 return (rl_vi_rubout (-count
, key
));
1571 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1572 end
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, count
, MB_FIND_NONZERO
);
1574 end
= rl_point
+ count
;
1579 rl_kill_text (rl_point
, end
);
1581 if (rl_point
> 0 && rl_point
== rl_end
)
1582 rl_backward_char (1, key
);
1588 rl_vi_back_to_indent (count
, key
)
1591 rl_beg_of_line (1, key
);
1592 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
1598 rl_vi_first_print (count
, key
)
1601 return (rl_vi_back_to_indent (1, key
));
1604 static int _rl_cs_dir
, _rl_cs_orig_dir
;
1606 #if defined (READLINE_CALLBACKS)
1608 _rl_vi_callback_char_search (data
)
1609 _rl_callback_generic_arg
*data
;
1612 #if defined (HANDLE_MULTIBYTE)
1613 c
= _rl_vi_last_search_mblen
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1615 RL_SETSTATE(RL_STATE_MOREINPUT
);
1617 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1623 #if !defined (HANDLE_MULTIBYTE)
1624 _rl_vi_last_search_char
= c
;
1627 _rl_callback_func
= 0;
1628 _rl_want_redisplay
= 1;
1630 #if defined (HANDLE_MULTIBYTE)
1631 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_mbchar
, _rl_vi_last_search_mblen
));
1633 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_char
));
1639 rl_vi_char_search (count
, key
)
1643 #if defined (HANDLE_MULTIBYTE)
1644 static char *target
;
1650 if (key
== ';' || key
== ',')
1652 if (_rl_cs_orig_dir
== 0)
1654 #if defined (HANDLE_MULTIBYTE)
1655 if (_rl_vi_last_search_mblen
== 0)
1658 if (_rl_vi_last_search_char
== 0)
1661 _rl_cs_dir
= (key
== ';') ? _rl_cs_orig_dir
: -_rl_cs_orig_dir
;
1668 _rl_cs_orig_dir
= _rl_cs_dir
= FTO
;
1672 _rl_cs_orig_dir
= _rl_cs_dir
= BTO
;
1676 _rl_cs_orig_dir
= _rl_cs_dir
= FFIND
;
1680 _rl_cs_orig_dir
= _rl_cs_dir
= BFIND
;
1686 /* set target and tlen below */
1688 #if defined (READLINE_CALLBACKS)
1689 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1691 _rl_callback_data
= _rl_callback_data_alloc (count
);
1692 _rl_callback_data
->i1
= _rl_cs_dir
;
1693 _rl_callback_func
= _rl_vi_callback_char_search
;
1699 #if defined (HANDLE_MULTIBYTE)
1700 c
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1703 _rl_vi_last_search_mblen
= c
;
1705 RL_SETSTATE(RL_STATE_MOREINPUT
);
1707 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1710 _rl_vi_last_search_char
= c
;
1715 #if defined (HANDLE_MULTIBYTE)
1716 target
= _rl_vi_last_search_mbchar
;
1717 tlen
= _rl_vi_last_search_mblen
;
1719 target
= _rl_vi_last_search_char
;
1722 #if defined (HANDLE_MULTIBYTE)
1723 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
, tlen
));
1725 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
));
1729 /* Match brackets */
1731 rl_vi_match (ignore
, key
)
1734 int count
= 1, brack
, pos
, tmp
, pre
;
1737 if ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1739 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1741 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1744 rl_forward_char (1, key
);
1745 if (pre
== rl_point
)
1750 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0 &&
1751 rl_point
< rl_end
- 1)
1752 rl_forward_char (1, key
);
1769 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1773 pos
= _rl_find_prev_mbchar (rl_line_buffer
, pos
, MB_FIND_ANY
);
1779 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1782 else if (b
== brack
)
1796 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1799 pos
= _rl_find_next_mbchar (rl_line_buffer
, pos
, 1, MB_FIND_ANY
);
1803 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1806 else if (b
== brack
)
1827 case ')': return -1;
1829 case ']': return -2;
1831 case '}': return -3;
1837 _rl_vi_change_char (count
, c
, mb
)
1843 if (c
== '\033' || c
== CTRL ('C'))
1846 rl_begin_undo_group ();
1847 while (count
-- && rl_point
< rl_end
)
1850 rl_vi_delete (1, c
);
1851 if (rl_point
< p
) /* Did we retreat at EOL? */
1853 #if defined (HANDLE_MULTIBYTE)
1854 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1855 rl_insert_text (mb
);
1858 _rl_insert_char (1, c
);
1861 /* The cursor shall be left on the last character changed. */
1862 rl_backward_char (1, c
);
1864 rl_end_undo_group ();
1870 _rl_vi_callback_getchar (mb
, mlen
)
1876 RL_SETSTATE(RL_STATE_MOREINPUT
);
1878 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1883 #if defined (HANDLE_MULTIBYTE)
1884 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1885 c
= _rl_read_mbstring (c
, mb
, mlen
);
1891 #if defined (READLINE_CALLBACKS)
1893 _rl_vi_callback_change_char (data
)
1894 _rl_callback_generic_arg
*data
;
1897 char mb
[MB_LEN_MAX
];
1899 _rl_vi_last_replacement
= c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
1904 _rl_callback_func
= 0;
1905 _rl_want_redisplay
= 1;
1907 return (_rl_vi_change_char (data
->count
, c
, mb
));
1912 rl_vi_change_char (count
, key
)
1916 char mb
[MB_LEN_MAX
];
1920 c
= _rl_vi_last_replacement
;
1924 #if defined (READLINE_CALLBACKS)
1925 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1927 _rl_callback_data
= _rl_callback_data_alloc (count
);
1928 _rl_callback_func
= _rl_vi_callback_change_char
;
1933 _rl_vi_last_replacement
= c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
1938 return (_rl_vi_change_char (count
, c
, mb
));
1942 rl_vi_subst (count
, key
)
1945 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1946 if (vi_redoing
== 0)
1947 rl_stuff_char ((key
== 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1949 return (rl_vi_change_to (count
, 'c'));
1953 rl_vi_overstrike (count
, key
)
1956 if (_rl_vi_doing_insert
== 0)
1958 _rl_vi_doing_insert
= 1;
1959 rl_begin_undo_group ();
1964 _rl_overwrite_char (count
, key
);
1965 vi_replace_count
+= count
;
1972 rl_vi_overstrike_delete (count
, key
)
1977 for (i
= 0; i
< count
; i
++)
1979 if (vi_replace_count
== 0)
1990 rl_backward_char (1, key
);
1993 if (vi_replace_count
== 0 && _rl_vi_doing_insert
)
1995 rl_end_undo_group ();
1997 _rl_vi_doing_insert
= 0;
2003 rl_vi_replace (count
, key
)
2008 vi_replace_count
= 0;
2010 if (vi_replace_map
== 0)
2012 vi_replace_map
= rl_make_bare_keymap ();
2014 for (i
= 0; i
< ' '; i
++)
2015 if (vi_insertion_keymap
[i
].type
== ISFUNC
)
2016 vi_replace_map
[i
].function
= vi_insertion_keymap
[i
].function
;
2018 for (i
= ' '; i
< KEYMAP_SIZE
; i
++)
2019 vi_replace_map
[i
].function
= rl_vi_overstrike
;
2021 vi_replace_map
[RUBOUT
].function
= rl_vi_overstrike_delete
;
2023 /* Make sure these are what we want. */
2024 vi_replace_map
[ESC
].function
= rl_vi_movement_mode
;
2025 vi_replace_map
[RETURN
].function
= rl_newline
;
2026 vi_replace_map
[NEWLINE
].function
= rl_newline
;
2028 /* If the normal vi insertion keymap has ^H bound to erase, do the
2029 same here. Probably should remove the assignment to RUBOUT up
2030 there, but I don't think it will make a difference in real life. */
2031 if (vi_insertion_keymap
[CTRL ('H')].type
== ISFUNC
&&
2032 vi_insertion_keymap
[CTRL ('H')].function
== rl_rubout
)
2033 vi_replace_map
[CTRL ('H')].function
= rl_vi_overstrike_delete
;
2037 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
2039 _rl_vi_last_key_before_insert
= key
;
2040 _rl_keymap
= vi_replace_map
;
2046 /* Try to complete the word we are standing on or the word that ends with
2047 the previous character. A space matches everything. Word delimiters are
2050 rl_vi_possible_completions()
2052 int save_pos
= rl_point
;
2054 if (rl_line_buffer
[rl_point
] != ' ' && rl_line_buffer
[rl_point
] != ';')
2056 while (rl_point
< rl_end
&& rl_line_buffer
[rl_point
] != ' ' &&
2057 rl_line_buffer
[rl_point
] != ';')
2060 else if (rl_line_buffer
[rl_point
- 1] == ';')
2066 rl_possible_completions ();
2067 rl_point
= save_pos
;
2073 /* Functions to save and restore marks. */
2079 RL_SETSTATE(RL_STATE_MOREINPUT
);
2080 ch
= rl_read_key ();
2081 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
2083 if (ch
< 0 || ch
< 'a' || ch
> 'z') /* make test against 0 explicit */
2089 vi_mark_chars
[ch
] = rl_point
;
2093 #if defined (READLINE_CALLBACKS)
2095 _rl_vi_callback_set_mark (data
)
2096 _rl_callback_generic_arg
*data
;
2098 _rl_callback_func
= 0;
2099 _rl_want_redisplay
= 1;
2101 return (_rl_vi_set_mark ());
2106 rl_vi_set_mark (count
, key
)
2109 #if defined (READLINE_CALLBACKS)
2110 if (RL_ISSTATE (RL_STATE_CALLBACK
))
2112 _rl_callback_data
= 0;
2113 _rl_callback_func
= _rl_vi_callback_set_mark
;
2118 return (_rl_vi_set_mark ());
2126 RL_SETSTATE(RL_STATE_MOREINPUT
);
2127 ch
= rl_read_key ();
2128 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
2135 else if (ch
< 0 || ch
< 'a' || ch
> 'z') /* make test against 0 explicit */
2142 if (vi_mark_chars
[ch
] == -1)
2147 rl_point
= vi_mark_chars
[ch
];
2151 #if defined (READLINE_CALLBACKS)
2153 _rl_vi_callback_goto_mark (data
)
2154 _rl_callback_generic_arg
*data
;
2156 _rl_callback_func
= 0;
2157 _rl_want_redisplay
= 1;
2159 return (_rl_vi_goto_mark ());
2164 rl_vi_goto_mark (count
, key
)
2167 #if defined (READLINE_CALLBACKS)
2168 if (RL_ISSTATE (RL_STATE_CALLBACK
))
2170 _rl_callback_data
= 0;
2171 _rl_callback_func
= _rl_vi_callback_goto_mark
;
2176 return (_rl_vi_goto_mark ());
2178 #endif /* VI_MODE */