[gnu.bash.bug] enhancements for vi

jeff1@stretch.MUN.EDU (Jeff Sparkes) (09/12/89)

Here are the diffs for a much enhanced vi mode.  It is fairly complete;
let me know if I've missed something.

Here are some of the current problems:
	- "*" only does completion, not expansion.  Readline is not 
	  well set up to make emacs do it one way, and vi the other.
	- "." isn't implemented.  I'll get to it later this week. I wanted 
	  to get these diffs out before too many changes were made to bash.
	- undo is emacs like. Undoing twice doesn't get the original line
	  back.  The cursor is also left in the wrong position.

P.S.  Brian, please let me know any troubles with this.  I'd really like
to get it into the mainstream bash.

Only in ./readline: .emacs_jeff1
Only in ./readline: TODO
Only in ./readline: TODO~
Only in ./readline: funmap.o
diff -rc ../b3/readline/history.c ./readline/history.c
*** ../b3/readline/history.c	Thu Aug 31 18:40:07 1989
--- ./readline/history.c	Wed Sep  6 11:25:18 1989
***************
*** 263,269 ****
  	index--;
        }
      } else {
!       register int limit = (string_len - index) + 1;
        index = 0;
  
        while (index < limit) {
--- 263,269 ----
  	index--;
        }
      } else {
!       register int limit = (index - string_len) + 1;
        index = 0;
  
        while (index < limit) {
***************
*** 282,287 ****
--- 282,316 ----
    }
  }
  
+ /* Make searching a little saner.  Allows searching to take place from
+    any position in the history list.  This avoids the copying of the list
+    that takes place in readline. */
+ int
+ history_search_pos (string, dir, pos)
+      char *string;
+      int dir, pos;
+ {
+   int ret, old = where_history ();
+   history_set_pos (pos);
+   if (history_search (string, dir) == -1) {
+     history_set_pos (old);
+     return -1;
+   }
+   ret = where_history ();
+   history_set_pos (old);
+   return ret;
+ }
+ 
+ HIST_ENTRY *
+ history_set_pos (pos)
+      int pos;
+ {
+   if (pos > history_length || pos < 0 || !the_history)
+     return 0;
+   history_offset = pos;
+   return current_history ();
+ }
+  
  /* Remove history element WHICH from the history.  The removed
     element is returned to you so you can free the line, data,
     and containing structure. */
Only in ./readline: history.c~
diff -rc ../b3/readline/history.h ./readline/history.h
*** ../b3/readline/history.h	Thu Jun 29 22:58:07 1989
--- ./readline/history.h	Wed Sep  6 09:40:41 1989
***************
*** 21,26 ****
--- 21,29 ----
     looking at.  */
  extern int where_history ();
  
+ /* Set the position in the history list and return that element. */
+ extern HIST_ENTRY *history_set_pos ();
+    
  /* A reasonably useless function, only here for completeness.  WHICH
     is the magic number that tells us which element to delete.  The
     elements are numbered from 0. */
***************
*** 76,81 ****
--- 79,89 ----
     is the offset in the line of that history entry that the string was
     found in.  Otherwise, nothing is changed, and a -1 is returned. */
  extern int history_search ();
+ 
+ /* Start a history search for STRING in DIRECTION, starting at POS,
+    returning the position in the history where string was found,
+    -1 otherwise. */
+ extern int history_search_pos ();
  
  /* Expand the string STRING, placing the result into OUTPUT, a pointer
     to a string.  Returns:
Only in ./readline: history.h~
Only in ./readline: history.o
Only in ./readline: keymaps.o
Only in ./readline: libreadline.a
diff -rc ../b3/readline/readline.c ./readline/readline.c
*** ../b3/readline/readline.c	Fri Sep  1 13:28:33 1989
--- ./readline/readline.c	Fri Sep  8 14:27:46 1989
***************
*** 98,103 ****
--- 98,110 ----
  #define member(c, s) ((c) ? index ((s), (c)) : 0)
  #endif
  
+ #ifndef isident
+ #define isident(c) ((isletter(c) || digit(c) || c == '_'))
+ #endif
+ 
+ #ifndef exchange
+ #define exchange(x, y) ({int _t_; _t_ = x; x = y; y = _t_;})
+ #endif
  static update_line ();
  static void output_character_function ();
  static delete_chars ();
***************
*** 155,160 ****
--- 162,168 ----
  
  /* The current offset in the current input line. */
  int rl_point;
+ int rl_mark;
  
  /* Length of the current input line. */
  int rl_end;
***************
*** 165,170 ****
--- 173,194 ----
  /* The last function executed by readline. */
  Function *rl_last_func = (Function *)NULL;
  
+ /* Last string searched for in vi mode. */
+ static char *rl_vi_last_search = 0;
+ static int rl_vi_histpos;
+ 
+ /* A vi command that goes into insert mode uses this */
+ static int rl_vi_doing_insert = 0;
+ 
+ /* Command keys which do movement for xxx_to commands. */
+ static char *rl_vi_motion = " hl^$0ftFt;,%wbeWBE|";
+ 
+ /* Keymap used for replace.  Created dynamically since it is rarely used. */
+ static Keymap rl_vi_replace_map;
+ 
+ /* Number of characters inserted in the current replace operation. */
+ static int rl_vi_replace_count;
+ 
  /* Top level environment for readline_internal (). */
  static jmp_buf readline_top_level;
  
***************
*** 418,423 ****
--- 442,449 ----
  	  if (lk == last_command_was_kill)
  	    last_command_was_kill = 0;
  	}
+       if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap)
+ 	rl_vi_check ();
        if (!rl_done)
  	rl_redisplay ();
      }
***************
*** 599,605 ****
  rl_dispatch (key)
       register int key;
  {
!   if (keymap[key]) (*keymap[key])(rl_numeric_arg * arg_sign, key);
    else ding ();
  
    /* If we have input pending, then the last command was a prefix
--- 625,632 ----
  rl_dispatch (key)
       register int key;
  {
!   int ret = -1;
!   if (keymap[key]) ret = (*keymap[key])(rl_numeric_arg * arg_sign, key);
    else ding ();
  
    /* If we have input pending, then the last command was a prefix
***************
*** 606,611 ****
--- 633,639 ----
       command.  Don't change the state of rl_last_func. */
    if (!rl_pending_input)
      rl_last_func = keymap[key];
+   return ret;
  }
  
  /* Initliaze readline (and terminal if not already). */
***************
*** 789,794 ****
--- 817,852 ----
    }
  }
  
+ /* A simplified loop for vi. Don't dispatch key at end. */
+ rl_digit_loop1 ()
+ {
+   int key, c;
+   while (1) {
+     rl_message ("(arg: %d) ", arg_sign * rl_numeric_arg);
+     key = c = rl_read_key ();
+ 
+     if (keymap[c] == rl_universal_argument)
+       {
+ 	rl_numeric_arg *= 4;
+ 	continue;
+       }
+     c = UNMETA (c);
+     if (numeric (c))
+       {
+ 	if (rl_explicit_arg)
+ 	  rl_numeric_arg = (rl_numeric_arg * 10) + (c - '0');
+ 	else
+ 	  rl_numeric_arg = (c - '0');
+ 	rl_explicit_arg = 1;
+       }
+     else {
+       rl_clear_message ();
+       rl_stuff_char (key);
+       return;
+     }
+   }
+ }
+ 
  
  /* **************************************************************** */
  /*								    */
***************
*** 1786,1791 ****
--- 1844,1850 ----
        fprintf (stderr, "\007");
        fflush (stderr);
      }
+   return -1;
  }
  
  /* How to abort things. */
***************
*** 1910,1916 ****
     i.e., it is always safe to place '\0' there.
  
     rl_point is the place in the string where the cursor is.  Sometimes
!    this is the same as rl_end.
  
     Any command that is called interactively receives two arguments.
     The first is a count: the numeric arg pased to this command.
--- 1969,1975 ----
     i.e., it is always safe to place '\0' there.
  
     rl_point is the place in the string where the cursor is.  Sometimes
!    this is the same as rl_end, but not when in vi mode.
  
     Any command that is called interactively receives two arguments.
     The first is a count: the numeric arg pased to this command.
***************
*** 1938,1950 ****
    else
      while (count)
        {
! 	if (rl_point == rl_end)
! 	  {
! 	    ding ();
! 	    return;
! 	  }
! 	else
! 	  rl_point++;
  	--count;
        }
  }
--- 1997,2016 ----
    else
      while (count)
        {
! 	if (rl_editing_mode == emacs_mode) {
! 	  if (rl_point == rl_end)
! 	    {
! 	      ding ();
! 	      return;
! 	    }
! 	} else { /* vi_mode */
! 	  if (rl_point == rl_end - 1)
! 	    {
! 	      ding ();
! 	      return;
! 	    }
! 	}
! 	rl_point++;
  	--count;
        }
  }
***************
*** 2202,2207 ****
--- 2268,2277 ----
       int count, key;
  {
    rl_done = 1;
+   if (rl_vi_doing_insert) {
+     rl_end_undo_group ();
+     rl_vi_doing_insert = 0;
+   }
    if (readline_echoing_p)
      {
        move_vert (vis_botlin);
***************
*** 2587,2592 ****
--- 2657,2672 ----
      printf ("%s", the_line);
  }
  
+ rl_vi_complete (ignore, key)
+      int ignore, key;
+ {
+   if (!whitespace (the_line[rl_point])) {
+     rl_vi_end_word (1, 'E');
+     rl_point++;
+   }
+   rl_complete_internal ('*');
+ }
+ 
  /* List the possible completions.  See description of rl_complete (). */
  rl_possible_completions ()
  {
***************
*** 2815,2820 ****
--- 2895,2921 ----
  	    }
  	  break;
  
+ 	case '*':
+ 	  {
+ 	    int i = 1;
+ 	    
+ 	    rl_delete_text (start, rl_point);
+ 	    rl_point = start;
+ 	    rl_begin_undo_group ();
+ 	    if (matches[1]) {
+ 	      while (matches[i]) {
+ 		rl_insert_text (matches[i++]);
+ 		rl_insert_text (" ");
+ 	      }
+ 	    } else {
+ 	      rl_insert_text (matches[0]);
+ 	      rl_insert_text (" ");
+ 	    }
+ 	    rl_end_undo_group ();
+ 	  }
+ 	  rl_vi_insertion_mode ();
+ 	  break;
+ 	    
  	case '?':
  	  {
  	    int len, count, limit, max = 0;
***************
*** 3419,3435 ****
      strcpy (the_line, temp->line);
      rl_undo_list = (UNDO_LIST *)temp->data;
      rl_end = rl_point = strlen (the_line);
    }
  }
  
  /* There is a command in ksh which yanks into this line, the last word
     of the previous line.  Here it is.  We left it on M-. */
! rl_yank_previous_last_arg (ignore)
!      int ignore;
  {
  }
  
  
  
  /* **************************************************************** */
  /*								    */
--- 3520,3679 ----
      strcpy (the_line, temp->line);
      rl_undo_list = (UNDO_LIST *)temp->data;
      rl_end = rl_point = strlen (the_line);
+     if (rl_editing_mode == vi_mode)
+       rl_point = 0;
    }
  }
  
  /* There is a command in ksh which yanks into this line, the last word
     of the previous line.  Here it is.  We left it on M-. */
! rl_vi_yank_arg (count)
!      int count;
  {
+   HIST_ENTRY *hist;
+   char *new, *line, *n, *p, *q;
+ 
+   if ((hist = previous_history ()) != NULL)
+     next_history ();
+   line = hist->line;
+   if (line == NULL || line[0] == NULL)
+     return ding();
+   if (rl_explicit_arg == 0) {
+     p = &(line[strlen (line)-1]);
+     while (--p != line)
+       if (whitespace (*p)) {
+ 	p++;
+ 	break;
+       }
+   } else {
+     p = line;
+     while (*p && whitespace (*p))
+       p++;
+     while (--count && *p) {
+       while (*p && !whitespace (*p))
+ 	p++;
+       while (*p && whitespace (*p))
+ 	p++;
+     }
+     if (count || *p == NULL)
+       return ding();
+   }
+   q = p;
+   while (*q && !whitespace (*q))
+     q++;
+   n = new = xmalloc (q - p + 1);
+   while (p != q)
+     *n++ = *p++;
+   *n = 0;
+   rl_begin_undo_group ();
+   rl_insert (1, ' ');
+   rl_insert_text (new);
+   rl_end_undo_group ();
+   return 0;
  }
  
+ rl_vi_search_again (count, key)
+      int count, key;
+ {
+   switch (key) {
+   case 'n':
+     rl_vi_dosearch (rl_vi_last_search, -1);
+     break;
+   case 'N':
+     rl_vi_dosearch (rl_vi_last_search, 1);
+     break;
+   }
+   return 0;
+ }
  
+ rl_vi_search (count, key)
+      int count, key;
+ {
+   int dir, c;
+   char *p;
+   
+   switch (key) {
+   case '?':
+     dir = 1;
+     break;
+   case '/':
+     dir = -1;
+     break;
+   default:
+     return ding ();
+   }
+   rl_vi_histpos = where_history ();
+   maybe_save_line ();
+   the_line[0] = 0;
+   rl_end = rl_point = 0;
+   p = alloca (strlen (rl_prompt) + 2);
+   sprintf (p, "%s%c", rl_prompt, key);
+   rl_message (p);
+   while (c = rl_read_key (in_stream)) {	/* never exits normally */
+     switch (c) {
+     case CTRL('W'):
+     case CTRL('U'):
+     case CTRL('H'):
+     case RUBOUT:
+       rl_dispatch (c);
+       break;
+ #if 0
+     case CTRL('V'):
+       /* handle ^V processing */
+       break;
+ #endif 0
+     case ESC:
+     case RETURN:
+     case NEWLINE:
+       goto dosearch;
+       break;
+     case CTRL('C'):
+       maybe_unsave_line ();
+       rl_clear_message ();
+       rl_point = 0;
+       return ding ();
+       break;
+     default:
+       rl_insert (1, c);
+       break;
+     }
+     rl_redisplay ();
+   }
+  dosearch:
+   if (rl_vi_last_search)
+     free (rl_vi_last_search);
+   rl_vi_last_search = savestring (the_line);
+   rl_vi_dosearch (the_line, dir);
+   return 0;
+ }
+       
+ rl_vi_dosearch (string, dir)
+      char *string;
+      int dir;
+ {
+   int old, save = rl_vi_histpos;
+   HIST_ENTRY *h;
+   
+   if (string == 0 || *string == 0 || rl_vi_histpos < 0)
+     return ding ();
+   if ((save = history_search_pos (string, dir, rl_vi_histpos + dir)) == -1) {
+     maybe_unsave_line ();
+     rl_clear_message ();
+     rl_point = 0;
+     return ding ();
+   }
+   rl_vi_histpos = save;
+   old = where_history ();
+   h = history_set_pos (rl_vi_histpos);
+   history_set_pos (old);
+   strcpy (the_line, h->line);
+   rl_undo_list = (UNDO_LIST *)h->data;
+   rl_end = strlen (the_line);
+   rl_point = 0;
+   rl_clear_message ();
+   return 0;
+ }
+   
  
  /* **************************************************************** */
  /*								    */
***************
*** 3975,3998 ****
     anyway? Visual Idiocy? */
  
  /* Previous word in vi mode. */
! rl_vi_prev_word (count)
!      int count;
  {
    if (count < 0)
!     rl_vi_next_word (-count);
!   rl_backward_word (count);
  }
  
  /* Next word in vi mode. */
! rl_vi_next_word (count)
!      int count;
  {
    if (count < 0)
!     rl_vi_prev_word (-count);
    else
!     rl_forward_word (count);
  }
  
  /* What to do in the case of C-d. */
  rl_vi_eof_maybe (count, c)
       int count, c;
--- 4219,4356 ----
     anyway? Visual Idiocy? */
  
  /* Previous word in vi mode. */
! rl_vi_prev_word (count, key)
!      int count, key;
  {
    if (count < 0)
!     return rl_vi_next_word (-count, key);
!   if (uppercase_p (key))
!     return rl_vi_bWord (count);
!   else
!     return rl_vi_bword (count);
  }
  
  /* Next word in vi mode. */
! rl_vi_next_word (count, key)
!      int count, key;
  {
    if (count < 0)
!     return rl_vi_prev_word (-count, key);
! 
!   if (uppercase_p (key))
!     return rl_vi_fWord (count);
    else
!     return rl_vi_fword (count);
  }
  
+ rl_vi_end_word (count, key)
+      int count, key;
+ {
+   /* But vi doesn't have negative args. */
+   if (count < 0)
+     return ding();
+   if (uppercase_p (key))
+     return rl_vi_eWord (count);
+   else
+     return rl_vi_eword (count);
+ }
+ 
+ rl_vi_fWord (count)
+      int count;
+ {
+   while (count-- && rl_point < rl_end - 1) {
+     while (!whitespace (the_line[rl_point]) && rl_point < rl_end)
+       rl_point++;
+     while (whitespace (the_line[rl_point]) && rl_point < rl_end)
+       rl_point++;
+   }
+   return 0;
+ }
+ 
+ rl_vi_bWord (count)
+      int count;
+ {
+   while (count--&& rl_point > 0) {
+     while (rl_point-- >= 0 && whitespace (the_line[rl_point]))
+       ;
+     while (rl_point >= 0 && !whitespace (the_line[rl_point]))
+       rl_point--;
+     rl_point++;
+   }
+   return 0;
+ }
+ 
+ 
+ rl_vi_eWord (count)
+      int count;
+ {
+   while (count-- && rl_point < rl_end - 1) {
+     while (rl_point++ < rl_end && whitespace (the_line[rl_point]))
+       ;
+     while (rl_point++ < rl_end && !whitespace (the_line[rl_point]))
+       ;
+     rl_point--;
+   }
+   return 0;
+ }
+ 
+ rl_vi_fword (count)
+      int count;
+ {
+   while (count-- && rl_point < rl_end - 1) {
+     if (isident (the_line[rl_point]))
+       while (isident (the_line[rl_point]) && rl_point < rl_end)
+ 	rl_point += 1;
+     else if (!whitespace (the_line[rl_point]))
+       while (!isident (the_line[rl_point]) &&
+ 	     !whitespace (the_line[rl_point]) && rl_point < rl_end)
+ 	rl_point += 1;
+     while (whitespace (the_line[rl_point]) && rl_point < rl_end)
+       rl_point++;
+   }
+   return 0;
+ }
+ 
+ rl_vi_bword (count)
+      int count;
+ {
+   while (count-- && rl_point > 0) {
+     while (--rl_point > 0 && whitespace (the_line[rl_point]))
+       ;
+     if (rl_point > 0) {
+       if (isident (the_line[rl_point]))
+ 	while (--rl_point >= 0 && isident (the_line[rl_point]))
+ 	  ;
+       else
+ 	while (--rl_point >= 0 && !isident (the_line[rl_point]) &&
+ 	       !whitespace (the_line[rl_point]))
+ 	  ;
+       rl_point++;
+     }
+   }
+   return 0;
+ }
+   
+ rl_vi_eword (count)
+      int count;
+ {
+   while (count-- && rl_point < rl_end - 1) {
+     while (++rl_point < rl_end && whitespace (the_line[rl_point]))
+       ;
+     if (rl_point < rl_end) {
+       if (isident (the_line[rl_point]))
+ 	while (++rl_point < rl_end && isident (the_line[rl_point]))
+ 	  ;
+       else
+ 	while (++rl_point < rl_end && !isident (the_line[rl_point])
+ 	       && !whitespace (the_line[rl_point]))
+ 	  ;
+       rl_point--;
+     }
+   }
+   return 0;
+ }
+ 
  /* What to do in the case of C-d. */
  rl_vi_eof_maybe (count, c)
       int count, c;
***************
*** 4007,4017 ****
--- 4365,4405 ----
  rl_vi_insertion_mode ()
  {
    keymap = vi_insertion_keymap;
+   return 0;
  }
  
+ rl_vi_insert_beg ()
+ {
+   rl_beg_of_line ();
+   rl_vi_insertion_mode ();
+   return 0;
+ }
+ 
+ rl_vi_append_mode ()
+ {
+   if (rl_point < rl_end)
+     rl_point += 1;
+   rl_vi_insertion_mode ();
+   return 0;
+ }
+ 
+ rl_vi_append_eol ()
+ {
+   rl_end_of_line ();
+   rl_vi_append_mode ();
+   return 0;
+ }
+ 
  rl_vi_movement_mode ()
  {
+   if (rl_point > 0)
+     rl_backward (1);
    keymap = vi_movement_keymap;
+   if (rl_vi_doing_insert) {
+     rl_end_undo_group ();
+     rl_vi_doing_insert = 0;
+   }
+   return 0;
  }
  
  rl_vi_arg_digit (count, c)
***************
*** 4023,4043 ****
      rl_digit_argument (count, c);
  }
  
! rl_vi_change (count)
!      int count;
  {
  }
  
! rl_vi_char_search (count)
       int count;
  {
  }
  
  /* How to toggle back and forth between editing modes. */
  rl_vi_editing_mode ()
  {
    rl_editing_mode = vi_mode;
    rl_vi_insertion_mode ();
  }
  
  rl_emacs_editing_mode ()
--- 4411,4797 ----
      rl_digit_argument (count, c);
  }
  
! /* Doesn't take an arg count in vi */
! rl_vi_change_case ()
  {
+   char c = 0;
+   
+   if (uppercase_p (the_line[rl_point]))
+     c = to_lower (the_line[rl_point]);
+   else if (lowercase_p (the_line[rl_point]))
+     c = to_upper (the_line[rl_point]);
+   /* Vi is kind of strange here */
+   if (c) {
+     rl_begin_undo_group ();
+     rl_delete (1);
+     rl_insert (1, c);
+     rl_end_undo_group ();
+     rl_vi_check ();
+   } else
+     rl_forward (1);
+   return 0;
+ }	
+     
+ rl_vi_put (count, key)
+      int count, key;
+ {
+   if (!uppercase_p (key))
+     rl_forward (1);
+   rl_yank ();
+   rl_backward (1);
+   return 0;
  }
  
! rl_vi_check ()
! {
!   if (rl_point && rl_point == rl_end)
!     rl_point--;
!   return 0;
! }
!       
! rl_vi_column (count)
! {
!   if (count > rl_end)
!     rl_end_of_line ();
!   else
!     rl_point = count - 1;
!   return 0;
! }
! 
! rl_vi_domove ()
! {
!   int c, save;
!   
!   rl_mark = rl_point;
!   c = rl_read_key (in_stream);
!   if (!member (c, rl_vi_motion)) {
!     if (digit (c)) {
!       save = rl_numeric_arg;
!       rl_digit_loop1 ();
!       rl_numeric_arg *= save;
!     } else
!       return -1;
!   }
!   if (rl_dispatch (c) < 0)
!     return -1;
!   if ((c == 'w' || c == 'W') && rl_point < rl_end)
!     rl_point--;
!   if (rl_mark < rl_point)
!     exchange (rl_point, rl_mark);
!   return 0;
! }
! 
! rl_vi_delete_to (count, key)
!      int count, key;
! {
!   if (uppercase_p (key))
!     rl_stuff_char ('$');
!   if (rl_vi_domove ())
!     return ding ();
!   rl_kill_text (rl_point, rl_mark);
!   return 0;
! }
! 
! rl_vi_change_to (count, key)
!      int count, key;
! {
!   if (uppercase_p (key))
!     rl_stuff_char ('$');
!   if (rl_vi_domove ())
!     return ding ();
!   rl_begin_undo_group ();
!   rl_vi_doing_insert = 1;
!   rl_kill_text (rl_point, rl_mark);
!   rl_vi_insertion_mode ();
!   return 0;
! }
! 
! rl_vi_yank_to (count, key)
!      int count, key;
! {
!   int save = rl_point;
!   
!   if (uppercase_p (key))
!     rl_stuff_char ('$');
!   if (rl_vi_domove ())
!     return ding ();
!   rl_begin_undo_group ();
!   rl_kill_text (rl_point, rl_mark);
!   rl_end_undo_group ();
!   rl_do_undo ();
!   rl_point = save;
!   return 0;
! }
! 
! rl_vi_delete (count)
! {
!   if (rl_point >= rl_end - 1) {
!     rl_delete (count);
!     if (rl_point > 0)
!       rl_backward (1);
!   } else
!     rl_delete (count);
!   return 0;
! }
! 
! /* Turn the current line into a comment in shell history.  A ksh function */
! rl_vi_comment ()
! {
!   rl_beg_of_line ();
!   rl_insert_text (": ");	/* # doesn't work in interactive mode */
!   rl_redisplay ();
!   rl_newline (1, '\010');
!   return 0;
! }
! 
! rl_vi_first_print ()
! {
!   int	save = rl_point;
!   
!   rl_beg_of_line ();
!   while (whitespace (the_line[rl_point])) {
!     save = rl_point;
!     rl_forward (1);
!     if (save == rl_point)
!       break;
!   }
!   return 0;
! }
! 
! /* NOTE: it is necessary that opposite directions are inverses */
! #define	FTO	 1		/* forward to */
! #define BTO	-1		/* backward to */
! #define FFIND	 2		/* forward find */
! #define BFIND	-2		/* backward find */
! 
! rl_vi_char_search (count, key)
!      int count, key;
! {
!   static char target;
!   static int orig_dir, dir;
!   int pos;
! 
!   switch (key) {
!   case 't':
!     target = rl_getc (in_stream);
!     orig_dir = dir = FTO;
!     break;
!   case 'T':
!     target = rl_getc (in_stream);
!     orig_dir = dir = BTO;
!     break;
!   case 'f':
!     target = rl_getc (in_stream);
!     orig_dir = dir = FFIND;
!     break;
!   case 'F':
!     target = rl_getc (in_stream);
!     orig_dir = dir = BFIND;
!     break;
!   case ';':
!     dir = orig_dir;
!     break;
!   case ',':
!     dir = -orig_dir;
!     break;
!   }
!   pos = rl_point;
!   if (dir < 0) {
!     pos--;
!     do {
!       if (the_line[pos] == target) {
! 	if (dir == BTO)
! 	  rl_point = pos + 1;
! 	else
! 	  rl_point = pos;
! 	return 0;
!       }
!     } while (pos--);
!     if (pos < 0)
!       return ding();
!   } else { /* dir > 0 */
!     pos++;
!     do {
!       if (the_line[pos] == target) {
! 	if (dir == FTO)
! 	  rl_point = pos - 1;
! 	else
! 	  rl_point = pos;
! 	return 0;
!       }
!     } while (++pos < rl_end);
!     if (pos >= rl_end - 1);
!       return ding();
!   }
!   return 0;
! }
! 
! /* Match brackets */
! rl_vi_match ()
! {
!   int count = 1, brack, pos;
!   
!   pos = rl_point;
!   if ((brack = rl_vi_bracktype (the_line[rl_point])) == 0) {
!     while ((brack = rl_vi_bracktype (the_line[rl_point])) == 0 &&
! 	   rl_point < rl_end - 1)
!       rl_forward (1);
!     if (brack <= 0) {
!       rl_point = pos;
!       return ding();
!     }
!   }
!   pos = rl_point;
!   if (brack < 0) {
!     while (count) {
!       if (--pos >= 0) {
! 	int b = rl_vi_bracktype (the_line[pos]);
! 	if (b == -brack) {
! 	  count--;
! 	} else if (b == brack) {
! 	  count++;
! 	}
!       } else
! 	return ding();
!     }
!   } else { /* brack > 0 */
!     while (count) {
!       if (++pos < rl_end) {
! 	int b = rl_vi_bracktype (the_line[pos]);
! 	if (b == -brack)
! 	  count--;
! 	else if (b == brack)
! 	  count++;
!       } else
! 	return ding();
!     }
!   }
!   rl_point = pos;
!   return 0;
! }
! 	      
! int
! rl_vi_bracktype (c)
!      int c;
! {
!   switch (c) {
!   case '(': return  1;
!   case ')': return -1;
!   case '[': return  2;
!   case ']': return -2;
!   case '{': return  3;
!   case '}': return -3;
!   default:  return  0;
!   }
! }
! 
! rl_vi_change_char ()
! {
!   int c;
! 
!   c = rl_getc (in_stream);
!   switch (c) {
!   case '\033':
!   case CTRL('C'):
!     return;
!   default:
!     rl_begin_undo_group ();
!     rl_delete (1);
!     rl_insert (1, c);
!     rl_end_undo_group ();
!     break;
!   }
!   return 0;
! }
! 
! rl_vi_subst (count, key)
!      int count, key;
! {
!   rl_begin_undo_group ();
!   rl_vi_doing_insert = 1;
!   if (uppercase_p (key)) {
!     rl_beg_of_line ();
!     rl_kill_line (1);
!   } else {
!     rl_delete (1);
!   }
!   rl_vi_insertion_mode ();
!   return 0;
! }
! 
! rl_vi_overstrike (count, key)
!      int count, key;
! {
!   int i;
! 
!   if (rl_vi_doing_insert == 0) {
!     rl_vi_doing_insert = 1;
!     rl_begin_undo_group ();
!   }
!   for (i = 0; i < count; i++) {
!     rl_vi_replace_count++;
!     rl_begin_undo_group ();
!     if (rl_point < rl_end) {
!       rl_delete (1);
!       rl_insert (1, key);
!     } else
!       rl_insert (1, key);
!     rl_end_undo_group ();
!   }
!   return 0;
! }
! 
! rl_vi_overstrike_delete (count)
       int count;
  {
+   int i, s;
+ 
+   for (i = 0; i < count; i++) {
+     if (rl_vi_replace_count == 0) {
+       ding ();
+       break;
+     }
+     s = rl_point;
+     if (rl_do_undo ()) {
+       rl_vi_replace_count--;
+     }
+     if (rl_point == s)
+       rl_backward (1);
+   }
+   if (rl_vi_replace_count == 0 && rl_vi_doing_insert) {
+     rl_end_undo_group ();
+     rl_do_undo ();
+     rl_vi_doing_insert = 0;
+   }
+   return 0;
  }
  
+ rl_vi_replace ()
+ {
+   int i;
+ 
+   rl_vi_replace_count = 0;
+   rl_vi_replace_map = rl_make_bare_keymap ();
+   for (i = ' '; i < 127; i++)
+     rl_vi_replace_map[i] = rl_vi_overstrike;
+   for (i = 0; i < ' '; i++)
+     rl_vi_replace_map[i] = (Function *)0;
+   for (i = 127; i < 255; i++)
+     rl_vi_replace_map[i] = (Function *)0;
+   rl_vi_replace_map[RUBOUT] = rl_vi_overstrike_delete;
+   rl_vi_replace_map[ESC] = rl_vi_movement_mode;
+   rl_vi_replace_map[RETURN] = rl_newline;
+   rl_vi_replace_map[NEWLINE] = rl_newline;
+   keymap = rl_vi_replace_map;
+   return 0;
+ }
+ 
  /* How to toggle back and forth between editing modes. */
  rl_vi_editing_mode ()
  {
    rl_editing_mode = vi_mode;
    rl_vi_insertion_mode ();
+   return 0;
  }
  
  rl_emacs_editing_mode ()
Only in ./readline: readline.c.orig
Only in ./readline: readline.c.rej
Only in ./readline: readline.c~
diff -rc ../b3/readline/readline.h ./readline/readline.h
*** ../b3/readline/readline.h	Fri Aug 11 22:21:28 1989
--- ./readline/readline.h	Fri Sep  8 09:36:00 1989
***************
*** 31,37 ****
  /* Things for vi mode. */
  extern int rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
  rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (), rl_vi_change (),
! rl_vi_editing_mode (), rl_vi_eof_maybe ();
  
  /* Maintaining the state of undo.  We remember individual deletes and inserts
     on a chain of things to do. */
--- 31,45 ----
  /* Things for vi mode. */
  extern int rl_vi_movement_mode (), rl_vi_insertion_mode (), rl_vi_arg_digit (),
  rl_vi_prev_word (), rl_vi_next_word (), rl_vi_char_search (), rl_vi_change (),
! rl_vi_editing_mode (), rl_vi_eof_maybe (), rl_vi_append_mode (), rl_vi_put (),
! rl_vi_append_eol (), rl_vi_insert_beg (), rl_vi_delete (), rl_vi_comment (),
! rl_vi_first_print (), rl_vi_fword (), rl_vi_fWord (), rl_vi_bword (),
! rl_vi_bWord (), rl_vi_eword (), rl_vi_eWord (), rl_vi_end_word (),
! rl_vi_change_case (), rl_vi_match (), rl_vi_bracktype (), rl_vi_change_char (),
! rl_vi_yank (), rl_vi_yank_arg (), rl_vi_search (), rl_vi_search_again (),
! rl_vi_dosearch (), rl_vi_subst (), rl_vi_change (), rl_vi_overstrike (),
! rl_vi_overstrike_delete (), rl_vi_replace(), rl_vi_column (),
! rl_vi_delete_to (), rl_vi_change_to (), rl_vi_yank_to (), rl_vi_complete ();
  
  /* Maintaining the state of undo.  We remember individual deletes and inserts
     on a chain of things to do. */
Only in ./readline: readline.h.orig
Only in ./readline: readline.h~
Only in ./readline: readline.o
diff -rc ../b3/readline/vi_keymap.c ./readline/vi_keymap.c
*** ../b3/readline/vi_keymap.c	Wed Jul 26 13:20:30 1989
--- ./readline/vi_keymap.c	Fri Sep  8 11:31:15 1989
***************
*** 69,87 ****
    rl_forward,			/* SPACE */
    (Function *)0x0,		/* ! */
    (Function *)0x0,		/* " */
!   (Function *)0x0,		/* # */
    rl_end_of_line,		/* $ */
!   (Function *)0x0,		/* % */
    (Function *)0x0,		/* & */
    (Function *)0x0,		/* ' */
    (Function *)0x0,		/* ( */
    (Function *)0x0,		/* ) */
!   (Function *)0x0,		/* * */
!   (Function *)0x0,		/* + */
!   (Function *)0x0,		/* , */
!   rl_vi_arg_digit,		/* - */
    (Function *)0x0,		/* . */
!   (Function *)0x0,		/* / */
  
    /* Regular digits. */
    rl_vi_arg_digit,		/* 0 */
--- 69,87 ----
    rl_forward,			/* SPACE */
    (Function *)0x0,		/* ! */
    (Function *)0x0,		/* " */
!   rl_vi_comment,		/* # */
    rl_end_of_line,		/* $ */
!   rl_vi_match,			/* % */
    (Function *)0x0,		/* & */
    (Function *)0x0,		/* ' */
    (Function *)0x0,		/* ( */
    (Function *)0x0,		/* ) */
!   rl_vi_complete,		/* * */
!   rl_get_previous_history,	/* + */
!   rl_vi_char_search,		/* , */
!   rl_get_next_history,		/* - */
    (Function *)0x0,		/* . */
!   rl_vi_search,			/* / */
  
    /* Regular digits. */
    rl_vi_arg_digit,		/* 0 */
***************
*** 97,135 ****
  
    /* A little more punctuation. */
    (Function *)0x0,		/* : */
!   (Function *)0x0,		/* ; */
    (Function *)0x0,		/* < */
    (Function *)0x0,		/* = */
    (Function *)0x0,		/* > */
!   (Function *)0x0,		/* ? */
    (Function *)0x0,		/* @ */
  
    /* Uppercase alphabet. */
!   (Function *)0x0,		/* A */
!   (Function *)0x0,		/* B */
!   (Function *)0x0,		/* C */
!   (Function *)0x0,		/* D */
!   (Function *)0x0,		/* E */
!   (Function *)0x0,		/* F */
    (Function *)0x0,		/* G */
    (Function *)0x0,		/* H */
!   (Function *)0x0,		/* I */
    (Function *)0x0,		/* J */
    (Function *)0x0,		/* K */
    (Function *)0x0,		/* L */
    (Function *)0x0,		/* M */
!   (Function *)0x0,		/* N */
    (Function *)0x0,		/* O */
!   (Function *)0x0,		/* P */
    (Function *)0x0,		/* Q */
!   (Function *)0x0,		/* R */
!   (Function *)0x0,		/* S */
!   (Function *)0x0,		/* T */
!   (Function *)0x0,		/* U */
    (Function *)0x0,		/* V */
!   (Function *)0x0,		/* W */
!   (Function *)0x0,		/* X */
!   (Function *)0x0,		/* Y */
    (Function *)0x0,		/* Z */
  
    /* Some more punctuation. */
--- 97,135 ----
  
    /* A little more punctuation. */
    (Function *)0x0,		/* : */
!   rl_vi_char_search,		/* ; */
    (Function *)0x0,		/* < */
    (Function *)0x0,		/* = */
    (Function *)0x0,		/* > */
!   rl_vi_search,			/* ? */
    (Function *)0x0,		/* @ */
  
    /* Uppercase alphabet. */
!   rl_vi_append_eol,		/* A */
!   rl_vi_prev_word,		/* B */
!   rl_vi_change_to,		/* C */
!   rl_vi_delete_to,		/* D */
!   rl_vi_end_word,		/* E */
!   rl_vi_char_search,		/* F */
    (Function *)0x0,		/* G */
    (Function *)0x0,		/* H */
!   rl_vi_insert_beg,		/* I */
    (Function *)0x0,		/* J */
    (Function *)0x0,		/* K */
    (Function *)0x0,		/* L */
    (Function *)0x0,		/* M */
!   rl_vi_search_again,		/* N */
    (Function *)0x0,		/* O */
!   rl_vi_put,			/* P */
    (Function *)0x0,		/* Q */
!   rl_vi_replace,		/* R */
!   rl_vi_subst,			/* S */
!   rl_vi_char_search,		/* T */
!   rl_revert_line,		/* U */
    (Function *)0x0,		/* V */
!   rl_vi_next_word,		/* W */
!   rl_rubout,			/* X */
!   rl_vi_yank_to,		/* Y */
    (Function *)0x0,		/* Z */
  
    /* Some more punctuation. */
***************
*** 136,151 ****
    (Function *)0x0,		/* [ */
    (Function *)0x0,		/* \ */
    (Function *)0x0,		/* ] */
!   (Function *)0x0,		/* ^ */
!   (Function *)0x0,		/* _ */
    (Function *)0x0,		/* ` */
  
    /* Lowercase alphabet. */
!   (Function *)0x0,		/* a */
    rl_vi_prev_word,		/* b */
!   rl_vi_change,			/* c */
!   (Function *)0x0,		/* d */
!   (Function *)0x0,		/* e */
    rl_vi_char_search,		/* f */
    (Function *)0x0,		/* g */
    rl_backward,			/* h */
--- 136,151 ----
    (Function *)0x0,		/* [ */
    (Function *)0x0,		/* \ */
    (Function *)0x0,		/* ] */
!   rl_vi_first_print,		/* ^ */
!   rl_vi_yank_arg,		/* _ */
    (Function *)0x0,		/* ` */
  
    /* Lowercase alphabet. */
!   rl_vi_append_mode,		/* a */
    rl_vi_prev_word,		/* b */
!   rl_vi_change_to,		/* c */
!   rl_vi_delete_to,		/* d */
!   rl_vi_end_word,		/* e */
    rl_vi_char_search,		/* f */
    (Function *)0x0,		/* g */
    rl_backward,			/* h */
***************
*** 154,178 ****
    rl_get_previous_history,	/* k */
    rl_forward,			/* l */
    (Function *)0x0,		/* m */
!   (Function *)0x0,		/* n */
    (Function *)0x0,		/* o */
!   (Function *)0x0,		/* p */
    (Function *)0x0,		/* q */
!   (Function *)0x0,		/* r */
!   (Function *)0x0,		/* s */
!   (Function *)0x0,		/* t */
!   (Function *)0x0,		/* u */
    (Function *)0x0,		/* v */
    rl_vi_next_word,		/* w */
!   rl_delete,			/* x */
!   (Function *)0x0,		/* y */
    (Function *)0x0,		/* z */
  
    /* Final punctuation. */
    (Function *)0x0,		/* { */
!   (Function *)0x0,		/* | */
    (Function *)0x0,		/* } */
!   (Function *)0x0,		/* ~ */
    rl_backward,			/* RUBOUT */
  
    /* Meta keys.  Just like above, but the high bit is set. */
--- 154,178 ----
    rl_get_previous_history,	/* k */
    rl_forward,			/* l */
    (Function *)0x0,		/* m */
!   rl_vi_search_again,		/* n */
    (Function *)0x0,		/* o */
!   rl_vi_put,			/* p */
    (Function *)0x0,		/* q */
!   rl_vi_change_char,		/* r */
!   rl_vi_subst,			/* s */
!   rl_vi_char_search,		/* t */
!   rl_undo_command,		/* u */ /* not quite the right thing */
    (Function *)0x0,		/* v */
    rl_vi_next_word,		/* w */
!   rl_vi_delete,			/* x */
!   rl_vi_yank_to,		/* y */
    (Function *)0x0,		/* z */
  
    /* Final punctuation. */
    (Function *)0x0,		/* { */
!   rl_vi_column,			/* | */
    (Function *)0x0,		/* } */
!   rl_vi_change_case,		/* ~ */
    rl_backward,			/* RUBOUT */
  
    /* Meta keys.  Just like above, but the high bit is set. */
***************
*** 336,342 ****
    rl_insert,			/* Control-f */
    rl_insert,			/* Control-g */
    rl_insert,			/* Control-h */
!   rl_insert,			/* Control-i */
    rl_newline,			/* Control-j */
    rl_insert,			/* Control-k */
    rl_insert,			/* Control-l */
--- 336,342 ----
    rl_insert,			/* Control-f */
    rl_insert,			/* Control-g */
    rl_insert,			/* Control-h */
!   rl_complete,			/* Control-i */
    rl_newline,			/* Control-j */
    rl_insert,			/* Control-k */
    rl_insert,			/* Control-l */
***************
*** 483,489 ****
    (Function *)0x0,		/* Meta-Control-f */
    (Function *)0x0,		/* Meta-Control-g */
    (Function *)0x0,		/* Meta-Control-h */
!   (Function *)0x0,		/* Meta-Control-i */
    rl_emacs_editing_mode,	/* Meta-Control-j */
    (Function *)0x0,		/* Meta-Control-k */
    (Function *)0x0,		/* Meta-Control-l */
--- 483,489 ----
    (Function *)0x0,		/* Meta-Control-f */
    (Function *)0x0,		/* Meta-Control-g */
    (Function *)0x0,		/* Meta-Control-h */
!   rl_tab_insert,		/* Meta-Control-i */
    rl_emacs_editing_mode,	/* Meta-Control-j */
    (Function *)0x0,		/* Meta-Control-k */
    (Function *)0x0,		/* Meta-Control-l */
***************
*** 556,562 ****
    rl_forward_word,		/* Meta-F */
    (Function *)0x0,		/* Meta-G */
    (Function *)0x0,		/* Meta-H */
!   (Function *)0x0,		/* Meta-I */
    (Function *)0x0,		/* Meta-J */
    (Function *)0x0,		/* Meta-K */
    rl_downcase_word,		/* Meta-L */
--- 556,562 ----
    rl_forward_word,		/* Meta-F */
    (Function *)0x0,		/* Meta-G */
    (Function *)0x0,		/* Meta-H */
!   rl_tab_insert,		/* Meta-I */
    (Function *)0x0,		/* Meta-J */
    (Function *)0x0,		/* Meta-K */
    rl_downcase_word,		/* Meta-L */
Only in ./readline: vi_keymap.c.orig
Only in ./readline: vi_keymap.c~


-- 
Jeff Sparkes	jeff1@garfield.mun.edu || uunet!garfield!jeff1