From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28539 invoked by alias); 28 Jan 2014 23:07:34 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 32314 Received: (qmail 15086 invoked from network); 28 Jan 2014 23:07:17 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, T_TO_NO_BRKTS_FREEMAIL autolearn=ham version=3.3.2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s1024; t=1390950037; bh=8k2nAGgDkjgN+uWkgG2XUJqdi54a/bii2ASQ6zIngQw=; h=X-Yahoo-Newman-Id:X-Yahoo-Newman-Property:X-YMail-OSG:X-Yahoo-SMTP:X-Rocket-Received:Received:In-reply-to:From:References:To:Subject:MIME-Version:Content-Type:Content-ID:Date:Message-ID; b=3fPFOAmQ0idiohsV9ZOXDvDkyfv9wikMXx8J6vFU4+wiBX06SvXR24DmRRirzPLOzTMQ1YK5JYizbk63hUKmluQR60Bs/UWKCYU9vLuUOU7DzY2KND6iqjqEJcCvbFmjUTW+2rdpoyZEOlYYrR2lCxDJjzVZNPtZ8dfaIa10fHo= X-Yahoo-Newman-Id: 461743.33423.bm@smtp102.mail.ir2.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: sPOubcUVM1nW9wrBm_qjIzURzN3dj7w0SzzFQArHBYkDspF WyLVa93J1AWIJtF7XIdgYduhB60tFOIFgWtjZmLElhq9oNbAj2aZZK.QtF8_ MJjvUh6gvuFicPQeYTiJMh5a6pdwSGLxpUNNW.Yi78jNxEKLTEy3FAGeCpH6 wMPE9t2KUW9lkn_.Tuy5l9CZCPiTw7Q9hgKeVPgjX44y0Exw1zbaiD2gkGUm FFnjDGDo7RHAgQUmcZAcIyf0aSJA22gVZXgV4rfTeCKdlMu2gUyFEpQTk3qj XXhZUyiFqKAIlEucu_uoyEM4ZqBCtGYj7YuXCFhXu45OZIkLhvU2loyyrsXM VgMCp2tQrVLze0kMhydHIkY9MtJZFO_JpfCHcoGfAxXPDHKztWhxxWHMxulu XebzINlzV_Xl_mnc6DmzO4SlrbvRvhm6Gq8VXvoXYKvqiZkW5qXPmzj6WP04 T6xiCTQ4xPC9adk9QM61CAFc_8zFhtOeZF6Kuceh.5Shkp_5r6sbhz_5qdiE OVnh.qWWxdt.qLONzushV3E0N X-Yahoo-SMTP: opAkk_CswBAce_kJ3nIPlH80cJI- X-Rocket-Received: from kiddle.eu (okiddle@88.153.4.83 with plain [188.125.69.59]) by smtp102.mail.ir2.yahoo.com with SMTP; 28 Jan 2014 23:00:37 +0000 UTC In-reply-to: <20140127161124.2aa16b37@pwslap01u.europe.root.pri> From: Oliver Kiddle References: <20130923213014.15f97f9e@pws-pc.ntlworld.com> <3511.1390605547@thecus.kiddle.eu> <140125111530.ZM21792@torch.brasslantern.com> <20140127124301.4144f2d9@pwslap01u.europe.root.pri> <20140127161124.2aa16b37@pwslap01u.europe.root.pri> To: zsh-workers@zsh.org Subject: Re: zle: vi mode: wrong undo handling on fresh lines MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <2682.1390949871.1@thecus.kiddle.eu> Date: Wed, 29 Jan 2014 00:00:35 +0100 Message-ID: <2700.1390950035@thecus.kiddle.eu> 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();