aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt10
-rw-r--r--src/nvim/eval.c18
-rw-r--r--src/nvim/mark.c49
-rw-r--r--src/nvim/testdir/test_marks.vim44
-rw-r--r--test/functional/eval/setpos_spec.lua3
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})