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 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
);
1624 rl_vi_back_to_indent (count
, key
)
1627 rl_beg_of_line (1, key
);
1628 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
1634 rl_vi_first_print (count
, key
)
1637 return (rl_vi_back_to_indent (1, key
));
1640 static int _rl_cs_dir
, _rl_cs_orig_dir
;
1642 #if defined (READLINE_CALLBACKS)
1644 _rl_vi_callback_char_search (data
)
1645 _rl_callback_generic_arg
*data
;
1648 #if defined (HANDLE_MULTIBYTE)
1649 c
= _rl_vi_last_search_mblen
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1651 RL_SETSTATE(RL_STATE_MOREINPUT
);
1653 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1658 RL_UNSETSTATE (RL_STATE_CHARSEARCH
);
1662 #if !defined (HANDLE_MULTIBYTE)
1663 _rl_vi_last_search_char
= c
;
1666 _rl_callback_func
= 0;
1667 _rl_want_redisplay
= 1;
1668 RL_UNSETSTATE (RL_STATE_CHARSEARCH
);
1670 #if defined (HANDLE_MULTIBYTE)
1671 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_mbchar
, _rl_vi_last_search_mblen
));
1673 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_char
));
1679 rl_vi_char_search (count
, key
)
1683 #if defined (HANDLE_MULTIBYTE)
1684 static char *target
;
1690 if (key
== ';' || key
== ',')
1692 if (_rl_cs_orig_dir
== 0)
1694 #if defined (HANDLE_MULTIBYTE)
1695 if (_rl_vi_last_search_mblen
== 0)
1698 if (_rl_vi_last_search_char
== 0)
1701 _rl_cs_dir
= (key
== ';') ? _rl_cs_orig_dir
: -_rl_cs_orig_dir
;
1708 _rl_cs_orig_dir
= _rl_cs_dir
= FTO
;
1712 _rl_cs_orig_dir
= _rl_cs_dir
= BTO
;
1716 _rl_cs_orig_dir
= _rl_cs_dir
= FFIND
;
1720 _rl_cs_orig_dir
= _rl_cs_dir
= BFIND
;
1726 /* set target and tlen below */
1728 #if defined (READLINE_CALLBACKS)
1729 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1731 _rl_callback_data
= _rl_callback_data_alloc (count
);
1732 _rl_callback_data
->i1
= _rl_cs_dir
;
1733 _rl_callback_data
->i2
= key
;
1734 _rl_callback_func
= _rl_vi_callback_char_search
;
1735 RL_SETSTATE (RL_STATE_CHARSEARCH
);
1741 #if defined (HANDLE_MULTIBYTE)
1742 c
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1745 _rl_vi_last_search_mblen
= c
;
1747 RL_SETSTATE(RL_STATE_MOREINPUT
);
1749 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1752 _rl_vi_last_search_char
= c
;
1757 #if defined (HANDLE_MULTIBYTE)
1758 target
= _rl_vi_last_search_mbchar
;
1759 tlen
= _rl_vi_last_search_mblen
;
1761 target
= _rl_vi_last_search_char
;
1764 #if defined (HANDLE_MULTIBYTE)
1765 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
, tlen
));
1767 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
));
1771 /* Match brackets */
1773 rl_vi_match (ignore
, key
)
1776 int count
= 1, brack
, pos
, tmp
, pre
;
1779 if ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1781 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1783 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1786 rl_forward_char (1, key
);
1787 if (pre
== rl_point
)
1792 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0 &&
1793 rl_point
< rl_end
- 1)
1794 rl_forward_char (1, key
);
1811 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1815 pos
= _rl_find_prev_mbchar (rl_line_buffer
, pos
, MB_FIND_ANY
);
1821 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1824 else if (b
== brack
)
1838 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1841 pos
= _rl_find_next_mbchar (rl_line_buffer
, pos
, 1, MB_FIND_ANY
);
1845 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1848 else if (b
== brack
)
1869 case ')': return -1;
1871 case ']': return -2;
1873 case '}': return -3;
1879 _rl_vi_change_char (count
, c
, mb
)
1885 if (c
== '\033' || c
== CTRL ('C'))
1888 rl_begin_undo_group ();
1889 while (count
-- && rl_point
< rl_end
)
1892 rl_vi_delete (1, c
);
1893 if (rl_point
< p
) /* Did we retreat at EOL? */
1895 #if defined (HANDLE_MULTIBYTE)
1896 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1897 rl_insert_text (mb
);
1900 _rl_insert_char (1, c
);
1903 /* The cursor shall be left on the last character changed. */
1904 rl_backward_char (1, c
);
1906 rl_end_undo_group ();
1912 _rl_vi_callback_getchar (mb
, mlen
)
1918 RL_SETSTATE(RL_STATE_MOREINPUT
);
1920 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1925 #if defined (HANDLE_MULTIBYTE)
1926 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1927 c
= _rl_read_mbstring (c
, mb
, mlen
);
1933 #if defined (READLINE_CALLBACKS)
1935 _rl_vi_callback_change_char (data
)
1936 _rl_callback_generic_arg
*data
;
1939 char mb
[MB_LEN_MAX
];
1941 _rl_vi_last_replacement
= c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
1946 _rl_callback_func
= 0;
1947 _rl_want_redisplay
= 1;
1949 return (_rl_vi_change_char (data
->count
, c
, mb
));
1954 rl_vi_change_char (count
, key
)
1958 char mb
[MB_LEN_MAX
];
1962 c
= _rl_vi_last_replacement
;
1966 #if defined (READLINE_CALLBACKS)
1967 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1969 _rl_callback_data
= _rl_callback_data_alloc (count
);
1970 _rl_callback_func
= _rl_vi_callback_change_char
;
1975 _rl_vi_last_replacement
= c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
1980 return (_rl_vi_change_char (count
, c
, mb
));
1984 rl_vi_subst (count
, key
)
1987 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1988 if (_rl_vi_redoing
== 0)
1989 rl_stuff_char ((key
== 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1991 return (rl_vi_change_to (count
, 'c'));
1995 rl_vi_overstrike (count
, key
)
1998 if (_rl_vi_doing_insert
== 0)
2000 _rl_vi_doing_insert
= 1;
2001 rl_begin_undo_group ();
2006 _rl_overwrite_char (count
, key
);
2007 vi_replace_count
+= count
;
2014 rl_vi_overstrike_delete (count
, key
)
2019 for (i
= 0; i
< count
; i
++)
2021 if (vi_replace_count
== 0)
2032 rl_backward_char (1, key
);
2035 if (vi_replace_count
== 0 && _rl_vi_doing_insert
)
2037 rl_end_undo_group ();
2039 _rl_vi_doing_insert
= 0;
2045 rl_vi_replace (count
, key
)
2050 vi_replace_count
= 0;
2052 if (vi_replace_map
== 0)
2054 vi_replace_map
= rl_make_bare_keymap ();
2056 for (i
= 0; i
< ' '; i
++)
2057 if (vi_insertion_keymap
[i
].type
== ISFUNC
)
2058 vi_replace_map
[i
].function
= vi_insertion_keymap
[i
].function
;
2060 for (i
= ' '; i
< KEYMAP_SIZE
; i
++)
2061 vi_replace_map
[i
].function
= rl_vi_overstrike
;
2063 vi_replace_map
[RUBOUT
].function
= rl_vi_overstrike_delete
;
2065 /* Make sure these are what we want. */
2066 vi_replace_map
[ESC
].function
= rl_vi_movement_mode
;
2067 vi_replace_map
[RETURN
].function
= rl_newline
;
2068 vi_replace_map
[NEWLINE
].function
= rl_newline
;
2070 /* If the normal vi insertion keymap has ^H bound to erase, do the
2071 same here. Probably should remove the assignment to RUBOUT up
2072 there, but I don't think it will make a difference in real life. */
2073 if (vi_insertion_keymap
[CTRL ('H')].type
== ISFUNC
&&
2074 vi_insertion_keymap
[CTRL ('H')].function
== rl_rubout
)
2075 vi_replace_map
[CTRL ('H')].function
= rl_vi_overstrike_delete
;
2079 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
2081 _rl_vi_last_key_before_insert
= key
;
2082 _rl_keymap
= vi_replace_map
;
2088 /* Try to complete the word we are standing on or the word that ends with
2089 the previous character. A space matches everything. Word delimiters are
2092 rl_vi_possible_completions()
2094 int save_pos
= rl_point
;
2096 if (rl_line_buffer
[rl_point
] != ' ' && rl_line_buffer
[rl_point
] != ';')
2098 while (rl_point
< rl_end
&& rl_line_buffer
[rl_point
] != ' ' &&
2099 rl_line_buffer
[rl_point
] != ';')
2102 else if (rl_line_buffer
[rl_point
- 1] == ';')
2108 rl_possible_completions ();
2109 rl_point
= save_pos
;
2115 /* Functions to save and restore marks. */
2121 RL_SETSTATE(RL_STATE_MOREINPUT
);
2122 ch
= rl_read_key ();
2123 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
2125 if (ch
< 0 || ch
< 'a' || ch
> 'z') /* make test against 0 explicit */
2131 vi_mark_chars
[ch
] = rl_point
;
2135 #if defined (READLINE_CALLBACKS)
2137 _rl_vi_callback_set_mark (data
)
2138 _rl_callback_generic_arg
*data
;
2140 _rl_callback_func
= 0;
2141 _rl_want_redisplay
= 1;
2143 return (_rl_vi_set_mark ());
2148 rl_vi_set_mark (count
, key
)
2151 #if defined (READLINE_CALLBACKS)
2152 if (RL_ISSTATE (RL_STATE_CALLBACK
))
2154 _rl_callback_data
= 0;
2155 _rl_callback_func
= _rl_vi_callback_set_mark
;
2160 return (_rl_vi_set_mark ());
2168 RL_SETSTATE(RL_STATE_MOREINPUT
);
2169 ch
= rl_read_key ();
2170 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
2177 else if (ch
< 0 || ch
< 'a' || ch
> 'z') /* make test against 0 explicit */
2184 if (vi_mark_chars
[ch
] == -1)
2189 rl_point
= vi_mark_chars
[ch
];
2193 #if defined (READLINE_CALLBACKS)
2195 _rl_vi_callback_goto_mark (data
)
2196 _rl_callback_generic_arg
*data
;
2198 _rl_callback_func
= 0;
2199 _rl_want_redisplay
= 1;
2201 return (_rl_vi_goto_mark ());
2206 rl_vi_goto_mark (count
, key
)
2209 #if defined (READLINE_CALLBACKS)
2210 if (RL_ISSTATE (RL_STATE_CALLBACK
))
2212 _rl_callback_data
= 0;
2213 _rl_callback_func
= _rl_vi_callback_goto_mark
;
2218 return (_rl_vi_goto_mark ());
2220 #endif /* VI_MODE */