2003-05-13 Andreas Jaeger <aj@suse.de>
[deliverable/binutils-gdb.git] / readline / vi_mode.c
1 /* vi_mode.c -- A vi emulation mode for Bash.
2 Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
3
4 /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
5
6 This file is part of the GNU Readline Library, a library for
7 reading lines of text with interactive input and history editing.
8
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.
13
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.
18
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
24
25 /* **************************************************************** */
26 /* */
27 /* VI Emulation Mode */
28 /* */
29 /* **************************************************************** */
30 #include "rlconf.h"
31
32 #if defined (VI_MODE)
33
34 #if defined (HAVE_CONFIG_H)
35 # include <config.h>
36 #endif
37
38 #include <sys/types.h>
39
40 #if defined (HAVE_STDLIB_H)
41 # include <stdlib.h>
42 #else
43 # include "ansi_stdlib.h"
44 #endif /* HAVE_STDLIB_H */
45
46 #if defined (HAVE_UNISTD_H)
47 # include <unistd.h>
48 #endif
49
50 #include <stdio.h>
51
52 /* Some standard library routines. */
53 #include "rldefs.h"
54 #include "rlmbutil.h"
55
56 #include "readline.h"
57 #include "history.h"
58
59 #include "rlprivate.h"
60 #include "xmalloc.h"
61
62 #ifndef member
63 #define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
64 #endif
65
66 /* Non-zero means enter insertion mode. */
67 static int _rl_vi_doing_insert;
68
69 /* Command keys which do movement for xxx_to commands. */
70 static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|";
71
72 /* Keymap used for vi replace characters. Created dynamically since
73 rarely used. */
74 static Keymap vi_replace_map;
75
76 /* The number of characters inserted in the last replace operation. */
77 static int vi_replace_count;
78
79 /* If non-zero, we have text inserted after a c[motion] command that put
80 us implicitly into insert mode. Some people want this text to be
81 attached to the command so that it is `redoable' with `.'. */
82 static int vi_continued_command;
83 static char *vi_insert_buffer;
84 static int vi_insert_buffer_size;
85
86 static int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
87 static int _rl_vi_last_repeat = 1;
88 static int _rl_vi_last_arg_sign = 1;
89 static int _rl_vi_last_motion;
90 #if defined (HANDLE_MULTIBYTE)
91 static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
92 #else
93 static int _rl_vi_last_search_char;
94 #endif
95 static int _rl_vi_last_replacement;
96
97 static int _rl_vi_last_key_before_insert;
98
99 static int vi_redoing;
100
101 /* Text modification commands. These are the `redoable' commands. */
102 static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
103
104 /* Arrays for the saved marks. */
105 static int vi_mark_chars['z' - 'a' + 1];
106
107 static void _rl_vi_stuff_insert PARAMS((int));
108 static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
109 static int rl_digit_loop1 PARAMS((void));
110
111 void
112 _rl_vi_initialize_line ()
113 {
114 register int i;
115
116 for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
117 vi_mark_chars[i] = -1;
118 }
119
120 void
121 _rl_vi_reset_last ()
122 {
123 _rl_vi_last_command = 'i';
124 _rl_vi_last_repeat = 1;
125 _rl_vi_last_arg_sign = 1;
126 _rl_vi_last_motion = 0;
127 }
128
129 void
130 _rl_vi_set_last (key, repeat, sign)
131 int key, repeat, sign;
132 {
133 _rl_vi_last_command = key;
134 _rl_vi_last_repeat = repeat;
135 _rl_vi_last_arg_sign = sign;
136 }
137
138 /* Is the command C a VI mode text modification command? */
139 int
140 _rl_vi_textmod_command (c)
141 int c;
142 {
143 return (member (c, vi_textmod));
144 }
145
146 static void
147 _rl_vi_stuff_insert (count)
148 int count;
149 {
150 rl_begin_undo_group ();
151 while (count--)
152 rl_insert_text (vi_insert_buffer);
153 rl_end_undo_group ();
154 }
155
156 /* Bound to `.'. Called from command mode, so we know that we have to
157 redo a text modification command. The default for _rl_vi_last_command
158 puts you back into insert mode. */
159 int
160 rl_vi_redo (count, c)
161 int count, c;
162 {
163 int r;
164
165 if (!rl_explicit_arg)
166 {
167 rl_numeric_arg = _rl_vi_last_repeat;
168 rl_arg_sign = _rl_vi_last_arg_sign;
169 }
170
171 r = 0;
172 vi_redoing = 1;
173 /* If we're redoing an insert with `i', stuff in the inserted text
174 and do not go into insertion mode. */
175 if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
176 {
177 _rl_vi_stuff_insert (count);
178 /* And back up point over the last character inserted. */
179 if (rl_point > 0)
180 rl_point--;
181 }
182 else
183 r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
184 vi_redoing = 0;
185
186 return (r);
187 }
188
189 /* A placeholder for further expansion. */
190 int
191 rl_vi_undo (count, key)
192 int count, key;
193 {
194 return (rl_undo_command (count, key));
195 }
196
197 /* Yank the nth arg from the previous line into this line at point. */
198 int
199 rl_vi_yank_arg (count, key)
200 int count, key;
201 {
202 /* Readline thinks that the first word on a line is the 0th, while vi
203 thinks the first word on a line is the 1st. Compensate. */
204 if (rl_explicit_arg)
205 rl_yank_nth_arg (count - 1, 0);
206 else
207 rl_yank_nth_arg ('$', 0);
208
209 return (0);
210 }
211
212 /* With an argument, move back that many history lines, else move to the
213 beginning of history. */
214 int
215 rl_vi_fetch_history (count, c)
216 int count, c;
217 {
218 int wanted;
219
220 /* Giving an argument of n means we want the nth command in the history
221 file. The command number is interpreted the same way that the bash
222 `history' command does it -- that is, giving an argument count of 450
223 to this command would get the command listed as number 450 in the
224 output of `history'. */
225 if (rl_explicit_arg)
226 {
227 wanted = history_base + where_history () - count;
228 if (wanted <= 0)
229 rl_beginning_of_history (0, 0);
230 else
231 rl_get_previous_history (wanted, c);
232 }
233 else
234 rl_beginning_of_history (count, 0);
235 return (0);
236 }
237
238 /* Search again for the last thing searched for. */
239 int
240 rl_vi_search_again (count, key)
241 int count, key;
242 {
243 switch (key)
244 {
245 case 'n':
246 rl_noninc_reverse_search_again (count, key);
247 break;
248
249 case 'N':
250 rl_noninc_forward_search_again (count, key);
251 break;
252 }
253 return (0);
254 }
255
256 /* Do a vi style search. */
257 int
258 rl_vi_search (count, key)
259 int count, key;
260 {
261 switch (key)
262 {
263 case '?':
264 rl_noninc_forward_search (count, key);
265 break;
266
267 case '/':
268 rl_noninc_reverse_search (count, key);
269 break;
270
271 default:
272 rl_ding ();
273 break;
274 }
275 return (0);
276 }
277
278 /* Completion, from vi's point of view. */
279 int
280 rl_vi_complete (ignore, key)
281 int ignore, key;
282 {
283 if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
284 {
285 if (!whitespace (rl_line_buffer[rl_point + 1]))
286 rl_vi_end_word (1, 'E');
287 rl_point++;
288 }
289
290 if (key == '*')
291 rl_complete_internal ('*'); /* Expansion and replacement. */
292 else if (key == '=')
293 rl_complete_internal ('?'); /* List possible completions. */
294 else if (key == '\\')
295 rl_complete_internal (TAB); /* Standard Readline completion. */
296 else
297 rl_complete (0, key);
298
299 if (key == '*' || key == '\\')
300 {
301 _rl_vi_set_last (key, 1, rl_arg_sign);
302 rl_vi_insertion_mode (1, key);
303 }
304 return (0);
305 }
306
307 /* Tilde expansion for vi mode. */
308 int
309 rl_vi_tilde_expand (ignore, key)
310 int ignore, key;
311 {
312 rl_tilde_expand (0, key);
313 _rl_vi_set_last (key, 1, rl_arg_sign); /* XXX */
314 rl_vi_insertion_mode (1, key);
315 return (0);
316 }
317
318 /* Previous word in vi mode. */
319 int
320 rl_vi_prev_word (count, key)
321 int count, key;
322 {
323 if (count < 0)
324 return (rl_vi_next_word (-count, key));
325
326 if (rl_point == 0)
327 {
328 rl_ding ();
329 return (0);
330 }
331
332 if (_rl_uppercase_p (key))
333 rl_vi_bWord (count, key);
334 else
335 rl_vi_bword (count, key);
336
337 return (0);
338 }
339
340 /* Next word in vi mode. */
341 int
342 rl_vi_next_word (count, key)
343 int count, key;
344 {
345 if (count < 0)
346 return (rl_vi_prev_word (-count, key));
347
348 if (rl_point >= (rl_end - 1))
349 {
350 rl_ding ();
351 return (0);
352 }
353
354 if (_rl_uppercase_p (key))
355 rl_vi_fWord (count, key);
356 else
357 rl_vi_fword (count, key);
358 return (0);
359 }
360
361 /* Move to the end of the ?next? word. */
362 int
363 rl_vi_end_word (count, key)
364 int count, key;
365 {
366 if (count < 0)
367 {
368 rl_ding ();
369 return -1;
370 }
371
372 if (_rl_uppercase_p (key))
373 rl_vi_eWord (count, key);
374 else
375 rl_vi_eword (count, key);
376 return (0);
377 }
378
379 /* Move forward a word the way that 'W' does. */
380 int
381 rl_vi_fWord (count, ignore)
382 int count, ignore;
383 {
384 while (count-- && rl_point < (rl_end - 1))
385 {
386 /* Skip until whitespace. */
387 while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
388 rl_point++;
389
390 /* Now skip whitespace. */
391 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
392 rl_point++;
393 }
394 return (0);
395 }
396
397 int
398 rl_vi_bWord (count, ignore)
399 int count, ignore;
400 {
401 while (count-- && rl_point > 0)
402 {
403 /* If we are at the start of a word, move back to whitespace so
404 we will go back to the start of the previous word. */
405 if (!whitespace (rl_line_buffer[rl_point]) &&
406 whitespace (rl_line_buffer[rl_point - 1]))
407 rl_point--;
408
409 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
410 rl_point--;
411
412 if (rl_point > 0)
413 {
414 while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
415 rl_point++;
416 }
417 }
418 return (0);
419 }
420
421 int
422 rl_vi_eWord (count, ignore)
423 int count, ignore;
424 {
425 while (count-- && rl_point < (rl_end - 1))
426 {
427 if (!whitespace (rl_line_buffer[rl_point]))
428 rl_point++;
429
430 /* Move to the next non-whitespace character (to the start of the
431 next word). */
432 while (++rl_point < rl_end && whitespace (rl_line_buffer[rl_point]));
433
434 if (rl_point && rl_point < rl_end)
435 {
436 /* Skip whitespace. */
437 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
438 rl_point++;
439
440 /* Skip until whitespace. */
441 while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
442 rl_point++;
443
444 /* Move back to the last character of the word. */
445 rl_point--;
446 }
447 }
448 return (0);
449 }
450
451 int
452 rl_vi_fword (count, ignore)
453 int count, ignore;
454 {
455 while (count-- && rl_point < (rl_end - 1))
456 {
457 /* Move to white space (really non-identifer). */
458 if (_rl_isident (rl_line_buffer[rl_point]))
459 {
460 while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
461 rl_point++;
462 }
463 else /* if (!whitespace (rl_line_buffer[rl_point])) */
464 {
465 while (!_rl_isident (rl_line_buffer[rl_point]) &&
466 !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
467 rl_point++;
468 }
469
470 /* Move past whitespace. */
471 while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
472 rl_point++;
473 }
474 return (0);
475 }
476
477 int
478 rl_vi_bword (count, ignore)
479 int count, ignore;
480 {
481 while (count-- && rl_point > 0)
482 {
483 int last_is_ident;
484
485 /* If we are at the start of a word, move back to whitespace
486 so we will go back to the start of the previous word. */
487 if (!whitespace (rl_line_buffer[rl_point]) &&
488 whitespace (rl_line_buffer[rl_point - 1]))
489 rl_point--;
490
491 /* If this character and the previous character are `opposite', move
492 back so we don't get messed up by the rl_point++ down there in
493 the while loop. Without this code, words like `l;' screw up the
494 function. */
495 last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
496 if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
497 (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
498 rl_point--;
499
500 while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
501 rl_point--;
502
503 if (rl_point > 0)
504 {
505 if (_rl_isident (rl_line_buffer[rl_point]))
506 while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
507 else
508 while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
509 !whitespace (rl_line_buffer[rl_point]));
510 rl_point++;
511 }
512 }
513 return (0);
514 }
515
516 int
517 rl_vi_eword (count, ignore)
518 int count, ignore;
519 {
520 while (count-- && rl_point < rl_end - 1)
521 {
522 if (!whitespace (rl_line_buffer[rl_point]))
523 rl_point++;
524
525 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
526 rl_point++;
527
528 if (rl_point < rl_end)
529 {
530 if (_rl_isident (rl_line_buffer[rl_point]))
531 while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
532 else
533 while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
534 && !whitespace (rl_line_buffer[rl_point]));
535 }
536 rl_point--;
537 }
538 return (0);
539 }
540
541 int
542 rl_vi_insert_beg (count, key)
543 int count, key;
544 {
545 rl_beg_of_line (1, key);
546 rl_vi_insertion_mode (1, key);
547 return (0);
548 }
549
550 int
551 rl_vi_append_mode (count, key)
552 int count, key;
553 {
554 if (rl_point < rl_end)
555 {
556 if (MB_CUR_MAX == 1 || rl_byte_oriented)
557 rl_point++;
558 else
559 {
560 int point = rl_point;
561 rl_forward_char (1, key);
562 if (point == rl_point)
563 rl_point = rl_end;
564 }
565 }
566 rl_vi_insertion_mode (1, key);
567 return (0);
568 }
569
570 int
571 rl_vi_append_eol (count, key)
572 int count, key;
573 {
574 rl_end_of_line (1, key);
575 rl_vi_append_mode (1, key);
576 return (0);
577 }
578
579 /* What to do in the case of C-d. */
580 int
581 rl_vi_eof_maybe (count, c)
582 int count, c;
583 {
584 return (rl_newline (1, '\n'));
585 }
586
587 /* Insertion mode stuff. */
588
589 /* Switching from one mode to the other really just involves
590 switching keymaps. */
591 int
592 rl_vi_insertion_mode (count, key)
593 int count, key;
594 {
595 _rl_keymap = vi_insertion_keymap;
596 _rl_vi_last_key_before_insert = key;
597 return (0);
598 }
599
600 static void
601 _rl_vi_save_insert (up)
602 UNDO_LIST *up;
603 {
604 int len, start, end;
605
606 if (up == 0)
607 {
608 if (vi_insert_buffer_size >= 1)
609 vi_insert_buffer[0] = '\0';
610 return;
611 }
612
613 start = up->start;
614 end = up->end;
615 len = end - start + 1;
616 if (len >= vi_insert_buffer_size)
617 {
618 vi_insert_buffer_size += (len + 32) - (len % 32);
619 vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
620 }
621 strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
622 vi_insert_buffer[len-1] = '\0';
623 }
624
625 void
626 _rl_vi_done_inserting ()
627 {
628 if (_rl_vi_doing_insert)
629 {
630 /* The `C', `s', and `S' commands set this. */
631 rl_end_undo_group ();
632 /* Now, the text between rl_undo_list->next->start and
633 rl_undo_list->next->end is what was inserted while in insert
634 mode. It gets copied to VI_INSERT_BUFFER because it depends
635 on absolute indices into the line which may change (though they
636 probably will not). */
637 _rl_vi_doing_insert = 0;
638 _rl_vi_save_insert (rl_undo_list->next);
639 vi_continued_command = 1;
640 }
641 else
642 {
643 if (_rl_vi_last_key_before_insert == 'i' && rl_undo_list)
644 _rl_vi_save_insert (rl_undo_list);
645 /* XXX - Other keys probably need to be checked. */
646 else if (_rl_vi_last_key_before_insert == 'C')
647 rl_end_undo_group ();
648 while (_rl_undo_group_level > 0)
649 rl_end_undo_group ();
650 vi_continued_command = 0;
651 }
652 }
653
654 int
655 rl_vi_movement_mode (count, key)
656 int count, key;
657 {
658 if (rl_point > 0)
659 rl_backward_char (1, key);
660
661 _rl_keymap = vi_movement_keymap;
662 _rl_vi_done_inserting ();
663 return (0);
664 }
665
666 int
667 rl_vi_arg_digit (count, c)
668 int count, c;
669 {
670 if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
671 return (rl_beg_of_line (1, c));
672 else
673 return (rl_digit_argument (count, c));
674 }
675
676 /* Change the case of the next COUNT characters. */
677 #if defined (HANDLE_MULTIBYTE)
678 static int
679 _rl_vi_change_mbchar_case (count)
680 int count;
681 {
682 wchar_t wc;
683 char mb[MB_LEN_MAX];
684 mbstate_t ps;
685
686 memset (&ps, 0, sizeof (mbstate_t));
687 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
688 count--;
689 while (count-- && rl_point < rl_end)
690 {
691 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
692 if (iswupper (wc))
693 wc = towlower (wc);
694 else if (iswlower (wc))
695 wc = towupper (wc);
696 else
697 {
698 /* Just skip over chars neither upper nor lower case */
699 rl_forward_char (1, 0);
700 continue;
701 }
702
703 /* Vi is kind of strange here. */
704 if (wc)
705 {
706 wctomb (mb, wc);
707 rl_begin_undo_group ();
708 rl_delete (1, 0);
709 rl_insert_text (mb);
710 rl_end_undo_group ();
711 rl_vi_check ();
712 }
713 else
714 rl_forward_char (1, 0);
715 }
716
717 return 0;
718 }
719 #endif
720
721 int
722 rl_vi_change_case (count, ignore)
723 int count, ignore;
724 {
725 char c = 0;
726
727 /* Don't try this on an empty line. */
728 if (rl_point >= rl_end)
729 return (0);
730
731 #if defined (HANDLE_MULTIBYTE)
732 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
733 return (_rl_vi_change_mbchar_case (count));
734 #endif
735
736 while (count-- && rl_point < rl_end)
737 {
738 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
739 c = _rl_to_lower (rl_line_buffer[rl_point]);
740 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
741 c = _rl_to_upper (rl_line_buffer[rl_point]);
742 else
743 {
744 /* Just skip over characters neither upper nor lower case. */
745 rl_forward_char (1, c);
746 continue;
747 }
748
749 /* Vi is kind of strange here. */
750 if (c)
751 {
752 rl_begin_undo_group ();
753 rl_delete (1, c);
754 _rl_insert_char (1, c);
755 rl_end_undo_group ();
756 rl_vi_check ();
757 }
758 else
759 rl_forward_char (1, c);
760 }
761 return (0);
762 }
763
764 int
765 rl_vi_put (count, key)
766 int count, key;
767 {
768 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
769 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
770
771 rl_yank (1, key);
772 rl_backward_char (1, key);
773 return (0);
774 }
775
776 int
777 rl_vi_check ()
778 {
779 if (rl_point && rl_point == rl_end)
780 {
781 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
782 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
783 else
784 rl_point--;
785 }
786 return (0);
787 }
788
789 int
790 rl_vi_column (count, key)
791 int count, key;
792 {
793 if (count > rl_end)
794 rl_end_of_line (1, key);
795 else
796 rl_point = count - 1;
797 return (0);
798 }
799
800 int
801 rl_vi_domove (key, nextkey)
802 int key, *nextkey;
803 {
804 int c, save;
805 int old_end;
806
807 rl_mark = rl_point;
808 RL_SETSTATE(RL_STATE_MOREINPUT);
809 c = rl_read_key ();
810 RL_UNSETSTATE(RL_STATE_MOREINPUT);
811 *nextkey = c;
812
813 if (!member (c, vi_motion))
814 {
815 if (_rl_digit_p (c))
816 {
817 save = rl_numeric_arg;
818 rl_numeric_arg = _rl_digit_value (c);
819 rl_digit_loop1 ();
820 rl_numeric_arg *= save;
821 RL_SETSTATE(RL_STATE_MOREINPUT);
822 c = rl_read_key (); /* real command */
823 RL_UNSETSTATE(RL_STATE_MOREINPUT);
824 *nextkey = c;
825 }
826 else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
827 {
828 rl_mark = rl_end;
829 rl_beg_of_line (1, c);
830 _rl_vi_last_motion = c;
831 return (0);
832 }
833 else
834 return (-1);
835 }
836
837 _rl_vi_last_motion = c;
838
839 /* Append a blank character temporarily so that the motion routines
840 work right at the end of the line. */
841 old_end = rl_end;
842 rl_line_buffer[rl_end++] = ' ';
843 rl_line_buffer[rl_end] = '\0';
844
845 _rl_dispatch (c, _rl_keymap);
846
847 /* Remove the blank that we added. */
848 rl_end = old_end;
849 rl_line_buffer[rl_end] = '\0';
850 if (rl_point > rl_end)
851 rl_point = rl_end;
852
853 /* No change in position means the command failed. */
854 if (rl_mark == rl_point)
855 return (-1);
856
857 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
858 word. If we are not at the end of the line, and we are on a
859 non-whitespace character, move back one (presumably to whitespace). */
860 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
861 !whitespace (rl_line_buffer[rl_point]))
862 rl_point--;
863
864 /* If cw or cW, back up to the end of a word, so the behaviour of ce
865 or cE is the actual result. Brute-force, no subtlety. */
866 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
867 {
868 /* Don't move farther back than where we started. */
869 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
870 rl_point--;
871
872 /* Posix.2 says that if cw or cW moves the cursor towards the end of
873 the line, the character under the cursor should be deleted. */
874 if (rl_point == rl_mark)
875 rl_point++;
876 else
877 {
878 /* Move past the end of the word so that the kill doesn't
879 remove the last letter of the previous word. Only do this
880 if we are not at the end of the line. */
881 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
882 rl_point++;
883 }
884 }
885
886 if (rl_mark < rl_point)
887 SWAP (rl_point, rl_mark);
888
889 return (0);
890 }
891
892 /* A simplified loop for vi. Don't dispatch key at end.
893 Don't recognize minus sign?
894 Should this do rl_save_prompt/rl_restore_prompt? */
895 static int
896 rl_digit_loop1 ()
897 {
898 int key, c;
899
900 RL_SETSTATE(RL_STATE_NUMERICARG);
901 while (1)
902 {
903 if (rl_numeric_arg > 1000000)
904 {
905 rl_explicit_arg = rl_numeric_arg = 0;
906 rl_ding ();
907 rl_clear_message ();
908 RL_UNSETSTATE(RL_STATE_NUMERICARG);
909 return 1;
910 }
911 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
912 RL_SETSTATE(RL_STATE_MOREINPUT);
913 key = c = rl_read_key ();
914 RL_UNSETSTATE(RL_STATE_MOREINPUT);
915
916 if (c >= 0 && _rl_keymap[c].type == ISFUNC &&
917 _rl_keymap[c].function == rl_universal_argument)
918 {
919 rl_numeric_arg *= 4;
920 continue;
921 }
922
923 c = UNMETA (c);
924 if (_rl_digit_p (c))
925 {
926 if (rl_explicit_arg)
927 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
928 else
929 rl_numeric_arg = _rl_digit_value (c);
930 rl_explicit_arg = 1;
931 }
932 else
933 {
934 rl_clear_message ();
935 rl_stuff_char (key);
936 break;
937 }
938 }
939
940 RL_UNSETSTATE(RL_STATE_NUMERICARG);
941 return (0);
942 }
943
944 int
945 rl_vi_delete_to (count, key)
946 int count, key;
947 {
948 int c;
949
950 if (_rl_uppercase_p (key))
951 rl_stuff_char ('$');
952 else if (vi_redoing)
953 rl_stuff_char (_rl_vi_last_motion);
954
955 if (rl_vi_domove (key, &c))
956 {
957 rl_ding ();
958 return -1;
959 }
960
961 /* These are the motion commands that do not require adjusting the
962 mark. */
963 if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
964 rl_mark++;
965
966 rl_kill_text (rl_point, rl_mark);
967 return (0);
968 }
969
970 int
971 rl_vi_change_to (count, key)
972 int count, key;
973 {
974 int c, start_pos;
975
976 if (_rl_uppercase_p (key))
977 rl_stuff_char ('$');
978 else if (vi_redoing)
979 rl_stuff_char (_rl_vi_last_motion);
980
981 start_pos = rl_point;
982
983 if (rl_vi_domove (key, &c))
984 {
985 rl_ding ();
986 return -1;
987 }
988
989 /* These are the motion commands that do not require adjusting the
990 mark. c[wW] are handled by special-case code in rl_vi_domove(),
991 and already leave the mark at the correct location. */
992 if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
993 rl_mark++;
994
995 /* The cursor never moves with c[wW]. */
996 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
997 rl_point = start_pos;
998
999 if (vi_redoing)
1000 {
1001 if (vi_insert_buffer && *vi_insert_buffer)
1002 rl_begin_undo_group ();
1003 rl_delete_text (rl_point, rl_mark);
1004 if (vi_insert_buffer && *vi_insert_buffer)
1005 {
1006 rl_insert_text (vi_insert_buffer);
1007 rl_end_undo_group ();
1008 }
1009 }
1010 else
1011 {
1012 rl_begin_undo_group (); /* to make the `u' command work */
1013 rl_kill_text (rl_point, rl_mark);
1014 /* `C' does not save the text inserted for undoing or redoing. */
1015 if (_rl_uppercase_p (key) == 0)
1016 _rl_vi_doing_insert = 1;
1017 _rl_vi_set_last (key, count, rl_arg_sign);
1018 rl_vi_insertion_mode (1, key);
1019 }
1020
1021 return (0);
1022 }
1023
1024 int
1025 rl_vi_yank_to (count, key)
1026 int count, key;
1027 {
1028 int c, save = rl_point;
1029
1030 if (_rl_uppercase_p (key))
1031 rl_stuff_char ('$');
1032
1033 if (rl_vi_domove (key, &c))
1034 {
1035 rl_ding ();
1036 return -1;
1037 }
1038
1039 /* These are the motion commands that do not require adjusting the
1040 mark. */
1041 if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
1042 rl_mark++;
1043
1044 rl_begin_undo_group ();
1045 rl_kill_text (rl_point, rl_mark);
1046 rl_end_undo_group ();
1047 rl_do_undo ();
1048 rl_point = save;
1049
1050 return (0);
1051 }
1052
1053 int
1054 rl_vi_delete (count, key)
1055 int count, key;
1056 {
1057 int end;
1058
1059 if (rl_end == 0)
1060 {
1061 rl_ding ();
1062 return -1;
1063 }
1064
1065 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1066 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1067 else
1068 end = rl_point + count;
1069
1070 if (end >= rl_end)
1071 end = rl_end;
1072
1073 rl_kill_text (rl_point, end);
1074
1075 if (rl_point > 0 && rl_point == rl_end)
1076 rl_backward_char (1, key);
1077 return (0);
1078 }
1079
1080 int
1081 rl_vi_back_to_indent (count, key)
1082 int count, key;
1083 {
1084 rl_beg_of_line (1, key);
1085 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1086 rl_point++;
1087 return (0);
1088 }
1089
1090 int
1091 rl_vi_first_print (count, key)
1092 int count, key;
1093 {
1094 return (rl_vi_back_to_indent (1, key));
1095 }
1096
1097 int
1098 rl_vi_char_search (count, key)
1099 int count, key;
1100 {
1101 #if defined (HANDLE_MULTIBYTE)
1102 static char *target;
1103 static int mb_len;
1104 #else
1105 static char target;
1106 #endif
1107 static int orig_dir, dir;
1108
1109 if (key == ';' || key == ',')
1110 dir = key == ';' ? orig_dir : -orig_dir;
1111 else
1112 {
1113 if (vi_redoing)
1114 #if defined (HANDLE_MULTIBYTE)
1115 target = _rl_vi_last_search_mbchar;
1116 #else
1117 target = _rl_vi_last_search_char;
1118 #endif
1119 else
1120 {
1121 #if defined (HANDLE_MULTIBYTE)
1122 mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1123 target = _rl_vi_last_search_mbchar;
1124 #else
1125 RL_SETSTATE(RL_STATE_MOREINPUT);
1126 _rl_vi_last_search_char = target = rl_read_key ();
1127 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1128 #endif
1129 }
1130
1131 switch (key)
1132 {
1133 case 't':
1134 orig_dir = dir = FTO;
1135 break;
1136
1137 case 'T':
1138 orig_dir = dir = BTO;
1139 break;
1140
1141 case 'f':
1142 orig_dir = dir = FFIND;
1143 break;
1144
1145 case 'F':
1146 orig_dir = dir = BFIND;
1147 break;
1148 }
1149 }
1150
1151 #if defined (HANDLE_MULTIBYTE)
1152 return (_rl_char_search_internal (count, dir, target, mb_len));
1153 #else
1154 return (_rl_char_search_internal (count, dir, target));
1155 #endif
1156 }
1157
1158 /* Match brackets */
1159 int
1160 rl_vi_match (ignore, key)
1161 int ignore, key;
1162 {
1163 int count = 1, brack, pos, tmp, pre;
1164
1165 pos = rl_point;
1166 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1167 {
1168 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1169 {
1170 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1171 {
1172 pre = rl_point;
1173 rl_forward_char (1, key);
1174 if (pre == rl_point)
1175 break;
1176 }
1177 }
1178 else
1179 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1180 rl_point < rl_end - 1)
1181 rl_forward_char (1, key);
1182
1183 if (brack <= 0)
1184 {
1185 rl_point = pos;
1186 rl_ding ();
1187 return -1;
1188 }
1189 }
1190
1191 pos = rl_point;
1192
1193 if (brack < 0)
1194 {
1195 while (count)
1196 {
1197 tmp = pos;
1198 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1199 pos--;
1200 else
1201 {
1202 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1203 if (tmp == pos)
1204 pos--;
1205 }
1206 if (pos >= 0)
1207 {
1208 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1209 if (b == -brack)
1210 count--;
1211 else if (b == brack)
1212 count++;
1213 }
1214 else
1215 {
1216 rl_ding ();
1217 return -1;
1218 }
1219 }
1220 }
1221 else
1222 { /* brack > 0 */
1223 while (count)
1224 {
1225 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1226 pos++;
1227 else
1228 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1229
1230 if (pos < rl_end)
1231 {
1232 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1233 if (b == -brack)
1234 count--;
1235 else if (b == brack)
1236 count++;
1237 }
1238 else
1239 {
1240 rl_ding ();
1241 return -1;
1242 }
1243 }
1244 }
1245 rl_point = pos;
1246 return (0);
1247 }
1248
1249 int
1250 rl_vi_bracktype (c)
1251 int c;
1252 {
1253 switch (c)
1254 {
1255 case '(': return 1;
1256 case ')': return -1;
1257 case '[': return 2;
1258 case ']': return -2;
1259 case '{': return 3;
1260 case '}': return -3;
1261 default: return 0;
1262 }
1263 }
1264
1265 /* XXX - think about reading an entire mbchar with _rl_read_mbchar and
1266 inserting it in one bunch instead of the loop below (like in
1267 rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0]
1268 for test against 033 or ^C. Make sure that _rl_read_mbchar does
1269 this right. */
1270 int
1271 rl_vi_change_char (count, key)
1272 int count, key;
1273 {
1274 int c;
1275
1276 if (vi_redoing)
1277 c = _rl_vi_last_replacement;
1278 else
1279 {
1280 RL_SETSTATE(RL_STATE_MOREINPUT);
1281 _rl_vi_last_replacement = c = rl_read_key ();
1282 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1283 }
1284
1285 if (c == '\033' || c == CTRL ('C'))
1286 return -1;
1287
1288 while (count-- && rl_point < rl_end)
1289 {
1290 rl_begin_undo_group ();
1291
1292 rl_delete (1, c);
1293 #if defined (HANDLE_MULTIBYTE)
1294 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1295 while (_rl_insert_char (1, c))
1296 {
1297 RL_SETSTATE (RL_STATE_MOREINPUT);
1298 c = rl_read_key ();
1299 RL_UNSETSTATE (RL_STATE_MOREINPUT);
1300 }
1301 else
1302 #endif
1303 _rl_insert_char (1, c);
1304 if (count == 0)
1305 rl_backward_char (1, c);
1306
1307 rl_end_undo_group ();
1308 }
1309 return (0);
1310 }
1311
1312 int
1313 rl_vi_subst (count, key)
1314 int count, key;
1315 {
1316 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1317 if (vi_redoing == 0)
1318 rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */
1319
1320 return (rl_vi_change_to (count, 'c'));
1321 }
1322
1323 int
1324 rl_vi_overstrike (count, key)
1325 int count, key;
1326 {
1327 if (_rl_vi_doing_insert == 0)
1328 {
1329 _rl_vi_doing_insert = 1;
1330 rl_begin_undo_group ();
1331 }
1332
1333 if (count > 0)
1334 {
1335 _rl_overwrite_char (count, key);
1336 vi_replace_count += count;
1337 }
1338
1339 return (0);
1340 }
1341
1342 int
1343 rl_vi_overstrike_delete (count, key)
1344 int count, key;
1345 {
1346 int i, s;
1347
1348 for (i = 0; i < count; i++)
1349 {
1350 if (vi_replace_count == 0)
1351 {
1352 rl_ding ();
1353 break;
1354 }
1355 s = rl_point;
1356
1357 if (rl_do_undo ())
1358 vi_replace_count--;
1359
1360 if (rl_point == s)
1361 rl_backward_char (1, key);
1362 }
1363
1364 if (vi_replace_count == 0 && _rl_vi_doing_insert)
1365 {
1366 rl_end_undo_group ();
1367 rl_do_undo ();
1368 _rl_vi_doing_insert = 0;
1369 }
1370 return (0);
1371 }
1372
1373 int
1374 rl_vi_replace (count, key)
1375 int count, key;
1376 {
1377 int i;
1378
1379 vi_replace_count = 0;
1380
1381 if (!vi_replace_map)
1382 {
1383 vi_replace_map = rl_make_bare_keymap ();
1384
1385 for (i = ' '; i < KEYMAP_SIZE; i++)
1386 vi_replace_map[i].function = rl_vi_overstrike;
1387
1388 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1389 vi_replace_map[ESC].function = rl_vi_movement_mode;
1390 vi_replace_map[RETURN].function = rl_newline;
1391 vi_replace_map[NEWLINE].function = rl_newline;
1392
1393 /* If the normal vi insertion keymap has ^H bound to erase, do the
1394 same here. Probably should remove the assignment to RUBOUT up
1395 there, but I don't think it will make a difference in real life. */
1396 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1397 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1398 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1399
1400 }
1401 _rl_keymap = vi_replace_map;
1402 return (0);
1403 }
1404
1405 #if 0
1406 /* Try to complete the word we are standing on or the word that ends with
1407 the previous character. A space matches everything. Word delimiters are
1408 space and ;. */
1409 int
1410 rl_vi_possible_completions()
1411 {
1412 int save_pos = rl_point;
1413
1414 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1415 {
1416 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1417 rl_line_buffer[rl_point] != ';')
1418 rl_point++;
1419 }
1420 else if (rl_line_buffer[rl_point - 1] == ';')
1421 {
1422 rl_ding ();
1423 return (0);
1424 }
1425
1426 rl_possible_completions ();
1427 rl_point = save_pos;
1428
1429 return (0);
1430 }
1431 #endif
1432
1433 /* Functions to save and restore marks. */
1434 int
1435 rl_vi_set_mark (count, key)
1436 int count, key;
1437 {
1438 int ch;
1439
1440 RL_SETSTATE(RL_STATE_MOREINPUT);
1441 ch = rl_read_key ();
1442 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1443
1444 if (ch < 'a' || ch > 'z')
1445 {
1446 rl_ding ();
1447 return -1;
1448 }
1449 ch -= 'a';
1450 vi_mark_chars[ch] = rl_point;
1451 return 0;
1452 }
1453
1454 int
1455 rl_vi_goto_mark (count, key)
1456 int count, key;
1457 {
1458 int ch;
1459
1460 RL_SETSTATE(RL_STATE_MOREINPUT);
1461 ch = rl_read_key ();
1462 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1463
1464 if (ch == '`')
1465 {
1466 rl_point = rl_mark;
1467 return 0;
1468 }
1469 else if (ch < 'a' || ch > 'z')
1470 {
1471 rl_ding ();
1472 return -1;
1473 }
1474
1475 ch -= 'a';
1476 if (vi_mark_chars[ch] == -1)
1477 {
1478 rl_ding ();
1479 return -1;
1480 }
1481 rl_point = vi_mark_chars[ch];
1482 return 0;
1483 }
1484
1485 #endif /* VI_MODE */
This page took 0.059877 seconds and 4 git commands to generate.