vim-patch:8.0.0255: setpos() does not use the buffer argument for all marks

Problem:    When calling setpos() with a buffer argument it often is ignored.
            (Matthew Malcomson)
Solution:   Make the buffer argument work for all marks local to a buffer.
            (neovim vim/vim#5713)  Add more tests.
f13e00b2cf
This commit is contained in:
Jan Edmund Lazo 2018-06-06 17:39:38 -04:00
parent 36ac80d5dd
commit 2d456f84d1
3 changed files with 76 additions and 27 deletions

View File

@ -6789,10 +6789,12 @@ setpos({expr}, {list})
[bufnum, lnum, col, off, curswant]
"bufnum" is the buffer number. Zero can be used for the
current buffer. Setting the cursor is only possible for
the current buffer. To set a mark in another buffer you can
use the |bufnr()| function to turn a file name into a buffer
number.
current buffer. When setting an uppercase mark "bufnum" is
used for the mark position. For other marks it specifies the
buffer to set the mark in. You can use the |bufnr()| function
to turn a file name into a buffer number.
For setting the cursor and the ' mark "bufnum" is ignored,
since these are associated with a window, not a buffer.
Does not change the jumplist.
"lnum" and "col" are the position in the buffer. The first

View File

@ -106,39 +106,41 @@ int setmark_pos(int c, pos_T *pos, int fnum)
return OK;
}
// Can't set a mark in a non-existant buffer.
buf_T *buf = buflist_findnr(fnum);
if (buf == NULL) {
return FAIL;
}
if (c == '"') {
RESET_FMARK(&curbuf->b_last_cursor, *pos, curbuf->b_fnum);
RESET_FMARK(&buf->b_last_cursor, *pos, buf->b_fnum);
return OK;
}
/* Allow setting '[ and '] for an autocommand that simulates reading a
* file. */
if (c == '[') {
curbuf->b_op_start = *pos;
buf->b_op_start = *pos;
return OK;
}
if (c == ']') {
curbuf->b_op_end = *pos;
buf->b_op_end = *pos;
return OK;
}
if (c == '<' || c == '>') {
if (c == '<')
curbuf->b_visual.vi_start = *pos;
else
curbuf->b_visual.vi_end = *pos;
if (curbuf->b_visual.vi_mode == NUL)
/* Visual_mode has not yet been set, use a sane default. */
curbuf->b_visual.vi_mode = 'v';
if (c == '<') {
buf->b_visual.vi_start = *pos;
} else {
buf->b_visual.vi_end = *pos;
}
if (buf->b_visual.vi_mode == NUL) {
// Visual_mode has not yet been set, use a sane default.
buf->b_visual.vi_mode = 'v';
}
return OK;
}
buf_T *buf = buflist_findnr(fnum);
// Can't set a mark in a non-existant buffer.
if (buf == NULL) {
return FAIL;
}
if (ASCII_ISLOWER(c)) {
i = c - 'a';
RESET_FMARK(buf->b_namedm + i, *pos, fnum);
@ -358,13 +360,14 @@ pos_T *getmark_buf_fnum(buf_T *buf, int c, int changefile, int *fnum)
} else if (c == '<' || c == '>') { /* start/end of visual area */
startp = &buf->b_visual.vi_start;
endp = &buf->b_visual.vi_end;
if ((c == '<') == lt(*startp, *endp))
if (((c == '<') == lt(*startp, *endp) || endp->lnum == 0)
&& startp->lnum != 0) {
posp = startp;
else
} else {
posp = endp;
/*
* For Visual line mode, set mark at begin or end of line
*/
}
// For Visual line mode, set mark at begin or end of line
if (buf->b_visual.vi_mode == 'V') {
pos_copy = *posp;
posp = &pos_copy;
@ -647,8 +650,8 @@ void do_marks(exarg_T *eap)
show_one_mark(-1, arg, NULL, NULL, false);
}
static void
show_one_mark (
static void
show_one_mark(
int c,
char_u *arg,
pos_T *p,

View File

@ -24,3 +24,47 @@ function! Test_Incr_Marks()
call assert_equal("XXX 123 123", getline(3))
enew!
endfunction
func Test_setpos()
new one
let onebuf = bufnr('%')
let onewin = win_getid()
call setline(1, ['aaa', 'bbb', 'ccc'])
new two
let twobuf = bufnr('%')
let twowin = win_getid()
call setline(1, ['aaa', 'bbb', 'ccc'])
" for the cursor the buffer number is ignored
call setpos(".", [0, 2, 1, 0])
call assert_equal([0, 2, 1, 0], getpos("."))
call setpos(".", [onebuf, 3, 3, 0])
call assert_equal([0, 3, 3, 0], getpos("."))
call setpos("''", [0, 1, 3, 0])
call assert_equal([0, 1, 3, 0], getpos("''"))
call setpos("''", [onebuf, 2, 2, 0])
call assert_equal([0, 2, 2, 0], getpos("''"))
" buffer-local marks
for mark in ["'a", "'\"", "'[", "']", "'<", "'>"]
call win_gotoid(twowin)
call setpos(mark, [0, 2, 1, 0])
call assert_equal([0, 2, 1, 0], getpos(mark), "for mark " . mark)
call setpos(mark, [onebuf, 1, 3, 0])
call win_gotoid(onewin)
call assert_equal([0, 1, 3, 0], getpos(mark), "for mark " . mark)
endfor
" global marks
call win_gotoid(twowin)
call setpos("'N", [0, 2, 1, 0])
call assert_equal([twobuf, 2, 1, 0], getpos("'N"))
call setpos("'N", [onebuf, 1, 3, 0])
call assert_equal([onebuf, 1, 3, 0], getpos("'N"))
call win_gotoid(onewin)
bwipe!
call win_gotoid(twowin)
bwipe!
endfunc