zsh-workers
 help / color / mirror / code / Atom feed
From: Oliver Kiddle <okiddle@yahoo.co.uk>
To: zsh-workers@zsh.org
Subject: Re: zle: vi mode: wrong undo handling on fresh lines
Date: Wed, 29 Jan 2014 00:00:35 +0100	[thread overview]
Message-ID: <2700.1390950035@thecus.kiddle.eu> (raw)
In-Reply-To: <20140127161124.2aa16b37@pwslap01u.europe.root.pri>

Peter Stephenson wrote:
> Or startvitext() and startvichange() may be buried too far in to want
> any changing.
> 
> I think this is starting to get somewhere, but I suspect it needs
> tweaking.  For example, should that synthesised 'i' really be an 'a'?

If someone has the overstrike option set, it should probably be 'R'.
Actually that option seems to be fully non-working for vi mode.

With a blank starting line, it really is much of a muchness. If pushed
for an answer, I'd say 'a'.

A non-blank starting line is possible with at least
accept-line-and-down-history and vi-push-input. In such cases, it
depends on the cursor position. If the cursor starts at the
beginning of the line then 'i' makes more sense.

> Is it OK to assume we're not in insert mode when vi-repeat is executed?

Yes. Of course someone can bind a key to the widget but that currently
just beeps which is fine. To do that in vi, you'd have to bind your key
to escape, followed by a dot.

> Some vi user will need to take over at this point.  All the action I'm
> aware of is in the functions I've changed and if you've looked at the
> code you understand it as well as I do.
> 
> I haven't thought further about the completion thing.  I've no idea
> how that ever did anything useful.

How about the following approach to the undo problem:
The variable undoing was serving as a flag to indicate whether each
change should be added as an undo event. In vi-mode this would be
skipped so that the whole vi change became a single undo change. What
this does is remove that handling and instead merge all the undo events
corresponding to the vi change in the vi-cmd-mode widget.

This means, undo done the vi way works as in vi. undo invoked in insert
mode works exactly as in emacs mode and exactly as it used to do (up
till the first time vi command mode is invoked after which there are
differences). It also avoids the need for any special extra
vi-complete-word etc widgets that call handleundo(). The main
disadvantage is that undo will appear to be doing different things in
insert verses command mode which would probably need documenting under
the undo widget even though the change is in vi-cmd-mode. Any thoughts?

Are there other ways to get into vi command mode besides vi-cmd-mode
that might get around this? In vim, cursor movement in insert mode works
as if you had switched to command mode so we have some differences
there.

Oliver

diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index a2b20df..f5aec84 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -157,10 +157,10 @@ mod_export char *statusline;
 /**/
 int stackhist, stackcs;
 
-/* != 0 if we are making undo records */
+/* position in undo stack from when the current vi change started */
 
 /**/
-int undoing;
+zlong vistartchange;
 
 /* current modifier status */
 
@@ -1080,8 +1080,7 @@ zlecore(void)
 	    if (invicmdmode() && zlecs > findbol() &&
 		(zlecs == zlell || zleline[zlecs] == ZWC('\n')))
 		DECCS();
-	    if (undoing)
-		handleundo();
+	    handleundo();
 	} else {
 	    errflag = 1;
 	    break;
@@ -1190,7 +1189,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
     zlereadflags = flags;
     zlecontext = context;
     histline = curhist;
-    undoing = 1;
+    vistartchange = 0;
     zleline = (ZLE_STRING_T)zalloc(((linesz = 256) + 2) * ZLE_CHAR_SIZE);
     *zleline = ZWC('\0');
     virangeflag = lastcmd = done = zlecs = zlell = mark = 0;
@@ -1198,6 +1197,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
     viinsbegin = 0;
     statusline = NULL;
     selectkeymap("main", 1);
+    initundo();
     /*
      * If main is linked to the viins keymap, we need to register
      * explicitly that we're now in vi insert mode as there's
@@ -1222,7 +1222,6 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
 	    stackhist = -1;
 	}
     }
-    initundo();
     if (isset(PROMPTCR))
 	putc('\r', shout);
     if (tmout)
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index 9d163ad..2689d0f 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -611,8 +611,7 @@ docomplete(int lst)
     active = 1;
     comprecursive = 0;
     makecommaspecial(0);
-    if (undoing)
-	setlastline();
+    setlastline();
 
     /* From the C-code's point of view, we can only use compctl as a default
      * type of completion. Load it if it hasn't been loaded already and
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index b82e54c..61ae85c 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -1354,7 +1354,10 @@ handlesuffix(UNUSED(char **args))
 
 /* head of the undo list, and the current position */
 
-static struct change *changes, *curchange;
+/**/
+struct change *curchange;
+
+static struct change *changes;
 
 /* list of pending changes, not yet in the undo system */
 
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 31f2933..9e9cc2f 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -107,7 +107,7 @@ startvitext(int im)
 {
     startvichange(im);
     selectkeymap("main", 1);
-    undoing = 0;
+    vistartchange = (curchange && curchange->prev) ? curchange->prev->changeno : 0;
     viinsbegin = zlecs;
 }
 
@@ -399,7 +399,7 @@ vichange(UNUSED(char **args))
 	forekill(c2 - zlecs, CUT_RAW);
 	selectkeymap("main", 1);
 	viinsbegin = zlecs;
-	undoing = 0;
+	vistartchange = curchange->prev->changeno;
     }
     return ret;
 }
@@ -584,7 +584,13 @@ vicmdmode(UNUSED(char **args))
 {
     if (invicmdmode() || selectkeymap("vicmd", 0))
 	return 1;
-    undoing = 1;
+    struct change *current = curchange->prev;
+    while (current && current->changeno > vistartchange+1) {
+	current->flags |= CH_PREV;
+	current = current->prev;
+	if (!current) break;
+	current->flags |= CH_NEXT;
+    }
     vichgflag = 0;
     if (zlecs != findbol())
 	DECCS();


  parent reply	other threads:[~2014-01-28 23:07 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-22 12:37 Hauke Petersen
2013-09-22 18:24 ` Bart Schaefer
2013-09-22 20:27   ` Hauke Petersen
2013-09-23  4:57     ` Bart Schaefer
2013-09-23 20:30 ` Peter Stephenson
2014-01-24 23:19   ` Oliver Kiddle
2014-01-25 19:15     ` Bart Schaefer
2014-01-27 12:43       ` Peter Stephenson
2014-01-27 16:11         ` Peter Stephenson
2014-01-28 14:58           ` Peter Stephenson
2014-01-28 16:28             ` Bart Schaefer
2014-01-28 16:47               ` Peter Stephenson
2014-01-28 17:41                 ` Bart Schaefer
2014-01-28 23:00           ` Oliver Kiddle [this message]
2014-01-29  2:59             ` Bart Schaefer
2014-01-29 10:50               ` Oliver Kiddle
2014-01-29 14:48                 ` Bart Schaefer
2014-01-30 14:51             ` Jun T.
2014-01-30 15:38               ` Peter Stephenson
2014-01-30 16:03                 ` Bart Schaefer
2014-01-31 12:00               ` Jun T.
2014-01-31 15:19                 ` Bart Schaefer
2014-01-31 15:33                   ` Peter Stephenson
     [not found]               ` <16181.1391175951@thecus.kiddle.eu>
2014-01-31 16:43                 ` Jun T.
2014-01-31 21:37               ` Oliver Kiddle
2014-01-31 22:32                 ` Oliver Kiddle
2014-02-01 19:27                   ` Bart Schaefer
2014-02-03 16:20                   ` Jun T.
2014-02-03 21:29                     ` Oliver Kiddle
2014-02-03 22:20                       ` Bart Schaefer
2014-02-03 23:26                         ` Oliver Kiddle
2014-02-04 17:11                           ` Jun T.
2014-02-05 22:00                             ` Oliver Kiddle
2014-02-02 22:10             ` Oliver Kiddle
2014-02-07 14:43             ` Oliver Kiddle
2014-02-07 16:22               ` Bart Schaefer
2014-01-27 16:29         ` Bart Schaefer

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=2700.1390950035@thecus.kiddle.eu \
    --to=okiddle@yahoo.co.uk \
    --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).