2005-01-13 Michael Snyder <msnyder@redhat.com>
[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+1];
684 int mblen;
685 mbstate_t ps;
686
687 memset (&ps, 0, sizeof (mbstate_t));
688 if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
689 count--;
690 while (count-- && rl_point < rl_end)
691 {
692 mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
693 if (iswupper (wc))
694 wc = towlower (wc);
695 else if (iswlower (wc))
696 wc = towupper (wc);
697 else
698 {
699 /* Just skip over chars neither upper nor lower case */
700 rl_forward_char (1, 0);
701 continue;
702 }
703
704 /* Vi is kind of strange here. */
705 if (wc)
706 {
707 mblen = wctomb (mb, wc);
708 if (mblen >= 0)
709 mb[mblen] = '\0';
710 rl_begin_undo_group ();
711 rl_delete (1, 0);
712 rl_insert_text (mb);
713 rl_end_undo_group ();
714 rl_vi_check ();
715 }
716 else
717 rl_forward_char (1, 0);
718 }
719
720 return 0;
721 }
722 #endif
723
724 int
725 rl_vi_change_case (count, ignore)
726 int count, ignore;
727 {
728 char c = 0;
729
730 /* Don't try this on an empty line. */
731 if (rl_point >= rl_end)
732 return (0);
733
734 #if defined (HANDLE_MULTIBYTE)
735 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
736 return (_rl_vi_change_mbchar_case (count));
737 #endif
738
739 while (count-- && rl_point < rl_end)
740 {
741 if (_rl_uppercase_p (rl_line_buffer[rl_point]))
742 c = _rl_to_lower (rl_line_buffer[rl_point]);
743 else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
744 c = _rl_to_upper (rl_line_buffer[rl_point]);
745 else
746 {
747 /* Just skip over characters neither upper nor lower case. */
748 rl_forward_char (1, c);
749 continue;
750 }
751
752 /* Vi is kind of strange here. */
753 if (c)
754 {
755 rl_begin_undo_group ();
756 rl_delete (1, c);
757 _rl_insert_char (1, c);
758 rl_end_undo_group ();
759 rl_vi_check ();
760 }
761 else
762 rl_forward_char (1, c);
763 }
764 return (0);
765 }
766
767 int
768 rl_vi_put (count, key)
769 int count, key;
770 {
771 if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
772 rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
773
774 rl_yank (1, key);
775 rl_backward_char (1, key);
776 return (0);
777 }
778
779 int
780 rl_vi_check ()
781 {
782 if (rl_point && rl_point == rl_end)
783 {
784 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
785 rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
786 else
787 rl_point--;
788 }
789 return (0);
790 }
791
792 int
793 rl_vi_column (count, key)
794 int count, key;
795 {
796 if (count > rl_end)
797 rl_end_of_line (1, key);
798 else
799 rl_point = count - 1;
800 return (0);
801 }
802
803 int
804 rl_vi_domove (key, nextkey)
805 int key, *nextkey;
806 {
807 int c, save;
808 int old_end;
809
810 rl_mark = rl_point;
811 RL_SETSTATE(RL_STATE_MOREINPUT);
812 c = rl_read_key ();
813 RL_UNSETSTATE(RL_STATE_MOREINPUT);
814 *nextkey = c;
815
816 if (!member (c, vi_motion))
817 {
818 if (_rl_digit_p (c))
819 {
820 save = rl_numeric_arg;
821 rl_numeric_arg = _rl_digit_value (c);
822 rl_digit_loop1 ();
823 rl_numeric_arg *= save;
824 RL_SETSTATE(RL_STATE_MOREINPUT);
825 c = rl_read_key (); /* real command */
826 RL_UNSETSTATE(RL_STATE_MOREINPUT);
827 *nextkey = c;
828 }
829 else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
830 {
831 rl_mark = rl_end;
832 rl_beg_of_line (1, c);
833 _rl_vi_last_motion = c;
834 return (0);
835 }
836 else
837 return (-1);
838 }
839
840 _rl_vi_last_motion = c;
841
842 /* Append a blank character temporarily so that the motion routines
843 work right at the end of the line. */
844 old_end = rl_end;
845 rl_line_buffer[rl_end++] = ' ';
846 rl_line_buffer[rl_end] = '\0';
847
848 _rl_dispatch (c, _rl_keymap);
849
850 /* Remove the blank that we added. */
851 rl_end = old_end;
852 rl_line_buffer[rl_end] = '\0';
853 if (rl_point > rl_end)
854 rl_point = rl_end;
855
856 /* No change in position means the command failed. */
857 if (rl_mark == rl_point)
858 return (-1);
859
860 /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
861 word. If we are not at the end of the line, and we are on a
862 non-whitespace character, move back one (presumably to whitespace). */
863 if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
864 !whitespace (rl_line_buffer[rl_point]))
865 rl_point--;
866
867 /* If cw or cW, back up to the end of a word, so the behaviour of ce
868 or cE is the actual result. Brute-force, no subtlety. */
869 if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
870 {
871 /* Don't move farther back than where we started. */
872 while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
873 rl_point--;
874
875 /* Posix.2 says that if cw or cW moves the cursor towards the end of
876 the line, the character under the cursor should be deleted. */
877 if (rl_point == rl_mark)
878 rl_point++;
879 else
880 {
881 /* Move past the end of the word so that the kill doesn't
882 remove the last letter of the previous word. Only do this
883 if we are not at the end of the line. */
884 if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
885 rl_point++;
886 }
887 }
888
889 if (rl_mark < rl_point)
890 SWAP (rl_point, rl_mark);
891
892 return (0);
893 }
894
895 /* A simplified loop for vi. Don't dispatch key at end.
896 Don't recognize minus sign?
897 Should this do rl_save_prompt/rl_restore_prompt? */
898 static int
899 rl_digit_loop1 ()
900 {
901 int key, c;
902
903 RL_SETSTATE(RL_STATE_NUMERICARG);
904 while (1)
905 {
906 if (rl_numeric_arg > 1000000)
907 {
908 rl_explicit_arg = rl_numeric_arg = 0;
909 rl_ding ();
910 rl_clear_message ();
911 RL_UNSETSTATE(RL_STATE_NUMERICARG);
912 return 1;
913 }
914 rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
915 RL_SETSTATE(RL_STATE_MOREINPUT);
916 key = c = rl_read_key ();
917 RL_UNSETSTATE(RL_STATE_MOREINPUT);
918
919 if (c >= 0 && _rl_keymap[c].type == ISFUNC &&
920 _rl_keymap[c].function == rl_universal_argument)
921 {
922 rl_numeric_arg *= 4;
923 continue;
924 }
925
926 c = UNMETA (c);
927 if (_rl_digit_p (c))
928 {
929 if (rl_explicit_arg)
930 rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
931 else
932 rl_numeric_arg = _rl_digit_value (c);
933 rl_explicit_arg = 1;
934 }
935 else
936 {
937 rl_clear_message ();
938 rl_stuff_char (key);
939 break;
940 }
941 }
942
943 RL_UNSETSTATE(RL_STATE_NUMERICARG);
944 return (0);
945 }
946
947 int
948 rl_vi_delete_to (count, key)
949 int count, key;
950 {
951 int c;
952
953 if (_rl_uppercase_p (key))
954 rl_stuff_char ('$');
955 else if (vi_redoing)
956 rl_stuff_char (_rl_vi_last_motion);
957
958 if (rl_vi_domove (key, &c))
959 {
960 rl_ding ();
961 return -1;
962 }
963
964 /* These are the motion commands that do not require adjusting the
965 mark. */
966 if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
967 rl_mark++;
968
969 rl_kill_text (rl_point, rl_mark);
970 return (0);
971 }
972
973 int
974 rl_vi_change_to (count, key)
975 int count, key;
976 {
977 int c, start_pos;
978
979 if (_rl_uppercase_p (key))
980 rl_stuff_char ('$');
981 else if (vi_redoing)
982 rl_stuff_char (_rl_vi_last_motion);
983
984 start_pos = rl_point;
985
986 if (rl_vi_domove (key, &c))
987 {
988 rl_ding ();
989 return -1;
990 }
991
992 /* These are the motion commands that do not require adjusting the
993 mark. c[wW] are handled by special-case code in rl_vi_domove(),
994 and already leave the mark at the correct location. */
995 if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
996 rl_mark++;
997
998 /* The cursor never moves with c[wW]. */
999 if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
1000 rl_point = start_pos;
1001
1002 if (vi_redoing)
1003 {
1004 if (vi_insert_buffer && *vi_insert_buffer)
1005 rl_begin_undo_group ();
1006 rl_delete_text (rl_point, rl_mark);
1007 if (vi_insert_buffer && *vi_insert_buffer)
1008 {
1009 rl_insert_text (vi_insert_buffer);
1010 rl_end_undo_group ();
1011 }
1012 }
1013 else
1014 {
1015 rl_begin_undo_group (); /* to make the `u' command work */
1016 rl_kill_text (rl_point, rl_mark);
1017 /* `C' does not save the text inserted for undoing or redoing. */
1018 if (_rl_uppercase_p (key) == 0)
1019 _rl_vi_doing_insert = 1;
1020 _rl_vi_set_last (key, count, rl_arg_sign);
1021 rl_vi_insertion_mode (1, key);
1022 }
1023
1024 return (0);
1025 }
1026
1027 int
1028 rl_vi_yank_to (count, key)
1029 int count, key;
1030 {
1031 int c, save = rl_point;
1032
1033 if (_rl_uppercase_p (key))
1034 rl_stuff_char ('$');
1035
1036 if (rl_vi_domove (key, &c))
1037 {
1038 rl_ding ();
1039 return -1;
1040 }
1041
1042 /* These are the motion commands that do not require adjusting the
1043 mark. */
1044 if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
1045 rl_mark++;
1046
1047 rl_begin_undo_group ();
1048 rl_kill_text (rl_point, rl_mark);
1049 rl_end_undo_group ();
1050 rl_do_undo ();
1051 rl_point = save;
1052
1053 return (0);
1054 }
1055
1056 int
1057 rl_vi_delete (count, key)
1058 int count, key;
1059 {
1060 int end;
1061
1062 if (rl_end == 0)
1063 {
1064 rl_ding ();
1065 return -1;
1066 }
1067
1068 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1069 end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
1070 else
1071 end = rl_point + count;
1072
1073 if (end >= rl_end)
1074 end = rl_end;
1075
1076 rl_kill_text (rl_point, end);
1077
1078 if (rl_point > 0 && rl_point == rl_end)
1079 rl_backward_char (1, key);
1080 return (0);
1081 }
1082
1083 int
1084 rl_vi_back_to_indent (count, key)
1085 int count, key;
1086 {
1087 rl_beg_of_line (1, key);
1088 while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
1089 rl_point++;
1090 return (0);
1091 }
1092
1093 int
1094 rl_vi_first_print (count, key)
1095 int count, key;
1096 {
1097 return (rl_vi_back_to_indent (1, key));
1098 }
1099
1100 int
1101 rl_vi_char_search (count, key)
1102 int count, key;
1103 {
1104 #if defined (HANDLE_MULTIBYTE)
1105 static char *target;
1106 static int mb_len;
1107 #else
1108 static char target;
1109 #endif
1110 static int orig_dir, dir;
1111
1112 if (key == ';' || key == ',')
1113 dir = key == ';' ? orig_dir : -orig_dir;
1114 else
1115 {
1116 if (vi_redoing)
1117 #if defined (HANDLE_MULTIBYTE)
1118 target = _rl_vi_last_search_mbchar;
1119 #else
1120 target = _rl_vi_last_search_char;
1121 #endif
1122 else
1123 {
1124 #if defined (HANDLE_MULTIBYTE)
1125 mb_len = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
1126 target = _rl_vi_last_search_mbchar;
1127 #else
1128 RL_SETSTATE(RL_STATE_MOREINPUT);
1129 _rl_vi_last_search_char = target = rl_read_key ();
1130 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1131 #endif
1132 }
1133
1134 switch (key)
1135 {
1136 case 't':
1137 orig_dir = dir = FTO;
1138 break;
1139
1140 case 'T':
1141 orig_dir = dir = BTO;
1142 break;
1143
1144 case 'f':
1145 orig_dir = dir = FFIND;
1146 break;
1147
1148 case 'F':
1149 orig_dir = dir = BFIND;
1150 break;
1151 }
1152 }
1153
1154 #if defined (HANDLE_MULTIBYTE)
1155 return (_rl_char_search_internal (count, dir, target, mb_len));
1156 #else
1157 return (_rl_char_search_internal (count, dir, target));
1158 #endif
1159 }
1160
1161 /* Match brackets */
1162 int
1163 rl_vi_match (ignore, key)
1164 int ignore, key;
1165 {
1166 int count = 1, brack, pos, tmp, pre;
1167
1168 pos = rl_point;
1169 if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1170 {
1171 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1172 {
1173 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
1174 {
1175 pre = rl_point;
1176 rl_forward_char (1, key);
1177 if (pre == rl_point)
1178 break;
1179 }
1180 }
1181 else
1182 while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
1183 rl_point < rl_end - 1)
1184 rl_forward_char (1, key);
1185
1186 if (brack <= 0)
1187 {
1188 rl_point = pos;
1189 rl_ding ();
1190 return -1;
1191 }
1192 }
1193
1194 pos = rl_point;
1195
1196 if (brack < 0)
1197 {
1198 while (count)
1199 {
1200 tmp = pos;
1201 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1202 pos--;
1203 else
1204 {
1205 pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
1206 if (tmp == pos)
1207 pos--;
1208 }
1209 if (pos >= 0)
1210 {
1211 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1212 if (b == -brack)
1213 count--;
1214 else if (b == brack)
1215 count++;
1216 }
1217 else
1218 {
1219 rl_ding ();
1220 return -1;
1221 }
1222 }
1223 }
1224 else
1225 { /* brack > 0 */
1226 while (count)
1227 {
1228 if (MB_CUR_MAX == 1 || rl_byte_oriented)
1229 pos++;
1230 else
1231 pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
1232
1233 if (pos < rl_end)
1234 {
1235 int b = rl_vi_bracktype (rl_line_buffer[pos]);
1236 if (b == -brack)
1237 count--;
1238 else if (b == brack)
1239 count++;
1240 }
1241 else
1242 {
1243 rl_ding ();
1244 return -1;
1245 }
1246 }
1247 }
1248 rl_point = pos;
1249 return (0);
1250 }
1251
1252 int
1253 rl_vi_bracktype (c)
1254 int c;
1255 {
1256 switch (c)
1257 {
1258 case '(': return 1;
1259 case ')': return -1;
1260 case '[': return 2;
1261 case ']': return -2;
1262 case '{': return 3;
1263 case '}': return -3;
1264 default: return 0;
1265 }
1266 }
1267
1268 /* XXX - think about reading an entire mbchar with _rl_read_mbchar and
1269 inserting it in one bunch instead of the loop below (like in
1270 rl_vi_char_search or _rl_vi_change_mbchar_case. Set c to mbchar[0]
1271 for test against 033 or ^C. Make sure that _rl_read_mbchar does
1272 this right. */
1273 int
1274 rl_vi_change_char (count, key)
1275 int count, key;
1276 {
1277 int c;
1278
1279 if (vi_redoing)
1280 c = _rl_vi_last_replacement;
1281 else
1282 {
1283 RL_SETSTATE(RL_STATE_MOREINPUT);
1284 _rl_vi_last_replacement = c = rl_read_key ();
1285 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1286 }
1287
1288 if (c == '\033' || c == CTRL ('C'))
1289 return -1;
1290
1291 while (count-- && rl_point < rl_end)
1292 {
1293 rl_begin_undo_group ();
1294
1295 rl_delete (1, c);
1296 #if defined (HANDLE_MULTIBYTE)
1297 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1298 while (_rl_insert_char (1, c))
1299 {
1300 RL_SETSTATE (RL_STATE_MOREINPUT);
1301 c = rl_read_key ();
1302 RL_UNSETSTATE (RL_STATE_MOREINPUT);
1303 }
1304 else
1305 #endif
1306 _rl_insert_char (1, c);
1307 if (count == 0)
1308 rl_backward_char (1, c);
1309
1310 rl_end_undo_group ();
1311 }
1312 return (0);
1313 }
1314
1315 int
1316 rl_vi_subst (count, key)
1317 int count, key;
1318 {
1319 /* If we are redoing, rl_vi_change_to will stuff the last motion char */
1320 if (vi_redoing == 0)
1321 rl_stuff_char ((key == 'S') ? 'c' : ' '); /* `S' == `cc', `s' == `c ' */
1322
1323 return (rl_vi_change_to (count, 'c'));
1324 }
1325
1326 int
1327 rl_vi_overstrike (count, key)
1328 int count, key;
1329 {
1330 if (_rl_vi_doing_insert == 0)
1331 {
1332 _rl_vi_doing_insert = 1;
1333 rl_begin_undo_group ();
1334 }
1335
1336 if (count > 0)
1337 {
1338 _rl_overwrite_char (count, key);
1339 vi_replace_count += count;
1340 }
1341
1342 return (0);
1343 }
1344
1345 int
1346 rl_vi_overstrike_delete (count, key)
1347 int count, key;
1348 {
1349 int i, s;
1350
1351 for (i = 0; i < count; i++)
1352 {
1353 if (vi_replace_count == 0)
1354 {
1355 rl_ding ();
1356 break;
1357 }
1358 s = rl_point;
1359
1360 if (rl_do_undo ())
1361 vi_replace_count--;
1362
1363 if (rl_point == s)
1364 rl_backward_char (1, key);
1365 }
1366
1367 if (vi_replace_count == 0 && _rl_vi_doing_insert)
1368 {
1369 rl_end_undo_group ();
1370 rl_do_undo ();
1371 _rl_vi_doing_insert = 0;
1372 }
1373 return (0);
1374 }
1375
1376 int
1377 rl_vi_replace (count, key)
1378 int count, key;
1379 {
1380 int i;
1381
1382 vi_replace_count = 0;
1383
1384 if (!vi_replace_map)
1385 {
1386 vi_replace_map = rl_make_bare_keymap ();
1387
1388 for (i = ' '; i < KEYMAP_SIZE; i++)
1389 vi_replace_map[i].function = rl_vi_overstrike;
1390
1391 vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
1392 vi_replace_map[ESC].function = rl_vi_movement_mode;
1393 vi_replace_map[RETURN].function = rl_newline;
1394 vi_replace_map[NEWLINE].function = rl_newline;
1395
1396 /* If the normal vi insertion keymap has ^H bound to erase, do the
1397 same here. Probably should remove the assignment to RUBOUT up
1398 there, but I don't think it will make a difference in real life. */
1399 if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
1400 vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
1401 vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
1402
1403 }
1404 _rl_keymap = vi_replace_map;
1405 return (0);
1406 }
1407
1408 #if 0
1409 /* Try to complete the word we are standing on or the word that ends with
1410 the previous character. A space matches everything. Word delimiters are
1411 space and ;. */
1412 int
1413 rl_vi_possible_completions()
1414 {
1415 int save_pos = rl_point;
1416
1417 if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
1418 {
1419 while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
1420 rl_line_buffer[rl_point] != ';')
1421 rl_point++;
1422 }
1423 else if (rl_line_buffer[rl_point - 1] == ';')
1424 {
1425 rl_ding ();
1426 return (0);
1427 }
1428
1429 rl_possible_completions ();
1430 rl_point = save_pos;
1431
1432 return (0);
1433 }
1434 #endif
1435
1436 /* Functions to save and restore marks. */
1437 int
1438 rl_vi_set_mark (count, key)
1439 int count, key;
1440 {
1441 int ch;
1442
1443 RL_SETSTATE(RL_STATE_MOREINPUT);
1444 ch = rl_read_key ();
1445 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1446
1447 if (ch < 'a' || ch > 'z')
1448 {
1449 rl_ding ();
1450 return -1;
1451 }
1452 ch -= 'a';
1453 vi_mark_chars[ch] = rl_point;
1454 return 0;
1455 }
1456
1457 int
1458 rl_vi_goto_mark (count, key)
1459 int count, key;
1460 {
1461 int ch;
1462
1463 RL_SETSTATE(RL_STATE_MOREINPUT);
1464 ch = rl_read_key ();
1465 RL_UNSETSTATE(RL_STATE_MOREINPUT);
1466
1467 if (ch == '`')
1468 {
1469 rl_point = rl_mark;
1470 return 0;
1471 }
1472 else if (ch < 'a' || ch > 'z')
1473 {
1474 rl_ding ();
1475 return -1;
1476 }
1477
1478 ch -= 'a';
1479 if (vi_mark_chars[ch] == -1)
1480 {
1481 rl_ding ();
1482 return -1;
1483 }
1484 rl_point = vi_mark_chars[ch];
1485 return 0;
1486 }
1487
1488 #endif /* VI_MODE */
This page took 0.061592 seconds and 4 git commands to generate.