Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: s/pattern/pattern/g on the commandline ?



On Thu, 29 Mar 2012 14:06:24 +0200
Vincent Lefevre <vincent@xxxxxxxxxx> wrote:
> > zlewidget "\e%" replace-regexp replace-string
> 
> But after such a replacement, if one wants to revert, "undo" doesn't
> work.

(It does work, if you persevere, it just sucks.)

This has been in my mind on and off (mostly off) for some time.

The following adds the UNDO_CHANGE_NO zle parameter which returns the
current state of undo and an optional argument to undo which indicates
a change number back to which the editing history should be wound.

I'm a bit suspicious of this since it seemed to work perfectly first
time.  This nearly always means I screwed something major up.

Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.96
diff -p -u -r1.96 zle.yo
--- Doc/Zsh/zle.yo	5 Jan 2012 20:01:25 -0000	1.96
+++ Doc/Zsh/zle.yo	29 Mar 2012 20:17:47 -0000
@@ -877,6 +877,12 @@ any predisplay string should be highligh
 Note that the effect of tt(region_highlight) is not saved and disappears
 as soon as the line is accepted.
 )
+vindex(UNDO_CHANGE_NO)
+item(tt(UNDO_CHANGE_NO) (integer))
+A number representing the state of the undo history.  The only use
+of this is passing as an argument to the tt(undo) widget in order to
+undo back to the recorded point.  Read-only.
+)
 vindex(WIDGET)
 item(tt(WIDGET) (scalar))(
 The name of the widget currently being executed; read-only.
@@ -2164,7 +2170,10 @@ command is typed.  By default it beeps.
 )
 tindex(undo)
 item(tt(undo) (^_ ^Xu ^X^U) (unbound) (unbound))(
-Incrementally undo the last text modification.
+Incrementally undo the last text modification.  When called from a
+user-defined widget, takes an optional argument indicating a previous state
+of the undo history as returned by the tt(UNDO_CHANGE_NO) variable;
+modifications are undone until that state is reached.
 )
 tindex(redo)
 item(tt(redo))(
Index: Functions/Zle/replace-string
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/replace-string,v
retrieving revision 1.6
diff -p -u -r1.6 replace-string
--- Functions/Zle/replace-string	7 Nov 2011 11:13:50 -0000	1.6
+++ Functions/Zle/replace-string	29 Mar 2012 20:17:47 -0000
@@ -4,6 +4,9 @@ setopt extendedglob
 autoload -Uz read-from-minibuffer replace-string-again
 
 local p1  p2
+integer changeno=$UNDO_CHANGE_NO
+
+{
 
 if [[ -n $_replace_string_src ]]; then
   p1="[$_replace_string_src -> $_replace_string_rep]"$'\n'
@@ -30,4 +33,10 @@ if [[ -n $REPLY ]]; then
   typeset -g _replace_string_rep=$REPLY
 fi
 
+} always {
+  # Undo back to the original line; we don't want the
+  # undo history of editing the strings left.
+  zle undo $changeno
+}
+
 replace-string-again $curwidget
Index: Src/Zle/zle.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle.h,v
retrieving revision 1.43
diff -p -u -r1.43 zle.h
--- Src/Zle/zle.h	18 Feb 2011 22:08:46 -0000	1.43
+++ Src/Zle/zle.h	29 Mar 2012 20:17:47 -0000
@@ -269,6 +269,7 @@ struct change {
     ZLE_STRING_T ins;		/* characters to insert */
     int insl;			/* no. of characters in ins */
     int old_cs, new_cs;		/* old and new cursor positions */
+    zlong changeno;             /* unique number of this change */
 };
 
 #define CH_NEXT (1<<0)   /* next structure is also part of this change */
Index: Src/Zle/zle_params.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_params.c,v
retrieving revision 1.36
diff -p -u -r1.36 zle_params.c
--- Src/Zle/zle_params.c	27 Mar 2011 17:55:41 -0000	1.36
+++ Src/Zle/zle_params.c	29 Mar 2012 20:17:47 -0000
@@ -93,6 +93,8 @@ static const struct gsu_integer pending_
 { get_pending, NULL, zleunsetfn };
 static const struct gsu_integer region_active_gsu =
 { get_region_active, set_region_active, zleunsetfn };
+static const struct gsu_integer undo_change_no_gsu =
+{ get_undo_current_change, NULL, zleunsetfn };
 
 static const struct gsu_array killring_gsu =
 { get_killring, set_killring, unset_killring };
@@ -133,6 +135,8 @@ static struct zleparam {
     { "RBUFFER", PM_SCALAR,  GSU(rbuffer_gsu), NULL },
     { "REGION_ACTIVE", PM_INTEGER, GSU(region_active_gsu), NULL},
     { "region_highlight", PM_ARRAY, GSU(region_highlight_gsu), NULL },
+    { "UNDO_CHANGE_NO", PM_INTEGER | PM_READONLY, GSU(undo_change_no_gsu),
+      NULL },
     { "WIDGET", PM_SCALAR | PM_READONLY, GSU(widget_gsu), NULL },
     { "WIDGETFUNC", PM_SCALAR | PM_READONLY, GSU(widgetfunc_gsu), NULL },
     { "WIDGETSTYLE", PM_SCALAR | PM_READONLY, GSU(widgetstyle_gsu), NULL },
Index: Src/Zle/zle_utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_utils.c,v
retrieving revision 1.62
diff -p -u -r1.62 zle_utils.c
--- Src/Zle/zle_utils.c	13 May 2011 11:59:05 -0000	1.62
+++ Src/Zle/zle_utils.c	29 Mar 2012 20:17:47 -0000
@@ -1359,6 +1359,10 @@ static struct change *changes, *curchang
 
 static struct change *nextchanges, *endnextchanges;
 
+/* incremented to provide a unique change number */
+
+static zlong undo_changeno;
+
 /**/
 void
 initundo(void)
@@ -1368,6 +1372,7 @@ initundo(void)
     curchange->prev = curchange->next = NULL;
     curchange->del = curchange->ins = NULL;
     curchange->dell = curchange->insl = 0;
+    curchange->changeno = undo_changeno = 0;
     lastline = zalloc((lastlinesz = linesz) * ZLE_CHAR_SIZE);
     ZS_memcpy(lastline, zleline, (lastll = zlell));
     lastcs = zlecs;
@@ -1492,6 +1497,7 @@ mkundoent(void)
 	ch->flags = 0;
 	ch->prev = NULL;
     }
+    ch->changeno = ++undo_changeno;
     endnextchanges = ch;
 }
 
@@ -1512,8 +1518,15 @@ setlastline(void)
 
 /**/
 int
-undo(UNUSED(char **args))
+undo(char **args)
 {
+    zlong last_change = (zlong)0;
+
+    if (*args)
+    {
+	last_change = zstrtol(*args, NULL, 0);
+    }
+
     handleundo();
     do {
 	if(!curchange->prev)
@@ -1522,7 +1535,8 @@ undo(UNUSED(char **args))
 	    curchange = curchange->prev;
 	else
 	    break;
-    } while(curchange->flags & CH_PREV);
+    } while (*args ? curchange->changeno != last_change :
+	     (curchange->flags & CH_PREV));
     setlastline();
     return 0;
 }
@@ -1637,3 +1651,15 @@ zlecallhook(char *name, char *arg)
     errflag = saverrflag;
     retflag = savretflag;
 }
+
+/*
+ * Return the number corresponding to the last change made.
+ */
+
+/**/
+zlong
+get_undo_current_change(UNUSED(Param pm))
+{
+    return undo_changeno;
+}
+

- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



Messages sorted by: Reverse Date, Date, Thread, Author