[gnu.bash.bug] some patches for 1.04

jeff1@garfield.mun.edu (Jeff Sparkes) (11/20/89)

This set of patches contains:
	1. a bunch of fixes for vi mode, including the two recent
reports.  There are also extra bindings (in input mode): C-e to list
completions, and C-x to do a * expansion.  I made some hook functions
to more completely isolate vi code.
	2. undoable undos.  These work the same as in emacs (I hope).

BTW, anyone compiled bash under MIPS 4.[01]?  I can't deal with dbx
anymore.

diff -rc readline.orig/funmap.c readline/funmap.c
*** readline.orig/funmap.c	Tue Nov 14 15:07:47 1989
--- readline/funmap.c	Sun Nov 19 16:43:19 1989
***************
*** 122,127 ****
--- 122,128 ----
    { "vi-change-to", rl_vi_change_to },
    { "vi-yank-to", rl_vi_yank_to },
    { "vi-complete", rl_vi_complete },
+   { "vi-rubout", rl_vi_rubout, },
  #endif /* VI_MODE */
  
   {(char *)NULL, (Function *)NULL }
diff -rc readline.orig/readline.c readline/readline.c
*** readline.orig/readline.c	Tue Nov 14 15:07:50 1989
--- readline/readline.c	Fri Nov 17 19:53:41 1989
***************
*** 159,164 ****
--- 159,167 ----
  /* Non-zero if the previous command was a kill command. */
  static int last_command_was_kill = 0;
  
+ /* Non-zero if the previous commands was undo. */
+ static int last_command_was_undo = 0;
+ 
  /* The current value of the numeric argument specified by the user. */
  int rl_numeric_arg = 1;
  
***************
*** 312,317 ****
--- 315,321 ----
    while (!rl_done)
      {
        int lk = last_command_was_kill;
+       int lu = last_command_was_undo;
        int code = setjmp (readline_top_level);
  
        if (code)
***************
*** 348,360 ****
  	{
  	  if (lk == last_command_was_kill)
  	    last_command_was_kill = 0;
  	}
  
  #ifdef VI_MODE
!       /* In vi mode, when you exit insert mode, the cursor moves back
! 	 over the previous character.  We explicitly check for that here. */
!       if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap)
! 	rl_vi_check ();
  #endif
  
        if (!rl_done)
--- 352,363 ----
  	{
  	  if (lk == last_command_was_kill)
  	    last_command_was_kill = 0;
+ 	  if (lu == last_command_was_undo)
+ 	    last_command_was_undo = 0;
  	}
  
  #ifdef VI_MODE
!       rl_vi_display_hook ();
  #endif
  
        if (!rl_done)
***************
*** 2248,2253 ****
--- 2251,2259 ----
    rl_point += l;
    rl_end += l;
    the_line[rl_end] = '\0';
+ #ifdef VI_MODE
+   rl_vi_insert_hook ();
+ #endif  
  }
  
  /* Delete the string between FROM and TO.  FROM is
***************
*** 2591,2604 ****
    rl_done = 1;
  
  #ifdef VI_MODE
!   {
!     extern int vi_doing_insert;
!     if (vi_doing_insert)
!       {
! 	rl_end_undo_group ();
! 	vi_doing_insert = 0;
!       }
!   }
  #endif /* VI_MODE */
  
    if (readline_echoing_p)
--- 2597,2603 ----
    rl_done = 1;
  
  #ifdef VI_MODE
!   rl_vi_newline_hook  ();
  #endif /* VI_MODE */
  
    if (readline_echoing_p)
***************
*** 3520,3525 ****
--- 3519,3527 ----
  /* The current undo list for THE_LINE. */
  UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
  
+ /* Current position in the undo list during multiple undos. */
+ UNDO_LIST *rl_undo_p = (UNDO_LIST *)NULL;     
+ 
  /* Remember how to undo something.  Concatenate some undos if that
     seems right. */
  rl_add_undo (what, start, end, text)
***************
*** 3550,3609 ****
    }
  }
  
! /* Undo the next thing in the list.  Return 0 if there
!    is nothing to undo, or non-zero if there was. */
! int
! rl_do_undo ()
! {
!   UNDO_LIST *release;
!   int waiting_for_begin = 0;
! 
! undo_thing:
!   if (!rl_undo_list)
!     return (0);
! 
!   doing_an_undo = 1;
  
!   switch (rl_undo_list->what) {
  
-     /* Undoing deletes means inserting some text. */
    case UNDO_DELETE:
!     rl_point = rl_undo_list->start;
!     rl_insert_text (rl_undo_list->text);
!     free (rl_undo_list->text);
      break;
  
-     /* Undoing inserts means deleting some text. */
    case UNDO_INSERT:
!     rl_delete_text (rl_undo_list->start, rl_undo_list->end);
!     rl_point = rl_undo_list->start;
      break;
  
-     /* Undoing an END means undoing everything 'til we get to
-        a BEGIN. */
    case UNDO_END:
!     waiting_for_begin++;
      break;
  
-     /* Undoing a BEGIN means that we are done with this group. */
    case UNDO_BEGIN:
!     if (waiting_for_begin)
!       waiting_for_begin--;
!     else
!       abort ();
      break;
!   }
! 
!   doing_an_undo = 0;
! 
!   release = rl_undo_list;
!   rl_undo_list = rl_undo_list->next;
!   free (release);
! 
!   if (waiting_for_begin)
!     goto undo_thing;
! 
!   return (1);
  }
  
  /* Begin a group.  Subsequent undos are undone as an atomic operation. */
--- 3552,3595 ----
    }
  }
  
! /* Undo the next thing in the list. Note that these undos are undoable. */
! UNDO_LIST *
! rl_do_undo (head, looking)
!      UNDO_LIST *head;
!      int looking;
! {
!   UNDO_LIST *temp = head->next;
  
!   if (!head)
!     return;
!   switch (head->what) {
  
    case UNDO_DELETE:
!     rl_point = head->start;
!     rl_insert_text (savestring(head->text));
!     if (looking)
!       temp = rl_do_undo (head->next, looking);
      break;
  
    case UNDO_INSERT:
!     rl_delete_text (head->start, head->end);
!     rl_point = head->start;
!     if (looking)
!       temp = rl_do_undo (head->next, looking);
      break;
  
    case UNDO_END:
!     rl_begin_undo_group ();
!     temp = rl_do_undo (head->next, looking + 1);
      break;
  
    case UNDO_BEGIN:
!     rl_end_undo_group ();
!     if (--looking)
!       temp = rl_do_undo (head->next, looking);
      break;
!   } 
!   return temp;
  }
  
  /* Begin a group.  Subsequent undos are undone as an atomic operation. */
***************
*** 3644,3671 ****
  {
    if (!rl_undo_list) ding ();
    else {
      while (rl_undo_list)
!       rl_do_undo ();
    }
  }
  
  /* Do some undoing of things that were done. */
! rl_undo_command (count)
  {
!   if (count < 0) return;	/* Nothing to do. */
! 
!   while (count)
!     {
!       if (rl_do_undo ())
! 	{
! 	  count--;
! 	}
!       else
! 	{
! 	  ding ();
! 	  break;
! 	}
      }
  }
  
  /* **************************************************************** */
--- 3630,3662 ----
  {
    if (!rl_undo_list) ding ();
    else {
+     doing_an_undo = 1;
      while (rl_undo_list)
!       rl_undo_list = rl_do_undo (rl_undo_list, 0);
!     doing_an_undo = 0;
    }
  }
  
  /* Do some undoing of things that were done. */
! rl_undo_command (count, key)
  {
!   if (count < 0 ||!rl_undo_list)
!     return ding();
!   if (!last_command_was_undo++)
!     rl_undo_p = rl_undo_list;
! #ifdef VI_MODE
!   /* Vi undo only undos last action.  Shouldn't add to undo list though. */
!   if (rl_editing_mode == vi_mode && key == 'u')
!     rl_undo_p = rl_undo_list;
! #endif  
!   while (count--) {
!     if (rl_undo_p)
!       rl_undo_p = rl_do_undo (rl_undo_p, 0);
!     else {
!       ding ();
!       break;
      }
+   }
  }
  
  /* **************************************************************** */
***************
*** 3841,3850 ****
        strcpy (the_line, temp->line);
        rl_undo_list = (UNDO_LIST *)temp->data;
        rl_end = rl_point = strlen (the_line);
- #ifdef VI_MODE
-       if (rl_editing_mode == vi_mode)
- 	rl_point = 0;
- #endif /* VI_MODE */
      }
  }
  
--- 3832,3837 ----
diff -rc readline.orig/readline.h readline/readline.h
*** readline.orig/readline.h	Tue Nov 14 15:07:51 1989
--- readline/readline.h	Tue Nov 14 15:21:27 1989
***************
*** 43,49 ****
  rl_vi_yank_arg (), rl_vi_search (), rl_vi_search_again (),
  rl_vi_dosearch (), rl_vi_subst (), 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 ();
  #endif /* VI_MODE */
  
  /* Keyboard macro commands. */
--- 43,50 ----
  rl_vi_yank_arg (), rl_vi_search (), rl_vi_search_again (),
  rl_vi_dosearch (), rl_vi_subst (), 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 (),
! rl_vi_delete (), rl_vi_rubout (), rl_vi_newline_hook (), rl_vi_insert_hook ();
  #endif /* VI_MODE */
  
  /* Keyboard macro commands. */
diff -rc readline.orig/vi_keymap.c readline/vi_keymap.c
*** readline.orig/vi_keymap.c	Tue Nov 14 15:07:52 1989
--- readline/vi_keymap.c	Tue Nov 14 15:21:26 1989
***************
*** 128,134 ****
    { ISFUNC, rl_revert_line },		/* U */
    { ISFUNC, (Function *)0x0 },		/* V */
    { ISFUNC, rl_vi_next_word },		/* W */
!   { ISFUNC, rl_rubout },		/* X */
    { ISFUNC, rl_vi_yank_to },		/* Y */
    { ISFUNC, (Function *)0x0 },		/* Z */
  
--- 128,134 ----
    { ISFUNC, rl_revert_line },		/* U */
    { ISFUNC, (Function *)0x0 },		/* V */
    { ISFUNC, rl_vi_next_word },		/* W */
!   { ISFUNC, rl_vi_rubout },		/* X */
    { ISFUNC, rl_vi_yank_to },		/* Y */
    { ISFUNC, (Function *)0x0 },		/* Z */
  
***************
*** 185,192 ****
    { ISFUNC, rl_insert },		/* Control-b */
    { ISFUNC, rl_insert },		/* Control-c */
    { ISFUNC, rl_vi_eof_maybe },		/* Control-d */
!   { ISFUNC, rl_insert },		/* Control-e */
!   { ISFUNC, rl_insert },		/* Control-f */
    { ISFUNC, rl_insert },		/* Control-g */
    { ISFUNC, rl_insert },		/* Control-h */
    { ISFUNC, rl_complete },		/* Control-i */
--- 185,192 ----
    { ISFUNC, rl_insert },		/* Control-b */
    { ISFUNC, rl_insert },		/* Control-c */
    { ISFUNC, rl_vi_eof_maybe },		/* Control-d */
!   { ISFUNC, rl_possible_completions },	/* Control-e */
!   { ISFUNC, rl_complete },		/* Control-f */
    { ISFUNC, rl_insert },		/* Control-g */
    { ISFUNC, rl_insert },		/* Control-h */
    { ISFUNC, rl_complete },		/* Control-i */
***************
*** 204,210 ****
    { ISFUNC, rl_unix_line_discard },	/* Control-u */
    { ISFUNC, rl_quoted_insert },		/* Control-v */
    { ISFUNC, rl_unix_word_rubout },	/* Control-w */
!   { ISFUNC, rl_insert },		/* Control-x */
    { ISFUNC, rl_yank },			/* Control-y */
    { ISFUNC, rl_insert },		/* Control-z */
  
--- 204,210 ----
    { ISFUNC, rl_unix_line_discard },	/* Control-u */
    { ISFUNC, rl_quoted_insert },		/* Control-v */
    { ISFUNC, rl_unix_word_rubout },	/* Control-w */
!   { ISFUNC, rl_vi_complete },		/* Control-x */
    { ISFUNC, rl_yank },			/* Control-y */
    { ISFUNC, rl_insert },		/* Control-z */
  
diff -rc readline.orig/vi_mode.c readline/vi_mode.c
*** readline.orig/vi_mode.c	Tue Nov 14 15:07:52 1989
--- readline/vi_mode.c	Sun Nov 19 16:48:12 1989
***************
*** 1,5 ****
  /* vi_mode.c -- A vi emulation mode for Bash.
!    Mostly written by Jeff Sparkes (jeff1@????).
   */
  
  
--- 1,5 ----
  /* vi_mode.c -- A vi emulation mode for Bash.
!    Mostly written by Jeff Sparkes (jeff1@garfield.mun.edu).
   */
  
  
***************
*** 16,21 ****
--- 16,24 ----
  /* Non-zero means enter insertion mode. */
  static vi_doing_insert = 0;
  
+ /* To allow undo of input expansion. */
+ static vi_just_expanded = 0;
+ 
  /* *** UNCLEAN *** */
  /* Command keys which do movement for xxx_to commands. */
  static char *vi_motion = " hl^$0ftFt;,%wbeWBE|";
***************
*** 162,173 ****
--- 165,186 ----
  rl_vi_complete (ignore, key)
       int ignore, key;
  {
+   if (vi_just_expanded) {
+     rl_do_undo ();
+     vi_just_expanded = 0;
+   }
+   if (keymap == vi_insertion_keymap)
+     rl_vi_insertion_mode ();
    if (!whitespace (the_line[rl_point]))
      {
        rl_vi_end_word (1, 'E');
        rl_point++;
      }
+   rl_begin_undo_group ();
+   /* If this returned a status value, we could avoid changing modes. */
    rl_complete_internal ('*');
+   rl_end_undo_group ();
+   vi_just_expanded = 1;
    rl_vi_insertion_mode ();
  }
  
***************
*** 355,371 ****
    keymap = vi_insertion_keymap;
  }
  
  rl_vi_movement_mode ()
  {
    if (rl_point > 0)
      rl_backward (1);
- 
-   keymap = vi_movement_keymap;
-   if (vi_doing_insert)
-     {
-       rl_end_undo_group ();
-       vi_doing_insert = 0;
-     }
  }
  
  rl_vi_arg_digit (count, c)
--- 368,387 ----
    keymap = vi_insertion_keymap;
  }
  
+ rl_vi_end_insertion_mode ()
+ {
+   if (vi_doing_insert) {
+     rl_end_undo_group ();
+     vi_doing_insert = 0;
+   }
+ }
+ 
  rl_vi_movement_mode ()
  {
+   rl_vi_end_insertion_mode ();
+   keymap = vi_movement_keymap;
    if (rl_point > 0)
      rl_backward (1);
  }
  
  rl_vi_arg_digit (count, c)
***************
*** 426,462 ****
  }
  
  int
! rl_vi_domove ()
  {
    int c, save;
  
    rl_mark = rl_point;
    c = rl_read_key (in_stream);
  
!   if (!member (c, vi_motion))
!     {
        if (digit (c))
! 	{
! 	  save = rl_numeric_arg;
! 	  rl_digit_loop1 ();
! 	  rl_numeric_arg *= save;
! 	}
        else
  	return (-1);
!     }
! 
!   rl_dispatch (c, keymap);
! 
!   /* No change in position means the command failed. */
!   if (rl_mark == rl_point)
!     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);
  }
  
--- 442,488 ----
  }
  
  int
! rl_vi_domove (invoked)
!      int invoked;
  {
+   /* Don't increment rl_point after these chars. */
+   static char *not_after = " hl^$wbWB";
    int c, save;
  
    rl_mark = rl_point;
    c = rl_read_key (in_stream);
  
!   if (c == invoked) {
!     rl_mark = rl_end;
!     rl_point = 0;
!   } else {
!     if (!member (c, vi_motion))
        if (digit (c))
! 	rl_digit_argument (0, c);
        else
  	return (-1);
!     else
!       rl_dispatch (c, keymap);
  
!     /* No change in position means the command failed. */
!     if (rl_mark == rl_point)
!       return (-1);
!     
!     /* Fix word wierdness for change command. */
!     if (invoked == 'c' && (c == 'w' || c == 'W') && rl_point < rl_end)
!       if (!whitespace (the_line[rl_point])) {
! 	rl_point--;
! 	while (whitespace (the_line[rl_point]))
! 	  rl_point--;
! 	rl_point++;
!       } 
  
!     if (rl_mark < rl_point && !member(c, not_after))
!       rl_point++;
  
+     if (rl_mark < rl_point)
+       exchange (rl_point, rl_mark);
+   }
    return (0);
  }
  
***************
*** 548,565 ****
    rl_point = save;
  }
  
  rl_vi_delete (count)
  {
!   if (rl_point >= rl_end - 1)
!     {
!       rl_delete (count);
!       if (rl_point > 0)
! 	rl_backward (1);
!     }
!   else
!     rl_delete (count);
  }
- 
  /* Turn the current line into a comment in shell history.  A ksh function */
  rl_vi_comment ()
  {
--- 574,599 ----
    rl_point = save;
  }
  
+ /* Even single char deletes kill text. */
  rl_vi_delete (count)
  {
!   if ((rl_point +count) > rl_end - 1) {
!     rl_kill_text (rl_point, rl_end);
!     if (rl_point > 0)
!       rl_backward (1);
!   } else
!     rl_kill_text (rl_point, rl_point + count);
! }
! 
! rl_vi_rubout (count)
! {
!   rl_point -= count;
!   if (rl_point < 0) {
!     count += rl_point;
!     rl_point = 0;
!   }
!   rl_kill_text (rl_point, rl_point + count);
  }
  /* Turn the current line into a comment in shell history.  A ksh function */
  rl_vi_comment ()
  {
***************
*** 856,859 ****
--- 890,909 ----
    vi_replace_map[RETURN].function = rl_newline;
    vi_replace_map[NEWLINE].function = rl_newline;
    keymap = vi_replace_map;
+ }
+ 
+ rl_vi_display_hook ()
+ {
+   if (rl_editing_mode == vi_mode && keymap == vi_movement_keymap)
+     rl_vi_check ();
+ }
+ 
+ rl_vi_insert_hook ()
+ {
+   vi_just_expanded = 0;
+ }
+ 
+ rl_vi_newline_hook ()
+ {
+   rl_vi_end_insertion_mode ();
  }

--
Jeff Sparkes	jeff1@garfield.mun.edu || uunet!garfield!jeff1
Humans couldn't have invented golf without alien intervention--Kids in the Hall