Ok, here is my attempt at a recursive version of the keepjumps command.
It's called lockjumps, and works in the same way as keepjumps except that:
1) it's recursive
2) it only locks the jumplist, it does not affect the marks list

Again, it seems to work as intended, "make test" passes and valgrind too.

The reason for not touching the marks is that:
1) I think it is actually fairly common for functions/plugins/etc to use marks 
in jumping around, e.g. calling "normal ``" to get back after a jump, or having 
a mapping which does things like "ggdd``". It is much more uncommon to use 
CTRL-O in a script I think.
2) The marks can be set explicitly by the user and are much easier to control 
from user code (e.g. it is trivial to write a save_marks()/restore_marks() pair 
if needed).

All things considered, I prefer this version to the previous one with the 
option. (I just hope it's correct!)


On Monday, May 25, 2015 at 9:44:52 PM UTC+2, Carlo Baldassi wrote:
> On Saturday, May 23, 2015 at 10:52:16 PM UTC+2, Justin M. Keyes wrote:
> > But why can't keepjumps be made recursive instead?
> 
> That's the first thing I thought too. Of course it would break existing code, 
> so it should be something else, perhaps keepjumps!. But it also seemed a more 
> complicated and less flexible model to me: does it apply to exec'd code, 
> mappings etc.? Well, essentially if the answer to all questions is no you'd 
> almost have what I have here. One trickier point is what to do if the code 
> changes window.
> The option route seemed the most straightforward to me; I can have a look at 
> a different implementation (but again, my knowledge of vim source code is 
> extremely poor).
> 
> > These one-off commands ("keepjumps", "lockjumps", etc, etc) are
> > extremely disappointing to me. Why can't there be, instead, a general
> > mechanism to save/restore these lists? Similar to
> > winsaveview()/winrestview(), except, you know--not a band-aid
> > solution. A *general* solution.
> 
> I'm open to suggestions, but I don't see what you have in mind exactly. Care 
> to elaborate?

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1321,6 +1321,7 @@
 |:lnoremap|    :ln[oremap]     like ":noremap!" but includes Lang-Arg mode
 |:loadkeymap|  :loadk[eymap]   load the following keymaps until EOF
 |:loadview|    :lo[adview]     load view for current window from a file
+|:lockjumps|   :lockj[umps]    following command keeps the jumplist
 |:lockmarks|   :loc[kmarks]    following command keeps marks where they are
 |:lockvar|     :lockv[ar]      lock variables
 |:lolder|      :lol[der]       go to older location list
diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt
--- a/runtime/doc/motion.txt
+++ b/runtime/doc/motion.txt
@@ -787,7 +787,7 @@
                                g`"
 <                      jumps to the last known position in a file.  See
                        $VIMRUNTIME/vimrc_example.vim.
-                       Also see |:keepjumps|.
+                       Also see |:keepjumps| and |:lockjumps|.
                        {not in Vi}
 
                                                *:marks*
@@ -1009,9 +1009,28 @@
 <
                        Note that ":keepjumps" must be used for every command.
                        When invoking a function the commands in that function
-                       can still change the jumplist.  Also, for
-                       ":keepjumps exe 'command '" the "command" won't keep
-                       jumps.  Instead use: ":exe 'keepjumps command'"
+                       can still change the jumplist. Use |:lockjumps| to
+                       avoid that.  Also, for ":keepjumps exe 'command '" the
+                       "command" won't keep jumps.  Instead use:
+                       ":exe 'keepjumps command'", or |:lockjumps|.
+
+                                                       *:lockj* *:lockjumps*
+:lockj[umps] {command}
+                       Similar to |:keepjumps|, but only affects the 
|jumplist|,
+                       and is recursive: it can be used for example when
+                       calling a function which would otherwise alter the
+                       |jumplist|: >
+
+                               :lockjumps call SomeFunction()
+<
+                       Another example could be invoking a |mapping| which in
+                       turn changes the |jumplist|: >
+
+                                :nnoremap <F4> ggdd``
+                                :lockjumps normal <F4>
+<
+                       Note that marks are still recorded when using this
+                       modifier.
 
 ==============================================================================
 8. Jumps                                       *jump-motions*
@@ -1083,10 +1102,10 @@
 The result is that when repeating CTRL-O you will get back to old positions
 only once.
 
-When the |:keepjumps| command modifier is used, jumps are not stored in the
-jumplist.  Jumps are also not stored in other cases, e.g., in a |:global|
-command.  You can explicitly add a jump by setting the ' mark with "m'".  Note
-that calling setpos() does not do this.
+When the |:keepjumps| or |:lockjumps| command modifiers are used, jumps are not
+stored in the jumplist.  Jumps are also not stored in other cases, e.g., in a
+|:global| command.  You can explicitly add a jump by setting the ' mark with 
"m'".
+Note that calling setpos() does not do this.
 
 After the CTRL-O command that got you into line 1154 you could give another
 jump command (e.g., "G").  The jump list would then become:
diff --git a/runtime/doc/tags b/runtime/doc/tags
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -2414,6 +2414,8 @@
 :loadkeymap    mbyte.txt       /*:loadkeymap*
 :loadview      starting.txt    /*:loadview*
 :loc   motion.txt      /*:loc*
+:lockj motion.txt      /*:lockj*
+:lockjumps     motion.txt      /*:lockjumps*
 :lockmarks     motion.txt      /*:lockmarks*
 :lockv eval.txt        /*:lockv*
 :lockvar       eval.txt        /*:lockvar*
@@ -6733,6 +6735,7 @@
 lcs-extends    options.txt     /*lcs-extends*
 lcs-nbsp       options.txt     /*lcs-nbsp*
 lcs-precedes   options.txt     /*lcs-precedes*
+lcs-space      options.txt     /*lcs-space*
 lcs-tab        options.txt     /*lcs-tab*
 lcs-trail      options.txt     /*lcs-trail*
 left-right-motions     motion.txt      /*left-right-motions*
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -804,6 +804,9 @@
 EX(CMD_lockmarks,      "lockmarks",    ex_wrongmodifier,
                        NEEDARG|EXTRA|NOTRLCOM,
                        ADDR_LINES),
+EX(CMD_lockjumps,      "lockjumps",    ex_wrongmodifier,
+                       NEEDARG|EXTRA|NOTRLCOM,
+                       ADDR_LINES),
 EX(CMD_lockvar,                "lockvar",      ex_lockvar,
                        BANG|EXTRA|NEEDARG|SBOXOK|CMDWIN,
                        ADDR_LINES),
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -1858,6 +1858,9 @@
     save_cmdmod = cmdmod;
     vim_memset(&cmdmod, 0, sizeof(cmdmod));
 
+    /* lockjumps is recursive */
+    cmdmod.lockjumps = save_cmdmod.lockjumps;
+
     /* "#!anything" is handled like a comment. */
     if ((*cmdlinep)[0] == '#' && (*cmdlinep)[1] == '!')
        goto doend;
@@ -1970,6 +1973,11 @@
                            cmdmod.lockmarks = TRUE;
                            continue;
                        }
+                       if (checkforcmd(&ea.cmd, "lockjumps", 5))
+                       {
+                           cmdmod.lockjumps = TRUE;
+                           continue;
+                       }
 
                        if (!checkforcmd(&ea.cmd, "leftabove", 5))
                            break;
@@ -2839,6 +2847,7 @@
            case CMD_leftabove:
            case CMD_let:
            case CMD_lockmarks:
+           case CMD_lockjumps:
            case CMD_lua:
            case CMD_match:
            case CMD_mzscheme:
@@ -3341,6 +3350,7 @@
     {"keeppatterns", 5, FALSE},
     {"leftabove", 5, FALSE},
     {"lockmarks", 3, FALSE},
+    {"lockjumps", 5, FALSE},
     {"noautocmd", 3, FALSE},
     {"noswapfile", 3, FALSE},
     {"rightbelow", 6, FALSE},
diff --git a/src/mark.c b/src/mark.c
--- a/src/mark.c
+++ b/src/mark.c
@@ -156,39 +156,42 @@
     curwin->w_pcmark = curwin->w_cursor;
 
 #ifdef FEAT_JUMPLIST
+    if (!cmdmod.lockjumps)
+    {
 # ifdef JUMPLIST_ROTATE
-    /*
-     * If last used entry is not at the top, put it at the top by rotating
-     * the stack until it is (the newer entries will be at the bottom).
-     * Keep one entry (the last used one) at the top.
-     */
-    if (curwin->w_jumplistidx < curwin->w_jumplistlen)
-       ++curwin->w_jumplistidx;
-    while (curwin->w_jumplistidx < curwin->w_jumplistlen)
-    {
-       tempmark = curwin->w_jumplist[curwin->w_jumplistlen - 1];
-       for (i = curwin->w_jumplistlen - 1; i > 0; --i)
-           curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
-       curwin->w_jumplist[0] = tempmark;
-       ++curwin->w_jumplistidx;
-    }
+       /*
+        * If last used entry is not at the top, put it at the top by rotating
+        * the stack until it is (the newer entries will be at the bottom).
+        * Keep one entry (the last used one) at the top.
+        */
+       if (curwin->w_jumplistidx < curwin->w_jumplistlen)
+           ++curwin->w_jumplistidx;
+       while (curwin->w_jumplistidx < curwin->w_jumplistlen)
+       {
+           tempmark = curwin->w_jumplist[curwin->w_jumplistlen - 1];
+           for (i = curwin->w_jumplistlen - 1; i > 0; --i)
+               curwin->w_jumplist[i] = curwin->w_jumplist[i - 1];
+           curwin->w_jumplist[0] = tempmark;
+           ++curwin->w_jumplistidx;
+       }
 # endif
 
-    /* If jumplist is full: remove oldest entry */
-    if (++curwin->w_jumplistlen > JUMPLISTSIZE)
-    {
-       curwin->w_jumplistlen = JUMPLISTSIZE;
-       vim_free(curwin->w_jumplist[0].fname);
-       for (i = 1; i < JUMPLISTSIZE; ++i)
-           curwin->w_jumplist[i - 1] = curwin->w_jumplist[i];
+       /* If jumplist is full: remove oldest entry */
+       if (++curwin->w_jumplistlen > JUMPLISTSIZE)
+       {
+           curwin->w_jumplistlen = JUMPLISTSIZE;
+           vim_free(curwin->w_jumplist[0].fname);
+           for (i = 1; i < JUMPLISTSIZE; ++i)
+               curwin->w_jumplist[i - 1] = curwin->w_jumplist[i];
+       }
+       curwin->w_jumplistidx = curwin->w_jumplistlen;
+       fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
+
+       fm->fmark.mark = curwin->w_pcmark;
+       fm->fmark.fnum = curbuf->b_fnum;
+       fm->fname = NULL;
+#endif
     }
-    curwin->w_jumplistidx = curwin->w_jumplistlen;
-    fm = &curwin->w_jumplist[curwin->w_jumplistlen - 1];
-
-    fm->fmark.mark = curwin->w_pcmark;
-    fm->fmark.fnum = curbuf->b_fnum;
-    fm->fname = NULL;
-#endif
 }
 
 /*
diff --git a/src/structs.h b/src/structs.h
--- a/src/structs.h
+++ b/src/structs.h
@@ -550,6 +550,7 @@
     int                keepmarks;              /* TRUE when ":keepmarks" was 
used */
     int                keepjumps;              /* TRUE when ":keepjumps" was 
used */
     int                lockmarks;              /* TRUE when ":lockmarks" was 
used */
+    int                lockjumps;              /* TRUE when ":lockjumps" was 
used */
     int                keeppatterns;           /* TRUE when ":keeppatterns" 
was used */
     int                noswapfile;             /* TRUE when ":noswapfile" was 
used */
 # ifdef FEAT_AUTOCMD

Raspunde prin e-mail lui