commit eac2f0443e032ba238ca6b4a9e2fd6135be454b3
parent 5f22cf5af3425fb0d461bf82220a633bebe10932
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date: Fri, 19 Dec 2025 23:32:09 +0000
feat(tag): respect jumpoptions=view when popping tagstack (#37021)
Problem: jumpoptions=view has no effect when popping from the tagstack.
Solution: make it work.
Diffstat:
6 files changed, 110 insertions(+), 6 deletions(-)
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -328,6 +328,7 @@ OPTIONS
• 'diffopt' `inline:` configures diff highlighting for changes within a line.
• 'fillchars' has new flag "foldinner".
• 'grepformat' is now a |global-local| option.
+• 'jumpoptions' flag "view" now applies when popping the |tagstack|.
• 'maxsearchcount' sets maximum value for |searchcount()| and defaults to 999.
• 'pummaxwidth' sets maximum width for the completion popup menu.
• 'winborder' "bold" style, custom border style.
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
@@ -3870,8 +3870,9 @@ A jump table for the options with a short description can be found at |Q_op|.
jumping to a location. |jumplist-stack|
view When moving through the jumplist, |changelist|,
- |alternate-file| or using |mark-motions| try to
- restore the |mark-view| in which the action occurred.
+ |alternate-file|, using |mark-motions| or when popping
+ the |tagstack| try to restore the |mark-view| in which
+ the action occurred.
clean Remove unloaded buffers from the jumplist.
EXPERIMENTAL: this flag may change in the future.
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
@@ -3795,8 +3795,9 @@ vim.go.js = vim.go.joinspaces
--- jumping to a location. `jumplist-stack`
---
--- view When moving through the jumplist, `changelist`,
---- `alternate-file` or using `mark-motions` try to
---- restore the `mark-view` in which the action occurred.
+--- `alternate-file`, using `mark-motions` or when popping
+--- the `tagstack` try to restore the `mark-view` in which
+--- the action occurred.
---
--- clean Remove unloaded buffers from the jumplist.
--- EXPERIMENTAL: this flag may change in the future.
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
@@ -4991,8 +4991,9 @@ local options = {
jumping to a location. |jumplist-stack|
view When moving through the jumplist, |changelist|,
- |alternate-file| or using |mark-motions| try to
- restore the |mark-view| in which the action occurred.
+ |alternate-file|, using |mark-motions| or when popping
+ the |tagstack| try to restore the |mark-view| in which
+ the action occurred.
clean Remove unloaded buffers from the jumplist.
EXPERIMENTAL: this flag may change in the future.
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
@@ -343,6 +343,7 @@ void do_tag(char *tag, int type, int count, int forceit, bool verbose)
clearpos(&saved_fmark.mark); // shutup gcc 4.0
saved_fmark.fnum = 0;
+ saved_fmark.view = (fmarkv_T)INIT_FMARKV;
// Don't add a tag to the tagstack if 'tagstack' has been reset.
assert(tag != NULL);
@@ -446,6 +447,9 @@ void do_tag(char *tag, int type, int count, int forceit, bool verbose)
}
curwin->w_cursor.col = saved_fmark.mark.col;
curwin->w_set_curswant = true;
+ if (jop_flags & kOptJopFlagView) {
+ mark_view_restore(&saved_fmark);
+ }
check_cursor(curwin);
if ((fdo_flags & kOptFdoFlagTag) && old_KeyTyped) {
foldOpenCursor();
@@ -530,6 +534,7 @@ void do_tag(char *tag, int type, int count, int forceit, bool verbose)
if (save_pos) {
tagstack[tagstackidx].fmark.mark = curwin->w_cursor;
tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum;
+ tagstack[tagstackidx].fmark.view = mark_view_make(curwin->w_topline, curwin->w_cursor);
}
// Curwin will change in the call to jumpto_tag() if ":stag" was
@@ -3426,6 +3431,7 @@ static void tagstack_push_item(win_T *wp, char *tagname, int cur_fnum, int cur_m
tagstack[idx].cur_match = MAX(tagstack[idx].cur_match, 0);
tagstack[idx].fmark.mark = mark;
tagstack[idx].fmark.fnum = fnum;
+ tagstack[idx].fmark.view = (fmarkv_T)INIT_FMARKV;
tagstack[idx].user_data = user_data;
}
diff --git a/test/functional/editor/jump_spec.lua b/test/functional/editor/jump_spec.lua
@@ -505,4 +505,98 @@ describe('jumpoptions=view', function()
|
]])
end)
+
+ describe('tagstack popping', function()
+ local tags_file = 'Xtestfile-functional-editor-jumps-tags'
+ before_each(function()
+ write_file(
+ tags_file,
+ '!_TAG_FILE_ENCODING\tutf-8\t//\n'
+ .. ('10\t%s\t2\n'):format(file1)
+ .. ('30\t%s\t20\n'):format(file2),
+ false,
+ false
+ )
+ command('set tags=' .. tags_file)
+ end)
+ after_each(function()
+ os.remove(tags_file)
+ end)
+
+ it('restores the view', function()
+ local screen = Screen.new(5, 6)
+ command('set laststatus=2 | set statusline=%f | edit ' .. file1)
+ feed('10Gzb<C-]>30Gzt<C-]>')
+ screen:expect([[
+ 19 line |
+ ^20 line |
+ 21 line |
+ 22 line |
+ {3:<tor-jumps-2}|
+ |
+ ]])
+ feed('<C-T>')
+ screen:expect([[
+ ^30 line |
+ {1:~ }|*3
+ {3:<ditor-jumps}|
+ |
+ ]])
+ feed('<C-T>')
+ screen:expect([[
+ 7 line |
+ 8 line |
+ 9 line |
+ ^10 line |
+ {3:<ditor-jumps}|
+ |
+ ]])
+
+ local tagstack = ' # TO tag FROM line in file/text\n'
+ .. '> 1 1 10 10 \n'
+ .. ' 2 1 30 30 '
+ eq(tagstack, exec_capture('tags'))
+ -- Un-pop via `:tag`; like `:tag 10` it should go to L2. (restoring cursor/view doesn't apply)
+ -- However, after a `:pop`, it should restore the view from after the single `<C-E>` below.
+ feed('<C-E>')
+ command('tag')
+ screen:expect([[
+ 1 line |
+ ^2 line |
+ 3 line |
+ 4 line |
+ {3:<ditor-jumps}|
+ |
+ ]])
+ command('pop')
+ screen:expect([[
+ 8 line |
+ 9 line |
+ ^10 line |
+ 11 line |
+ {3:<ditor-jumps}|
+ |
+ ]])
+ eq(tagstack, exec_capture('tags'))
+
+ -- No view information associated with tags set via settagstack().
+ -- (specifically, replacing tag "10" shouldn't continue to use it's now unrelated view)
+ fn.settagstack(fn.win_getid(), {
+ items = { { from = { fn.bufnr(), 11, 1, 0, 1 }, tagname = 'settagstack!!!' } },
+ }, 'r')
+ tagstack = ' # TO tag FROM line in file/text\n'
+ .. ' 1 1 settagstack!!! 11 \n'
+ .. '>'
+ eq(tagstack, exec_capture('tags'))
+ feed('G<C-T>')
+ screen:expect([[
+ 10 line |
+ ^11 line |
+ 12 line |
+ 13 line |
+ {3:<ditor-jumps}|
+ |
+ ]])
+ end)
+ end)
end)