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:
parent
ab85ca4e6a
commit
f4a1d1c054
@ -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))
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -749,9 +749,12 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
|
||||
foldMoveRange(&win->w_folds, line1, line2, dest);
|
||||
}
|
||||
#endif
|
||||
if (!cmdmod.lockmarks)
|
||||
{
|
||||
curbuf->b_op_start.lnum = dest - num_lines + 1;
|
||||
curbuf->b_op_end.lnum = dest;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L);
|
||||
@ -761,9 +764,13 @@ do_move(linenr_T line1, linenr_T line2, linenr_T dest)
|
||||
foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2);
|
||||
}
|
||||
#endif
|
||||
if (!cmdmod.lockmarks)
|
||||
{
|
||||
curbuf->b_op_start.lnum = dest + 1;
|
||||
curbuf->b_op_end.lnum = dest + num_lines;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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,6 +3300,8 @@ 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 */
|
||||
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)
|
||||
@ -3283,6 +3309,7 @@ ex_append(exarg_T *eap)
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
|
16
src/fileio.c
16
src/fileio.c
@ -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.
|
||||
*/
|
||||
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
|
||||
/*
|
||||
|
@ -1001,10 +1001,13 @@ op_reindent(oparg_T *oap, int (*how)(void))
|
||||
smsg(NGETTEXT("%ld line indented ",
|
||||
"%ld lines indented ", i), i);
|
||||
}
|
||||
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)
|
||||
|
||||
#if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) || defined(PROTO)
|
||||
|
37
src/ops.c
37
src/ops.c
@ -206,15 +206,16 @@ op_shift(oparg_T *oap, int curs_top, int amount)
|
||||
msg((char *)IObuff);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set "'[" and "']" marks.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shift the current line one shiftwidth left (if left != 0) or right
|
||||
@ -981,6 +982,8 @@ op_delete(oparg_T *oap)
|
||||
msgmore(curbuf->b_ml.ml_line_count - old_lcount);
|
||||
|
||||
setmarks:
|
||||
if (!cmdmod.lockmarks)
|
||||
{
|
||||
if (oap->block_mode)
|
||||
{
|
||||
curbuf->b_op_end.lnum = oap->end.lnum;
|
||||
@ -989,6 +992,7 @@ setmarks:
|
||||
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);
|
||||
|
||||
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.
|
||||
*/
|
||||
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,6 +2276,7 @@ op_format(
|
||||
/* When there is no change: need to remove the Visual selection */
|
||||
redraw_curbuf_later(INVERTED);
|
||||
|
||||
if (!cmdmod.lockmarks)
|
||||
/* Set '[ mark at the start of the formatted area */
|
||||
curbuf->b_op_start = oap->start;
|
||||
|
||||
@ -2289,6 +2298,7 @@ op_format(
|
||||
old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
|
||||
msgmore(old_line_count);
|
||||
|
||||
if (!cmdmod.lockmarks)
|
||||
/* put '] mark on the end of the formatted area */
|
||||
curbuf->b_op_end = curwin->w_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"));
|
||||
|
@ -1316,6 +1316,8 @@ op_yank(oparg_T *oap, int deleting, int mess)
|
||||
}
|
||||
}
|
||||
|
||||
if (!cmdmod.lockmarks)
|
||||
{
|
||||
// Set "'[" and "']" marks.
|
||||
curbuf->b_op_start = oap->start;
|
||||
curbuf->b_op_end = oap->end;
|
||||
@ -1324,6 +1326,7 @@ op_yank(oparg_T *oap, int deleting, int mess)
|
||||
curbuf->b_op_start.col = 0;
|
||||
curbuf->b_op_end.col = MAXCOL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FEAT_CLIPBOARD
|
||||
// If we were yanking to the '*' register, send result to 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 == '=')
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -741,6 +741,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2302,
|
||||
/**/
|
||||
2301,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user