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-2005 Free Software Foundation, Inc.
6 This file is part of the GNU Readline Library, a library for
7 reading lines of text with interactive input and history editing.
9 The GNU Readline Library is free software; you can redistribute it
10 and/or modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2, or
12 (at your option) any later version.
14 The GNU Readline Library is distributed in the hope that it will be
15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 The GNU General Public License is often shipped with GNU software, and
20 is generally kept in a file called COPYING or LICENSE. If you do not
21 have a copy of the license, write to the Free Software Foundation,
22 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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 /* Non-zero means enter insertion mode. */
69 static int _rl_vi_doing_insert
;
71 /* Command keys which do movement for xxx_to commands. */
72 static const char *vi_motion
= " hl^$0ftFT;,%wbeWBE|";
74 /* Keymap used for vi replace characters. Created dynamically since
76 static Keymap vi_replace_map
;
78 /* The number of characters inserted in the last replace operation. */
79 static int vi_replace_count
;
81 /* If non-zero, we have text inserted after a c[motion] command that put
82 us implicitly into insert mode. Some people want this text to be
83 attached to the command so that it is `redoable' with `.'. */
84 static int vi_continued_command
;
85 static char *vi_insert_buffer
;
86 static int vi_insert_buffer_size
;
88 static int _rl_vi_last_repeat
= 1;
89 static int _rl_vi_last_arg_sign
= 1;
90 static int _rl_vi_last_motion
;
91 #if defined (HANDLE_MULTIBYTE)
92 static char _rl_vi_last_search_mbchar
[MB_LEN_MAX
];
93 static int _rl_vi_last_search_mblen
;
95 static int _rl_vi_last_search_char
;
97 static int _rl_vi_last_replacement
;
99 static int _rl_vi_last_key_before_insert
;
101 static int vi_redoing
;
103 /* Text modification commands. These are the `redoable' commands. */
104 static const char *vi_textmod
= "_*\\AaIiCcDdPpYyRrSsXx~";
106 /* Arrays for the saved marks. */
107 static int vi_mark_chars
['z' - 'a' + 1];
109 static void _rl_vi_stuff_insert
PARAMS((int));
110 static void _rl_vi_save_insert
PARAMS((UNDO_LIST
*));
112 static void _rl_vi_backup
PARAMS((void));
114 static int _rl_vi_arg_dispatch
PARAMS((int));
115 static int rl_digit_loop1
PARAMS((void));
117 static int _rl_vi_set_mark
PARAMS((void));
118 static int _rl_vi_goto_mark
PARAMS((void));
120 static void _rl_vi_append_forward
PARAMS((int));
122 static int _rl_vi_callback_getchar
PARAMS((char *, int));
124 #if defined (READLINE_CALLBACKS)
125 static int _rl_vi_callback_set_mark
PARAMS((_rl_callback_generic_arg
*));
126 static int _rl_vi_callback_goto_mark
PARAMS((_rl_callback_generic_arg
*));
127 static int _rl_vi_callback_change_char
PARAMS((_rl_callback_generic_arg
*));
128 static int _rl_vi_callback_char_search
PARAMS((_rl_callback_generic_arg
*));
132 _rl_vi_initialize_line ()
136 for (i
= 0; i
< sizeof (vi_mark_chars
) / sizeof (int); i
++)
137 vi_mark_chars
[i
] = -1;
139 RL_UNSETSTATE(RL_STATE_VICMDONCE
);
145 _rl_vi_last_command
= 'i';
146 _rl_vi_last_repeat
= 1;
147 _rl_vi_last_arg_sign
= 1;
148 _rl_vi_last_motion
= 0;
152 _rl_vi_set_last (key
, repeat
, sign
)
153 int key
, repeat
, sign
;
155 _rl_vi_last_command
= key
;
156 _rl_vi_last_repeat
= repeat
;
157 _rl_vi_last_arg_sign
= sign
;
160 /* A convenience function that calls _rl_vi_set_last to save the last command
161 information and enters insertion mode. */
163 rl_vi_start_inserting (key
, repeat
, sign
)
164 int key
, repeat
, sign
;
166 _rl_vi_set_last (key
, repeat
, sign
);
167 rl_vi_insertion_mode (1, key
);
170 /* Is the command C a VI mode text modification command? */
172 _rl_vi_textmod_command (c
)
175 return (member (c
, vi_textmod
));
179 _rl_vi_stuff_insert (count
)
182 rl_begin_undo_group ();
184 rl_insert_text (vi_insert_buffer
);
185 rl_end_undo_group ();
188 /* Bound to `.'. Called from command mode, so we know that we have to
189 redo a text modification command. The default for _rl_vi_last_command
190 puts you back into insert mode. */
192 rl_vi_redo (count
, c
)
197 if (!rl_explicit_arg
)
199 rl_numeric_arg
= _rl_vi_last_repeat
;
200 rl_arg_sign
= _rl_vi_last_arg_sign
;
205 /* If we're redoing an insert with `i', stuff in the inserted text
206 and do not go into insertion mode. */
207 if (_rl_vi_last_command
== 'i' && vi_insert_buffer
&& *vi_insert_buffer
)
209 _rl_vi_stuff_insert (count
);
210 /* And back up point over the last character inserted. */
214 /* Ditto for redoing an insert with `a', but move forward a character first
215 like the `a' command does. */
216 else if (_rl_vi_last_command
== 'a' && vi_insert_buffer
&& *vi_insert_buffer
)
218 _rl_vi_append_forward ('a');
219 _rl_vi_stuff_insert (count
);
224 r
= _rl_dispatch (_rl_vi_last_command
, _rl_keymap
);
230 /* A placeholder for further expansion. */
232 rl_vi_undo (count
, key
)
235 return (rl_undo_command (count
, key
));
238 /* Yank the nth arg from the previous line into this line at point. */
240 rl_vi_yank_arg (count
, key
)
243 /* Readline thinks that the first word on a line is the 0th, while vi
244 thinks the first word on a line is the 1st. Compensate. */
246 rl_yank_nth_arg (count
- 1, 0);
248 rl_yank_nth_arg ('$', 0);
253 /* With an argument, move back that many history lines, else move to the
254 beginning of history. */
256 rl_vi_fetch_history (count
, c
)
261 /* Giving an argument of n means we want the nth command in the history
262 file. The command number is interpreted the same way that the bash
263 `history' command does it -- that is, giving an argument count of 450
264 to this command would get the command listed as number 450 in the
265 output of `history'. */
268 wanted
= history_base
+ where_history () - count
;
270 rl_beginning_of_history (0, 0);
272 rl_get_previous_history (wanted
, c
);
275 rl_beginning_of_history (count
, 0);
279 /* Search again for the last thing searched for. */
281 rl_vi_search_again (count
, key
)
287 rl_noninc_reverse_search_again (count
, key
);
291 rl_noninc_forward_search_again (count
, key
);
297 /* Do a vi style search. */
299 rl_vi_search (count
, key
)
305 _rl_free_saved_history_line ();
306 rl_noninc_forward_search (count
, key
);
310 _rl_free_saved_history_line ();
311 rl_noninc_reverse_search (count
, key
);
321 /* Completion, from vi's point of view. */
323 rl_vi_complete (ignore
, key
)
326 if ((rl_point
< rl_end
) && (!whitespace (rl_line_buffer
[rl_point
])))
328 if (!whitespace (rl_line_buffer
[rl_point
+ 1]))
329 rl_vi_end_word (1, 'E');
334 rl_complete_internal ('*'); /* Expansion and replacement. */
336 rl_complete_internal ('?'); /* List possible completions. */
337 else if (key
== '\\')
338 rl_complete_internal (TAB
); /* Standard Readline completion. */
340 rl_complete (0, key
);
342 if (key
== '*' || key
== '\\')
343 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
348 /* Tilde expansion for vi mode. */
350 rl_vi_tilde_expand (ignore
, key
)
353 rl_tilde_expand (0, key
);
354 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
358 /* Previous word in vi mode. */
360 rl_vi_prev_word (count
, key
)
364 return (rl_vi_next_word (-count
, key
));
372 if (_rl_uppercase_p (key
))
373 rl_vi_bWord (count
, key
);
375 rl_vi_bword (count
, key
);
380 /* Next word in vi mode. */
382 rl_vi_next_word (count
, key
)
386 return (rl_vi_prev_word (-count
, key
));
388 if (rl_point
>= (rl_end
- 1))
394 if (_rl_uppercase_p (key
))
395 rl_vi_fWord (count
, key
);
397 rl_vi_fword (count
, key
);
401 /* Move to the end of the ?next? word. */
403 rl_vi_end_word (count
, key
)
412 if (_rl_uppercase_p (key
))
413 rl_vi_eWord (count
, key
);
415 rl_vi_eword (count
, key
);
419 /* Move forward a word the way that 'W' does. */
421 rl_vi_fWord (count
, ignore
)
424 while (count
-- && rl_point
< (rl_end
- 1))
426 /* Skip until whitespace. */
427 while (!whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
430 /* Now skip whitespace. */
431 while (whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
438 rl_vi_bWord (count
, ignore
)
441 while (count
-- && rl_point
> 0)
443 /* If we are at the start of a word, move back to whitespace so
444 we will go back to the start of the previous word. */
445 if (!whitespace (rl_line_buffer
[rl_point
]) &&
446 whitespace (rl_line_buffer
[rl_point
- 1]))
449 while (rl_point
> 0 && whitespace (rl_line_buffer
[rl_point
]))
454 while (--rl_point
>= 0 && !whitespace (rl_line_buffer
[rl_point
]));
462 rl_vi_eWord (count
, ignore
)
465 while (count
-- && rl_point
< (rl_end
- 1))
467 if (!whitespace (rl_line_buffer
[rl_point
]))
470 /* Move to the next non-whitespace character (to the start of the
472 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
475 if (rl_point
&& rl_point
< rl_end
)
477 /* Skip whitespace. */
478 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
481 /* Skip until whitespace. */
482 while (rl_point
< rl_end
&& !whitespace (rl_line_buffer
[rl_point
]))
485 /* Move back to the last character of the word. */
493 rl_vi_fword (count
, ignore
)
496 while (count
-- && rl_point
< (rl_end
- 1))
498 /* Move to white space (really non-identifer). */
499 if (_rl_isident (rl_line_buffer
[rl_point
]))
501 while (_rl_isident (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
504 else /* if (!whitespace (rl_line_buffer[rl_point])) */
506 while (!_rl_isident (rl_line_buffer
[rl_point
]) &&
507 !whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
511 /* Move past whitespace. */
512 while (whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
519 rl_vi_bword (count
, ignore
)
522 while (count
-- && rl_point
> 0)
526 /* If we are at the start of a word, move back to whitespace
527 so we will go back to the start of the previous word. */
528 if (!whitespace (rl_line_buffer
[rl_point
]) &&
529 whitespace (rl_line_buffer
[rl_point
- 1]))
532 /* If this character and the previous character are `opposite', move
533 back so we don't get messed up by the rl_point++ down there in
534 the while loop. Without this code, words like `l;' screw up the
536 last_is_ident
= _rl_isident (rl_line_buffer
[rl_point
- 1]);
537 if ((_rl_isident (rl_line_buffer
[rl_point
]) && !last_is_ident
) ||
538 (!_rl_isident (rl_line_buffer
[rl_point
]) && last_is_ident
))
541 while (rl_point
> 0 && whitespace (rl_line_buffer
[rl_point
]))
546 if (_rl_isident (rl_line_buffer
[rl_point
]))
547 while (--rl_point
>= 0 && _rl_isident (rl_line_buffer
[rl_point
]));
549 while (--rl_point
>= 0 && !_rl_isident (rl_line_buffer
[rl_point
]) &&
550 !whitespace (rl_line_buffer
[rl_point
]));
558 rl_vi_eword (count
, ignore
)
561 while (count
-- && rl_point
< rl_end
- 1)
563 if (!whitespace (rl_line_buffer
[rl_point
]))
566 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
569 if (rl_point
< rl_end
)
571 if (_rl_isident (rl_line_buffer
[rl_point
]))
572 while (++rl_point
< rl_end
&& _rl_isident (rl_line_buffer
[rl_point
]));
574 while (++rl_point
< rl_end
&& !_rl_isident (rl_line_buffer
[rl_point
])
575 && !whitespace (rl_line_buffer
[rl_point
]));
583 rl_vi_insert_beg (count
, key
)
586 rl_beg_of_line (1, key
);
587 rl_vi_insertion_mode (1, key
);
592 _rl_vi_append_forward (key
)
597 if (rl_point
< rl_end
)
599 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
604 rl_forward_char (1, key
);
605 if (point
== rl_point
)
612 rl_vi_append_mode (count
, key
)
615 _rl_vi_append_forward (key
);
616 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
621 rl_vi_append_eol (count
, key
)
624 rl_end_of_line (1, key
);
625 rl_vi_append_mode (1, key
);
629 /* What to do in the case of C-d. */
631 rl_vi_eof_maybe (count
, c
)
634 return (rl_newline (1, '\n'));
637 /* Insertion mode stuff. */
639 /* Switching from one mode to the other really just involves
640 switching keymaps. */
642 rl_vi_insertion_mode (count
, key
)
645 _rl_keymap
= vi_insertion_keymap
;
646 _rl_vi_last_key_before_insert
= key
;
651 _rl_vi_save_insert (up
)
656 if (up
== 0 || up
->what
!= UNDO_INSERT
)
658 if (vi_insert_buffer_size
>= 1)
659 vi_insert_buffer
[0] = '\0';
665 len
= end
- start
+ 1;
666 if (len
>= vi_insert_buffer_size
)
668 vi_insert_buffer_size
+= (len
+ 32) - (len
% 32);
669 vi_insert_buffer
= (char *)xrealloc (vi_insert_buffer
, vi_insert_buffer_size
);
671 strncpy (vi_insert_buffer
, rl_line_buffer
+ start
, len
- 1);
672 vi_insert_buffer
[len
-1] = '\0';
676 _rl_vi_done_inserting ()
678 if (_rl_vi_doing_insert
)
680 /* The `C', `s', and `S' commands set this. */
681 rl_end_undo_group ();
682 /* Now, the text between rl_undo_list->next->start and
683 rl_undo_list->next->end is what was inserted while in insert
684 mode. It gets copied to VI_INSERT_BUFFER because it depends
685 on absolute indices into the line which may change (though they
686 probably will not). */
687 _rl_vi_doing_insert
= 0;
688 _rl_vi_save_insert (rl_undo_list
->next
);
689 vi_continued_command
= 1;
693 if ((_rl_vi_last_key_before_insert
== 'i' || _rl_vi_last_key_before_insert
== 'a') && rl_undo_list
)
694 _rl_vi_save_insert (rl_undo_list
);
695 /* XXX - Other keys probably need to be checked. */
696 else if (_rl_vi_last_key_before_insert
== 'C')
697 rl_end_undo_group ();
698 while (_rl_undo_group_level
> 0)
699 rl_end_undo_group ();
700 vi_continued_command
= 0;
705 rl_vi_movement_mode (count
, key
)
709 rl_backward_char (1, key
);
711 _rl_keymap
= vi_movement_keymap
;
712 _rl_vi_done_inserting ();
714 /* This is how POSIX.2 says `U' should behave -- everything up until the
715 first time you go into command mode should not be undone. */
716 if (RL_ISSTATE (RL_STATE_VICMDONCE
) == 0)
717 rl_free_undo_list ();
719 RL_SETSTATE (RL_STATE_VICMDONCE
);
724 rl_vi_arg_digit (count
, c
)
727 if (c
== '0' && rl_numeric_arg
== 1 && !rl_explicit_arg
)
728 return (rl_beg_of_line (1, c
));
730 return (rl_digit_argument (count
, c
));
733 /* Change the case of the next COUNT characters. */
734 #if defined (HANDLE_MULTIBYTE)
736 _rl_vi_change_mbchar_case (count
)
740 char mb
[MB_LEN_MAX
+1];
744 memset (&ps
, 0, sizeof (mbstate_t));
745 if (_rl_adjust_point (rl_line_buffer
, rl_point
, &ps
) > 0)
747 while (count
-- && rl_point
< rl_end
)
749 mbrtowc (&wc
, rl_line_buffer
+ rl_point
, rl_end
- rl_point
, &ps
);
752 else if (iswlower (wc
))
756 /* Just skip over chars neither upper nor lower case */
757 rl_forward_char (1, 0);
761 /* Vi is kind of strange here. */
765 mlen
= wcrtomb (mb
, wc
, &ps
);
768 rl_begin_undo_group ();
770 if (rl_point
< p
) /* Did we retreat at EOL? */
771 rl_point
++; /* XXX - should we advance more than 1 for mbchar? */
773 rl_end_undo_group ();
777 rl_forward_char (1, 0);
785 rl_vi_change_case (count
, ignore
)
790 /* Don't try this on an empty line. */
791 if (rl_point
>= rl_end
)
795 #if defined (HANDLE_MULTIBYTE)
796 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
797 return (_rl_vi_change_mbchar_case (count
));
800 while (count
-- && rl_point
< rl_end
)
802 if (_rl_uppercase_p (rl_line_buffer
[rl_point
]))
803 c
= _rl_to_lower (rl_line_buffer
[rl_point
]);
804 else if (_rl_lowercase_p (rl_line_buffer
[rl_point
]))
805 c
= _rl_to_upper (rl_line_buffer
[rl_point
]);
808 /* Just skip over characters neither upper nor lower case. */
809 rl_forward_char (1, c
);
813 /* Vi is kind of strange here. */
817 rl_begin_undo_group ();
819 if (rl_point
< p
) /* Did we retreat at EOL? */
821 _rl_insert_char (1, c
);
822 rl_end_undo_group ();
826 rl_forward_char (1, c
);
832 rl_vi_put (count
, key
)
835 if (!_rl_uppercase_p (key
) && (rl_point
+ 1 <= rl_end
))
836 rl_point
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, 1, MB_FIND_NONZERO
);
841 rl_backward_char (1, key
);
848 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
849 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
857 if (rl_point
&& rl_point
== rl_end
)
859 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
860 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
868 rl_vi_column (count
, key
)
872 rl_end_of_line (1, key
);
874 rl_point
= count
- 1;
879 rl_vi_domove (key
, nextkey
)
886 RL_SETSTATE(RL_STATE_MOREINPUT
);
888 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
891 if (!member (c
, vi_motion
))
895 save
= rl_numeric_arg
;
896 rl_numeric_arg
= _rl_digit_value (c
);
898 RL_SETSTATE (RL_STATE_NUMERICARG
|RL_STATE_VIMOTION
);
900 RL_UNSETSTATE (RL_STATE_VIMOTION
);
901 rl_numeric_arg
*= save
;
902 RL_SETSTATE(RL_STATE_MOREINPUT
);
903 c
= rl_read_key (); /* real command */
904 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
907 else if (key
== c
&& (key
== 'd' || key
== 'y' || key
== 'c'))
910 rl_beg_of_line (1, c
);
911 _rl_vi_last_motion
= c
;
918 _rl_vi_last_motion
= c
;
920 /* Append a blank character temporarily so that the motion routines
921 work right at the end of the line. */
923 rl_line_buffer
[rl_end
++] = ' ';
924 rl_line_buffer
[rl_end
] = '\0';
926 _rl_dispatch (c
, _rl_keymap
);
928 /* Remove the blank that we added. */
930 rl_line_buffer
[rl_end
] = '\0';
931 if (rl_point
> rl_end
)
934 /* No change in position means the command failed. */
935 if (rl_mark
== rl_point
)
938 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
939 word. If we are not at the end of the line, and we are on a
940 non-whitespace character, move back one (presumably to whitespace). */
941 if ((_rl_to_upper (c
) == 'W') && rl_point
< rl_end
&& rl_point
> rl_mark
&&
942 !whitespace (rl_line_buffer
[rl_point
]))
945 /* If cw or cW, back up to the end of a word, so the behaviour of ce
946 or cE is the actual result. Brute-force, no subtlety. */
947 if (key
== 'c' && rl_point
>= rl_mark
&& (_rl_to_upper (c
) == 'W'))
949 /* Don't move farther back than where we started. */
950 while (rl_point
> rl_mark
&& whitespace (rl_line_buffer
[rl_point
]))
953 /* Posix.2 says that if cw or cW moves the cursor towards the end of
954 the line, the character under the cursor should be deleted. */
955 if (rl_point
== rl_mark
)
959 /* Move past the end of the word so that the kill doesn't
960 remove the last letter of the previous word. Only do this
961 if we are not at the end of the line. */
962 if (rl_point
>= 0 && rl_point
< (rl_end
- 1) && !whitespace (rl_line_buffer
[rl_point
]))
967 if (rl_mark
< rl_point
)
968 SWAP (rl_point
, rl_mark
);
973 /* Process C as part of the current numeric argument. Return -1 if the
974 argument should be aborted, 0 if we should not read any more chars, and
975 1 if we should continue to read chars. */
977 _rl_vi_arg_dispatch (c
)
983 if (c
>= 0 && _rl_keymap
[c
].type
== ISFUNC
&& _rl_keymap
[c
].function
== rl_universal_argument
)
994 rl_numeric_arg
= (rl_numeric_arg
* 10) + _rl_digit_value (c
);
996 rl_numeric_arg
= _rl_digit_value (c
);
1002 rl_clear_message ();
1003 rl_stuff_char (key
);
1008 /* A simplified loop for vi. Don't dispatch key at end.
1009 Don't recognize minus sign?
1010 Should this do rl_save_prompt/rl_restore_prompt? */
1018 if (_rl_arg_overflow ())
1021 c
= _rl_arg_getchar ();
1023 r
= _rl_vi_arg_dispatch (c
);
1028 RL_UNSETSTATE(RL_STATE_NUMERICARG
);
1033 rl_vi_delete_to (count
, key
)
1038 if (_rl_uppercase_p (key
))
1039 rl_stuff_char ('$');
1040 else if (vi_redoing
)
1041 rl_stuff_char (_rl_vi_last_motion
);
1043 if (rl_vi_domove (key
, &c
))
1049 /* These are the motion commands that do not require adjusting the
1051 if ((strchr (" l|h^0bB", c
) == 0) && (rl_mark
< rl_end
))
1054 rl_kill_text (rl_point
, rl_mark
);
1059 rl_vi_change_to (count
, key
)
1064 if (_rl_uppercase_p (key
))
1065 rl_stuff_char ('$');
1066 else if (vi_redoing
)
1067 rl_stuff_char (_rl_vi_last_motion
);
1069 start_pos
= rl_point
;
1071 if (rl_vi_domove (key
, &c
))
1077 /* These are the motion commands that do not require adjusting the
1078 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1079 and already leave the mark at the correct location. */
1080 if ((strchr (" l|hwW^0bB", c
) == 0) && (rl_mark
< rl_end
))
1083 /* The cursor never moves with c[wW]. */
1084 if ((_rl_to_upper (c
) == 'W') && rl_point
< start_pos
)
1085 rl_point
= start_pos
;
1089 if (vi_insert_buffer
&& *vi_insert_buffer
)
1090 rl_begin_undo_group ();
1091 rl_delete_text (rl_point
, rl_mark
);
1092 if (vi_insert_buffer
&& *vi_insert_buffer
)
1094 rl_insert_text (vi_insert_buffer
);
1095 rl_end_undo_group ();
1100 rl_begin_undo_group (); /* to make the `u' command work */
1101 rl_kill_text (rl_point
, rl_mark
);
1102 /* `C' does not save the text inserted for undoing or redoing. */
1103 if (_rl_uppercase_p (key
) == 0)
1104 _rl_vi_doing_insert
= 1;
1105 rl_vi_start_inserting (key
, rl_numeric_arg
, rl_arg_sign
);
1112 rl_vi_yank_to (count
, key
)
1118 if (_rl_uppercase_p (key
))
1119 rl_stuff_char ('$');
1121 if (rl_vi_domove (key
, &c
))
1127 /* These are the motion commands that do not require adjusting the
1129 if ((strchr (" l|h^0%bB", c
) == 0) && (rl_mark
< rl_end
))
1132 rl_begin_undo_group ();
1133 rl_kill_text (rl_point
, rl_mark
);
1134 rl_end_undo_group ();
1142 rl_vi_rubout (count
, key
)
1148 return (rl_vi_delete (-count
, key
));
1157 if (count
> 1 && MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1158 rl_backward_char (count
, key
);
1159 else if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1160 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
1167 rl_kill_text (rl_point
, opoint
);
1173 rl_vi_delete (count
, key
)
1179 return (rl_vi_rubout (-count
, key
));
1187 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1188 end
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, count
, MB_FIND_NONZERO
);
1190 end
= rl_point
+ count
;
1195 rl_kill_text (rl_point
, end
);
1197 if (rl_point
> 0 && rl_point
== rl_end
)
1198 rl_backward_char (1, key
);
1204 rl_vi_back_to_indent (count
, key
)
1207 rl_beg_of_line (1, key
);
1208 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
1214 rl_vi_first_print (count
, key
)
1217 return (rl_vi_back_to_indent (1, key
));
1220 static int _rl_cs_dir
, _rl_cs_orig_dir
;
1222 #if defined (READLINE_CALLBACKS)
1224 _rl_vi_callback_char_search (data
)
1225 _rl_callback_generic_arg
*data
;
1227 #if defined (HANDLE_MULTIBYTE)
1228 _rl_vi_last_search_mblen
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1230 RL_SETSTATE(RL_STATE_MOREINPUT
);
1231 _rl_vi_last_search_char
= rl_read_key ();
1232 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1235 _rl_callback_func
= 0;
1236 _rl_want_redisplay
= 1;
1238 #if defined (HANDLE_MULTIBYTE)
1239 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_mbchar
, _rl_vi_last_search_mblen
));
1241 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_char
));
1247 rl_vi_char_search (count
, key
)
1250 #if defined (HANDLE_MULTIBYTE)
1251 static char *target
;
1257 if (key
== ';' || key
== ',')
1258 _rl_cs_dir
= (key
== ';') ? _rl_cs_orig_dir
: -_rl_cs_orig_dir
;
1264 _rl_cs_orig_dir
= _rl_cs_dir
= FTO
;
1268 _rl_cs_orig_dir
= _rl_cs_dir
= BTO
;
1272 _rl_cs_orig_dir
= _rl_cs_dir
= FFIND
;
1276 _rl_cs_orig_dir
= _rl_cs_dir
= BFIND
;
1282 /* set target and tlen below */
1284 #if defined (READLINE_CALLBACKS)
1285 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1287 _rl_callback_data
= _rl_callback_data_alloc (count
);
1288 _rl_callback_data
->i1
= _rl_cs_dir
;
1289 _rl_callback_func
= _rl_vi_callback_char_search
;
1295 #if defined (HANDLE_MULTIBYTE)
1296 _rl_vi_last_search_mblen
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1298 RL_SETSTATE(RL_STATE_MOREINPUT
);
1299 _rl_vi_last_search_char
= rl_read_key ();
1300 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1305 #if defined (HANDLE_MULTIBYTE)
1306 target
= _rl_vi_last_search_mbchar
;
1307 tlen
= _rl_vi_last_search_mblen
;
1309 target
= _rl_vi_last_search_char
;
1312 #if defined (HANDLE_MULTIBYTE)
1313 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
, tlen
));
1315 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
));
1319 /* Match brackets */
1321 rl_vi_match (ignore
, key
)
1324 int count
= 1, brack
, pos
, tmp
, pre
;
1327 if ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1329 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1331 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1334 rl_forward_char (1, key
);
1335 if (pre
== rl_point
)
1340 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0 &&
1341 rl_point
< rl_end
- 1)
1342 rl_forward_char (1, key
);
1359 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1363 pos
= _rl_find_prev_mbchar (rl_line_buffer
, pos
, MB_FIND_ANY
);
1369 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1372 else if (b
== brack
)
1386 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1389 pos
= _rl_find_next_mbchar (rl_line_buffer
, pos
, 1, MB_FIND_ANY
);
1393 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1396 else if (b
== brack
)
1417 case ')': return -1;
1419 case ']': return -2;
1421 case '}': return -3;
1427 _rl_vi_change_char (count
, c
, mb
)
1433 if (c
== '\033' || c
== CTRL ('C'))
1436 rl_begin_undo_group ();
1437 while (count
-- && rl_point
< rl_end
)
1440 rl_vi_delete (1, c
);
1441 if (rl_point
< p
) /* Did we retreat at EOL? */
1443 #if defined (HANDLE_MULTIBYTE)
1444 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1445 rl_insert_text (mb
);
1448 _rl_insert_char (1, c
);
1451 /* The cursor shall be left on the last character changed. */
1452 rl_backward_char (1, c
);
1454 rl_end_undo_group ();
1460 _rl_vi_callback_getchar (mb
, mlen
)
1466 RL_SETSTATE(RL_STATE_MOREINPUT
);
1468 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1470 #if defined (HANDLE_MULTIBYTE)
1471 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1472 c
= _rl_read_mbstring (c
, mb
, mlen
);
1478 #if defined (READLINE_CALLBACKS)
1480 _rl_vi_callback_change_char (data
)
1481 _rl_callback_generic_arg
*data
;
1484 char mb
[MB_LEN_MAX
];
1486 _rl_vi_last_replacement
= c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
1488 _rl_callback_func
= 0;
1489 _rl_want_redisplay
= 1;
1491 return (_rl_vi_change_char (data
->count
, c
, mb
));
1496 rl_vi_change_char (count
, key
)
1500 char mb
[MB_LEN_MAX
];
1504 c
= _rl_vi_last_replacement
;
1508 #if defined (READLINE_CALLBACKS)
1509 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1511 _rl_callback_data
= _rl_callback_data_alloc (count
);
1512 _rl_callback_func
= _rl_vi_callback_change_char
;
1517 _rl_vi_last_replacement
= c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
1519 return (_rl_vi_change_char (count
, c
, mb
));
1523 rl_vi_subst (count
, key
)
1526 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1527 if (vi_redoing
== 0)
1528 rl_stuff_char ((key
== 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
1530 return (rl_vi_change_to (count
, 'c'));
1534 rl_vi_overstrike (count
, key
)
1537 if (_rl_vi_doing_insert
== 0)
1539 _rl_vi_doing_insert
= 1;
1540 rl_begin_undo_group ();
1545 _rl_overwrite_char (count
, key
);
1546 vi_replace_count
+= count
;
1553 rl_vi_overstrike_delete (count
, key
)
1558 for (i
= 0; i
< count
; i
++)
1560 if (vi_replace_count
== 0)
1571 rl_backward_char (1, key
);
1574 if (vi_replace_count
== 0 && _rl_vi_doing_insert
)
1576 rl_end_undo_group ();
1578 _rl_vi_doing_insert
= 0;
1584 rl_vi_replace (count
, key
)
1589 vi_replace_count
= 0;
1591 if (!vi_replace_map
)
1593 vi_replace_map
= rl_make_bare_keymap ();
1595 for (i
= ' '; i
< KEYMAP_SIZE
; i
++)
1596 vi_replace_map
[i
].function
= rl_vi_overstrike
;
1598 vi_replace_map
[RUBOUT
].function
= rl_vi_overstrike_delete
;
1599 vi_replace_map
[ESC
].function
= rl_vi_movement_mode
;
1600 vi_replace_map
[RETURN
].function
= rl_newline
;
1601 vi_replace_map
[NEWLINE
].function
= rl_newline
;
1603 /* If the normal vi insertion keymap has ^H bound to erase, do the
1604 same here. Probably should remove the assignment to RUBOUT up
1605 there, but I don't think it will make a difference in real life. */
1606 if (vi_insertion_keymap
[CTRL ('H')].type
== ISFUNC
&&
1607 vi_insertion_keymap
[CTRL ('H')].function
== rl_rubout
)
1608 vi_replace_map
[CTRL ('H')].function
= rl_vi_overstrike_delete
;
1611 _rl_keymap
= vi_replace_map
;
1616 /* Try to complete the word we are standing on or the word that ends with
1617 the previous character. A space matches everything. Word delimiters are
1620 rl_vi_possible_completions()
1622 int save_pos
= rl_point
;
1624 if (rl_line_buffer
[rl_point
] != ' ' && rl_line_buffer
[rl_point
] != ';')
1626 while (rl_point
< rl_end
&& rl_line_buffer
[rl_point
] != ' ' &&
1627 rl_line_buffer
[rl_point
] != ';')
1630 else if (rl_line_buffer
[rl_point
- 1] == ';')
1636 rl_possible_completions ();
1637 rl_point
= save_pos
;
1643 /* Functions to save and restore marks. */
1649 RL_SETSTATE(RL_STATE_MOREINPUT
);
1650 ch
= rl_read_key ();
1651 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1653 if (ch
< 'a' || ch
> 'z')
1659 vi_mark_chars
[ch
] = rl_point
;
1663 #if defined (READLINE_CALLBACKS)
1665 _rl_vi_callback_set_mark (data
)
1666 _rl_callback_generic_arg
*data
;
1668 _rl_callback_func
= 0;
1669 _rl_want_redisplay
= 1;
1671 return (_rl_vi_set_mark ());
1676 rl_vi_set_mark (count
, key
)
1679 #if defined (READLINE_CALLBACKS)
1680 if (RL_ISSTATE (RL_STATE_CALLBACK
))
1682 _rl_callback_data
= 0;
1683 _rl_callback_func
= _rl_vi_callback_set_mark
;
1688 return (_rl_vi_set_mark ());
1696 RL_SETSTATE(RL_STATE_MOREINPUT
);
1697 ch
= rl_read_key ();
1698 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1705 else if (ch
< 'a' || ch
> 'z')
1712 if (vi_mark_chars
[ch
] == -1)
1717 rl_point
= vi_mark_chars
[ch
];
1721 #if defined (READLINE_CALLBACKS)
1723 _rl_vi_callback_goto_mark (data
)
1724 _rl_callback_generic_arg
*data
;
1726 _rl_callback_func
= 0;
1727 _rl_want_redisplay
= 1;
1729 return (_rl_vi_goto_mark ());
1734 rl_vi_goto_mark (count
, key
)
1737 #if defined (READLINE_CALLBACKS)
1738 if (RL_ISSTATE (RL_STATE_CALLBACK
))
1740 _rl_callback_data
= 0;
1741 _rl_callback_func
= _rl_vi_callback_goto_mark
;
1746 return (_rl_vi_goto_mark ());
1748 #endif /* VI_MODE */