1 /* vi_mode.c -- A vi emulation mode for Bush.
2 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
4 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
6 This file is part of the GNU Readline Library (Readline), a library
7 for reading lines of text with interactive input and history editing.
9 Readline is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Readline is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Readline. If not, see <http://www.gnu.org/licenses/>.
23 #define READLINE_LIBRARY
25 /* **************************************************************** */
27 /* VI Emulation Mode */
29 /* **************************************************************** */
34 #if defined (HAVE_CONFIG_H)
38 #include <sys/types.h>
40 #if defined (HAVE_STDLIB_H)
43 # include "ansi_stdlib.h"
44 #endif /* HAVE_STDLIB_H */
46 #if defined (HAVE_UNISTD_H)
52 /* Some standard library routines. */
59 #include "rlprivate.h"
63 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
66 /* Increment START to the next character in RL_LINE_BUFFER, handling multibyte chars */
67 #if defined (HANDLE_MULTIBYTE)
68 #define INCREMENT_POS(start) \
70 if (MB_CUR_MAX == 1 || rl_byte_oriented) \
73 start = _rl_find_next_mbchar (rl_line_buffer, start, 1, MB_FIND_ANY); \
75 #else /* !HANDLE_MULTIBYTE */
76 #define INCREMENT_POS(start) (start)++
77 #endif /* !HANDLE_MULTIBYTE */
79 /* This is global so other parts of the code can check whether the last
80 command was a text modification command. */
81 int _rl_vi_last_command
= 'i'; /* default `.' puts you in insert mode */
83 _rl_vimotion_cxt
*_rl_vimvcxt
= 0;
85 /* Non-zero indicates we are redoing a vi-mode command with `.' */
88 /* Non-zero means enter insertion mode. */
89 static int _rl_vi_doing_insert
;
91 /* Command keys which do movement for xxx_to commands. */
92 static const char * const vi_motion
= " hl^$0ftFT;,%wbeWBE|`";
94 /* Keymap used for vi replace characters. Created dynamically since
96 static Keymap vi_replace_map
;
98 /* The number of characters inserted in the last replace operation. */
99 static int vi_replace_count
;
101 /* If non-zero, we have text inserted after a c[motion] command that put
102 us implicitly into insert mode. Some people want this text to be
103 attached to the command so that it is `redoable' with `.'. */
104 static int vi_continued_command
;
105 static char *vi_insert_buffer
;
106 static int vi_insert_buffer_size
;
108 static int _rl_vi_last_repeat
= 1;
109 static int _rl_vi_last_arg_sign
= 1;
110 static int _rl_vi_last_motion
;
111 #if defined (HANDLE_MULTIBYTE)
112 static char _rl_vi_last_search_mbchar
[MB_LEN_MAX
];
113 static int _rl_vi_last_search_mblen
;
115 static int _rl_vi_last_search_char
;
117 static char _rl_vi_last_replacement
[MB_LEN_MAX
+1]; /* reserve for trailing NULL */
119 static int _rl_vi_last_key_before_insert
;
121 /* Text modification commands. These are the `redoable' commands. */
122 static const char * const vi_textmod
= "_*\\AaIiCcDdPpYyRrSsXx~";
124 /* Arrays for the saved marks. */
125 static int vi_mark_chars
['z' - 'a' + 1];
127 static void _rl_vi_replace_insert
PARAMS((int));
128 static void _rl_vi_save_replace
PARAMS((void));
129 static void _rl_vi_stuff_insert
PARAMS((int));
130 static void _rl_vi_save_insert
PARAMS((UNDO_LIST
*));
132 static void vi_save_insert_buffer
PARAMS ((int, int));
134 static inline void _rl_vi_backup
PARAMS((void));
136 static int _rl_vi_arg_dispatch
PARAMS((int));
137 static int rl_digit_loop1
PARAMS((void));
139 static int _rl_vi_set_mark
PARAMS((void));
140 static int _rl_vi_goto_mark
PARAMS((void));
142 static inline int _rl_vi_advance_point
PARAMS((void));
143 static inline int _rl_vi_backup_point
PARAMS((void));
145 static void _rl_vi_append_forward
PARAMS((int));
147 static int _rl_vi_callback_getchar
PARAMS((char *, int));
149 #if defined (READLINE_CALLBACKS)
150 static int _rl_vi_callback_set_mark
PARAMS((_rl_callback_generic_arg
*));
151 static int _rl_vi_callback_goto_mark
PARAMS((_rl_callback_generic_arg
*));
152 static int _rl_vi_callback_change_char
PARAMS((_rl_callback_generic_arg
*));
153 static int _rl_vi_callback_char_search
PARAMS((_rl_callback_generic_arg
*));
156 static int rl_domove_read_callback
PARAMS((_rl_vimotion_cxt
*));
157 static int rl_domove_motion_callback
PARAMS((_rl_vimotion_cxt
*));
158 static int rl_vi_domove_getchar
PARAMS((_rl_vimotion_cxt
*));
160 static int vi_change_dispatch
PARAMS((_rl_vimotion_cxt
*));
161 static int vi_delete_dispatch
PARAMS((_rl_vimotion_cxt
*));
162 static int vi_yank_dispatch
PARAMS((_rl_vimotion_cxt
*));
164 static int vidomove_dispatch
PARAMS((_rl_vimotion_cxt
*));
167 _rl_vi_initialize_line (void)
171 n
= sizeof (vi_mark_chars
) / sizeof (vi_mark_chars
[0]);
172 for (i
= 0; i
< n
; i
++)
173 vi_mark_chars
[i
] = -1;
175 RL_UNSETSTATE(RL_STATE_VICMDONCE
);
179 _rl_vi_reset_last (void)
181 _rl_vi_last_command
= 'i';
182 _rl_vi_last_repeat
= 1;
183 _rl_vi_last_arg_sign
= 1;
184 _rl_vi_last_motion
= 0;
188 _rl_vi_set_last (int key
, int repeat
, int sign
)
190 _rl_vi_last_command
= key
;
191 _rl_vi_last_repeat
= repeat
;
192 _rl_vi_last_arg_sign
= sign
;
195 /* A convenience function that calls _rl_vi_set_last to save the last command
196 information and enters insertion mode. */
198 rl_vi_start_inserting (int key
, int repeat
, int sign
)
200 _rl_vi_set_last (key
, repeat
, sign
);
201 rl_begin_undo_group (); /* ensure inserts aren't concatenated */
202 rl_vi_insertion_mode (1, key
);
205 /* Is the command C a VI mode text modification command? */
207 _rl_vi_textmod_command (int c
)
209 return (member (c
, vi_textmod
));
213 _rl_vi_motion_command (int c
)
215 return (member (c
, vi_motion
));
219 _rl_vi_replace_insert (int count
)
223 nchars
= strlen (vi_insert_buffer
);
225 rl_begin_undo_group ();
227 /* nchars-1 to compensate for _rl_replace_text using `end+1' in call
229 _rl_replace_text (vi_insert_buffer
, rl_point
, rl_point
+nchars
-1);
230 rl_end_undo_group ();
234 _rl_vi_stuff_insert (int count
)
236 rl_begin_undo_group ();
238 rl_insert_text (vi_insert_buffer
);
239 rl_end_undo_group ();
242 /* Bound to `.'. Called from command mode, so we know that we have to
243 redo a text modification command. The default for _rl_vi_last_command
244 puts you back into insert mode. */
246 rl_vi_redo (int count
, int c
)
250 if (rl_explicit_arg
== 0)
252 rl_numeric_arg
= _rl_vi_last_repeat
;
253 rl_arg_sign
= _rl_vi_last_arg_sign
;
258 /* If we're redoing an insert with `i', stuff in the inserted text
259 and do not go into insertion mode. */
260 if (_rl_vi_last_command
== 'i' && vi_insert_buffer
&& *vi_insert_buffer
)
262 _rl_vi_stuff_insert (count
);
263 /* And back up point over the last character inserted. */
267 else if (_rl_vi_last_command
== 'R' && vi_insert_buffer
&& *vi_insert_buffer
)
269 _rl_vi_replace_insert (count
);
270 /* And back up point over the last character inserted. */
274 /* Ditto for redoing an insert with `I', but move to the beginning of the
275 line like the `I' command does. */
276 else if (_rl_vi_last_command
== 'I' && vi_insert_buffer
&& *vi_insert_buffer
)
278 rl_beg_of_line (1, 'I');
279 _rl_vi_stuff_insert (count
);
283 /* Ditto for redoing an insert with `a', but move forward a character first
284 like the `a' command does. */
285 else if (_rl_vi_last_command
== 'a' && vi_insert_buffer
&& *vi_insert_buffer
)
287 _rl_vi_append_forward ('a');
288 _rl_vi_stuff_insert (count
);
292 /* Ditto for redoing an insert with `A', but move to the end of the line
293 like the `A' command does. */
294 else if (_rl_vi_last_command
== 'A' && vi_insert_buffer
&& *vi_insert_buffer
)
296 rl_end_of_line (1, 'A');
297 _rl_vi_stuff_insert (count
);
301 else if (_rl_vi_last_command
== '.' && _rl_keymap
== vi_movement_keymap
)
307 r
= _rl_dispatch (_rl_vi_last_command
, _rl_keymap
);
314 /* A placeholder for further expansion. */
316 rl_vi_undo (int count
, int key
)
318 return (rl_undo_command (count
, key
));
321 /* Yank the nth arg from the previous line into this line at point. */
323 rl_vi_yank_arg (int count
, int key
)
325 /* Readline thinks that the first word on a line is the 0th, while vi
326 thinks the first word on a line is the 1st. Compensate. */
328 rl_yank_nth_arg (count
- 1, key
);
330 rl_yank_nth_arg ('$', key
);
335 /* With an argument, move back that many history lines, else move to the
336 beginning of history. */
338 rl_vi_fetch_history (int count
, int c
)
342 /* Giving an argument of n means we want the nth command in the history
343 file. The command number is interpreted the same way that the bush
344 `history' command does it -- that is, giving an argument count of 450
345 to this command would get the command listed as number 450 in the
346 output of `history'. */
349 wanted
= history_base
+ where_history () - count
;
351 rl_beginning_of_history (0, 0);
353 rl_get_previous_history (wanted
, c
);
356 rl_beginning_of_history (count
, 0);
360 /* Search again for the last thing searched for. */
362 rl_vi_search_again (int count
, int key
)
367 rl_noninc_reverse_search_again (count
, key
);
371 rl_noninc_forward_search_again (count
, key
);
377 /* Do a vi style search. */
379 rl_vi_search (int count
, int key
)
384 _rl_free_saved_history_line ();
385 rl_noninc_forward_search (count
, key
);
389 _rl_free_saved_history_line ();
390 rl_noninc_reverse_search (count
, key
);
400 /* Completion, from vi's point of view. */
402 rl_vi_complete (int ignore
, int key
)
404 if ((rl_point
< rl_end
) && (!whitespace (rl_line_buffer
[rl_point
])))
406 if (!whitespace (rl_line_buffer
[rl_point
+ 1]))
407 rl_vi_end_word (1, 'E');
408 _rl_vi_advance_point ();
412 rl_complete_internal ('*'); /* Expansion and replacement. */
414 rl_complete_internal ('?'); /* List possible completions. */
415 else if (key
== '\\')
416 rl_complete_internal (TAB
); /* Standard Readline completion. */
418 rl_complete (0, key
);
420 if (key
== '*' || key
== '\\')
421 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
426 /* Tilde expansion for vi mode. */
428 rl_vi_tilde_expand (int ignore
, int key
)
430 rl_tilde_expand (0, key
);
431 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
435 /* Previous word in vi mode. */
437 rl_vi_prev_word (int count
, int key
)
440 return (rl_vi_next_word (-count
, key
));
448 if (_rl_uppercase_p (key
))
449 rl_vi_bWord (count
, key
);
451 rl_vi_bword (count
, key
);
456 /* Next word in vi mode. */
458 rl_vi_next_word (int count
, int key
)
461 return (rl_vi_prev_word (-count
, key
));
463 if (rl_point
>= (rl_end
- 1))
469 if (_rl_uppercase_p (key
))
470 rl_vi_fWord (count
, key
);
472 rl_vi_fword (count
, key
);
477 _rl_vi_advance_point (void)
482 if (rl_point
< rl_end
)
483 #if defined (HANDLE_MULTIBYTE)
485 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
490 rl_point
= _rl_forward_char_internal (1);
491 if (point
== rl_point
|| rl_point
> rl_end
)
502 /* Move the cursor back one character. */
506 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
507 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
512 /* Move the point back one character, returning the starting value and not
513 doing anything at the beginning of the line */
515 _rl_vi_backup_point (void)
521 #if defined (HANDLE_MULTIBYTE)
523 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
528 rl_point
= _rl_backward_char_internal (1);
530 rl_point
= 0; /* XXX - not really necessary */
539 /* Move to the end of the ?next? word. */
541 rl_vi_end_word (int count
, int key
)
549 if (_rl_uppercase_p (key
))
550 rl_vi_eWord (count
, key
);
552 rl_vi_eword (count
, key
);
556 /* Move forward a word the way that 'W' does. */
558 rl_vi_fWord (int count
, int ignore
)
560 while (count
-- && rl_point
< (rl_end
- 1))
562 /* Skip until whitespace. */
563 while (!whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
564 _rl_vi_advance_point ();
566 /* Now skip whitespace. */
567 while (whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
568 _rl_vi_advance_point ();
574 rl_vi_bWord (int count
, int ignore
)
576 while (count
-- && rl_point
> 0)
578 /* If we are at the start of a word, move back to whitespace so
579 we will go back to the start of the previous word. */
580 if (!whitespace (rl_line_buffer
[rl_point
]) &&
581 whitespace (rl_line_buffer
[rl_point
- 1]))
584 while (rl_point
> 0 && whitespace (rl_line_buffer
[rl_point
]))
585 _rl_vi_backup_point ();
590 _rl_vi_backup_point ();
591 while (rl_point
> 0 && !whitespace (rl_line_buffer
[rl_point
]));
592 if (rl_point
> 0) /* hit whitespace */
603 rl_vi_eWord (int count
, int ignore
)
607 while (count
-- && rl_point
< (rl_end
- 1))
609 if (whitespace (rl_line_buffer
[rl_point
]) == 0)
610 _rl_vi_advance_point ();
612 /* Move to the next non-whitespace character (to the start of the
614 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
615 _rl_vi_advance_point ();
617 if (rl_point
&& rl_point
< rl_end
)
621 /* Skip whitespace. */
622 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
623 opoint
= _rl_vi_advance_point (); /* XXX - why? */
625 /* Skip until whitespace. */
626 while (rl_point
< rl_end
&& !whitespace (rl_line_buffer
[rl_point
]))
627 opoint
= _rl_vi_advance_point ();
629 /* Move back to the last character of the word. */
637 rl_vi_fword (int count
, int ignore
)
641 while (count
-- && rl_point
< (rl_end
- 1))
643 /* Move to white space (really non-identifer). */
644 if (_rl_isident (rl_line_buffer
[rl_point
]))
646 while (_rl_isident (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
647 _rl_vi_advance_point ();
649 else /* if (!whitespace (rl_line_buffer[rl_point])) */
651 while (!_rl_isident (rl_line_buffer
[rl_point
]) &&
652 !whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
653 _rl_vi_advance_point ();
658 /* Move past whitespace. */
659 while (whitespace (rl_line_buffer
[rl_point
]) && rl_point
< rl_end
)
660 opoint
= _rl_vi_advance_point ();
666 rl_vi_bword (int count
, int ignore
)
670 while (count
-- && rl_point
> 0)
672 int prev_is_ident
, cur_is_ident
;
674 /* If we are at the start of a word, move back to whitespace
675 so we will go back to the start of the previous word. */
676 if (!whitespace (rl_line_buffer
[rl_point
]) &&
677 whitespace (rl_line_buffer
[rl_point
- 1]))
681 /* If this character and the previous character are `opposite', move
682 back so we don't get messed up by the rl_point++ down there in
683 the while loop. Without this code, words like `l;' screw up the
685 cur_is_ident
= _rl_isident (rl_line_buffer
[rl_point
]);
686 opoint
= _rl_vi_backup_point ();
687 prev_is_ident
= _rl_isident (rl_line_buffer
[rl_point
]);
688 if ((cur_is_ident
&& !prev_is_ident
) || (!cur_is_ident
&& prev_is_ident
))
689 ; /* leave point alone, we backed it up one character */
693 while (rl_point
> 0 && whitespace (rl_line_buffer
[rl_point
]))
694 _rl_vi_backup_point ();
699 if (_rl_isident (rl_line_buffer
[rl_point
]))
701 opoint
= _rl_vi_backup_point ();
702 while (rl_point
> 0 && _rl_isident (rl_line_buffer
[rl_point
]));
705 opoint
= _rl_vi_backup_point ();
706 while (rl_point
> 0 && !_rl_isident (rl_line_buffer
[rl_point
]) &&
707 !whitespace (rl_line_buffer
[rl_point
]));
720 rl_vi_eword (int count
, int ignore
)
724 while (count
-- && rl_point
< (rl_end
- 1))
726 if (whitespace (rl_line_buffer
[rl_point
]) == 0)
727 _rl_vi_advance_point ();
729 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
730 _rl_vi_advance_point ();
733 if (rl_point
< rl_end
)
735 if (_rl_isident (rl_line_buffer
[rl_point
]))
738 opoint
= _rl_vi_advance_point ();
740 while (rl_point
< rl_end
&& _rl_isident (rl_line_buffer
[rl_point
]));
744 opoint
= _rl_vi_advance_point ();
746 while (rl_point
< rl_end
&& !_rl_isident (rl_line_buffer
[rl_point
])
747 && !whitespace (rl_line_buffer
[rl_point
]));
755 rl_vi_insert_beg (int count
, int key
)
757 rl_beg_of_line (1, key
);
758 rl_vi_insert_mode (1, key
);
763 _rl_vi_append_forward (int key
)
765 _rl_vi_advance_point ();
769 rl_vi_append_mode (int count
, int key
)
771 _rl_vi_append_forward (key
);
772 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
777 rl_vi_append_eol (int count
, int key
)
779 rl_end_of_line (1, key
);
780 rl_vi_append_mode (1, key
);
784 /* What to do in the case of C-d. */
786 rl_vi_eof_maybe (int count
, int c
)
788 return (rl_newline (1, '\n'));
791 /* Insertion mode stuff. */
793 /* Switching from one mode to the other really just involves
794 switching keymaps. */
796 rl_vi_insertion_mode (int count
, int key
)
798 _rl_keymap
= vi_insertion_keymap
;
799 _rl_vi_last_key_before_insert
= key
;
800 if (_rl_show_mode_in_prompt
)
806 rl_vi_insert_mode (int count
, int key
)
808 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
813 vi_save_insert_buffer (int start
, int len
)
815 /* Same code as _rl_vi_save_insert below */
816 if (len
>= vi_insert_buffer_size
)
818 vi_insert_buffer_size
+= (len
+ 32) - (len
% 32);
819 vi_insert_buffer
= (char *)xrealloc (vi_insert_buffer
, vi_insert_buffer_size
);
821 strncpy (vi_insert_buffer
, rl_line_buffer
+ start
, len
- 1);
822 vi_insert_buffer
[len
-1] = '\0';
826 _rl_vi_save_replace (void)
832 if (up
== 0 || up
->what
!= UNDO_END
|| vi_replace_count
<= 0)
834 if (vi_insert_buffer_size
>= 1)
835 vi_insert_buffer
[0] = '\0';
838 /* Let's try it the quick and easy way for now. This should essentially
839 accommodate every UNDO_INSERT and save the inserted text to
842 start
= end
- vi_replace_count
+ 1;
843 len
= vi_replace_count
+ 1;
851 vi_save_insert_buffer (start
, len
);
855 _rl_vi_save_insert (UNDO_LIST
*up
)
859 if (up
== 0 || up
->what
!= UNDO_INSERT
)
861 if (vi_insert_buffer_size
>= 1)
862 vi_insert_buffer
[0] = '\0';
868 len
= end
- start
+ 1;
870 vi_save_insert_buffer (start
, len
);
874 _rl_vi_done_inserting (void)
876 if (_rl_vi_doing_insert
)
878 /* The `c', `s', `S', and `R' commands set this. */
879 rl_end_undo_group (); /* for the group in rl_vi_start_inserting */
880 /* Now, the text between rl_undo_list->next->start and
881 rl_undo_list->next->end is what was inserted while in insert
882 mode. It gets copied to VI_INSERT_BUFFER because it depends
883 on absolute indices into the line which may change (though they
884 probably will not). */
885 _rl_vi_doing_insert
= 0;
886 if (_rl_vi_last_key_before_insert
== 'R')
887 _rl_vi_save_replace (); /* Half the battle */
889 _rl_vi_save_insert (rl_undo_list
->next
);
890 /* sanity check, should always be >= 1 here */
891 if (_rl_undo_group_level
> 0)
892 rl_end_undo_group (); /* for the group in the command (change or replace) */
896 if (rl_undo_list
&& (_rl_vi_last_key_before_insert
== 'i' ||
897 _rl_vi_last_key_before_insert
== 'a' ||
898 _rl_vi_last_key_before_insert
== 'I' ||
899 _rl_vi_last_key_before_insert
== 'A'))
900 _rl_vi_save_insert (rl_undo_list
);
901 /* XXX - Other keys probably need to be checked. */
902 else if (_rl_vi_last_key_before_insert
== 'C')
903 rl_end_undo_group ();
906 /* Sanity check, make sure all the undo groups are closed before we leave
908 while (_rl_undo_group_level
> 0)
909 rl_end_undo_group ();
913 rl_vi_movement_mode (int count
, int key
)
916 rl_backward_char (1, key
);
918 _rl_keymap
= vi_movement_keymap
;
919 _rl_vi_done_inserting ();
921 /* This is how POSIX.2 says `U' should behave -- everything up until the
922 first time you go into command mode should not be undone. */
923 if (RL_ISSTATE (RL_STATE_VICMDONCE
) == 0)
924 rl_free_undo_list ();
926 if (_rl_show_mode_in_prompt
)
929 RL_SETSTATE (RL_STATE_VICMDONCE
);
934 rl_vi_arg_digit (int count
, int c
)
936 if (c
== '0' && rl_numeric_arg
== 1 && !rl_explicit_arg
)
937 return (rl_beg_of_line (1, c
));
939 return (rl_digit_argument (count
, c
));
942 /* Change the case of the next COUNT characters. */
943 #if defined (HANDLE_MULTIBYTE)
945 _rl_vi_change_mbchar_case (int count
)
948 char mb
[MB_LEN_MAX
+1];
953 memset (&ps
, 0, sizeof (mbstate_t));
954 if (_rl_adjust_point (rl_line_buffer
, rl_point
, &ps
) > 0)
956 while (count
-- && rl_point
< rl_end
)
958 m
= mbrtowc (&wc
, rl_line_buffer
+ rl_point
, rl_end
- rl_point
, &ps
);
959 if (MB_INVALIDCH (m
))
960 wc
= (wchar_t)rl_line_buffer
[rl_point
];
961 else if (MB_NULLWCH (m
))
965 else if (iswlower (wc
))
969 /* Just skip over chars neither upper nor lower case */
970 rl_forward_char (1, 0);
974 /* Vi is kind of strange here. */
978 mlen
= wcrtomb (mb
, wc
, &ps
);
981 rl_begin_undo_group ();
983 if (rl_point
< p
) /* Did we retreat at EOL? */
984 _rl_vi_advance_point ();
986 rl_end_undo_group ();
990 rl_forward_char (1, 0);
998 rl_vi_change_case (int count
, int ignore
)
1002 /* Don't try this on an empty line. */
1003 if (rl_point
>= rl_end
)
1007 #if defined (HANDLE_MULTIBYTE)
1008 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1009 return (_rl_vi_change_mbchar_case (count
));
1012 while (count
-- && rl_point
< rl_end
)
1014 if (_rl_uppercase_p (rl_line_buffer
[rl_point
]))
1015 c
= _rl_to_lower (rl_line_buffer
[rl_point
]);
1016 else if (_rl_lowercase_p (rl_line_buffer
[rl_point
]))
1017 c
= _rl_to_upper (rl_line_buffer
[rl_point
]);
1020 /* Just skip over characters neither upper nor lower case. */
1021 rl_forward_char (1, c
);
1025 /* Vi is kind of strange here. */
1029 rl_begin_undo_group ();
1030 rl_vi_delete (1, c
);
1031 if (rl_point
< p
) /* Did we retreat at EOL? */
1033 _rl_insert_char (1, c
);
1034 rl_end_undo_group ();
1038 rl_forward_char (1, c
);
1044 rl_vi_put (int count
, int key
)
1046 if (!_rl_uppercase_p (key
) && (rl_point
+ 1 <= rl_end
))
1047 rl_point
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, 1, MB_FIND_NONZERO
);
1052 rl_backward_char (1, key
);
1056 /* Move the cursor back one character if you're at the end of the line */
1060 if (rl_point
&& rl_point
== rl_end
)
1065 /* Move to the character position specified by COUNT */
1067 rl_vi_column (int count
, int key
)
1070 rl_end_of_line (1, key
);
1074 rl_point
= _rl_forward_char_internal (count
- 1);
1079 /* Process C as part of the current numeric argument. Return -1 if the
1080 argument should be aborted, 0 if we should not read any more chars, and
1081 1 if we should continue to read chars. */
1083 _rl_vi_arg_dispatch (int c
)
1088 if (c
>= 0 && _rl_keymap
[c
].type
== ISFUNC
&& _rl_keymap
[c
].function
== rl_universal_argument
)
1090 rl_numeric_arg
*= 4;
1096 if (_rl_digit_p (c
))
1098 if (rl_explicit_arg
)
1099 rl_numeric_arg
= (rl_numeric_arg
* 10) + _rl_digit_value (c
);
1101 rl_numeric_arg
= _rl_digit_value (c
);
1102 rl_explicit_arg
= 1;
1103 return 1; /* keep going */
1107 rl_clear_message ();
1108 rl_stuff_char (key
);
1109 return 0; /* done */
1113 /* A simplified loop for vi. Don't dispatch key at end.
1114 Don't recognize minus sign?
1115 Should this do rl_save_prompt/rl_restore_prompt? */
1117 rl_digit_loop1 (void)
1123 if (_rl_arg_overflow ())
1126 c
= _rl_arg_getchar ();
1128 r
= _rl_vi_arg_dispatch (c
);
1133 RL_UNSETSTATE(RL_STATE_NUMERICARG
);
1137 /* This set of functions is basically to handle the commands that take a
1138 motion argument while in callback mode: read the command, read the motion
1139 command modifier, find the extent of the text to affect, and dispatch the
1140 command for execution. */
1142 _rl_mvcxt_init (_rl_vimotion_cxt
*m
, int op
, int key
)
1145 m
->state
= m
->flags
= 0;
1147 m
->numeric_arg
= -1;
1148 m
->start
= rl_point
;
1154 static _rl_vimotion_cxt
*
1155 _rl_mvcxt_alloc (int op
, int key
)
1157 _rl_vimotion_cxt
*m
;
1159 m
= xmalloc (sizeof (_rl_vimotion_cxt
));
1160 _rl_mvcxt_init (m
, op
, key
);
1165 _rl_mvcxt_dispose (_rl_vimotion_cxt
*m
)
1171 rl_domove_motion_callback (_rl_vimotion_cxt
*m
)
1175 _rl_vi_last_motion
= c
= m
->motion
;
1177 /* Append a blank character temporarily so that the motion routines
1178 work right at the end of the line. Original value of rl_end is saved
1180 rl_extend_line_buffer (rl_end
+ 1);
1181 rl_line_buffer
[rl_end
++] = ' ';
1182 rl_line_buffer
[rl_end
] = '\0';
1184 _rl_dispatch (c
, _rl_keymap
);
1186 #if defined (READLINE_CALLBACKS)
1187 if (RL_ISSTATE (RL_STATE_CALLBACK
))
1189 /* Messy case where char search can be vi motion command; see rest of
1190 details in callback.c. vi_char_search and callback_char_search just
1191 set and unset the CHARSEARCH state. This is where any vi motion
1192 command that needs to set its own state should be handled, with any
1193 corresponding code to manage that state in callback.c */
1194 if (RL_ISSTATE (RL_STATE_CHARSEARCH
))
1197 return (_rl_vi_domove_motion_cleanup (c
, m
));
1201 return (_rl_vi_domove_motion_cleanup (c
, m
));
1205 _rl_vi_domove_motion_cleanup (int c
, _rl_vimotion_cxt
*m
)
1209 /* Remove the blank that we added in rl_domove_motion_callback. */
1211 rl_line_buffer
[rl_end
] = '\0';
1214 /* No change in position means the command failed. */
1215 if (rl_mark
== rl_point
)
1217 /* 'c' and 'C' enter insert mode after the delete even if the motion
1218 didn't delete anything, as long as the motion command is valid. */
1219 if (_rl_to_upper (m
->key
) == 'C' && _rl_vi_motion_command (c
))
1220 return (vidomove_dispatch (m
));
1221 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1225 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
1226 word. If we are not at the end of the line, and we are on a
1227 non-whitespace character, move back one (presumably to whitespace). */
1228 if ((_rl_to_upper (c
) == 'W') && rl_point
< rl_end
&& rl_point
> rl_mark
&&
1229 !whitespace (rl_line_buffer
[rl_point
]))
1230 rl_point
--; /* XXX */
1232 /* If cw or cW, back up to the end of a word, so the behaviour of ce
1233 or cE is the actual result. Brute-force, no subtlety. */
1234 if (m
->key
== 'c' && rl_point
>= rl_mark
&& (_rl_to_upper (c
) == 'W'))
1236 /* Don't move farther back than where we started. */
1237 while (rl_point
> rl_mark
&& whitespace (rl_line_buffer
[rl_point
]))
1240 /* Posix.2 says that if cw or cW moves the cursor towards the end of
1241 the line, the character under the cursor should be deleted. */
1242 if (rl_point
== rl_mark
)
1243 _rl_vi_advance_point ();
1246 /* Move past the end of the word so that the kill doesn't
1247 remove the last letter of the previous word. Only do this
1248 if we are not at the end of the line. */
1249 if (rl_point
>= 0 && rl_point
< (rl_end
- 1) && !whitespace (rl_line_buffer
[rl_point
]))
1250 _rl_vi_advance_point ();
1254 if (rl_mark
< rl_point
)
1255 SWAP (rl_point
, rl_mark
);
1257 #if defined (READLINE_CALLBACKS)
1258 if (RL_ISSTATE (RL_STATE_CALLBACK
))
1259 (*rl_redisplay_function
)(); /* make sure motion is displayed */
1262 r
= vidomove_dispatch (m
);
1267 #define RL_VIMOVENUMARG() (RL_ISSTATE (RL_STATE_VIMOTION) && RL_ISSTATE (RL_STATE_NUMERICARG))
1270 rl_domove_read_callback (_rl_vimotion_cxt
*m
)
1276 if (member (c
, vi_motion
))
1278 #if defined (READLINE_CALLBACKS)
1279 /* If we just read a vi-mode motion command numeric argument, turn off
1280 the `reading numeric arg' state */
1281 if (RL_ISSTATE (RL_STATE_CALLBACK
) && RL_VIMOVENUMARG())
1282 RL_UNSETSTATE (RL_STATE_NUMERICARG
);
1284 /* Should do everything, including turning off RL_STATE_VIMOTION */
1285 return (rl_domove_motion_callback (m
));
1287 else if (m
->key
== c
&& (m
->key
== 'd' || m
->key
== 'y' || m
->key
== 'c'))
1290 rl_beg_of_line (1, c
);
1291 _rl_vi_last_motion
= c
;
1292 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1293 return (vidomove_dispatch (m
));
1295 #if defined (READLINE_CALLBACKS)
1296 /* XXX - these need to handle rl_universal_argument bindings */
1297 /* Reading vi motion char continuing numeric argument */
1298 else if (_rl_digit_p (c
) && RL_ISSTATE (RL_STATE_CALLBACK
) && RL_VIMOVENUMARG())
1300 return (_rl_vi_arg_dispatch (c
));
1302 /* Readine vi motion char starting numeric argument */
1303 else if (_rl_digit_p (c
) && RL_ISSTATE (RL_STATE_CALLBACK
) && RL_ISSTATE (RL_STATE_VIMOTION
) && (RL_ISSTATE (RL_STATE_NUMERICARG
) == 0))
1305 RL_SETSTATE (RL_STATE_NUMERICARG
);
1306 return (_rl_vi_arg_dispatch (c
));
1309 else if (_rl_digit_p (c
))
1311 /* This code path taken when not in callback mode */
1312 save
= rl_numeric_arg
;
1313 rl_numeric_arg
= _rl_digit_value (c
);
1314 rl_explicit_arg
= 1;
1315 RL_SETSTATE (RL_STATE_NUMERICARG
);
1317 rl_numeric_arg
*= save
;
1318 c
= rl_vi_domove_getchar (m
);
1325 return (rl_domove_motion_callback (m
));
1329 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1330 RL_UNSETSTATE (RL_STATE_NUMERICARG
);
1336 rl_vi_domove_getchar (_rl_vimotion_cxt
*m
)
1338 return (_rl_bracketed_read_key ());
1341 #if defined (READLINE_CALLBACKS)
1343 _rl_vi_domove_callback (_rl_vimotion_cxt
*m
)
1347 m
->motion
= c
= rl_vi_domove_getchar (m
);
1350 r
= rl_domove_read_callback (m
);
1352 return ((r
== 0) ? r
: 1); /* normalize return values */
1356 /* This code path is taken when not in callback mode. */
1358 rl_vi_domove (int x
, int *ignore
)
1361 _rl_vimotion_cxt
*m
;
1364 *ignore
= m
->motion
= rl_vi_domove_getchar (m
);
1372 return (rl_domove_read_callback (m
));
1376 vi_delete_dispatch (_rl_vimotion_cxt
*m
)
1378 /* These are the motion commands that do not require adjusting the
1380 if (((strchr (" l|h^0bBFT`", m
->motion
) == 0) && (rl_point
>= m
->start
)) &&
1382 INCREMENT_POS (rl_mark
);
1384 rl_kill_text (rl_point
, rl_mark
);
1389 rl_vi_delete_to (int count
, int key
)
1394 _rl_mvcxt_init (_rl_vimvcxt
, VIM_DELETE
, key
);
1396 _rl_vimvcxt
= _rl_mvcxt_alloc (VIM_DELETE
, key
);
1398 _rl_vimvcxt
->start
= rl_point
;
1401 if (_rl_uppercase_p (key
))
1403 _rl_vimvcxt
->motion
= '$';
1404 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1406 else if (_rl_vi_redoing
&& _rl_vi_last_motion
!= 'd') /* `dd' is special */
1408 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1409 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1411 else if (_rl_vi_redoing
) /* handle redoing `dd' here */
1413 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1415 rl_beg_of_line (1, key
);
1416 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1417 r
= vidomove_dispatch (_rl_vimvcxt
);
1419 #if defined (READLINE_CALLBACKS)
1420 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1422 RL_SETSTATE (RL_STATE_VIMOTION
);
1427 r
= rl_vi_domove (key
, &c
);
1435 _rl_mvcxt_dispose (_rl_vimvcxt
);
1442 vi_change_dispatch (_rl_vimotion_cxt
*m
)
1444 /* These are the motion commands that do not require adjusting the
1445 mark. c[wW] are handled by special-case code in rl_vi_domove(),
1446 and already leave the mark at the correct location. */
1447 if (((strchr (" l|hwW^0bBFT`", m
->motion
) == 0) && (rl_point
>= m
->start
)) &&
1449 INCREMENT_POS (rl_mark
);
1451 /* The cursor never moves with c[wW]. */
1452 if ((_rl_to_upper (m
->motion
) == 'W') && rl_point
< m
->start
)
1453 rl_point
= m
->start
;
1457 if (vi_insert_buffer
&& *vi_insert_buffer
)
1458 rl_begin_undo_group ();
1459 rl_delete_text (rl_point
, rl_mark
);
1460 if (vi_insert_buffer
&& *vi_insert_buffer
)
1462 rl_insert_text (vi_insert_buffer
);
1463 rl_end_undo_group ();
1468 rl_begin_undo_group (); /* to make the `u' command work */
1469 rl_kill_text (rl_point
, rl_mark
);
1470 /* `C' does not save the text inserted for undoing or redoing. */
1471 if (_rl_uppercase_p (m
->key
) == 0)
1472 _rl_vi_doing_insert
= 1;
1473 /* XXX -- TODO -- use m->numericarg? */
1474 rl_vi_start_inserting (m
->key
, rl_numeric_arg
, rl_arg_sign
);
1481 rl_vi_change_to (int count
, int key
)
1486 _rl_mvcxt_init (_rl_vimvcxt
, VIM_CHANGE
, key
);
1488 _rl_vimvcxt
= _rl_mvcxt_alloc (VIM_CHANGE
, key
);
1489 _rl_vimvcxt
->start
= rl_point
;
1492 if (_rl_uppercase_p (key
))
1494 _rl_vimvcxt
->motion
= '$';
1495 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1497 else if (_rl_vi_redoing
&& _rl_vi_last_motion
!= 'c') /* `cc' is special */
1499 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1500 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1502 else if (_rl_vi_redoing
) /* handle redoing `cc' here */
1504 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1506 rl_beg_of_line (1, key
);
1507 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1508 r
= vidomove_dispatch (_rl_vimvcxt
);
1510 #if defined (READLINE_CALLBACKS)
1511 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1513 RL_SETSTATE (RL_STATE_VIMOTION
);
1518 r
= rl_vi_domove (key
, &c
);
1523 r
= -1; /* normalize return value */
1526 _rl_mvcxt_dispose (_rl_vimvcxt
);
1533 vi_yank_dispatch (_rl_vimotion_cxt
*m
)
1535 /* These are the motion commands that do not require adjusting the
1537 if (((strchr (" l|h^0%bBFT`", m
->motion
) == 0) && (rl_point
>= m
->start
)) &&
1539 INCREMENT_POS (rl_mark
);
1541 rl_begin_undo_group ();
1542 rl_kill_text (rl_point
, rl_mark
);
1543 rl_end_undo_group ();
1545 rl_point
= m
->start
;
1553 rl_vi_yank_to (int count
, int key
)
1558 _rl_mvcxt_init (_rl_vimvcxt
, VIM_YANK
, key
);
1560 _rl_vimvcxt
= _rl_mvcxt_alloc (VIM_YANK
, key
);
1561 _rl_vimvcxt
->start
= rl_point
;
1564 if (_rl_uppercase_p (key
))
1566 _rl_vimvcxt
->motion
= '$';
1567 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1569 else if (_rl_vi_redoing
&& _rl_vi_last_motion
!= 'y') /* `yy' is special */
1571 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1572 r
= rl_domove_motion_callback (_rl_vimvcxt
);
1574 else if (_rl_vi_redoing
) /* handle redoing `yy' here */
1576 _rl_vimvcxt
->motion
= _rl_vi_last_motion
;
1578 rl_beg_of_line (1, key
);
1579 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1580 r
= vidomove_dispatch (_rl_vimvcxt
);
1582 #if defined (READLINE_CALLBACKS)
1583 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1585 RL_SETSTATE (RL_STATE_VIMOTION
);
1590 r
= rl_vi_domove (key
, &c
);
1598 _rl_mvcxt_dispose (_rl_vimvcxt
);
1605 vidomove_dispatch (_rl_vimotion_cxt
*m
)
1612 r
= vi_delete_dispatch (m
);
1615 r
= vi_change_dispatch (m
);
1618 r
= vi_yank_dispatch (m
);
1621 _rl_errmsg ("vidomove_dispatch: unknown operator %d", m
->op
);
1626 RL_UNSETSTATE (RL_STATE_VIMOTION
);
1631 rl_vi_rubout (int count
, int key
)
1636 return (rl_vi_delete (-count
, key
));
1645 if (count
> 1 && MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1646 rl_backward_char (count
, key
);
1647 else if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1648 rl_point
= _rl_find_prev_mbchar (rl_line_buffer
, rl_point
, MB_FIND_NONZERO
);
1655 rl_kill_text (rl_point
, opoint
);
1661 rl_vi_delete (int count
, int key
)
1666 return (rl_vi_rubout (-count
, key
));
1674 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1675 end
= _rl_find_next_mbchar (rl_line_buffer
, rl_point
, count
, MB_FIND_NONZERO
);
1677 end
= rl_point
+ count
;
1682 rl_kill_text (rl_point
, end
);
1684 if (rl_point
> 0 && rl_point
== rl_end
)
1685 rl_backward_char (1, key
);
1690 /* This does what Posix specifies vi-mode C-w to do: using whitespace and
1691 punctuation characters as the word boundaries. */
1693 #define vi_unix_word_boundary(c) (whitespace(c) || ispunct(c))
1696 rl_vi_unix_word_rubout (int count
, int key
)
1704 orig_point
= rl_point
;
1710 /* This isn't quite what ksh93 does but it seems to match what the
1711 Posix description of sh specifies, with a few accommodations
1712 for sequences of whitespace characters between words and at
1713 the end of the line. */
1715 /* Skip over whitespace at the end of the line as a special case */
1716 if (rl_point
> 0 && (rl_line_buffer
[rl_point
] == 0) &&
1717 whitespace (rl_line_buffer
[rl_point
- 1]))
1718 while (--rl_point
> 0 && whitespace (rl_line_buffer
[rl_point
]))
1721 /* If we're at the start of a word, move back to word boundary so we
1722 move back to the `preceding' word */
1723 if (rl_point
> 0 && (vi_unix_word_boundary (rl_line_buffer
[rl_point
]) == 0) &&
1724 vi_unix_word_boundary (rl_line_buffer
[rl_point
- 1]))
1727 /* If we are at a word boundary (whitespace/punct), move backward
1728 past a sequence of word boundary characters. If we are at the
1729 end of a word (non-word boundary), move back to a word boundary */
1730 if (rl_point
> 0 && vi_unix_word_boundary (rl_line_buffer
[rl_point
]))
1731 while (rl_point
&& vi_unix_word_boundary (rl_line_buffer
[rl_point
- 1]))
1733 else if (rl_point
> 0 && vi_unix_word_boundary (rl_line_buffer
[rl_point
]) == 0)
1734 while (rl_point
> 0 && (vi_unix_word_boundary (rl_line_buffer
[rl_point
- 1]) == 0))
1735 _rl_vi_backup_point ();
1738 rl_kill_text (orig_point
, rl_point
);
1746 rl_vi_back_to_indent (int count
, int key
)
1748 rl_beg_of_line (1, key
);
1749 while (rl_point
< rl_end
&& whitespace (rl_line_buffer
[rl_point
]))
1755 rl_vi_first_print (int count
, int key
)
1757 return (rl_vi_back_to_indent (1, key
));
1760 static int _rl_cs_dir
, _rl_cs_orig_dir
;
1762 #if defined (READLINE_CALLBACKS)
1764 _rl_vi_callback_char_search (_rl_callback_generic_arg
*data
)
1767 #if defined (HANDLE_MULTIBYTE)
1768 c
= _rl_vi_last_search_mblen
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1770 RL_SETSTATE(RL_STATE_MOREINPUT
);
1772 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1777 RL_UNSETSTATE (RL_STATE_CHARSEARCH
);
1781 #if !defined (HANDLE_MULTIBYTE)
1782 _rl_vi_last_search_char
= c
;
1785 _rl_callback_func
= 0;
1786 _rl_want_redisplay
= 1;
1787 RL_UNSETSTATE (RL_STATE_CHARSEARCH
);
1789 #if defined (HANDLE_MULTIBYTE)
1790 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_mbchar
, _rl_vi_last_search_mblen
));
1792 return (_rl_char_search_internal (data
->count
, _rl_cs_dir
, _rl_vi_last_search_char
));
1798 rl_vi_char_search (int count
, int key
)
1801 #if defined (HANDLE_MULTIBYTE)
1802 static char *target
;
1808 if (key
== ';' || key
== ',')
1810 if (_rl_cs_orig_dir
== 0)
1812 #if defined (HANDLE_MULTIBYTE)
1813 if (_rl_vi_last_search_mblen
== 0)
1816 if (_rl_vi_last_search_char
== 0)
1819 _rl_cs_dir
= (key
== ';') ? _rl_cs_orig_dir
: -_rl_cs_orig_dir
;
1826 _rl_cs_orig_dir
= _rl_cs_dir
= FTO
;
1830 _rl_cs_orig_dir
= _rl_cs_dir
= BTO
;
1834 _rl_cs_orig_dir
= _rl_cs_dir
= FFIND
;
1838 _rl_cs_orig_dir
= _rl_cs_dir
= BFIND
;
1844 /* set target and tlen below */
1846 #if defined (READLINE_CALLBACKS)
1847 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
1849 _rl_callback_data
= _rl_callback_data_alloc (count
);
1850 _rl_callback_data
->i1
= _rl_cs_dir
;
1851 _rl_callback_data
->i2
= key
;
1852 _rl_callback_func
= _rl_vi_callback_char_search
;
1853 RL_SETSTATE (RL_STATE_CHARSEARCH
);
1859 #if defined (HANDLE_MULTIBYTE)
1860 c
= _rl_read_mbchar (_rl_vi_last_search_mbchar
, MB_LEN_MAX
);
1863 _rl_vi_last_search_mblen
= c
;
1865 RL_SETSTATE(RL_STATE_MOREINPUT
);
1867 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
1870 _rl_vi_last_search_char
= c
;
1875 #if defined (HANDLE_MULTIBYTE)
1876 target
= _rl_vi_last_search_mbchar
;
1877 tlen
= _rl_vi_last_search_mblen
;
1879 target
= _rl_vi_last_search_char
;
1882 #if defined (HANDLE_MULTIBYTE)
1883 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
, tlen
));
1885 return (_rl_char_search_internal (count
, _rl_cs_dir
, target
));
1889 /* Match brackets */
1891 rl_vi_match (int ignore
, int key
)
1893 int count
= 1, brack
, pos
, tmp
, pre
;
1896 if ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1898 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1900 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0)
1903 rl_forward_char (1, key
);
1904 if (pre
== rl_point
)
1909 while ((brack
= rl_vi_bracktype (rl_line_buffer
[rl_point
])) == 0 &&
1910 rl_point
< rl_end
- 1)
1911 rl_forward_char (1, key
);
1928 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1932 pos
= _rl_find_prev_mbchar (rl_line_buffer
, pos
, MB_FIND_ANY
);
1938 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1941 else if (b
== brack
)
1955 if (MB_CUR_MAX
== 1 || rl_byte_oriented
)
1958 pos
= _rl_find_next_mbchar (rl_line_buffer
, pos
, 1, MB_FIND_ANY
);
1962 int b
= rl_vi_bracktype (rl_line_buffer
[pos
]);
1965 else if (b
== brack
)
1980 rl_vi_bracktype (int c
)
1985 case ')': return -1;
1987 case ']': return -2;
1989 case '}': return -3;
1995 _rl_vi_change_char (int count
, int c
, char *mb
)
1999 if (c
== '\033' || c
== CTRL ('C'))
2002 rl_begin_undo_group ();
2003 while (count
-- && rl_point
< rl_end
)
2006 rl_vi_delete (1, c
);
2007 if (rl_point
< p
) /* Did we retreat at EOL? */
2008 _rl_vi_append_forward (c
);
2009 #if defined (HANDLE_MULTIBYTE)
2010 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
2011 rl_insert_text (mb
);
2014 _rl_insert_char (1, c
);
2017 /* The cursor shall be left on the last character changed. */
2018 rl_backward_char (1, c
);
2020 rl_end_undo_group ();
2026 _rl_vi_callback_getchar (char *mb
, int mlen
)
2028 return (_rl_bracketed_read_mbstring (mb
, mlen
));
2031 #if defined (READLINE_CALLBACKS)
2033 _rl_vi_callback_change_char (_rl_callback_generic_arg
*data
)
2036 char mb
[MB_LEN_MAX
+1];
2038 c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
2039 #if defined (HANDLE_MULTIBYTE)
2040 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
2041 strncpy (_rl_vi_last_replacement
, mb
, MB_LEN_MAX
);
2044 _rl_vi_last_replacement
[0] = c
;
2045 _rl_vi_last_replacement
[MB_LEN_MAX
] = '\0'; /* XXX */
2050 _rl_callback_func
= 0;
2051 _rl_want_redisplay
= 1;
2053 return (_rl_vi_change_char (data
->count
, c
, mb
));
2058 rl_vi_change_char (int count
, int key
)
2061 char mb
[MB_LEN_MAX
+1];
2065 strncpy (mb
, _rl_vi_last_replacement
, MB_LEN_MAX
);
2066 c
= (unsigned char)_rl_vi_last_replacement
[0]; /* XXX */
2067 mb
[MB_LEN_MAX
] = '\0';
2069 #if defined (READLINE_CALLBACKS)
2070 else if (RL_ISSTATE (RL_STATE_CALLBACK
))
2072 _rl_callback_data
= _rl_callback_data_alloc (count
);
2073 _rl_callback_func
= _rl_vi_callback_change_char
;
2079 c
= _rl_vi_callback_getchar (mb
, MB_LEN_MAX
);
2080 #ifdef HANDLE_MULTIBYTE
2081 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
2082 strncpy (_rl_vi_last_replacement
, mb
, MB_LEN_MAX
);
2085 _rl_vi_last_replacement
[0] = c
;
2086 _rl_vi_last_replacement
[MB_LEN_MAX
] = '\0'; /* just in case */
2092 return (_rl_vi_change_char (count
, c
, mb
));
2096 rl_vi_subst (int count
, int key
)
2098 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
2099 if (_rl_vi_redoing
== 0)
2100 rl_stuff_char ((key
== 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
2102 return (rl_vi_change_to (count
, 'c'));
2106 rl_vi_overstrike (int count
, int key
)
2108 if (_rl_vi_doing_insert
== 0)
2110 _rl_vi_doing_insert
= 1;
2111 rl_begin_undo_group ();
2116 _rl_overwrite_char (count
, key
);
2117 vi_replace_count
+= count
;
2124 rl_vi_overstrike_delete (int count
, int key
)
2128 for (i
= 0; i
< count
; i
++)
2130 if (vi_replace_count
== 0)
2138 vi_replace_count
--; /* XXX */
2141 rl_backward_char (1, key
);
2144 if (vi_replace_count
== 0 && _rl_vi_doing_insert
)
2146 rl_end_undo_group ();
2148 _rl_vi_doing_insert
= 0;
2154 rl_vi_overstrike_kill_line (int count
, int key
)
2159 r
= rl_unix_line_discard (count
, key
);
2160 vi_replace_count
-= end
- rl_end
;
2165 rl_vi_overstrike_kill_word (int count
, int key
)
2170 r
= rl_vi_unix_word_rubout (count
, key
);
2171 vi_replace_count
-= end
- rl_end
;
2176 rl_vi_overstrike_yank (int count
, int key
)
2181 r
= rl_yank (count
, key
);
2182 vi_replace_count
+= rl_end
- end
;
2186 /* Read bracketed paste mode pasted text and insert it in overwrite mode */
2188 rl_vi_overstrike_bracketed_paste (int count
, int key
)
2194 pbuf
= _rl_bracketed_text (&pblen
);
2202 _rl_unget_char ((unsigned char)pbuf
[r
]);
2205 while (_rl_pushed_input_available ())
2207 key
= rl_read_key ();
2208 r
= rl_vi_overstrike (1, key
);
2215 rl_vi_replace (int count
, int key
)
2219 vi_replace_count
= 0;
2221 if (vi_replace_map
== 0)
2223 vi_replace_map
= rl_make_bare_keymap ();
2225 for (i
= 0; i
< ' '; i
++)
2226 if (vi_insertion_keymap
[i
].type
== ISFUNC
)
2227 vi_replace_map
[i
].function
= vi_insertion_keymap
[i
].function
;
2229 for (i
= ' '; i
< KEYMAP_SIZE
; i
++)
2230 vi_replace_map
[i
].function
= rl_vi_overstrike
;
2232 vi_replace_map
[RUBOUT
].function
= rl_vi_overstrike_delete
;
2234 /* Make sure these are what we want. */
2235 vi_replace_map
[ESC
].function
= rl_vi_movement_mode
;
2236 vi_replace_map
[RETURN
].function
= rl_newline
;
2237 vi_replace_map
[NEWLINE
].function
= rl_newline
;
2239 /* If the normal vi insertion keymap has ^H bound to erase, do the
2240 same here. Probably should remove the assignment to RUBOUT up
2241 there, but I don't think it will make a difference in real life. */
2242 if (vi_insertion_keymap
[CTRL ('H')].type
== ISFUNC
&&
2243 vi_insertion_keymap
[CTRL ('H')].function
== rl_rubout
)
2244 vi_replace_map
[CTRL ('H')].function
= rl_vi_overstrike_delete
;
2246 /* Same for ^U and unix-line-discard. */
2247 if (vi_insertion_keymap
[CTRL ('U')].type
== ISFUNC
&&
2248 vi_insertion_keymap
[CTRL ('U')].function
== rl_unix_line_discard
)
2249 vi_replace_map
[CTRL ('U')].function
= rl_vi_overstrike_kill_line
;
2251 /* And for ^W and unix-word-rubout. */
2252 if (vi_insertion_keymap
[CTRL ('W')].type
== ISFUNC
&&
2253 vi_insertion_keymap
[CTRL ('W')].function
== rl_vi_unix_word_rubout
)
2254 vi_replace_map
[CTRL ('W')].function
= rl_vi_overstrike_kill_word
;
2256 /* And finally for ^Y and yank. */
2257 if (vi_insertion_keymap
[CTRL ('Y')].type
== ISFUNC
&&
2258 vi_insertion_keymap
[CTRL ('Y')].function
== rl_yank
)
2259 vi_replace_map
[CTRL ('Y')].function
= rl_vi_overstrike_yank
;
2261 /* Make sure this is the value we need. */
2262 vi_replace_map
[ANYOTHERKEY
].type
= ISFUNC
;
2263 vi_replace_map
[ANYOTHERKEY
].function
= (rl_command_func_t
*)NULL
;
2266 rl_vi_start_inserting (key
, 1, rl_arg_sign
);
2268 _rl_vi_last_key_before_insert
= 'R'; /* in case someone rebinds it */
2269 _rl_keymap
= vi_replace_map
;
2271 if (_rl_enable_bracketed_paste
)
2272 rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF
, rl_vi_overstrike_bracketed_paste
);
2278 /* Try to complete the word we are standing on or the word that ends with
2279 the previous character. A space matches everything. Word delimiters are
2282 rl_vi_possible_completions (void)
2284 int save_pos
= rl_point
;
2286 if (rl_line_buffer
[rl_point
] != ' ' && rl_line_buffer
[rl_point
] != ';')
2288 while (rl_point
< rl_end
&& rl_line_buffer
[rl_point
] != ' ' &&
2289 rl_line_buffer
[rl_point
] != ';')
2290 _rl_vi_advance_point ();
2292 else if (rl_line_buffer
[rl_point
- 1] == ';')
2298 rl_possible_completions ();
2299 rl_point
= save_pos
;
2305 /* Functions to save and restore marks. */
2307 _rl_vi_set_mark (void)
2311 RL_SETSTATE(RL_STATE_MOREINPUT
);
2312 ch
= rl_read_key ();
2313 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
2315 if (ch
< 0 || ch
< 'a' || ch
> 'z') /* make test against 0 explicit */
2321 vi_mark_chars
[ch
] = rl_point
;
2325 #if defined (READLINE_CALLBACKS)
2327 _rl_vi_callback_set_mark (_rl_callback_generic_arg
*data
)
2329 _rl_callback_func
= 0;
2330 _rl_want_redisplay
= 1;
2332 return (_rl_vi_set_mark ());
2337 rl_vi_set_mark (int count
, int key
)
2339 #if defined (READLINE_CALLBACKS)
2340 if (RL_ISSTATE (RL_STATE_CALLBACK
))
2342 _rl_callback_data
= 0;
2343 _rl_callback_func
= _rl_vi_callback_set_mark
;
2348 return (_rl_vi_set_mark ());
2352 _rl_vi_goto_mark (void)
2356 RL_SETSTATE(RL_STATE_MOREINPUT
);
2357 ch
= rl_read_key ();
2358 RL_UNSETSTATE(RL_STATE_MOREINPUT
);
2366 else if (ch
< 0 || ch
< 'a' || ch
> 'z') /* make test against 0 explicit */
2373 if (vi_mark_chars
[ch
] == -1)
2378 rl_point
= vi_mark_chars
[ch
];
2383 #if defined (READLINE_CALLBACKS)
2385 _rl_vi_callback_goto_mark (_rl_callback_generic_arg
*data
)
2387 _rl_callback_func
= 0;
2388 _rl_want_redisplay
= 1;
2390 return (_rl_vi_goto_mark ());
2395 rl_vi_goto_mark (int count
, int key
)
2397 #if defined (READLINE_CALLBACKS)
2398 if (RL_ISSTATE (RL_STATE_CALLBACK
))
2400 _rl_callback_data
= 0;
2401 _rl_callback_func
= _rl_vi_callback_goto_mark
;
2406 return (_rl_vi_goto_mark ());
2408 #endif /* VI_MODE */