# HG changeset patch # User Christian Brabandt # Date 1485624604 -3600 # Node ID 44e9340dc604a1a53fcf7c8b51023e6149a53c4d # Parent 4441ce7a58f2a8a42d931bde197cdbe9f06d9d71 patch 8.0.0255: setpos() does not use the buffer argument for all marks commit https://github.com/vim/vim/commit/f13e00b2cf381e13fd327b5387a5bd6f004ac2a3 Author: Bram Moolenaar Date: Sat Jan 28 18:23:54 2017 +0100 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. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -6798,10 +6798,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 diff --git a/src/mark.c b/src/mark.c --- a/src/mark.c +++ b/src/mark.c @@ -57,6 +57,7 @@ setmark(int c) setmark_pos(int c, pos_T *pos, int fnum) { int i; + buf_T *buf; /* Check for a special key (may cause islower() to crash). */ if (c < 0) @@ -75,9 +76,13 @@ setmark_pos(int c, pos_T *pos, int fnum) return OK; } + buf = buflist_findnr(fnum); + if (buf == NULL) + return FAIL; + if (c == '"') { - curbuf->b_last_cursor = *pos; + buf->b_last_cursor = *pos; return OK; } @@ -85,31 +90,31 @@ setmark_pos(int c, pos_T *pos, int fnum) * 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; + buf->b_visual.vi_start = *pos; else - curbuf->b_visual.vi_end = *pos; - if (curbuf->b_visual.vi_mode == NUL) + buf->b_visual.vi_end = *pos; + if (buf->b_visual.vi_mode == NUL) /* Visual_mode has not yet been set, use a sane default. */ - curbuf->b_visual.vi_mode = 'v'; + buf->b_visual.vi_mode = 'v'; return OK; } if (ASCII_ISLOWER(c)) { i = c - 'a'; - curbuf->b_namedm[i] = *pos; + buf->b_namedm[i] = *pos; return OK; } if (ASCII_ISUPPER(c) || VIM_ISDIGIT(c)) @@ -396,7 +401,8 @@ getmark_buf_fnum( { 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 posp = endp; diff --git a/src/testdir/test_marks.vim b/src/testdir/test_marks.vim --- a/src/testdir/test_marks.vim +++ b/src/testdir/test_marks.vim @@ -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 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 255, +/**/ 254, /**/ 253,