aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2020-01-29 20:44:23 -0500
committerJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2020-01-29 21:00:11 -0500
commit31f31b40a8af67a3a55e85fa5dfa63d5a5999acc (patch)
tree705f39a1649e74e8fd0b107f2f5dca9349bc4bb1
parentf719b8898ba8aa18f0411be1924eea132a3b103e (diff)
downloadrneovim-31f31b40a8af67a3a55e85fa5dfa63d5a5999acc.tar.gz
rneovim-31f31b40a8af67a3a55e85fa5dfa63d5a5999acc.tar.bz2
rneovim-31f31b40a8af67a3a55e85fa5dfa63d5a5999acc.zip
vim-patch:8.2.0077: settagstack() cannot truncate at current index
Problem: settagstack() cannot truncate at current index. Solution: Add the "t" action. (Yegappan Lakshmanan, closes vim/vim#5417) https://github.com/vim/vim/commit/271fa08a35b8d320d3a40db4ddae83b698fdd4fb
-rw-r--r--runtime/doc/eval.txt18
-rw-r--r--src/nvim/eval.c3
-rw-r--r--src/nvim/tag.c34
-rw-r--r--src/nvim/testdir/test_tagjump.vim22
4 files changed, 64 insertions, 13 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 69b8b3cf39..e0ce83f8d2 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -7550,11 +7550,21 @@ settagstack({nr}, {dict} [, {action}]) *settagstack()*
{nr} can be the window number or the |window-ID|.
For a list of supported items in {dict}, refer to
- |gettagstack()|
+ |gettagstack()|. "curidx" takes effect before changing the tag
+ stack.
*E962*
- If {action} is not present or is set to 'r', then the tag
- stack is replaced. If {action} is set to 'a', then new entries
- from {dict} are pushed onto the tag stack.
+ How the tag stack is modified depends on the {action}
+ argument:
+ - If {action} is not present or is set to 'r', then the tag
+ stack is replaced.
+ - If {action} is set to 'a', then new entries from {dict} are
+ pushed (added) onto the tag stack.
+ - If {action} is set to 't', then all the entries from the
+ current entry in the tag stack or "curidx" in {dict} are
+ removed and then new entries are pushed to the stack.
+
+ The current index is set to one after the length of the tag
+ stack after the modification.
Returns zero for success, -1 for failure.
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index b3cc3282d5..47c094f49d 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -16242,7 +16242,8 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (actstr == NULL) {
return;
}
- if ((*actstr == 'r' || *actstr == 'a') && actstr[1] == NUL) {
+ if ((*actstr == 'r' || *actstr == 'a' || *actstr == 't')
+ && actstr[1] == NUL) {
action = *actstr;
} else {
EMSG2(_(e_invact2), actstr);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index a412ed0276..07f29977aa 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -3378,11 +3378,15 @@ static void tagstack_set_curidx(win_T *wp, int curidx)
}
// Set the tag stack entries of the specified window.
-// 'action' is set to either 'a' for append or 'r' for replace.
-int set_tagstack(win_T *wp, dict_T *d, int action)
+// 'action' is set to one of:
+// 'a' for append
+// 'r' for replace
+// 't' for truncate
+int set_tagstack(win_T *wp, const dict_T *d, int action)
+ FUNC_ATTR_NONNULL_ARG(1)
{
dictitem_T *di;
- list_T *l;
+ list_T *l = NULL;
// not allowed to alter the tag stack entries from inside tagfunc
if (tfu_in_use) {
@@ -3395,16 +3399,30 @@ int set_tagstack(win_T *wp, dict_T *d, int action)
return FAIL;
}
l = di->di_tv.vval.v_list;
+ }
- if (action == 'r') {
+ if ((di = tv_dict_find(d, "curidx", -1)) != NULL) {
+ tagstack_set_curidx(wp, (int)tv_get_number(&di->di_tv) - 1);
+ }
+ if (action == 't') { // truncate the stack
+ taggy_T *const tagstack = wp->w_tagstack;
+ const int tagstackidx = wp->w_tagstackidx;
+ int tagstacklen = wp->w_tagstacklen;
+ // delete all the tag stack entries above the current entry
+ while (tagstackidx < tagstacklen) {
+ tagstack_clear_entry(&tagstack[--tagstacklen]);
+ }
+ wp->w_tagstacklen = tagstacklen;
+ }
+
+ if (l != NULL) {
+ if (action == 'r') { // replace the stack
tagstack_clear(wp);
}
tagstack_push_items(wp, l);
- }
-
- if ((di = tv_dict_find(d, "curidx", -1)) != NULL) {
- tagstack_set_curidx(wp, (int)tv_get_number(&di->di_tv) - 1);
+ // set the current index after the last entry
+ wp->w_tagstackidx = wp->w_tagstacklen;
}
return OK;
diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim
index fe98ef1ae2..5fd71d8bfc 100644
--- a/src/nvim/testdir/test_tagjump.vim
+++ b/src/nvim/testdir/test_tagjump.vim
@@ -340,6 +340,28 @@ func Test_getsettagstack()
\ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 'a')
call assert_equal('abc', gettagstack().items[19].tagname)
+ " truncate the tag stack
+ call settagstack(1,
+ \ {'curidx' : 9,
+ \ 'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't')
+ let t = gettagstack()
+ call assert_equal(9, t.length)
+ call assert_equal(10, t.curidx)
+
+ " truncate the tag stack without pushing any new items
+ call settagstack(1, {'curidx' : 5}, 't')
+ let t = gettagstack()
+ call assert_equal(4, t.length)
+ call assert_equal(5, t.curidx)
+
+ " truncate an empty tag stack and push new items
+ call settagstack(1, {'items' : []})
+ call settagstack(1,
+ \ {'items' : [{'tagname' : 'abc', 'from' : [1, 10, 1, 0]}]}, 't')
+ let t = gettagstack()
+ call assert_equal(1, t.length)
+ call assert_equal(2, t.curidx)
+
" Tag with multiple matches
call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
\ "two\tXfile1\t1",