feat(tag): respect jumpoptions=view when popping tagstack (#37021)

Problem: jumpoptions=view has no effect when popping from the tagstack.
Solution: make it work.
This commit is contained in:
Sean Dewar
2025-12-19 23:32:09 +00:00
committed by GitHub
parent 5f22cf5af3
commit eac2f0443e
6 changed files with 110 additions and 6 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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)