0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.1.2302: :lockmarks does not work for '[ and ']

Problem:    :lockmarks does not work for '[ and '].
Solution:   save and restore '[ and '] marks. (James McCoy, closes #5222)
This commit is contained in:
Bram Moolenaar 2019-11-16 13:50:25 +01:00
parent ab85ca4e6a
commit f4a1d1c054
10 changed files with 208 additions and 69 deletions

View File

@ -683,6 +683,8 @@ buf_write(
context_sha256_T sha_ctx; context_sha256_T sha_ctx;
#endif #endif
unsigned int bkc = get_bkc_value(buf); 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 if (fname == NULL || *fname == NUL) // safety check
return FAIL; return FAIL;
@ -875,6 +877,13 @@ buf_write(
#endif #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; --no_wait_return;
msg_scroll = msg_save; msg_scroll = msg_save;
if (nofile_err) if (nofile_err)
@ -952,6 +961,13 @@ buf_write(
fname = buf->b_sfname; 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 #ifdef FEAT_NETBEANS_INTG
if (netbeans_active() && isNetbeansBuffer(buf)) if (netbeans_active() && isNetbeansBuffer(buf))
{ {

View File

@ -772,6 +772,7 @@ diff_write(buf_T *buf, diffin_T *din)
{ {
int r; int r;
char_u *save_ff; char_u *save_ff;
int save_lockmarks;
if (din->din_fname == NULL) if (din->din_fname == NULL)
return diff_write_buffer(buf, din); return diff_write_buffer(buf, din);
@ -779,9 +780,14 @@ diff_write(buf_T *buf, diffin_T *din)
// Always use 'fileformat' set to "unix". // Always use 'fileformat' set to "unix".
save_ff = buf->b_p_ff; save_ff = buf->b_p_ff;
buf->b_p_ff = vim_strsave((char_u *)FF_UNIX); 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, r = buf_write(buf, din->din_fname, NULL,
(linenr_T)1, buf->b_ml.ml_line_count, (linenr_T)1, buf->b_ml.ml_line_count,
NULL, FALSE, FALSE, FALSE, TRUE); NULL, FALSE, FALSE, FALSE, TRUE);
cmdmod.lockmarks = save_lockmarks;
free_string_option(buf->b_p_ff); free_string_option(buf->b_p_ff);
buf->b_p_ff = save_ff; buf->b_p_ff = save_ff;
return r; return r;

View File

@ -749,8 +749,11 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
foldMoveRange(&win->w_folds, line1, line2, dest); foldMoveRange(&win->w_folds, line1, line2, dest);
} }
#endif #endif
curbuf->b_op_start.lnum = dest - num_lines + 1; if (!cmdmod.lockmarks)
curbuf->b_op_end.lnum = dest; {
curbuf->b_op_start.lnum = dest - num_lines + 1;
curbuf->b_op_end.lnum = dest;
}
} }
else 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); foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2);
} }
#endif #endif
curbuf->b_op_start.lnum = dest + 1; if (!cmdmod.lockmarks)
curbuf->b_op_end.lnum = dest + num_lines; {
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, mark_adjust_nofold(last_line - num_lines + 1, last_line,
-(last_line - dest - extra), 0L); -(last_line - dest - extra), 0L);
@ -813,9 +820,12 @@ ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
char_u *p; char_u *p;
count = line2 - line1 + 1; count = line2 - line1 + 1;
curbuf->b_op_start.lnum = n + 1; if (!cmdmod.lockmarks)
curbuf->b_op_end.lnum = n + count; {
curbuf->b_op_start.col = curbuf->b_op_end.col = 0; 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: * there are three situations:
@ -1055,10 +1065,17 @@ do_filter(
char_u *cmd_buf; char_u *cmd_buf;
buf_T *old_curbuf = curbuf; buf_T *old_curbuf = curbuf;
int shell_flags = 0; 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 */ if (*cmd == NUL) /* no filter command */
return; 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; cursor_save = curwin->w_cursor;
linecount = line2 - line1 + 1; linecount = line2 - line1 + 1;
curwin->w_cursor.lnum = line1; curwin->w_cursor.lnum = line1;
@ -1287,11 +1304,18 @@ error:
filterend: filterend:
cmdmod.lockmarks = save_lockmarks;
if (curbuf != old_curbuf) if (curbuf != old_curbuf)
{ {
--no_wait_return; --no_wait_return;
emsg(_("E135: *Filter* Autocommands must not change current buffer")); 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) if (itmp != NULL)
mch_remove(itmp); mch_remove(itmp);
if (otmp != NULL) 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) * eap->line2 pointed to the end of the buffer and nothing was appended)
* "end" is set to lnum when something has been appended, otherwise * "end" is set to lnum when something has been appended, otherwise
* it is the same than "start" -- Acevedo */ * it is the same than "start" -- Acevedo */
curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ? if (!cmdmod.lockmarks)
eap->line2 + 1 : curbuf->b_ml.ml_line_count; {
if (eap->cmdidx != CMD_append) curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
--curbuf->b_op_start.lnum; eap->line2 + 1 : curbuf->b_ml.ml_line_count;
curbuf->b_op_end.lnum = (eap->line2 < lnum) if (eap->cmdidx != CMD_append)
? lnum : curbuf->b_op_start.lnum; --curbuf->b_op_start.lnum;
curbuf->b_op_start.col = curbuf->b_op_end.col = 0; 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; curwin->w_cursor.lnum = lnum;
check_cursor_lnum(); check_cursor_lnum();
beginline(BL_SOL | BL_FIX); beginline(BL_SOL | BL_FIX);
@ -4592,10 +4619,13 @@ outofmem:
if (sub_nsubs > start_nsubs) if (sub_nsubs > start_nsubs)
{ {
/* Set the '[ and '] marks. */ if (!cmdmod.lockmarks)
curbuf->b_op_start.lnum = eap->line1; {
curbuf->b_op_end.lnum = line2; // Set the '[ and '] marks.
curbuf->b_op_start.col = curbuf->b_op_end.col = 0; 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) if (!global_busy)
{ {

View File

@ -188,6 +188,7 @@ readfile(
wasn't possible */ wasn't possible */
char_u conv_rest[CONV_RESTLEN]; char_u conv_rest[CONV_RESTLEN];
int conv_restlen = 0; /* nr of bytes in conv_rest[] */ int conv_restlen = 0; /* nr of bytes in conv_rest[] */
pos_T orig_start;
buf_T *old_curbuf; buf_T *old_curbuf;
char_u *old_b_ffname; char_u *old_b_ffname;
char_u *old_b_fname; char_u *old_b_fname;
@ -250,9 +251,7 @@ readfile(
*/ */
if (!filtering && !read_stdin && !read_buffer) if (!filtering && !read_stdin && !read_buffer)
{ {
pos_T pos; orig_start = curbuf->b_op_start;
pos = curbuf->b_op_start;
/* Set '[ mark to the line above where the lines go (line 1 if zero). */ /* Set '[ mark to the line above where the lines go (line 1 if zero). */
curbuf->b_op_start.lnum = ((from == 0) ? 1 : from); curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
@ -276,7 +275,7 @@ readfile(
return OK; return OK;
#endif #endif
curbuf->b_op_start = pos; curbuf->b_op_start = orig_start;
} }
if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0) 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). * 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.lnum = ((from == 0) ? 1 : from);
curbuf->b_op_start.col = 0; curbuf->b_op_start.col = 0;
@ -658,6 +658,7 @@ readfile(
try_mac = (vim_strchr(p_ffs, 'm') != NULL); try_mac = (vim_strchr(p_ffs, 'm') != NULL);
try_dos = (vim_strchr(p_ffs, 'd') != NULL); try_dos = (vim_strchr(p_ffs, 'd') != NULL);
try_unix = (vim_strchr(p_ffs, 'x') != NULL); try_unix = (vim_strchr(p_ffs, 'x') != NULL);
curbuf->b_op_start = orig_start;
if (msg_scrolled == n) if (msg_scrolled == n)
msg_scroll = m; msg_scroll = m;
@ -2471,13 +2472,14 @@ failed:
check_cursor_lnum(); check_cursor_lnum();
beginline(BL_WHITE | BL_FIX); /* on first non-blank */ beginline(BL_WHITE | BL_FIX); /* on first non-blank */
/* if (!cmdmod.lockmarks)
* Set '[ and '] marks to the newly read lines. {
*/ // Set '[ and '] marks to the newly read lines.
curbuf->b_op_start.lnum = from + 1; curbuf->b_op_start.lnum = from + 1;
curbuf->b_op_start.col = 0; curbuf->b_op_start.col = 0;
curbuf->b_op_end.lnum = from + linecnt; curbuf->b_op_end.lnum = from + linecnt;
curbuf->b_op_end.col = 0; curbuf->b_op_end.col = 0;
}
#ifdef MSWIN #ifdef MSWIN
/* /*

View File

@ -1001,9 +1001,12 @@ op_reindent(oparg_T *oap, int (*how)(void))
smsg(NGETTEXT("%ld line indented ", smsg(NGETTEXT("%ld line indented ",
"%ld lines indented ", i), i); "%ld lines indented ", i), i);
} }
// set '[ and '] marks if (!cmdmod.lockmarks)
curbuf->b_op_start = oap->start; {
curbuf->b_op_end = oap->end; // set '[ and '] marks
curbuf->b_op_start = oap->start;
curbuf->b_op_end = oap->end;
}
} }
#endif // defined(FEAT_LISP) || defined(FEAT_CINDENT) #endif // defined(FEAT_LISP) || defined(FEAT_CINDENT)

View File

@ -206,14 +206,15 @@ op_shift(oparg_T *oap, int curs_top, int amount)
msg((char *)IObuff); msg((char *)IObuff);
} }
/* if (!cmdmod.lockmarks)
* Set "'[" and "']" marks. {
*/ // Set "'[" and "']" marks.
curbuf->b_op_start = oap->start; curbuf->b_op_start = oap->start;
curbuf->b_op_end.lnum = oap->end.lnum; curbuf->b_op_end.lnum = oap->end.lnum;
curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
if (curbuf->b_op_end.col > 0) if (curbuf->b_op_end.col > 0)
--curbuf->b_op_end.col; --curbuf->b_op_end.col;
}
} }
/* /*
@ -981,14 +982,17 @@ op_delete(oparg_T *oap)
msgmore(curbuf->b_ml.ml_line_count - old_lcount); msgmore(curbuf->b_ml.ml_line_count - old_lcount);
setmarks: setmarks:
if (oap->block_mode) if (!cmdmod.lockmarks)
{ {
curbuf->b_op_end.lnum = oap->end.lnum; if (oap->block_mode)
curbuf->b_op_end.col = oap->start.col; {
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; return OK;
} }
@ -1252,9 +1256,12 @@ op_replace(oparg_T *oap, int c)
check_cursor(); check_cursor();
changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L); changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L);
/* Set "'[" and "']" marks. */ if (!cmdmod.lockmarks)
curbuf->b_op_start = oap->start; {
curbuf->b_op_end = oap->end; /* Set "'[" and "']" marks. */
curbuf->b_op_start = oap->start;
curbuf->b_op_end = oap->end;
}
return OK; return OK;
} }
@ -1362,11 +1369,12 @@ op_tilde(oparg_T *oap)
/* No change: need to remove the Visual selection */ /* No change: need to remove the Visual selection */
redraw_curbuf_later(INVERTED); redraw_curbuf_later(INVERTED);
/* if (!cmdmod.lockmarks)
* Set '[ and '] marks. {
*/ // Set '[ and '] marks.
curbuf->b_op_start = oap->start; curbuf->b_op_start = oap->start;
curbuf->b_op_end = oap->end; curbuf->b_op_end = oap->end;
}
if (oap->line_count > p_report) if (oap->line_count > p_report)
smsg(NGETTEXT("%ld line changed", "%ld lines changed", smsg(NGETTEXT("%ld line changed", "%ld lines changed",
@ -1973,7 +1981,7 @@ do_join(
for (t = 0; t < count; ++t) for (t = 0; t < count; ++t)
{ {
curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + 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. */ /* Set the '[ mark. */
curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum; curwin->w_buffer->b_op_start.lnum = curwin->w_cursor.lnum;
@ -2129,7 +2137,7 @@ do_join(
#endif #endif
ml_replace(curwin->w_cursor.lnum, newp, FALSE); ml_replace(curwin->w_cursor.lnum, newp, FALSE);
if (setmark) if (setmark && !cmdmod.lockmarks)
{ {
/* Set the '] mark. */ /* Set the '] mark. */
curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum; 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 */ /* When there is no change: need to remove the Visual selection */
redraw_curbuf_later(INVERTED); redraw_curbuf_later(INVERTED);
/* Set '[ mark at the start of the formatted area */ if (!cmdmod.lockmarks)
curbuf->b_op_start = oap->start; /* 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 "gw" remember the cursor position and put it back below (adjusted
* for joined and split lines). */ * for joined and split lines). */
@ -2289,8 +2298,9 @@ op_format(
old_line_count = curbuf->b_ml.ml_line_count - old_line_count; old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
msgmore(old_line_count); msgmore(old_line_count);
/* put '] mark on the end of the formatted area */ if (!cmdmod.lockmarks)
curbuf->b_op_end = curwin->w_cursor; /* put '] mark on the end of the formatted area */
curbuf->b_op_end = curwin->w_cursor;
if (keep_cursor) if (keep_cursor)
{ {
@ -2984,7 +2994,7 @@ op_addsub(
/* Set '[ mark if something changed. Keep the last end /* Set '[ mark if something changed. Keep the last end
* position from do_addsub(). */ * position from do_addsub(). */
if (change_cnt > 0) if (change_cnt > 0 && !cmdmod.lockmarks)
curbuf->b_op_start = startpos; curbuf->b_op_start = startpos;
if (change_cnt > p_report) if (change_cnt > p_report)
@ -3384,7 +3394,7 @@ do_addsub(
--curwin->w_cursor.col; --curwin->w_cursor.col;
} }
if (did_change) if (did_change && !cmdmod.lockmarks)
{ {
/* set the '[ and '] marks */ /* set the '[ and '] marks */
curbuf->b_op_start = startpos; curbuf->b_op_start = startpos;
@ -3905,6 +3915,8 @@ op_function(oparg_T *oap UNUSED)
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
typval_T argv[2]; typval_T argv[2];
int save_virtual_op = virtual_op; 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) if (*p_opfunc == NUL)
emsg(_("E774: 'operatorfunc' is empty")); emsg(_("E774: 'operatorfunc' is empty"));
@ -3933,6 +3945,11 @@ op_function(oparg_T *oap UNUSED)
(void)call_func_retnr(p_opfunc, 1, argv); (void)call_func_retnr(p_opfunc, 1, argv);
virtual_op = save_virtual_op; virtual_op = save_virtual_op;
if (cmdmod.lockmarks)
{
curbuf->b_op_start = orig_start;
curbuf->b_op_end = orig_end;
}
} }
#else #else
emsg(_("E775: Eval feature not available")); emsg(_("E775: Eval feature not available"));

View File

@ -1316,13 +1316,16 @@ op_yank(oparg_T *oap, int deleting, int mess)
} }
} }
// Set "'[" and "']" marks. if (!cmdmod.lockmarks)
curbuf->b_op_start = oap->start;
curbuf->b_op_end = oap->end;
if (yanktype == MLINE && !oap->block_mode)
{ {
curbuf->b_op_start.col = 0; // Set "'[" and "']" marks.
curbuf->b_op_end.col = MAXCOL; 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 #ifdef FEAT_CLIPBOARD
@ -1474,6 +1477,8 @@ do_put(
char_u *insert_string = NULL; char_u *insert_string = NULL;
int allocated = FALSE; int allocated = FALSE;
long cnt; long cnt;
pos_T orig_start = curbuf->b_op_start;
pos_T orig_end = curbuf->b_op_end;
#ifdef FEAT_CLIPBOARD #ifdef FEAT_CLIPBOARD
// Adjust register name for "unnamed" in 'clipboard'. // Adjust register name for "unnamed" in 'clipboard'.
@ -2100,6 +2105,11 @@ error:
curwin->w_set_curswant = TRUE; curwin->w_set_curswant = TRUE;
end: end:
if (cmdmod.lockmarks)
{
curbuf->b_op_start = orig_start;
curbuf->b_op_end = orig_end;
}
if (allocated) if (allocated)
vim_free(insert_string); vim_free(insert_string);
if (regname == '=') if (regname == '=')

View File

@ -2297,3 +2297,37 @@ func Test_autocmd_was_using_freed_memory()
split split
au! WinEnter au! WinEnter
endfunc 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

View File

@ -989,3 +989,22 @@ func Test_diff_closeoff()
diffoff! diffoff!
enew! enew!
endfunc 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

View File

@ -741,6 +741,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2302,
/**/ /**/
2301, 2301,
/**/ /**/