1 /* vi_mode.c -- A vi emulation mode for Bash.
2 
3    Derived from code written by Jeff Sparkes (jeff1@????).
4  */
5 
6 
7 /* **************************************************************** */
8 /*								    */
9 /*			VI Emulation Mode			    */
10 /*								    */
11 /* **************************************************************** */
12 
13 /* Last string searched for from `/' or `?'. */
14 static char *vi_last_search = (char *)NULL;
15 static int vi_histpos;
16 
17 /* Non-zero means enter insertion mode. */
18 int vi_doing_insert = 0;
19 
20 /* *** UNCLEAN *** */
21 /* Command keys which do movement for xxx_to commands. */
22 static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
23 
24 /* Keymap used for vi replace characters.  Created dynamically since
25    rarely used. */
26 static Keymap vi_replace_map = (Keymap)NULL;
27 
28 /* The number of characters inserted in the last replace operation. */
29 static vi_replace_count = 0;
30 
31 /* Yank the nth arg from the previous line into this line at point. */
rl_vi_yank_arg(count)32 rl_vi_yank_arg (count)
33      int count;
34 {
35   rl_yank_nth_arg (count, 0);
36 }
37 
38 /* Search again for the last thing searched for. */
rl_vi_search_again(ignore,key)39 rl_vi_search_again (ignore, key)
40      int ignore, key;
41 {
42   switch (key)
43     {
44     case 'n':
45       rl_vi_dosearch (vi_last_search, -1);
46       break;
47 
48     case 'N':
49       rl_vi_dosearch (vi_last_search, 1);
50       break;
51     }
52 }
53 
54 /* Do a vi style search. */
rl_vi_search(count,key)55 rl_vi_search (count, key)
56      int count, key;
57 {
58   int dir, c, save_pos;
59   char *p;
60 
61   switch (key)
62     {
63     case '?':
64       dir = 1;
65       break;
66 
67     case '/':
68       dir = -1;
69       break;
70 
71     default:
72       ding ();
73       return;
74     }
75 
76   vi_histpos = where_history ();
77   maybe_save_line ();
78   save_pos = rl_point;
79 
80   /* Reuse the line input buffer to read the search string. */
81   the_line[0] = 0;
82   rl_end = rl_point = 0;
83   p = (char *)alloca (2 + (rl_prompt ? strlen (rl_prompt) : 0));
84 
85   sprintf (p, "%s%c", rl_prompt ? rl_prompt : "", key);
86 
87   rl_message (p, 0, 0);
88 
89   while (c = rl_read_key ())
90     {
91       switch (c)
92 	{
93 	case CTRL('H'):
94 	case RUBOUT:
95 	  if (rl_point == 0)
96 	    {
97 	      maybe_unsave_line ();
98 	      rl_clear_message ();
99 	      rl_point = save_pos;
100 	      return;
101 	    }
102 
103 	case CTRL('W'):
104 	case CTRL('U'):
105 	  rl_dispatch (c, keymap);
106 	  break;
107 
108 	case ESC:
109 	case RETURN:
110 	case NEWLINE:
111 	  goto dosearch;
112 	  break;
113 
114 	case CTRL('C'):
115 	  maybe_unsave_line ();
116 	  rl_clear_message ();
117 	  rl_point = 0;
118 	  ding ();
119 	  return;
120 
121 	default:
122 	  rl_insert (1, c);
123 	  break;
124 	}
125       rl_redisplay ();
126     }
127  dosearch:
128   if (vi_last_search)
129     free (vi_last_search);
130 
131   vi_last_search = savestring (the_line);
132   rl_vi_dosearch (the_line, dir);
133 }
134 
rl_vi_dosearch(string,dir)135 rl_vi_dosearch (string, dir)
136      char *string;
137      int dir;
138 {
139   int old, save = vi_histpos;
140   HIST_ENTRY *h;
141 
142   if (string == 0 || *string == 0 || vi_histpos < 0)
143     {
144       ding ();
145       return;
146     }
147 
148   if ((save = history_search_pos (string, dir, vi_histpos + dir)) == -1)
149     {
150       maybe_unsave_line ();
151       rl_clear_message ();
152       rl_point = 0;
153       ding ();
154       return;
155     }
156 
157   vi_histpos = save;
158 
159   old = where_history ();
160   history_set_pos (vi_histpos);
161   h = current_history ();
162   history_set_pos (old);
163 
164   strcpy (the_line, h->line);
165   rl_undo_list = (UNDO_LIST *)h->data;
166   rl_end = strlen (the_line);
167   rl_point = 0;
168   rl_clear_message ();
169 }
170 
171 /* Completion, from vi's point of view. */
rl_vi_complete(ignore,key)172 rl_vi_complete (ignore, key)
173      int ignore, key;
174 {
175   if ((rl_point < rl_end) && (!whitespace (the_line[rl_point])))
176     {
177       if (!whitespace (the_line[rl_point + 1]))
178 	rl_vi_end_word (1, 'E');
179       rl_point++;
180     }
181 
182   if (key == '*')
183     rl_complete_internal ('*');
184   else
185     rl_complete (0, key);
186 
187   rl_vi_insertion_mode ();
188 }
189 
190 /* Previous word in vi mode. */
rl_vi_prev_word(count,key)191 rl_vi_prev_word (count, key)
192      int count, key;
193 {
194   if (count < 0)
195     {
196       rl_vi_next_word (-count, key);
197       return;
198     }
199 
200   if (uppercase_p (key))
201     rl_vi_bWord (count);
202   else
203     rl_vi_bword (count);
204 }
205 
206 /* Next word in vi mode. */
rl_vi_next_word(count,key)207 rl_vi_next_word (count, key)
208      int count;
209 {
210   if (count < 0)
211     {
212       rl_vi_prev_word (-count, key);
213       return;
214     }
215 
216   if (uppercase_p (key))
217     rl_vi_fWord (count);
218   else
219     rl_vi_fword (count);
220 }
221 
222 /* Move to the end of the ?next? word. */
rl_vi_end_word(count,key)223 rl_vi_end_word (count, key)
224      int count, key;
225 {
226   if (count < 0)
227     {
228       ding ();
229       return;
230     }
231 
232   if (uppercase_p (key))
233     rl_vi_eWord (count);
234   else
235     rl_vi_eword (count);
236 }
237 
238 /* Move forward a word the way that 'W' does. */
239 /* Move forward a word the way that 'W' does. */
rl_vi_fWord(count)240 rl_vi_fWord (count)
241      int count;
242 {
243   while (count-- && rl_point < (rl_end - 1))
244     {
245       /* Skip until whitespace. */
246       while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
247         rl_point++;
248 
249       /* Now skip whitespace. */
250       while (whitespace (the_line[rl_point]) && rl_point < rl_end)
251         rl_point++;
252     }
253 }
254 
rl_vi_bWord(count)255 rl_vi_bWord (count)
256      int count;
257 {
258   while (count-- && rl_point > 0)
259     {
260       /* If we are at the start of a word, move back to whitespace so
261          we will go back to the start of the previous word. */
262       if (!whitespace (the_line[rl_point]) &&
263           whitespace (the_line[rl_point - 1]))
264         rl_point--;
265 
266       while (rl_point > 0 && whitespace (the_line[rl_point]))
267         rl_point--;
268 
269       if (rl_point > 0)
270         {
271           while (--rl_point >= 0 && !whitespace (the_line[rl_point]));
272           rl_point++;
273         }
274     }
275 }
276 
rl_vi_eWord(count)277 rl_vi_eWord (count)
278      int count;
279 {
280   while (count-- && rl_point < (rl_end - 1))
281     {
282       /* Move to white space. */
283       while (++rl_point < rl_end && whitespace (the_line[rl_point]))
284         ;
285 
286       if (rl_point && rl_point < rl_end)
287         {
288           /* Skip whitespace. */
289           while (rl_point < rl_end && whitespace (the_line[rl_point]))
290             rl_point++;
291 
292           /* Skip until whitespace. */
293           while (rl_point < rl_end && !whitespace (the_line[rl_point]))
294             rl_point++;
295 
296           /* Move back to the last character of the word. */
297           rl_point--;
298         }
299     }
300 }
301 
rl_vi_fword(count)302 rl_vi_fword (count)
303      int count;
304 {
305   while (count-- && rl_point < (rl_end - 1))
306     {
307       /* Move to white space (really non-identifer). */
308       if (isident (the_line[rl_point]))
309         {
310           while (isident (the_line[rl_point]) && rl_point < rl_end)
311             rl_point++;
312         }
313       else /* if (!whitespace (the_line[rl_point])) */
314         {
315           while (!isident (the_line[rl_point]) &&
316                  !whitespace (the_line[rl_point]) && rl_point < rl_end)
317             rl_point++;
318         }
319 
320       /* Move past whitespace. */
321       while (whitespace (the_line[rl_point]) && rl_point < rl_end)
322         rl_point++;
323     }
324 }
325 
rl_vi_bword(count)326 rl_vi_bword (count)
327      int count;
328 {
329   while (count-- && rl_point > 0)
330     {
331       int last_is_ident;
332 
333       /* If we are at the start of a word, move back to a non-identifier
334          so we will go back to the start of the previous word. */
335       if (isident (the_line[rl_point]) && !isident (the_line[rl_point - 1]))
336         rl_point--;
337 
338       /* If this character and the previous character are `opposite', move
339          back so we don't get messed up by the rl_point++ down there in
340          the while loop.  Without this code, words like `l;' screw up the
341          function. */
342       last_is_ident = isident (the_line[rl_point - 1]);
343       if ((isident (the_line[rl_point]) && !last_is_ident) ||
344           (!isident (the_line[rl_point]) && last_is_ident))
345         rl_point--;
346 
347       while (rl_point > 0 && whitespace (the_line[rl_point]))
348         rl_point--;
349 
350       if (rl_point > 0)
351         {
352           if (isident (the_line[rl_point]))
353             while (--rl_point >= 0 && isident (the_line[rl_point]));
354           else
355             while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
356                    !whitespace (the_line[rl_point]));
357           rl_point++;
358         }
359     }
360 }
361 
rl_vi_eword(count)362 rl_vi_eword (count)
363      int count;
364 {
365   while (count-- && rl_point < rl_end - 1)
366     {
367       while (++rl_point < rl_end && whitespace (the_line[rl_point]))
368         ;
369 
370       if (rl_point < rl_end)
371         {
372           if (isident (the_line[rl_point]))
373             while (++rl_point < rl_end && isident (the_line[rl_point]));
374           else
375             while (++rl_point < rl_end && !isident (the_line[rl_point])
376                    && !whitespace (the_line[rl_point]));
377           rl_point--;
378         }
379     }
380 }
381 
rl_vi_insert_beg()382 rl_vi_insert_beg ()
383 {
384   rl_beg_of_line ();
385   rl_vi_insertion_mode ();
386   return 0;
387 }
388 
rl_vi_append_mode()389 rl_vi_append_mode ()
390 {
391   if (rl_point < rl_end)
392     rl_point += 1;
393   rl_vi_insertion_mode ();
394   return 0;
395 }
396 
rl_vi_append_eol()397 rl_vi_append_eol ()
398 {
399   rl_end_of_line ();
400   rl_vi_append_mode ();
401   return 0;
402 }
403 
404 /* What to do in the case of C-d. */
rl_vi_eof_maybe(count,c)405 rl_vi_eof_maybe (count, c)
406      int count, c;
407 {
408   rl_newline (1, '\n');
409 }
410 
411 /* Insertion mode stuff. */
412 
413 /* Switching from one mode to the other really just involves
414    switching keymaps. */
rl_vi_insertion_mode()415 rl_vi_insertion_mode ()
416 {
417   keymap = vi_insertion_keymap;
418 }
419 
rl_vi_movement_mode()420 rl_vi_movement_mode ()
421 {
422   if (rl_point > 0)
423     rl_backward (1);
424 
425   keymap = vi_movement_keymap;
426   vi_done_inserting ();
427 }
428 
vi_done_inserting()429 vi_done_inserting ()
430 {
431   if (vi_doing_insert)
432     {
433       rl_end_undo_group ();
434       vi_doing_insert = 0;
435     }
436 }
437 
rl_vi_arg_digit(count,c)438 rl_vi_arg_digit (count, c)
439      int count, c;
440 {
441   if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
442     rl_beg_of_line ();
443   else
444     rl_digit_argument (count, c);
445 }
446 
447 /* Doesn't take an arg count in vi */
rl_vi_change_case(ignore1,ignore2)448 rl_vi_change_case (ignore1, ignore2)
449      int ignore1, ignore2;
450 {
451   char c = 0;
452 
453   /* Don't try this on an empty line. */
454   if (rl_point >= rl_end - 1)
455     return;
456 
457   if (uppercase_p (the_line[rl_point]))
458     c = to_lower (the_line[rl_point]);
459   else if (lowercase_p (the_line[rl_point]))
460     c = to_upper (the_line[rl_point]);
461 
462   /* Vi is kind of strange here. */
463   if (c)
464     {
465       rl_begin_undo_group ();
466       rl_delete (1, c);
467       rl_insert (1, c);
468       rl_end_undo_group ();
469       rl_vi_check ();
470     }
471   else
472     rl_forward (1);
473 }
474 
rl_vi_put(count,key)475 rl_vi_put (count, key)
476      int count, key;
477 {
478   if (!uppercase_p (key) && (rl_point + 1 <= rl_end))
479     rl_forward (1);
480 
481   rl_yank ();
482   rl_backward (1);
483 }
484 
rl_vi_check()485 rl_vi_check ()
486 {
487   if (rl_point && rl_point == rl_end)
488     rl_point--;
489 }
490 
rl_vi_column(count)491 rl_vi_column (count)
492 {
493   if (count > rl_end)
494     rl_end_of_line ();
495   else
496     rl_point = count - 1;
497 }
498 
499 int
rl_vi_domove(key,nextkey)500 rl_vi_domove (key, nextkey)
501      int key, *nextkey;
502 {
503   int c, save;
504 
505   rl_mark = rl_point;
506   c = rl_read_key ();
507   *nextkey = c;
508 
509   if (!member (c, vi_motion))
510     {
511       if (digit (c))
512 	{
513 	  save = rl_numeric_arg;
514 	  rl_digit_loop1 ();
515 	  rl_numeric_arg *= save;
516 	}
517       else if ((key == 'd' && c == 'd') ||
518 	       (key == 'c' && c == 'c'))
519 	{
520 	  rl_mark = rl_end;
521 	  rl_beg_of_line ();
522 	  return (0);
523 	}
524       else
525 	return (-1);
526     }
527 
528   rl_dispatch (c, keymap);
529 
530   /* No change in position means the command failed. */
531   if (rl_mark == rl_point)
532     return (-1);
533 
534   if ((c == 'w' || c == 'W') && rl_point < rl_end)
535     rl_point--;
536 
537   if (rl_mark < rl_point)
538     exchange (rl_point, rl_mark);
539 
540   return (0);
541 }
542 
543 /* A simplified loop for vi. Don't dispatch key at end.
544    Don't recognize minus sign? */
rl_digit_loop1()545 rl_digit_loop1 ()
546 {
547   int key, c;
548 
549   while (1)
550     {
551       rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg, 0);
552       key = c = rl_read_key ();
553 
554       if (keymap[c].type == ISFUNC &&
555 	  keymap[c].function == rl_universal_argument)
556 	{
557 	  rl_numeric_arg *= 4;
558 	  continue;
559 	}
560 
561       c = UNMETA (c);
562       if (numeric (c))
563 	{
564 	  if (rl_explicit_arg)
565 	    rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
566 	  else
567 	    rl_numeric_arg = (c - '0');
568 	  rl_explicit_arg = 1;
569 	}
570       else
571 	{
572 	  rl_clear_message ();
573 	  rl_stuff_char (key);
574 	  break;
575 	}
576     }
577 }
578 
rl_vi_delete_to(count,key)579 rl_vi_delete_to (count, key)
580      int count, key;
581 {
582   int c;
583 
584   if (uppercase_p (key))
585     rl_stuff_char ('$');
586 
587   if (rl_vi_domove (key, &c))
588     {
589       ding ();
590       return;
591     }
592 
593   if ((c != '|') && (c != 'h') && rl_mark < rl_end)
594     rl_mark++;
595 
596   rl_kill_text (rl_point, rl_mark);
597 }
598 
rl_vi_change_to(count,key)599 rl_vi_change_to (count, key)
600      int count, key;
601 {
602   int c;
603 
604   if (uppercase_p (key))
605     rl_stuff_char ('$');
606 
607   if (rl_vi_domove (key, &c))
608     {
609       ding ();
610       return;
611     }
612 
613   if ((c != '|') && (c != 'h') && rl_mark < rl_end)
614     rl_mark++;
615 
616   rl_begin_undo_group ();
617   vi_doing_insert = 1;
618   rl_kill_text (rl_point, rl_mark);
619   rl_vi_insertion_mode ();
620 }
621 
rl_vi_yank_to(count,key)622 rl_vi_yank_to (count, key)
623      int count, key;
624 {
625   int c, save = rl_point;
626 
627   if (uppercase_p (key))
628     rl_stuff_char ('$');
629 
630   if (rl_vi_domove (key, &c))
631     {
632       ding ();
633       return;
634     }
635 
636   rl_begin_undo_group ();
637   rl_kill_text (rl_point, rl_mark);
638   rl_end_undo_group ();
639   rl_do_undo ();
640   rl_point = save;
641 }
642 
rl_vi_delete(count)643 rl_vi_delete (count)
644 {
645   int end;
646 
647   if (rl_end == 0)
648     {
649       ding ();
650       return;
651     }
652 
653   end = rl_point + count;
654 
655   if (end >= rl_end)
656     end = rl_end;
657 
658   rl_kill_text (rl_point, end);
659 
660   if (rl_point > 0 && rl_point == rl_end)
661     rl_backward (1);
662 }
663 
664 /* Turn the current line into a comment in shell history.
665    A K*rn shell style function. */
rl_vi_comment()666 rl_vi_comment ()
667 {
668   rl_beg_of_line ();
669   rl_insert_text (": ");	/* `#' doesn't work in interactive mode */
670   rl_redisplay ();
671   rl_newline (1, '\010');
672 }
673 
rl_vi_first_print()674 rl_vi_first_print ()
675 {
676   rl_back_to_indent ();
677 }
678 
rl_back_to_indent(ignore1,ignore2)679 rl_back_to_indent (ignore1, ignore2)
680      int ignore1, ignore2;
681 {
682   rl_beg_of_line ();
683   while (rl_point < rl_end && whitespace (the_line[rl_point]))
684     rl_point++;
685 }
686 
687 /* NOTE: it is necessary that opposite directions are inverses */
688 #define	FTO	 1		/* forward to */
689 #define BTO	-1		/* backward to */
690 #define FFIND	 2		/* forward find */
691 #define BFIND	-2		/* backward find */
692 
rl_vi_char_search(count,key)693 rl_vi_char_search (count, key)
694      int count, key;
695 {
696   static char target;
697   static int orig_dir, dir;
698   int pos;
699 
700   if (key == ';' || key == ',')
701     dir = (key == ';' ? orig_dir : -orig_dir);
702   else
703     {
704       target = rl_getc (in_stream);
705 
706       switch (key)
707 	{
708 	case 't':
709 	  orig_dir = dir = FTO;
710 	  break;
711 
712 	case 'T':
713 	  orig_dir = dir = BTO;
714 	  break;
715 
716 	case 'f':
717 	  orig_dir = dir = FFIND;
718 	  break;
719 
720 	case 'F':
721 	  orig_dir = dir = BFIND;
722 	  break;
723 	}
724     }
725 
726   pos = rl_point;
727 
728   if (dir < 0)
729     {
730       pos--;
731       do
732 	{
733 	  if (the_line[pos] == target)
734 	    {
735 	      if (dir == BTO)
736 		rl_point = pos + 1;
737 	      else
738 		rl_point = pos;
739 	      return;
740 	    }
741 	}
742       while (pos--);
743 
744       if (pos < 0)
745 	{
746 	  ding ();
747 	  return;
748 	}
749     }
750   else
751     {			/* dir > 0 */
752       pos++;
753       do
754 	{
755 	  if (the_line[pos] == target)
756 	    {
757 	      if (dir == FTO)
758 		rl_point = pos - 1;
759 	      else
760 		rl_point = pos;
761 	      return;
762 	    }
763 	}
764       while (++pos < rl_end);
765 
766       if (pos >= (rl_end - 1))
767 	ding ();
768     }
769 }
770 
771 /* Match brackets */
rl_vi_match()772 rl_vi_match ()
773 {
774   int count = 1, brack, pos;
775 
776   pos = rl_point;
777   if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0)
778     {
779       while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
780 	     rl_point < rl_end - 1)
781 	rl_forward (1);
782 
783       if (brack <= 0)
784 	{
785 	  rl_point = pos;
786 	  ding ();
787 	  return;
788 	}
789     }
790 
791   pos = rl_point;
792 
793   if (brack < 0)
794     {
795       while (count)
796 	{
797 	  if (--pos >= 0)
798 	    {
799 	      int b = rl_vi_bracktype (the_line[pos]);
800 	      if (b == -brack)
801 		count--;
802 	      else if (b == brack)
803 		count++;
804 	    }
805 	  else
806 	    {
807 	      ding ();
808 	      return;
809 	    }
810 	}
811     }
812   else
813     {			/* brack > 0 */
814       while (count)
815 	{
816 	  if (++pos < rl_end)
817 	    {
818 	      int b = rl_vi_bracktype (the_line[pos]);
819 	      if (b == -brack)
820 		count--;
821 	      else if (b == brack)
822 		count++;
823 	    }
824 	  else
825 	    {
826 	      ding ();
827 	      return;
828 	    }
829 	}
830     }
831   rl_point = pos;
832 }
833 
834 int
rl_vi_bracktype(c)835 rl_vi_bracktype (c)
836      int c;
837 {
838   switch (c)
839     {
840     case '(': return  1;
841     case ')': return -1;
842     case '[': return  2;
843     case ']': return -2;
844     case '{': return  3;
845     case '}': return -3;
846     default:  return  0;
847     }
848 }
849 
rl_vi_change_char()850 rl_vi_change_char ()
851 {
852   int c;
853 
854   c = rl_getc (in_stream);
855 
856   switch (c)
857     {
858     case '\033':
859     case CTRL('C'):
860       return;
861 
862     default:
863       rl_begin_undo_group ();
864       rl_delete (1, c);
865       rl_insert (1, c);
866       rl_end_undo_group ();
867       break;
868     }
869 }
870 
rl_vi_subst(count,key)871 rl_vi_subst (count, key)
872      int count, key;
873 {
874   rl_begin_undo_group ();
875   vi_doing_insert = 1;
876 
877   if (uppercase_p (key))
878     {
879       rl_beg_of_line ();
880       rl_kill_line (1);
881     }
882   else
883     rl_delete (count, key);
884 
885   rl_vi_insertion_mode ();
886 }
887 
rl_vi_overstrike(count,key)888 rl_vi_overstrike (count, key)
889      int count, key;
890 {
891   int i;
892 
893   if (vi_doing_insert == 0)
894     {
895       vi_doing_insert = 1;
896       rl_begin_undo_group ();
897     }
898 
899   for (i = 0; i < count; i++)
900     {
901       vi_replace_count++;
902       rl_begin_undo_group ();
903 
904       if (rl_point < rl_end)
905 	{
906 	  rl_delete (1, key);
907 	  rl_insert (1, key);
908 	}
909       else
910 	rl_insert (1, key);
911 
912       rl_end_undo_group ();
913     }
914 }
915 
rl_vi_overstrike_delete(count)916 rl_vi_overstrike_delete (count)
917      int count;
918 {
919   int i, s;
920 
921   for (i = 0; i < count; i++)
922     {
923       if (vi_replace_count == 0)
924 	{
925 	  ding ();
926 	  break;
927 	}
928       s = rl_point;
929 
930       if (rl_do_undo ())
931 	vi_replace_count--;
932 
933       if (rl_point == s)
934 	rl_backward (1);
935     }
936 
937   if (vi_replace_count == 0 && vi_doing_insert)
938     {
939       rl_end_undo_group ();
940       rl_do_undo ();
941       vi_doing_insert = 0;
942     }
943 }
944 
rl_vi_replace()945 rl_vi_replace ()
946 {
947   int i;
948 
949   vi_replace_count = 0;
950 
951   vi_replace_map = rl_make_bare_keymap ();
952 
953   for (i = ' '; i < 127; i++)
954     vi_replace_map[i].function = rl_vi_overstrike;
955 
956   vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
957   vi_replace_map[ESC].function = rl_vi_movement_mode;
958   vi_replace_map[RETURN].function = rl_newline;
959   vi_replace_map[NEWLINE].function = rl_newline;
960   keymap = vi_replace_map;
961 }
962 
963 /*
964  * Try to complete the word we are standing on or the word that ends with
965  * the previous character. A space matches everything.
966  * Word delimiters are space and ;.
967  */
rl_vi_possible_completions()968 rl_vi_possible_completions()
969 {
970   int save_pos = rl_point;
971 
972   if (!index (" ;", the_line[rl_point]))
973     {
974       while (!index(" ;", the_line[++rl_point]))
975 	;
976     }
977   else if (the_line[rl_point-1] == ';')
978     {
979       ding ();
980       return (0);
981     }
982 
983   rl_possible_completions ();
984   rl_point = save_pos;
985 
986   return (0);
987 }
988