Skip to content

Commit f13e00b

Browse files
committed
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 #5713) Add more tests.
1 parent c7b831c commit f13e00b

4 files changed

Lines changed: 67 additions & 13 deletions

File tree

runtime/doc/eval.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6798,10 +6798,12 @@ setpos({expr}, {list})
67986798
[bufnum, lnum, col, off, curswant]
67996799

68006800
"bufnum" is the buffer number. Zero can be used for the
6801-
current buffer. Setting the cursor is only possible for
6802-
the current buffer. To set a mark in another buffer you can
6803-
use the |bufnr()| function to turn a file name into a buffer
6804-
number.
6801+
current buffer. When setting an uppercase mark "bufnum" is
6802+
used for the mark position. For other marks it specifies the
6803+
buffer to set the mark in. You can use the |bufnr()| function
6804+
to turn a file name into a buffer number.
6805+
For setting the cursor and the ' mark "bufnum" is ignored,
6806+
since these are associated with a window, not a buffer.
68056807
Does not change the jumplist.
68066808

68076809
"lnum" and "col" are the position in the buffer. The first

src/mark.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ setmark(int c)
5757
setmark_pos(int c, pos_T *pos, int fnum)
5858
{
5959
int i;
60+
buf_T *buf;
6061

6162
/* Check for a special key (may cause islower() to crash). */
6263
if (c < 0)
@@ -75,41 +76,45 @@ setmark_pos(int c, pos_T *pos, int fnum)
7576
return OK;
7677
}
7778

79+
buf = buflist_findnr(fnum);
80+
if (buf == NULL)
81+
return FAIL;
82+
7883
if (c == '"')
7984
{
80-
curbuf->b_last_cursor = *pos;
85+
buf->b_last_cursor = *pos;
8186
return OK;
8287
}
8388

8489
/* Allow setting '[ and '] for an autocommand that simulates reading a
8590
* file. */
8691
if (c == '[')
8792
{
88-
curbuf->b_op_start = *pos;
93+
buf->b_op_start = *pos;
8994
return OK;
9095
}
9196
if (c == ']')
9297
{
93-
curbuf->b_op_end = *pos;
98+
buf->b_op_end = *pos;
9499
return OK;
95100
}
96101

97102
if (c == '<' || c == '>')
98103
{
99104
if (c == '<')
100-
curbuf->b_visual.vi_start = *pos;
105+
buf->b_visual.vi_start = *pos;
101106
else
102-
curbuf->b_visual.vi_end = *pos;
103-
if (curbuf->b_visual.vi_mode == NUL)
107+
buf->b_visual.vi_end = *pos;
108+
if (buf->b_visual.vi_mode == NUL)
104109
/* Visual_mode has not yet been set, use a sane default. */
105-
curbuf->b_visual.vi_mode = 'v';
110+
buf->b_visual.vi_mode = 'v';
106111
return OK;
107112
}
108113

109114
if (ASCII_ISLOWER(c))
110115
{
111116
i = c - 'a';
112-
curbuf->b_namedm[i] = *pos;
117+
buf->b_namedm[i] = *pos;
113118
return OK;
114119
}
115120
if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c))
@@ -396,7 +401,8 @@ getmark_buf_fnum(
396401
{
397402
startp = &buf->b_visual.vi_start;
398403
endp = &buf->b_visual.vi_end;
399-
if ((c == '<') == lt(*startp, *endp))
404+
if (((c == '<') == lt(*startp, *endp) || endp->lnum == 0)
405+
&& startp->lnum != 0)
400406
posp = startp;
401407
else
402408
posp = endp;

src/testdir/test_marks.vim

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,47 @@ function! Test_Incr_Marks()
2424
call assert_equal("XXX 123 123", getline(3))
2525
enew!
2626
endfunction
27+
28+
func Test_setpos()
29+
new one
30+
let onebuf = bufnr('%')
31+
let onewin = win_getid()
32+
call setline(1, ['aaa', 'bbb', 'ccc'])
33+
new two
34+
let twobuf = bufnr('%')
35+
let twowin = win_getid()
36+
call setline(1, ['aaa', 'bbb', 'ccc'])
37+
38+
" for the cursor the buffer number is ignored
39+
call setpos(".", [0, 2, 1, 0])
40+
call assert_equal([0, 2, 1, 0], getpos("."))
41+
call setpos(".", [onebuf, 3, 3, 0])
42+
call assert_equal([0, 3, 3, 0], getpos("."))
43+
44+
call setpos("''", [0, 1, 3, 0])
45+
call assert_equal([0, 1, 3, 0], getpos("''"))
46+
call setpos("''", [onebuf, 2, 2, 0])
47+
call assert_equal([0, 2, 2, 0], getpos("''"))
48+
49+
" buffer-local marks
50+
for mark in ["'a", "'\"", "'[", "']", "'<", "'>"]
51+
call win_gotoid(twowin)
52+
call setpos(mark, [0, 2, 1, 0])
53+
call assert_equal([0, 2, 1, 0], getpos(mark), "for mark " . mark)
54+
call setpos(mark, [onebuf, 1, 3, 0])
55+
call win_gotoid(onewin)
56+
call assert_equal([0, 1, 3, 0], getpos(mark), "for mark " . mark)
57+
endfor
58+
59+
" global marks
60+
call win_gotoid(twowin)
61+
call setpos("'N", [0, 2, 1, 0])
62+
call assert_equal([twobuf, 2, 1, 0], getpos("'N"))
63+
call setpos("'N", [onebuf, 1, 3, 0])
64+
call assert_equal([onebuf, 1, 3, 0], getpos("'N"))
65+
66+
call win_gotoid(onewin)
67+
bwipe!
68+
call win_gotoid(twowin)
69+
bwipe!
70+
endfunc

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,8 @@ static char *(features[]) =
764764

765765
static int included_patches[] =
766766
{ /* Add new patch number below this line */
767+
/**/
768+
255,
767769
/**/
768770
254,
769771
/**/

0 commit comments

Comments
 (0)