zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: Zsh workers <zsh-workers@zsh.org>
Subject: Re: Undo is also confused with narrow-to-region
Date: Mon, 6 Jul 2015 20:25:54 +0100	[thread overview]
Message-ID: <20150706202554.02d6c73a@ntlworld.com> (raw)
In-Reply-To: <4900.1436183185@thecus.kiddle.eu>

On Mon, 06 Jul 2015 13:46:25 +0200
Oliver Kiddle <okiddle@yahoo.co.uk> wrote:
> That prevents redoing minibuffer changes from the main editor but
> doesn't stop you undoing main editor changes within the minibuffer. It
> might be sufficient to mark the current undo state as a point beyond
> which an undo will not go unless passed a change number as a parameter.

The following is easy.

The example I've given shows an explicit save and restore.  It should
also be possible to use the double function scope trick, though I didn't
actually try.

I haven't imposed any arbitrary limits on the value in UNDO_LIMIT_NO as,
on thinking about it, it seemed to create hostages to fortune for no
obvious gain.

pws

diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index d3f0670..da8ee47 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -960,6 +960,26 @@ 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(UNDO_LIMIT_NO)
+item(tt(UNDO_LIMIT_NO) (integer))(
+A number corresponding to an existing change in the undo history;
+compare tt(UNDO_CHANGE_NO).  If this is set to a value greater
+than zero, the tt(undo) command will not allow the line to
+be undone beyond the given change number.  It is still possible
+to use `tt(zle undo) var(change)' in a widget to undo beyond
+that point; in that case, it will not be possible to undo at
+all until tt(UNDO_LIMIT_NO) is reduced.  Set to 0 to disable the limit.
+
+A typical use of this variable in a widget function is as follows:
+
+example(integer save_limit=$UNDO_LIMIT_NO
+UNDO_LIMIT_NO=$UNDO_CHANGE_NO
+{
+  # Perform some form of recursive edit.
+} always {
+  UNDO_LIMIT_NO=save_limit
+})
+)
 vindex(WIDGET)
 item(tt(WIDGET) (scalar))(
 The name of the widget currently being executed; read-only.
@@ -2333,7 +2353,8 @@ item(tt(undo) (tt(^_ ^Xu ^X^U)) (tt(u)) (unbound))(
 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.
+modifications are undone until that state is reached, subject to
+any limit imposed by the tt(UNDO_LIMIT_NO) variable.
 
 Note that when invoked from vi command mode, the full prior change made in
 insert mode is reverted, the changes having been merged when command mode was
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index ce4b072..b84e720 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -95,6 +95,8 @@ 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_integer undo_limit_no_gsu =
+{ get_undo_limit_change, set_undo_limit_change, zleunsetfn };
 
 static const struct gsu_array killring_gsu =
 { get_killring, set_killring, unset_killring };
@@ -137,6 +139,7 @@ static struct zleparam {
     { "region_highlight", PM_ARRAY, GSU(region_highlight_gsu), NULL },
     { "UNDO_CHANGE_NO", PM_INTEGER | PM_READONLY, GSU(undo_change_no_gsu),
       NULL },
+    { "UNDO_LIMIT_NO", PM_INTEGER, GSU(undo_limit_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 },
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 06e4581..198c0ba 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -1405,6 +1405,10 @@ static struct change *nextchanges, *endnextchanges;
 /**/
 zlong undo_changeno;
 
+/* If positive, don't undo beyond this point */
+
+zlong undo_limitno;
+
 /* If non-zero, the last increment to undo_changeno was for the variable */
 
 static int undo_set_by_variable;
@@ -1418,7 +1422,7 @@ initundo(void)
     curchange->prev = curchange->next = NULL;
     curchange->del = curchange->ins = NULL;
     curchange->dell = curchange->insl = 0;
-    curchange->changeno = undo_changeno = 0;
+    curchange->changeno = undo_changeno = undo_limitno = 0;
     undo_set_by_variable = 0;
     lastline = zalloc((lastlinesz = linesz) * ZLE_CHAR_SIZE);
     ZS_memcpy(lastline, zleline, (lastll = zlell));
@@ -1582,6 +1586,8 @@ undo(char **args)
 	    return 1;
 	if (prev->changeno < last_change)
 	    break;
+	if (prev->changeno < undo_limitno && !*args)
+	    break;
 	if (unapplychange(prev))
 	    curchange = prev;
 	else
@@ -1744,7 +1750,21 @@ get_undo_current_change(UNUSED(Param pm))
      * Increment the number in case a change is in progress;
      * we don't want to back off what's already been done when
      * we return to this change number.  This eliminates any
-     * problem about the point where a change is numbered.
+     * problem about the point where a change is numbered
      */
     return ++undo_changeno;
 }
+
+/**/
+zlong
+get_undo_limit_change(UNUSED(Param pm))
+{
+    return undo_limitno;
+}
+
+/**/
+void
+set_undo_limit_change(UNUSED(Param pm), zlong value)
+{
+    undo_limitno = value;
+}


  reply	other threads:[~2015-07-06 19:31 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-03 15:26 Oliver Kiddle
2015-07-03 18:12 ` Mikael Magnusson
2015-07-06  8:39   ` Peter Stephenson
2015-07-06 11:46     ` Oliver Kiddle
2015-07-06 19:25       ` Peter Stephenson [this message]
2015-07-08 14:57         ` Oliver Kiddle
2015-07-09 18:32           ` Peter Stephenson
2015-07-10  9:34           ` Peter Stephenson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150706202554.02d6c73a@ntlworld.com \
    --to=p.w.stephenson@ntlworld.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).