home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / gdb / readline / vi_mode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  14.8 KB  |  876 lines

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