]> granicus.if.org Git - vim/commitdiff
patch 8.1.2302: :lockmarks does not work for '[ and '] v8.1.2302
authorBram Moolenaar <Bram@vim.org>
Sat, 16 Nov 2019 12:50:25 +0000 (13:50 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 16 Nov 2019 12:50:25 +0000 (13:50 +0100)
Problem:    :lockmarks does not work for '[ and '].
Solution:   save and restore '[ and '] marks. (James McCoy, closes #5222)

src/bufwrite.c
src/diff.c
src/ex_cmds.c
src/fileio.c
src/indent.c
src/ops.c
src/register.c
src/testdir/test_autocmd.vim
src/testdir/test_diffmode.vim
src/version.c

index 13091a336e473aa9b0359a17ace49446c9ac93b9..8393df1a0c52e0d9a7e1fb4b944efd3c35837a1e 100644 (file)
@@ -683,6 +683,8 @@ buf_write(
     context_sha256_T sha_ctx;
 #endif
     unsigned int    bkc = get_bkc_value(buf);
+    pos_T          orig_start = buf->b_op_start;
+    pos_T          orig_end = buf->b_op_end;
 
     if (fname == NULL || *fname == NUL)        // safety check
        return FAIL;
@@ -875,6 +877,13 @@ buf_write(
 #endif
                                       )
        {
+           if (buf != NULL && cmdmod.lockmarks)
+           {
+               // restore the original '[ and '] positions
+               buf->b_op_start = orig_start;
+               buf->b_op_end = orig_end;
+           }
+
            --no_wait_return;
            msg_scroll = msg_save;
            if (nofile_err)
@@ -952,6 +961,13 @@ buf_write(
            fname = buf->b_sfname;
     }
 
+    if (cmdmod.lockmarks)
+    {
+       // restore the original '[ and '] positions
+       buf->b_op_start = orig_start;
+       buf->b_op_end = orig_end;
+    }
+
 #ifdef FEAT_NETBEANS_INTG
     if (netbeans_active() && isNetbeansBuffer(buf))
     {
index b16f7b6f3e127df055f95e2ce2df7a560b23720f..dd5fb22f40274dc274224f8e0f48958e303622ea 100644 (file)
@@ -772,6 +772,7 @@ diff_write(buf_T *buf, diffin_T *din)
 {
     int                r;
     char_u     *save_ff;
+    int                save_lockmarks;
 
     if (din->din_fname == NULL)
        return diff_write_buffer(buf, din);
@@ -779,9 +780,14 @@ diff_write(buf_T *buf, diffin_T *din)
     // Always use 'fileformat' set to "unix".
     save_ff = buf->b_p_ff;
     buf->b_p_ff = vim_strsave((char_u *)FF_UNIX);
+    save_lockmarks = cmdmod.lockmarks;
+    // Writing the buffer is an implementation detail of performing the diff,
+    // so it shouldn't update the '[ and '] marks.
+    cmdmod.lockmarks = TRUE;
     r = buf_write(buf, din->din_fname, NULL,
                        (linenr_T)1, buf->b_ml.ml_line_count,
                        NULL, FALSE, FALSE, FALSE, TRUE);
+    cmdmod.lockmarks = save_lockmarks;
     free_string_option(buf->b_p_ff);
     buf->b_p_ff = save_ff;
     return r;
index c15bbc5f4cfc14f0b5079f2179c6a594adba876c..5615adcaa5de8430928345c3d20872d8a444ea05 100644 (file)
@@ -749,8 +749,11 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
                foldMoveRange(&win->w_folds, line1, line2, dest);
        }
 #endif
-       curbuf->b_op_start.lnum = dest - num_lines + 1;
-       curbuf->b_op_end.lnum = dest;
+       if (!cmdmod.lockmarks)
+       {
+           curbuf->b_op_start.lnum = dest - num_lines + 1;
+           curbuf->b_op_end.lnum = dest;
+       }
     }
     else
     {
@@ -761,10 +764,14 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
                foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2);
        }
 #endif
-       curbuf->b_op_start.lnum = dest + 1;
-       curbuf->b_op_end.lnum = dest + num_lines;
+       if (!cmdmod.lockmarks)
+       {
+           curbuf->b_op_start.lnum = dest + 1;
+           curbuf->b_op_end.lnum = dest + num_lines;
+       }
     }
-    curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+    if (!cmdmod.lockmarks)
+       curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
     mark_adjust_nofold(last_line - num_lines + 1, last_line,
                                             -(last_line - dest - extra), 0L);
 
@@ -813,9 +820,12 @@ ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
     char_u     *p;
 
     count = line2 - line1 + 1;
-    curbuf->b_op_start.lnum = n + 1;
-    curbuf->b_op_end.lnum = n + count;
-    curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+    if (!cmdmod.lockmarks)
+    {
+       curbuf->b_op_start.lnum = n + 1;
+       curbuf->b_op_end.lnum = n + count;
+       curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+    }
 
     /*
      * there are three situations:
@@ -1055,10 +1065,17 @@ do_filter(
     char_u     *cmd_buf;
     buf_T      *old_curbuf = curbuf;
     int                shell_flags = 0;
+    pos_T      orig_start = curbuf->b_op_start;
+    pos_T      orig_end = curbuf->b_op_end;
+    int                save_lockmarks = cmdmod.lockmarks;
 
     if (*cmd == NUL)       /* no filter command */
        return;
 
+    // Temporarily disable lockmarks since that's needed to propagate changed
+    // regions of the buffer for foldUpdate(), linecount, etc.
+    cmdmod.lockmarks = 0;
+
     cursor_save = curwin->w_cursor;
     linecount = line2 - line1 + 1;
     curwin->w_cursor.lnum = line1;
@@ -1287,11 +1304,18 @@ error:
 
 filterend:
 
+    cmdmod.lockmarks = save_lockmarks;
     if (curbuf != old_curbuf)
     {
        --no_wait_return;
        emsg(_("E135: *Filter* Autocommands must not change current buffer"));
     }
+    else if (cmdmod.lockmarks)
+    {
+       curbuf->b_op_start = orig_start;
+       curbuf->b_op_end = orig_end;
+    }
+
     if (itmp != NULL)
        mch_remove(itmp);
     if (otmp != NULL)
@@ -3276,13 +3300,16 @@ ex_append(exarg_T *eap)
      * eap->line2 pointed to the end of the buffer and nothing was appended)
      * "end" is set to lnum when something has been appended, otherwise
      * it is the same than "start"  -- Acevedo */
-    curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
-       eap->line2 + 1 : curbuf->b_ml.ml_line_count;
-    if (eap->cmdidx != CMD_append)
-       --curbuf->b_op_start.lnum;
-    curbuf->b_op_end.lnum = (eap->line2 < lnum)
-                                            ? lnum : curbuf->b_op_start.lnum;
-    curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+    if (!cmdmod.lockmarks)
+    {
+       curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
+           eap->line2 + 1 : curbuf->b_ml.ml_line_count;
+       if (eap->cmdidx != CMD_append)
+           --curbuf->b_op_start.lnum;
+       curbuf->b_op_end.lnum = (eap->line2 < lnum)
+                                                ? lnum : curbuf->b_op_start.lnum;
+       curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+    }
     curwin->w_cursor.lnum = lnum;
     check_cursor_lnum();
     beginline(BL_SOL | BL_FIX);
@@ -4592,10 +4619,13 @@ outofmem:
 
     if (sub_nsubs > start_nsubs)
     {
-       /* Set the '[ and '] marks. */
-       curbuf->b_op_start.lnum = eap->line1;
-       curbuf->b_op_end.lnum = line2;
-       curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+       if (!cmdmod.lockmarks)
+       {
+           // Set the '[ and '] marks.
+           curbuf->b_op_start.lnum = eap->line1;
+           curbuf->b_op_end.lnum = line2;
+           curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
+       }
 
        if (!global_busy)
        {
index 0c2238be6b51b963657d6a97a1edf01fb5437494..85c5e6827fa3ef5e65e46810495a5dab2cce1175 100644 (file)
@@ -188,6 +188,7 @@ readfile(
                                           wasn't possible */
     char_u     conv_rest[CONV_RESTLEN];
     int                conv_restlen = 0;       /* nr of bytes in conv_rest[] */
+    pos_T      orig_start;
     buf_T      *old_curbuf;
     char_u     *old_b_ffname;
     char_u     *old_b_fname;
@@ -250,9 +251,7 @@ readfile(
      */
     if (!filtering && !read_stdin && !read_buffer)
     {
-       pos_T       pos;
-
-       pos = curbuf->b_op_start;
+       orig_start = curbuf->b_op_start;
 
        /* Set '[ mark to the line above where the lines go (line 1 if zero). */
        curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
@@ -276,7 +275,7 @@ readfile(
            return OK;
 #endif
 
-       curbuf->b_op_start = pos;
+       curbuf->b_op_start = orig_start;
     }
 
     if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
@@ -617,6 +616,7 @@ readfile(
     /*
      * Set '[ mark to the line above where the lines go (line 1 if zero).
      */
+    orig_start = curbuf->b_op_start;
     curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
     curbuf->b_op_start.col = 0;
 
@@ -658,6 +658,7 @@ readfile(
        try_mac = (vim_strchr(p_ffs, 'm') != NULL);
        try_dos = (vim_strchr(p_ffs, 'd') != NULL);
        try_unix = (vim_strchr(p_ffs, 'x') != NULL);
+       curbuf->b_op_start = orig_start;
 
        if (msg_scrolled == n)
            msg_scroll = m;
@@ -2471,13 +2472,14 @@ failed:
        check_cursor_lnum();
        beginline(BL_WHITE | BL_FIX);       /* on first non-blank */
 
-       /*
-        * Set '[ and '] marks to the newly read lines.
-        */
-       curbuf->b_op_start.lnum = from + 1;
-       curbuf->b_op_start.col = 0;
-       curbuf->b_op_end.lnum = from + linecnt;
-       curbuf->b_op_end.col = 0;
+       if (!cmdmod.lockmarks)
+       {
+           // Set '[ and '] marks to the newly read lines.
+           curbuf->b_op_start.lnum = from + 1;
+           curbuf->b_op_start.col = 0;
+           curbuf->b_op_end.lnum = from + linecnt;
+           curbuf->b_op_end.col = 0;
+       }
 
 #ifdef MSWIN
        /*
index 755c3a9e44a81ba06f701816bef380eefb197016..8d574c8a7115f3454b293a5f0dd322e26162cecc 100644 (file)
@@ -1001,9 +1001,12 @@ op_reindent(oparg_T *oap, int (*how)(void))
        smsg(NGETTEXT("%ld line indented ",
                                                 "%ld lines indented ", i), i);
     }
-    // set '[ and '] marks
-    curbuf->b_op_start = oap->start;
-    curbuf->b_op_end = oap->end;
+    if (!cmdmod.lockmarks)
+    {
+       // set '[ and '] marks
+       curbuf->b_op_start = oap->start;
+       curbuf->b_op_end = oap->end;
+    }
 }
 #endif // defined(FEAT_LISP) || defined(FEAT_CINDENT)
 
index 258b27173ba258b9354e61a1733ae7a82d891186..b2827b263c121763973989cf242ba48ff5f5a765 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -206,14 +206,15 @@ op_shift(oparg_T *oap, int curs_top, int amount)
        msg((char *)IObuff);
     }
 
-    /*
-     * Set "'[" and "']" marks.
-     */
-    curbuf->b_op_start = oap->start;
-    curbuf->b_op_end.lnum = oap->end.lnum;
-    curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
-    if (curbuf->b_op_end.col > 0)
-       --curbuf->b_op_end.col;
+    if (!cmdmod.lockmarks)
+    {
+       // Set "'[" and "']" marks.
+       curbuf->b_op_start = oap->start;
+       curbuf->b_op_end.lnum = oap->end.lnum;
+       curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
+       if (curbuf->b_op_end.col > 0)
+           --curbuf->b_op_end.col;
+    }
 }
 
 /*
@@ -981,14 +982,17 @@ op_delete(oparg_T *oap)
     msgmore(curbuf->b_ml.ml_line_count - old_lcount);
 
 setmarks:
-    if (oap->block_mode)
+    if (!cmdmod.lockmarks)
     {
-       curbuf->b_op_end.lnum = oap->end.lnum;
-       curbuf->b_op_end.col = oap->start.col;
+       if (oap->block_mode)
+       {
+           curbuf->b_op_end.lnum = oap->end.lnum;
+           curbuf->b_op_end.col = oap->start.col;
+       }
+       else
+           curbuf->b_op_end = oap->start;
+       curbuf->b_op_start = oap->start;
     }
-    else
-       curbuf->b_op_end = oap->start;
-    curbuf->b_op_start = oap->start;
 
     return OK;
 }
@@ -1252,9 +1256,12 @@ op_replace(oparg_T *oap, int c)
     check_cursor();
     changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L);
 
-    /* Set "'[" and "']" marks. */
-    curbuf->b_op_start = oap->start;
-    curbuf->b_op_end = oap->end;
+    if (!cmdmod.lockmarks)
+    {
+       /* Set "'[" and "']" marks. */
+       curbuf->b_op_start = oap->start;
+       curbuf->b_op_end = oap->end;
+    }
 
     return OK;
 }
@@ -1362,11 +1369,12 @@ op_tilde(oparg_T *oap)
        /* No change: need to remove the Visual selection */
        redraw_curbuf_later(INVERTED);
 
-    /*
-     * Set '[ and '] marks.
-     */
-    curbuf->b_op_start = oap->start;
-    curbuf->b_op_end = oap->end;
+    if (!cmdmod.lockmarks)
+    {
+       // Set '[ and '] marks.
+       curbuf->b_op_start = oap->start;
+       curbuf->b_op_end = oap->end;
+    }
 
     if (oap->line_count > p_report)
        smsg(NGETTEXT("%ld line changed", "%ld lines changed",
@@ -1973,7 +1981,7 @@ do_join(
     for (t = 0; t < count; ++t)
     {
        curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t));
-       if (t == 0 && setmark)
+       if (t == 0 && setmark && !cmdmod.lockmarks)
        {
            /* Set the '[ mark. */
            curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum;
@@ -2129,7 +2137,7 @@ do_join(
 #endif
        ml_replace(curwin->w_cursor.lnum, newp, FALSE);
 
-    if (setmark)
+    if (setmark && !cmdmod.lockmarks)
     {
        /* Set the '] mark. */
        curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum;
@@ -2268,8 +2276,9 @@ op_format(
        /* When there is no change: need to remove the Visual selection */
        redraw_curbuf_later(INVERTED);
 
-    /* Set '[ mark at the start of the formatted area */
-    curbuf->b_op_start = oap->start;
+    if (!cmdmod.lockmarks)
+       /* Set '[ mark at the start of the formatted area */
+       curbuf->b_op_start = oap->start;
 
     /* For "gw" remember the cursor position and put it back below (adjusted
      * for joined and split lines). */
@@ -2289,8 +2298,9 @@ op_format(
     old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
     msgmore(old_line_count);
 
-    /* put '] mark on the end of the formatted area */
-    curbuf->b_op_end = curwin->w_cursor;
+    if (!cmdmod.lockmarks)
+       /* put '] mark on the end of the formatted area */
+       curbuf->b_op_end = curwin->w_cursor;
 
     if (keep_cursor)
     {
@@ -2984,7 +2994,7 @@ op_addsub(
 
        /* Set '[ mark if something changed. Keep the last end
         * position from do_addsub(). */
-       if (change_cnt > 0)
+       if (change_cnt > 0 && !cmdmod.lockmarks)
            curbuf->b_op_start = startpos;
 
        if (change_cnt > p_report)
@@ -3384,7 +3394,7 @@ do_addsub(
            --curwin->w_cursor.col;
     }
 
-    if (did_change)
+    if (did_change && !cmdmod.lockmarks)
     {
        /* set the '[ and '] marks */
        curbuf->b_op_start = startpos;
@@ -3905,6 +3915,8 @@ op_function(oparg_T *oap UNUSED)
 #ifdef FEAT_EVAL
     typval_T   argv[2];
     int                save_virtual_op = virtual_op;
+    pos_T      orig_start = curbuf->b_op_start;
+    pos_T      orig_end = curbuf->b_op_end;
 
     if (*p_opfunc == NUL)
        emsg(_("E774: 'operatorfunc' is empty"));
@@ -3933,6 +3945,11 @@ op_function(oparg_T *oap UNUSED)
        (void)call_func_retnr(p_opfunc, 1, argv);
 
        virtual_op = save_virtual_op;
+       if (cmdmod.lockmarks)
+       {
+           curbuf->b_op_start = orig_start;
+           curbuf->b_op_end = orig_end;
+       }
     }
 #else
     emsg(_("E775: Eval feature not available"));
index 2e838402b688878c97a751de0d4c8ca125b4c45e..ee7c618fe918ee84821a90d1ccce7ce292ec6aa0 100644 (file)
@@ -1316,13 +1316,16 @@ op_yank(oparg_T *oap, int deleting, int mess)
        }
     }
 
-    // Set "'[" and "']" marks.
-    curbuf->b_op_start = oap->start;
-    curbuf->b_op_end = oap->end;
-    if (yanktype == MLINE && !oap->block_mode)
+    if (!cmdmod.lockmarks)
     {
-       curbuf->b_op_start.col = 0;
-       curbuf->b_op_end.col = MAXCOL;
+       // Set "'[" and "']" marks.
+       curbuf->b_op_start = oap->start;
+       curbuf->b_op_end = oap->end;
+       if (yanktype == MLINE && !oap->block_mode)
+       {
+           curbuf->b_op_start.col = 0;
+           curbuf->b_op_end.col = MAXCOL;
+       }
     }
 
 #ifdef FEAT_CLIPBOARD
@@ -1474,6 +1477,8 @@ do_put(
     char_u     *insert_string = NULL;
     int                allocated = FALSE;
     long       cnt;
+    pos_T      orig_start = curbuf->b_op_start;
+    pos_T      orig_end = curbuf->b_op_end;
 
 #ifdef FEAT_CLIPBOARD
     // Adjust register name for "unnamed" in 'clipboard'.
@@ -2100,6 +2105,11 @@ error:
     curwin->w_set_curswant = TRUE;
 
 end:
+    if (cmdmod.lockmarks)
+    {
+       curbuf->b_op_start = orig_start;
+       curbuf->b_op_end = orig_end;
+    }
     if (allocated)
        vim_free(insert_string);
     if (regname == '=')
index eba365e399e0b874d4ffd2fc0ab16af70c0622bd..6d1897a4aa3165e0085b9d02712d649d48b7202a 100644 (file)
@@ -2297,3 +2297,37 @@ func Test_autocmd_was_using_freed_memory()
   split
   au! WinEnter
 endfunc
+
+func Test_BufWrite_lockmarks()
+  edit! Xtest
+  call setline(1, ['a', 'b', 'c', 'd'])
+
+  " :lockmarks preserves the marks
+  call SetChangeMarks(2, 3)
+  lockmarks write
+  call assert_equal([2, 3], [line("'["), line("']")])
+
+  " *WritePre autocmds get the correct line range, but lockmarks preserves the
+  " original values for the user
+  augroup lockmarks
+    au!
+    au BufWritePre,FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
+    au FileWritePre * call assert_equal([3, 4], [line("'["), line("']")])
+  augroup END
+
+  lockmarks write
+  call assert_equal([2, 3], [line("'["), line("']")])
+
+  if executable('cat')
+    lockmarks %!cat
+    call assert_equal([2, 3], [line("'["), line("']")])
+  endif
+
+  lockmarks 3,4write Xtest2
+  call assert_equal([2, 3], [line("'["), line("']")])
+
+  au! lockmarks
+  augroup! lockmarks
+  call delete('Xtest')
+  call delete('Xtest2')
+endfunc
index 6f4eaaf4316832f645d9978addde01539f23a905..9dfe2fefce3f4dff6233cfc0cb5d88a19d69a537 100644 (file)
@@ -989,3 +989,22 @@ func Test_diff_closeoff()
   diffoff!
   enew!
 endfunc
+
+func Test_diff_maintains_change_mark()
+  enew!
+  call setline(1, ['a', 'b', 'c', 'd'])
+  diffthis
+  new
+  call setline(1, ['a', 'b', 'c', 'e'])
+  " Set '[ and '] marks
+  2,3yank
+  call assert_equal([2, 3], [line("'["), line("']")])
+  " Verify they aren't affected by the implicit diff
+  diffthis
+  call assert_equal([2, 3], [line("'["), line("']")])
+  " Verify they aren't affected by an explicit diff
+  diffupdate
+  call assert_equal([2, 3], [line("'["), line("']")])
+  bwipe!
+  bwipe!
+endfunc
index b91643461d10246d48c3db5917f9757afa1fcf37..500ec911fcfb0fc811c50481d9342e98b25a61bd 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2302,
 /**/
     2301,
 /**/