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