diff options
-rw-r--r-- | runtime/doc/eval.txt | 10 | ||||
-rw-r--r-- | src/nvim/eval.c | 18 | ||||
-rw-r--r-- | src/nvim/mark.c | 49 | ||||
-rw-r--r-- | src/nvim/testdir/test_marks.vim | 44 | ||||
-rw-r--r-- | test/functional/eval/setpos_spec.lua | 3 |
5 files changed, 84 insertions, 40 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index fffdcef8d9..f404192abb 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -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 diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 69b16f2113..9c29f18c0c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -14809,18 +14809,14 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) pos.col = 0; } if (name[0] == '.' && name[1] == NUL) { - // set cursor - if (fnum == curbuf->b_fnum) { - curwin->w_cursor = pos; - if (curswant >= 0) { - curwin->w_curswant = curswant - 1; - curwin->w_set_curswant = false; - } - check_cursor(); - rettv->vval.v_number = 0; - } else { - EMSG(_(e_invarg)); + // set cursor; "fnum" is ignored + curwin->w_cursor = pos; + if (curswant >= 0) { + curwin->w_curswant = curswant - 1; + curwin->w_set_curswant = false; } + check_cursor(); + rettv->vval.v_number = 0; } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { // set mark if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) { diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 3cd26a5bf7..bcd9cf2090 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -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, diff --git a/src/nvim/testdir/test_marks.vim b/src/nvim/testdir/test_marks.vim index d00b1ddc88..18a0c71aab 100644 --- a/src/nvim/testdir/test_marks.vim +++ b/src/nvim/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/test/functional/eval/setpos_spec.lua b/test/functional/eval/setpos_spec.lua index 6a8b3a8732..935f387bcc 100644 --- a/test/functional/eval/setpos_spec.lua +++ b/test/functional/eval/setpos_spec.lua @@ -27,9 +27,8 @@ describe('setpos() function', function() eq(getpos("."), {0, 2, 1, 0}) setpos(".", {2, 1, 1, 0}) eq(getpos("."), {0, 1, 1, 0}) - -- Ensure get an error attempting to set position to another buffer local ret = exc_exec('call setpos(".", [1, 1, 1, 0])') - eq('Vim(call):E474: Invalid argument', ret) + eq(0, ret) end) it('can set lowercase marks in the current buffer', function() setpos("'d", {0, 2, 1, 0}) |