aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt17
-rw-r--r--runtime/doc/usr_41.txt1
-rw-r--r--src/nvim/eval.c34
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/ex_cmds.c1
-rw-r--r--src/nvim/testdir/test_changelist.vim48
-rw-r--r--src/nvim/testdir/test_substitute.vim18
7 files changed, 119 insertions, 1 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 22157206a4..b88138aea3 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2081,6 +2081,7 @@ getbufline({expr}, {lnum} [, {end}])
List lines {lnum} to {end} of buffer {expr}
getbufvar({expr}, {varname} [, {def}])
any variable {varname} in buffer {expr}
+getchangelist({expr}) List list of change list items
getchar([expr]) Number get one character from the user
getcharmod() Number modifiers for the last typed character
getcharsearch() Dict last character search
@@ -4013,6 +4014,22 @@ getbufvar({expr}, {varname} [, {def}]) *getbufvar()*
:let bufmodified = getbufvar(1, "&mod")
:echo "todo myvar = " . getbufvar("todo", "myvar")
<
+getchangelist({expr}) *getchangelist()*
+ Returns the |changelist| for the buffer {expr}. For the use
+ of {expr}, see |bufname()| above. If buffer {expr} doesn't
+ exist, an empty list is returned.
+
+ The returned list contains two entries: a list with the change
+ locations and the current position in the list. Each
+ entry in the change list is a dictionary with the following
+ entries:
+ col column number
+ coladd column offset for 'virtualedit'
+ lnum line number
+ If buffer {expr} is the current buffer, then the current
+ position refers to the position in the list. For other
+ buffers, it is set to the length of the list.
+
getchar([expr]) *getchar()*
Get a single character from the user or input stream.
If [expr] is omitted, wait until a character is available.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index 87164c8d90..234aba1932 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -806,6 +806,7 @@ Buffers, windows and the argument list:
getbufinfo() get a list with buffer information
gettabinfo() get a list with tab page information
getwininfo() get a list with window information
+ getchangelist() get a list of change list entries
getjumplist() get a list of jump list entries
Command line: *command-line-functions*
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 6479163028..de510a8bca 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -9547,6 +9547,40 @@ f_getbufvar_end:
}
}
+// "getchangelist()" function
+static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ tv_list_alloc_ret(rettv, 2);
+ vim_ignored = tv_get_number(&argvars[0]); // issue errmsg if type error
+ emsg_off++;
+ const buf_T *const buf = tv_get_buf(&argvars[0], false);
+ emsg_off--;
+ if (buf == NULL) {
+ return;
+ }
+
+ list_T *const l = tv_list_alloc(buf->b_changelistlen);
+ tv_list_append_list(rettv->vval.v_list, l);
+ // The current window change list index tracks only the position in the
+ // current buffer change list. For other buffers, use the change list
+ // length as the current index.
+ tv_list_append_number(rettv->vval.v_list,
+ (buf == curwin->w_buffer)
+ ? curwin->w_changelistidx
+ : buf->b_changelistlen);
+
+ for (int i = 0; i < buf->b_changelistlen; i++) {
+ if (buf->b_changelist[i].mark.lnum == 0) {
+ continue;
+ }
+ dict_T *const d = tv_dict_alloc();
+ tv_list_append_dict(l, d);
+ tv_dict_add_nr(d, S_LEN("lnum"), buf->b_changelist[i].mark.lnum);
+ tv_dict_add_nr(d, S_LEN("col"), buf->b_changelist[i].mark.col);
+ tv_dict_add_nr(d, S_LEN("coladd"), buf->b_changelist[i].mark.coladd);
+ }
+}
+
/*
* "getchar()" function
*/
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index d4bb69613e..aad2de5d30 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -116,6 +116,7 @@ return {
getbufinfo={args={0, 1}},
getbufline={args={2, 3}},
getbufvar={args={2, 3}},
+ getchangelist={args={1, 1}},
getchar={args={0, 1}},
getcharmod={},
getcharsearch={},
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 8436ac810e..b3933ac9a6 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -3817,6 +3817,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout,
// 3. Substitute the string. During 'inccommand' preview only do this if
// there is a replace pattern.
if (!preview || has_second_delim) {
+ save_ma = curbuf->b_p_ma;
if (subflags.do_count) {
// prevent accidentally changing the buffer by a function
curbuf->b_p_ma = false;
diff --git a/src/nvim/testdir/test_changelist.vim b/src/nvim/testdir/test_changelist.vim
new file mode 100644
index 0000000000..dd6ea9600c
--- /dev/null
+++ b/src/nvim/testdir/test_changelist.vim
@@ -0,0 +1,48 @@
+" Tests for the changelist functionality
+
+" Tests for the getchangelist() function
+func Test_getchangelist()
+ if !has("jumplist")
+ return
+ endif
+
+ bwipe!
+ enew
+ call assert_equal([], getchangelist(10))
+ call assert_equal([[], 0], getchangelist('%'))
+
+ call writefile(['line1', 'line2', 'line3'], 'Xfile1.txt')
+ call writefile(['line1', 'line2', 'line3'], 'Xfile2.txt')
+
+ edit Xfile1.txt
+ exe "normal 1Goline\<C-G>u1.1"
+ exe "normal 3Goline\<C-G>u2.1"
+ exe "normal 5Goline\<C-G>u3.1"
+ normal g;
+ call assert_equal([[
+ \ {'lnum' : 2, 'col' : 4, 'coladd' : 0},
+ \ {'lnum' : 4, 'col' : 4, 'coladd' : 0},
+ \ {'lnum' : 6, 'col' : 4, 'coladd' : 0}], 2],
+ \ getchangelist('%'))
+
+ hide edit Xfile2.txt
+ exe "normal 1GOline\<C-G>u1.0"
+ exe "normal 2Goline\<C-G>u2.0"
+ call assert_equal([[
+ \ {'lnum' : 1, 'col' : 6, 'coladd' : 0},
+ \ {'lnum' : 3, 'col' : 6, 'coladd' : 0}], 2],
+ \ getchangelist('%'))
+ hide enew
+
+ call assert_equal([[
+ \ {'lnum' : 2, 'col' : 4, 'coladd' : 0},
+ \ {'lnum' : 4, 'col' : 4, 'coladd' : 0},
+ \ {'lnum' : 6, 'col' : 4, 'coladd' : 0}], 3], getchangelist(2))
+ call assert_equal([[
+ \ {'lnum' : 1, 'col' : 6, 'coladd' : 0},
+ \ {'lnum' : 3, 'col' : 6, 'coladd' : 0}], 2], getchangelist(3))
+
+ bwipe!
+ call delete('Xfile1.txt')
+ call delete('Xfile2.txt')
+endfunc
diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim
index 8b306192f0..b29b678129 100644
--- a/src/nvim/testdir/test_substitute.vim
+++ b/src/nvim/testdir/test_substitute.vim
@@ -612,9 +612,24 @@ func Test_sub_replace_10()
call assert_equal('1aaa', substitute('123', '1\zs\|[23]', 'a', 'g'))
endfunc
+func Test_sub_cmd_9()
+ new
+ let input = ['1 aaa', '2 aaa', '3 aaa']
+ call setline(1, input)
+ func Foo()
+ return submatch(0)
+ endfunc
+ %s/aaa/\=Foo()/gn
+ call assert_equal(input, getline(1, '$'))
+ call assert_equal(1, &modifiable)
+
+ delfunc Foo
+ bw!
+endfunc
+
func Test_nocatch_sub_failure_handling()
" normal error results in all replacements
- func! Foo()
+ func Foo()
foobar
endfunc
new
@@ -650,6 +665,7 @@ func Test_nocatch_sub_failure_handling()
call assert_equal(1, error_caught)
call assert_equal(['1 aaa', '2 aaa', '3 aaa'], getline(1, 3))
+ delfunc Foo
bwipe!
endfunc