Skip to content

Commit

Permalink
refactor!: split close_behavior into two new config options
Browse files Browse the repository at this point in the history
Gracefully deprecates the close_behavior option. See :help
aerial-close-behavior for information on how to migrate.
  • Loading branch information
stevearc committed Aug 27, 2022
1 parent b9cde18 commit 8e1d575
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 173 deletions.
10 changes: 10 additions & 0 deletions doc/aerial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,16 @@ replicate the old behavior you could get with `open_automatic_min_lines` and
}
<

*aerial-close-behavior*
The `close_behavior` config option has been replaced by a combination of
`attach_mode` and `close_automatic_events`. I would recommend reading the docs
for each of these, but a migration cheat-sheet is provided below.
>
close_behavior = "global" --> attach_mode = "global"
close_behavior = "persist" --> this is the new effective default
close_behavior = "auto" --> close_automatic_events = { "unsupported" }
close_behavior = "close" --> close_automatic_events = { "switch_buffer" }
<

*SymbolKind* *symbol*
A quick note on SymbolKind. An authoritative list of valid SymbolKinds can be
Expand Down
112 changes: 72 additions & 40 deletions lua/aerial/autocommands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,63 @@ local window = require("aerial.window")

local M = {}

local function is_sticky(behavior)
return behavior == "persist" or behavior == "global"
local maybe_open_automatic = util.throttle(function()
window.maybe_open_automatic()
end, { delay = 5, reset_timer_on_call = true })

---@param aer_win integer
---@return boolean
local function should_close_aerial(aer_win)
local aer_buf = vim.api.nvim_win_get_buf(aer_win)
local src_win = util.get_source_win(aer_win)
-- If the aerial window has no valid source window, close it
if not src_win then
return true
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
return true
end
end
return false
end

local function close_orphans()
local orphans = util.get_aerial_orphans()
for _, winid in ipairs(orphans) do
if is_sticky(config.close_behavior) then
render.clear_buffer(vim.api.nvim_win_get_buf(winid))
else
vim.api.nvim_win_close(winid, true)
local function update_aerial_windows()
for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
local winbuf = vim.api.nvim_win_get_buf(winid)
if util.is_aerial_buffer(winbuf) then
local close = false
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)
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 util.get_source_win(winid) == vim.api.nvim_get_current_win() then
window.open_aerial_in_win(src_buf, src_win, winid)
end
end

if close or should_close_aerial(winid) then
vim.api.nvim_win_close(winid, true)
end
end
end
end
Expand All @@ -31,47 +77,33 @@ M.on_enter_buffer = util.throttle(function()
end

local mybuf = vim.api.nvim_get_current_buf()
if not util.is_aerial_buffer(mybuf) then
if config.close_behavior == "close" then
close_orphans()
end

-- If we're not in supported buffer
local backend = backends.get()
if not backend then
fold.restore_foldmethod()
close_orphans()
return
end

fold.maybe_set_foldmethod()
end

if util.is_aerial_buffer(mybuf) then
local source_win = util.get_source_win()
if
(not is_sticky(config.close_behavior) and util.is_aerial_buffer_orphaned(mybuf))
or vim.tbl_count(vim.api.nvim_list_wins()) == 1
(not source_win and config.attach_mode ~= "global")
or vim.tbl_count(vim.api.nvim_tabpage_list_wins(0)) == 1
then
vim.cmd("quit")
else
-- Hack to ignore winwidth
util.restore_width(0)
end
elseif window.is_open() then
close_orphans()
render.update_aerial_buffer()
return
end

update_aerial_windows()

-- If we're not in supported buffer
local backend = backends.get()
if not backend then
fold.restore_foldmethod()
else
local orphans = util.get_aerial_orphans()
if orphans[1] then
-- open our symbols in that window
vim.defer_fn(function()
window.open(false, nil, { winid = orphans[1] })
end, 5)
else
vim.defer_fn(function()
window.maybe_open_automatic()
end, 5)
end
fold.maybe_set_foldmethod()
end

if not window.is_open() then
maybe_open_automatic()
end
end, { delay = 10, reset_timer_on_call = true })

Expand Down
52 changes: 41 additions & 11 deletions lua/aerial/backends/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,26 @@ M.is_supported = function(bufnr, name)
end
end

---@param bufnr integer
---@return string[]
M.get_status_lines = function(bufnr)
local ret = {}
for _, name in ipairs(config.backends(bufnr)) do
local line = " " .. name
local supported, err = M.is_supported(bufnr, name)
if supported then
line = line .. " (supported)"
else
line = line .. " (not supported) [" .. err .. "]"
end
if M.is_backend_attached(bufnr, name) then
line = line .. " (attached)"
end
table.insert(ret, line)
end
return ret
end

---@param bufnr? integer
---@return aerial.Backend?
---@return string?
Expand All @@ -58,13 +78,13 @@ local function get_best_backend(bufnr)
return nil, nil
end

---@param bufnr integer
---@param bufnr? integer
---@param backend string
local function set_backend(bufnr, backend)
vim.api.nvim_buf_set_var(bufnr, "aerial_backend", backend)
vim.api.nvim_buf_set_var(bufnr or 0, "aerial_backend", backend)
end

---@param bufnr integer
---@param bufnr? integer
---@param backend? aerial.Backend
---@param name? string
---@param existing_backend_name? string
Expand All @@ -82,27 +102,32 @@ local function attach(bufnr, backend, name, existing_backend_name)
else
require("aerial.autocommands").attach_autocommands(bufnr)
require("aerial.fold").add_fold_mappings(bufnr)
local data = require("aerial.data")
local loading = require("aerial.loading")
local util = require("aerial.util")
local aer_bufnr = util.get_aerial_buffer(bufnr)
loading.set_loading(aer_bufnr, not data:has_received_data(bufnr))
end
if not existing_backend_name and config.on_attach then
config.on_attach(bufnr)
end
end

---@param bufnr integer
---@param bufnr? integer
---@return aerial.Backend?
M.get = function(bufnr)
local existing_backend_name = M.get_attached_backend(bufnr)
if existing_backend_name then
return M.get_backend_by_name(existing_backend_name)
return M.get_backend_by_name(existing_backend_name), existing_backend_name
end
local backend, name = get_best_backend(bufnr)
if backend and name then
attach(bufnr, backend, name, existing_backend_name)
end
return backend
return backend, name
end

---@param bufnr integer
---@param bufnr? integer
---@param items aerial.Symbol[]
M.set_symbols = function(bufnr, items)
if not bufnr or bufnr == 0 then
Expand All @@ -127,7 +152,12 @@ M.set_symbols = function(bufnr, items)
if not had_symbols then
fold.maybe_set_foldmethod(bufnr)
if bufnr == vim.api.nvim_get_current_buf() then
window.maybe_open_automatic(bufnr)
-- When switching buffers, this can complete before the BufEnter autocmd since it's throttled.
-- We need that autocmd to complete first so that it reallocates the existing aerial windows,
-- thus the defer. It's a bit of a hack :/
vim.defer_fn(function()
window.maybe_open_automatic(bufnr)
end, 15)
end
if config.on_first_symbols then
config.on_first_symbols(bufnr)
Expand All @@ -139,22 +169,22 @@ M.log_support_err = function()
vim.api.nvim_err_writeln("Aerial could find no supported backend")
end

---@param bufnr integer
---@param bufnr? integer
---@param backend string
---@return boolean?
M.is_backend_attached = function(bufnr, backend)
local b = M.get_attached_backend(bufnr)
return b and (b == backend or backend == nil)
end

---@param bufnr integer
---@param bufnr? integer
---@return string?
M.get_attached_backend = function(bufnr)
local ok, val = pcall(vim.api.nvim_buf_get_var, bufnr or 0, "aerial_backend")
return ok and val or nil
end

---@param bufnr integer
---@param bufnr? integer
---@param refresh? boolean
M.attach = function(bufnr, refresh)
if refresh then
Expand Down

0 comments on commit 8e1d575

Please sign in to comment.