Skip to content

Commit

Permalink
fix: improper window behavior when attach_mode = 'global' (#185)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevearc committed Nov 27, 2022
1 parent 4b42ddb commit e161ad5
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 29 deletions.
44 changes: 23 additions & 21 deletions lua/aerial/autocommands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ local function should_close_aerial(aer_win)
end
local src_buf = util.get_source_buffer(aer_buf)

if config.close_automatic_events.unfocus then
-- Close the window if the aerial source win is not the current win
if src_win ~= vim.api.nvim_get_current_win() then
return true
end
end

-- Close the aerial window if its attached buffer is unsupported
if config.close_automatic_events.unsupported then
if not vim.api.nvim_buf_is_valid(src_buf) or not backends.get(src_buf) then
Expand All @@ -39,29 +32,38 @@ end
local function update_aerial_windows()
local config = require("aerial.config")
local window = require("aerial.window")
local curwin = vim.api.nvim_get_current_win()
for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if not vim.api.nvim_win_is_valid(winid) then
if not vim.api.nvim_win_is_valid(winid) or not util.is_aerial_win(winid) then
goto continue
end
local winbuf = vim.api.nvim_win_get_buf(winid)
if not util.is_aerial_buffer(winbuf) then
goto continue
local src_win = util.get_source_win(winid)
local src_buf
if src_win then
src_buf = vim.api.nvim_win_get_buf(src_win)
end
local close = false

if config.close_automatic_events.unfocus and curwin ~= winid then
-- Close the window if the aerial source win is not the current win
if src_win ~= vim.api.nvim_get_current_win() then
close = true
end
end
if src_buf then
-- Close the aerial window if its source window has switched buffers
if config.close_automatic_events.switch_buffer then
if src_buf ~= util.get_source_buffer(winbuf) then
close = true
end
end
end

if config.attach_mode == "global" then
window.open_aerial_in_win(0, 0, winid)
elseif config.attach_mode == "window" then
local src_win = util.get_source_win(winid)
if src_win then
local src_buf = vim.api.nvim_win_get_buf(src_win)

-- Close the aerial window if its source window has switched buffers
if config.close_automatic_events.switch_buffer then
if src_buf ~= util.get_source_buffer(winbuf) then
close = true
end
end

if src_win and src_buf then
if util.get_source_win(winid) == vim.api.nvim_get_current_win() then
window.open_aerial_in_win(src_buf, src_win, winid)
end
Expand Down
3 changes: 3 additions & 0 deletions lua/aerial/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ end
---@param bufnr nil|integer
---@return boolean
M.is_aerial_buffer = function(bufnr)
if not vim.api.nvim_buf_is_valid(bufnr or 0) then
return false
end
local ft = vim.api.nvim_buf_get_option(bufnr or 0, "filetype")
return ft == "aerial"
end
Expand Down
16 changes: 10 additions & 6 deletions lua/aerial/window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,6 @@ end
---@param src_winid integer
---@param aer_winid integer
local function setup_aerial_win(src_winid, aer_winid, aer_bufnr)
if src_winid == 0 then
src_winid = vim.api.nvim_get_current_win()
end
if aer_winid == 0 then
aer_winid = vim.api.nvim_get_current_win()
end
vim.api.nvim_win_set_buf(aer_winid, aer_bufnr)
vim.api.nvim_win_set_option(aer_winid, "list", false)
vim.api.nvim_win_set_option(aer_winid, "winfixwidth", true)
Expand Down Expand Up @@ -174,9 +168,19 @@ end
---@param src_winid integer window containing source buffer
---@param aer_winid integer aerial window
M.open_aerial_in_win = function(src_bufnr, src_winid, aer_winid)
if src_winid == 0 then
src_winid = vim.api.nvim_get_current_win()
end
if aer_winid == 0 then
aer_winid = vim.api.nvim_get_current_win()
end
local aer_bufnr = util.get_aerial_buffer(src_bufnr)
-- If aerial is already open in the window, early return
if aer_bufnr == vim.api.nvim_win_get_buf(aer_winid) then
-- Always update the source/aerial win pointers because attach_mode = "global" requires that
-- they be up to date. We may be calling open_aerial_in_win for same buffer but in a new win.
vim.api.nvim_win_set_var(aer_winid, "source_win", src_winid)
vim.api.nvim_win_set_var(src_winid, "aerial_win", aer_winid)
return
end
if aer_bufnr == -1 then
Expand Down
136 changes: 134 additions & 2 deletions tests/attach_and_events_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,40 @@ local function has_no_symbols(bufnr)
return false
end

a.describe("config", function()
---@return integer
local function num_wins()
return #vim.api.nvim_tabpage_list_wins(0)
end

---@return integer
local function num_aerial_wins()
local ret = 0
for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if util.is_aerial_win(winid) then
ret = ret + 1
end
end
return ret
end

a.describe("config attach_mode = 'window'", function()
after_each(function()
test_util.reset_editor()
end)

a.it("attach_mode = 'window' updates symbols when changing to unsupported buffer", function()
a.it("opens one aerial window per source window", function()
aerial.setup({
attach_mode = "window",
})
vim.cmd.edit({ args = { "README.md" } })
aerial.open({ focus = false })
vim.cmd.vsplit()
aerial.toggle()
assert.equals(4, num_wins())
assert.equals(2, num_aerial_wins())
end)

a.it("updates symbols when changing to unsupported buffer", function()
aerial.setup({
lazy_load = false,
attach_mode = "window",
Expand Down Expand Up @@ -108,3 +136,107 @@ a.describe("config", function()
end
)
end)

a.describe("config attach_mode = 'global'", function()
after_each(function()
test_util.reset_editor()
end)

a.it("opens one aerial window ever", function()
aerial.setup({
attach_mode = "global",
})
vim.cmd.edit({ args = { "README.md" } })
aerial.open({ focus = false })
vim.cmd.vsplit()
sleep(10)
aerial.open()
assert.equals(3, num_wins())
assert.equals(1, num_aerial_wins())
end)

a.it("updates symbols when changing to unsupported buffer", function()
aerial.setup({
lazy_load = false,
attach_mode = "global",
})
vim.cmd.edit({ args = { "README.md" } })
aerial.toggle({ focus = false })
local aerial_win = util.get_aerial_win(0)
assert.is_not_nil(aerial_win)
-- Wait for symbols to populate
sleep(1)
assert.falsy(has_no_symbols(vim.api.nvim_win_get_buf(aerial_win)))
vim.cmd.edit({ args = { "LICENSE" } })
-- Wait for autocmd to run and attached buffer to switch
sleep(10)
local aerial_buf = vim.api.nvim_win_get_buf(aerial_win)
assert.truthy(loading.is_loading(aerial_buf))
sleep(50)
assert.falsy(loading.is_loading(aerial_buf))
assert.truthy(has_no_symbols(vim.api.nvim_win_get_buf(aerial_win)))
end)

a.it(
"close_automatic_events = 'unsupported' closes aerial when entering unsupported buffer",
function()
aerial.setup({
lazy_load = false,
attach_mode = "global",
close_automatic_events = { "unsupported" },
})
vim.cmd.edit({ args = { "README.md" } })
aerial.toggle({ focus = false })
local aerial_win = util.get_aerial_win(0)
assert.is_not_nil(aerial_win)
-- Wait for symbols to populate
sleep(1)
vim.cmd.edit({ args = { "LICENSE" } })
-- Wait for autocmd to run and attached buffer to switch
sleep(50)
assert.falsy(vim.api.nvim_win_is_valid(aerial_win))
end
)

a.it("close_automatic_events = 'unfocus' closes aerial when leaving window", function()
aerial.setup({
lazy_load = false,
attach_mode = "global",
close_automatic_events = { "unfocus" },
})
vim.cmd.edit({ args = { "README.md" } })
local main_win = vim.api.nvim_get_current_win()
aerial.toggle({ focus = true })
local aerial_win = vim.api.nvim_get_current_win()
assert.is_not.equals(main_win, aerial_win)
assert.truthy(vim.api.nvim_win_is_valid(aerial_win))
-- Wait for symbols to populate
sleep(1)
vim.api.nvim_set_current_win(main_win)
sleep(10)
assert.truthy(vim.api.nvim_win_is_valid(aerial_win))
vim.cmd.vsplit()
sleep(10)
assert.falsy(vim.api.nvim_win_is_valid(aerial_win))
end)

a.it(
"close_automatic_events = 'switch_buffer' closes aerial when buffer in window changes",
function()
aerial.setup({
lazy_load = false,
attach_mode = "global",
close_automatic_events = { "switch_buffer" },
})
vim.cmd.edit({ args = { "README.md" } })
aerial.toggle({ focus = false })
local aerial_win = util.get_aerial_win(0)
assert.truthy(vim.api.nvim_win_is_valid(aerial_win))
-- Wait for symbols to populate
sleep(1)
vim.cmd.edit({ args = { "doc/api.md" } })
sleep(10)
assert.falsy(vim.api.nvim_win_is_valid(aerial_win))
end
)
end)

0 comments on commit e161ad5

Please sign in to comment.