Skip to content

Commit cc4cecb

Browse files
committed
feat: allow follow_tab to be a function
Using window options should open some doors. Most notably, the simplification of some stuff
1 parent 76f219c commit cc4cecb

File tree

7 files changed

+62
-5
lines changed

7 files changed

+62
-5
lines changed

docs/src/routes/configuration/+page.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ return {
145145
switchbuf = "usetab,uselast",
146146
-- Auto open when a session is started and auto close when all sessions finish
147147
auto_toggle = false,
148-
-- Reopen dapview when switching tabs
148+
-- Reopen dapview when switching to a different tab
149+
-- Can also be a function to dynamically choose when to follow, by returning a boolean
150+
-- If a function, receives the name of the adapter for the current session as an argument
149151
follow_tab = false,
150152
}
151153
```

docs/src/routes/faq/+page.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ title: FAQ
99
```lua
1010
-- Your nvim-dap-view config
1111
return {
12+
-- Can also be a function to dynamically choose when to follow, by returning a boolean
1213
follow_tab = true,
1314
}
1415
```

lua/dap-view/actions.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ M.open = function(hide_terminal)
7979
local windows_config = setup.config.windows
8080
local term_config = windows_config.terminal
8181

82-
local term_position = require("dap-view.util").inverted_directions[term_config.position]
82+
local term_position = util.inverted_directions[term_config.position]
8383

8484
local anchor_win = windows_config.anchor and windows_config.anchor()
8585
local is_anchor_win_valid = util.is_win_valid(anchor_win)
@@ -97,6 +97,8 @@ M.open = function(hide_terminal)
9797

9898
state.winnr = winnr
9999

100+
vim.w[state.winnr].dapview_win = true
101+
100102
require("dap-view.views.options").set_options()
101103
require("dap-view.views.keymaps").set_keymaps()
102104

lua/dap-view/autocmds.lua

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
local dap = require("dap")
2+
13
local util = require("dap-view.util")
4+
local window = require("dap-view.util.window")
25
local state = require("dap-view.state")
36
local setup = require("dap-view.setup")
47
local globals = require("dap-view.globals")
@@ -18,7 +21,40 @@ api.nvim_create_autocmd({ "WinClosed", "WinNew" }, {
1821

1922
api.nvim_create_autocmd("TabEnter", {
2023
callback = function()
21-
if util.is_win_valid(state.winnr) and setup.config.follow_tab then
24+
local session = dap.session()
25+
local adapter = session and session.config.type
26+
27+
local follow_tab = setup.config.follow_tab
28+
local follow_tab_ = (type(follow_tab) == "function" and follow_tab(adapter))
29+
or (type(follow_tab) == "boolean" and follow_tab)
30+
31+
local open_winnr = window.fetch_window()
32+
33+
-- When follow_tab is a function, we have to "restore" what otherwise would be a leftover window
34+
--
35+
-- Consider the following scenario:
36+
-- - Tab 1 is active and has a dap-view window
37+
-- - User switches to tab 2, which is not eligible by `follow_tab`
38+
-- - `state.winnr` is now set to `nil`, but the window still exists on tab 1 (intended)
39+
-- - User switches to tab 3, which is eligible by `follow_tab`
40+
-- - Since there's a dap-view window elsewhere, we have to "reopen" to "follow the tab"
41+
-- (otherwise, visiting a non eligible tab wouldn't make much sense - afterwards, we'd keep the "closed" state)
42+
-- - We can do that just fine, since now we track the correct window with a (window) variable
43+
-- - Buf if the user closes the newly opened dap-view window on tab 3, and switches back to tab 1
44+
-- The original window will still be there! Since we closed, we don't want that!
45+
--
46+
-- This happens because the "close" function does not close all the the valid windows, only the one tracked by
47+
-- `state.winnr`, which is `nil` by then (massive oversight, I know)
48+
--
49+
-- This never came up before the dynamic `follow_tab` because we could always assume `state.winnr` was either
50+
-- from the current tab or the previous tab (which would then be handle by this very own autocmd)
51+
--
52+
-- By assigning `state.winnr` to the open window (which may be anywhere), `open`'s call to `close` will clean it
53+
if open_winnr and state.winnr == nil then
54+
state.winnr = open_winnr
55+
end
56+
57+
if util.is_win_valid(state.winnr) and follow_tab_ then
2258
require("dap-view.actions").open(state.term_winnr ~= nil)
2359
end
2460

lua/dap-view/config.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ local M = {}
7777
---@field icons dapview.IconsConfig Icons for each button
7878
---@field switchbuf string|dapview.SwitchBufFun Control how to jump when selecting a breakpoint or a call in the stack
7979
---@field auto_toggle boolean|"keep_terminal"
80-
---@field follow_tab boolean Reopen dapview when switching tabs
80+
---@field follow_tab boolean|fun(adapter?: string): boolean Reopen dapview when switching tabs
8181

8282
---@type dapview.ConfigStrict
8383
M.config = {

lua/dap-view/setup/validate/init.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function M.validate(config)
99
switchbuf = { config.switchbuf, { "string", "function" } },
1010
icons = { config.icons, "table" },
1111
auto_toggle = { config.auto_toggle, { "boolean", "string" } },
12-
follow_tab = { config.follow_tab, "boolean" },
12+
follow_tab = { config.follow_tab, { "boolean", "function" } },
1313
}, config)
1414

1515
if type(config.auto_toggle) == "string" and config.auto_toggle ~= "keep_terminal" then

lua/dap-view/util/window.lua

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
local api = vim.api
2+
3+
local M = {}
4+
5+
---@return integer?
6+
M.fetch_window = function()
7+
for _, tabpage in ipairs(api.nvim_list_tabpages()) do
8+
for _, win in ipairs(api.nvim_tabpage_list_wins(tabpage)) do
9+
if vim.w[win].dapview_win then
10+
return win
11+
end
12+
end
13+
end
14+
end
15+
16+
return M

0 commit comments

Comments
 (0)