refactor!: split close_behavior into two new config options

Gracefully deprecates the close_behavior option. See :help
aerial-close-behavior for information on how to migrate.
This commit is contained in:
Steven Arcangeli 2022-08-03 23:08:43 -07:00
parent b9cde181c3
commit 8e1d57562d
9 changed files with 342 additions and 172 deletions

View file

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

View file

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

View file

@ -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?
@ -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
@ -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
@ -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)
@ -139,7 +169,7 @@ 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)
@ -147,14 +177,14 @@ M.is_backend_attached = function(bufnr, backend)
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

View file

@ -12,26 +12,29 @@ local default_options = {
width = nil,
min_width = 10,
-- Enum: prefer_right, prefer_left, right, left, float
-- Determines the default direction to open the aerial window. The 'prefer'
-- options will open the window in the other direction *if* there is a
-- different buffer in the way of the preferred direction
-- Enum: prefer_right, prefer_left, right, left, float
default_direction = "prefer_right",
-- Enum: edge, group, window
-- Determines where the aerial window will be opened
-- edge - open aerial at the far right/left of the editor
-- group - open aerial to the right/left of the group of windows containing the current buffer
-- window - open aerial to the right/left of the current window
placement = "window",
},
-- Enum: persist, close, auto, global
-- persist - aerial window will stay open until closed
-- close - aerial window will close when original file is no longer visible
-- auto - aerial window will stay open as long as there is a visible
-- buffer to attach to
-- global - same as 'persist', and will always show symbols for the current buffer
close_behavior = "auto",
-- Determines how the aerial window decides which buffer to display symbols for
-- window - aerial window will display symbols for the buffer in the window from which it was opened
-- global - aerial window will display symbols for the current window
attach_mode = "window",
-- List of enum values that configure when to auto-close the aerial window
-- unfocus - close aerial when you leave the original source window
-- switch_buffer - close aerial when you change buffers in the source window
-- unsupported - close aerial when attaching to a buffer that has no symbol source
close_automatic_events = {},
-- Set to false to remove the default keybindings for the aerial buffer
default_bindings = true,
@ -56,7 +59,6 @@ local default_options = {
"Struct",
},
-- Enum: split_width, full_width, last, none
-- Determines line highlighting mode when multiple splits are visible.
-- split_width Each open window will have its cursor location marked in the
-- aerial buffer. Each line will only be partially highlighted
@ -87,7 +89,7 @@ local default_options = {
icons = {},
-- Control which windows and buffers aerial should ignore.
-- If close_behavior is "global", focusing an ignored window/buffer will
-- If attach_mode is "global", focusing an ignored window/buffer will
-- not cause the aerial window to update.
-- If open_automatic is true, focusing an ignored window/buffer will not
-- cause an aerial window to open.
@ -181,7 +183,7 @@ local default_options = {
-- Controls border appearance. Passed to nvim_open_win
border = "rounded",
-- Enum: cursor, editor, win
-- Determines location of floating window
-- cursor - Opens float on top of the cursor
-- editor - Opens float centered in the editor
-- win - Opens float centered in the window
@ -321,6 +323,28 @@ local function compat_move_option(opts, key, nested_key)
end
end
---@param value string
---@param values string[]
---@param opts? {allow_nil: boolean}
local function assert_enum(value, values, opts)
opts = opts or {}
local valid
if value == nil then
valid = opts.allow_nil
else
valid = vim.tbl_contains(values, value)
end
if valid then
return value
else
vim.notify(
string.format("Aerial got '%s', expected one of %s", value, table.concat(values, ", ")),
vim.log.levels.WARN
)
return values[1]
end
end
M.setup = function(opts)
opts = opts or {}
@ -336,13 +360,54 @@ M.setup = function(opts)
end
compat_move_option(opts, "placement_editor_edge", "layout")
if opts.close_behavior then
if opts.close_behavior == "global" then
opts.attach_mode = "global"
elseif opts.close_behavior == "persist" then
-- pass
elseif opts.close_behavior == "close" then
opts.close_automatic_events = { "switch_buffer" }
elseif opts.close_behavior == "auto" then
opts.close_automatic_events = { "unsupported" }
end
opts.close_behavior = nil
vim.notify(
"Deprecated[aerial]: close_behavior is deprecated. See :help aerial-close-behavior",
vim.log.levels.WARN
)
end
local newconf = vim.tbl_deep_extend("force", default_options, opts)
-- Asserts for all enum values
newconf.layout.default_direction = assert_enum(
newconf.layout.default_direction,
{ "prefer_right", "prefer_left", "right", "left", "float" }
)
newconf.layout.placement = assert_enum(newconf.layout.placement, { "window", "edge", "group" })
newconf.attach_mode = assert_enum(newconf.attach_mode, { "window", "global" })
for i, v in ipairs(newconf.close_automatic_events) do
newconf.close_automatic_events[i] =
assert_enum(v, { "unfocus", "switch_buffer", "unsupported" })
end
newconf.highlight_mode =
assert_enum(newconf.highlight_mode, { "split_width", "full_width", "last", "none" })
if newconf.auto_close ~= "persist" and newconf.auto_attach == "global" then
newconf.auto_close = "persist"
end
if newconf.nerd_font == "auto" then
local has_devicons = pcall(require, "nvim-web-devicons")
local has_lspkind = pcall(require, "lspkind")
newconf.nerd_font = has_devicons or has_lspkind
end
-- Add lookup to close_automatic_events
for i, v in ipairs(newconf.close_automatic_events) do
newconf.close_automatic_events[v] = i
end
-- Undocumented use_lspkind option for tests. End users can simply provide
-- their own icons
if newconf.use_lspkind == nil then

View file

@ -20,7 +20,7 @@ M.setup = function(opts)
vim.cmd([[
aug AerialEnterBuffer
au!
au BufEnter * lua require'aerial.autocommands'.on_enter_buffer()
au WinEnter,BufEnter * lua require'aerial.autocommands'.on_enter_buffer()
aug END
]])
command.create_commands()
@ -285,22 +285,13 @@ end
---Print out debug information for aerial
M.info = function()
local filetype = vim.api.nvim_buf_get_option(0, "filetype")
local bufnr = util.get_buffers(0)
local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype")
print("Aerial Info")
print("-----------")
print(string.format("Filetype: %s", filetype))
print("Configured backends:")
for _, name in ipairs(config.backends(0)) do
local line = " " .. name
local supported, err = backends.is_supported(0, name)
if supported then
line = line .. " (supported)"
else
line = line .. " (not supported) [" .. err .. "]"
end
if backends.is_backend_attached(0, name) then
line = line .. " (attached)"
end
for _, line in ipairs(backends.get_status_lines(bufnr)) do
print(line)
end
print(string.format("Show symbols: %s", config.get_filter_kind_map()))

View file

@ -1,3 +1,4 @@
local backends = require("aerial.backends")
local config = require("aerial.config")
local data = require("aerial.data")
local layout = require("aerial.layout")
@ -74,8 +75,13 @@ M.update_aerial_buffer = function(buf)
end
if not data:has_symbols(bufnr) then
local lines = { "No symbols" }
if config.lsp.filter_kind ~= false then
table.insert(lines, ":help aerial-filter")
if backends.get(bufnr) then
if config.lsp.filter_kind ~= false then
table.insert(lines, ":help aerial-filter")
end
else
table.insert(lines, "")
vim.list_extend(lines, backends.get_status_lines(bufnr))
end
resize_all_wins(aer_bufnr)
util.render_centered_text(aer_bufnr, lines)

View file

@ -61,17 +61,6 @@ M.go_buf_no_au = function(bufnr)
vim.cmd(string.format("noau b %d", bufnr))
end
M.get_aerial_orphans = function()
local orphans = {}
for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
local winbuf = vim.api.nvim_win_get_buf(winid)
if M.is_aerial_buffer(winbuf) and M.is_aerial_buffer_orphaned(winbuf) then
table.insert(orphans, winid)
end
end
return orphans
end
M.buf_first_win_in_tabpage = function(bufnr)
for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if vim.api.nvim_win_get_buf(winid) == bufnr then
@ -80,24 +69,41 @@ M.buf_first_win_in_tabpage = function(bufnr)
end
end
M.is_aerial_buffer_orphaned = function(bufnr)
local sourcebuf = M.get_source_buffer(bufnr)
if sourcebuf == -1 then
return true
---@param winid? integer
---@return integer? Source window
---@return integer? Aerial window
M.get_winids = function(winid)
if winid == nil or winid == 0 then
winid = vim.api.nvim_get_current_win()
end
if config.close_behavior == "global" and not M.is_aerial_buffer() then
return sourcebuf ~= vim.api.nvim_get_current_buf()
local bufnr = vim.api.nvim_win_get_buf(winid)
if M.is_aerial_buffer(bufnr) then
return M.get_source_win(winid), winid
else
return winid, M.get_aerial_win(winid)
end
for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
if vim.api.nvim_win_get_buf(winid) == sourcebuf then
return false
end
end
return true
end
M.get_aerial_buffer = function(bufnr)
return M.get_buffer_from_var(bufnr or 0, "aerial_buffer")
---@param winid integer
---@param varname string
---@return integer?
M.get_winid_from_var = function(winid, varname)
local status, result_winid = pcall(vim.api.nvim_win_get_var, winid, varname)
if status and result_winid ~= nil and vim.api.nvim_win_is_valid(result_winid) then
return result_winid
end
end
---@param winid? integer
---@return integer?
M.get_aerial_win = function(winid)
return M.get_winid_from_var(winid or 0, "aerial_win")
end
---@param winid? integer
---@return integer?
M.get_source_win = function(winid)
return M.get_winid_from_var(winid or 0, "source_win")
end
M.get_buffers = function(bufnr)
@ -111,6 +117,10 @@ M.get_buffers = function(bufnr)
end
end
M.get_aerial_buffer = function(bufnr)
return M.get_buffer_from_var(bufnr or 0, "aerial_buffer")
end
M.get_source_buffer = function(bufnr)
return M.get_buffer_from_var(bufnr or 0, "source_buffer")
end
@ -239,6 +249,8 @@ M.detect_split_direction = function(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
-- TODO make this smarter by accounting for placement = 'group' vs placement = 'window'
-- and also using winlayout()
left_available = vim.api.nvim_win_get_buf(wins[1]) == bufnr
right_available = vim.api.nvim_win_get_buf(wins[#wins]) == bufnr
end

View file

@ -3,16 +3,16 @@ local bindings = require("aerial.bindings")
local config = require("aerial.config")
local data = require("aerial.data")
local layout = require("aerial.layout")
local loading = require("aerial.loading")
local render = require("aerial.render")
local util = require("aerial.util")
local api = vim.api
local M = {}
local function create_aerial_buffer(bufnr)
local aer_bufnr = api.nvim_create_buf(false, true)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local aer_bufnr = vim.api.nvim_create_buf(false, true)
if config.default_bindings then
for _, binding in ipairs(bindings.keys) do
@ -21,41 +21,62 @@ local function create_aerial_buffer(bufnr)
keys = { keys }
end
for _, key in ipairs(keys) do
api.nvim_buf_set_keymap(aer_bufnr, "n", key, command, { silent = true, noremap = true })
vim.api.nvim_buf_set_keymap(aer_bufnr, "n", key, command, { silent = true, noremap = true })
end
end
end
api.nvim_buf_set_var(bufnr, "aerial_buffer", aer_bufnr)
vim.api.nvim_buf_set_var(bufnr, "aerial_buffer", aer_bufnr)
-- Set buffer options
api.nvim_buf_set_var(aer_bufnr, "source_buffer", bufnr)
loading.set_loading(aer_bufnr, not data:has_received_data(bufnr))
api.nvim_buf_set_option(aer_bufnr, "buftype", "nofile")
api.nvim_buf_set_option(aer_bufnr, "bufhidden", "wipe")
api.nvim_buf_set_option(aer_bufnr, "buflisted", false)
api.nvim_buf_set_option(aer_bufnr, "swapfile", false)
api.nvim_buf_set_option(aer_bufnr, "modifiable", false)
vim.api.nvim_buf_set_var(aer_bufnr, "source_buffer", bufnr)
vim.api.nvim_buf_set_option(aer_bufnr, "buftype", "nofile")
vim.api.nvim_buf_set_option(aer_bufnr, "bufhidden", "wipe")
vim.api.nvim_buf_set_option(aer_bufnr, "buflisted", false)
vim.api.nvim_buf_set_option(aer_bufnr, "swapfile", false)
vim.api.nvim_buf_set_option(aer_bufnr, "modifiable", false)
-- Set the filetype only after we enter the buffer so that ftplugins behave properly
vim.api.nvim_buf_call(aer_bufnr, function()
vim.api.nvim_buf_set_option(aer_bufnr, "filetype", "aerial")
end)
-- We create an autocmd to render the first time this buffer is displayed in a window
vim.cmd(string.format(
[[
au CursorMoved <buffer=%d> lua require('aerial.autocommands').on_cursor_move(true)
au BufLeave <buffer=%d> lua require('aerial.autocommands').on_leave_aerial_buf()
au BufWinEnter <buffer=%d> ++nested ++once lua require('aerial.render').update_aerial_buffer(%d)
]],
aer_bufnr,
aer_bufnr,
aer_bufnr,
aer_bufnr
))
return aer_bufnr
end
---@param src_winid integer
---@param aer_winid integer
local function setup_aerial_win(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
vim.api.nvim_win_set_option(aer_winid, "listchars", "tab:> ")
vim.api.nvim_win_set_option(aer_winid, "winfixwidth", true)
vim.api.nvim_win_set_option(aer_winid, "number", false)
vim.api.nvim_win_set_option(aer_winid, "signcolumn", "no")
vim.api.nvim_win_set_option(aer_winid, "foldcolumn", "0")
vim.api.nvim_win_set_option(aer_winid, "relativenumber", false)
vim.api.nvim_win_set_option(aer_winid, "wrap", false)
vim.api.nvim_win_set_option(aer_winid, "spell", false)
vim.api.nvim_win_set_var(aer_winid, "is_aerial_win", true)
vim.api.nvim_win_set_var(aer_winid, "source_win", src_winid)
vim.api.nvim_win_set_var(src_winid, "aerial_win", aer_winid)
util.restore_width(aer_winid)
end
local function create_aerial_window(bufnr, aer_bufnr, direction, existing_win)
-- We used to use < and > to indicate direction.
-- TODO: remove these at some point
if direction == "<" then
direction = "left"
vim.notify("Invalid aerial direction '<'. Use 'left'", vim.log.levels.WARN)
end
if direction == ">" then
vim.notify("Invalid aerial direction '>'. Use 'right'", vim.log.levels.WARN)
direction = "right"
end
if direction ~= "left" and direction ~= "right" and direction ~= "float" then
error("Expected direction to be 'left', 'right', or 'float'")
return
@ -65,7 +86,8 @@ local function create_aerial_window(bufnr, aer_bufnr, direction, existing_win)
aer_bufnr = create_aerial_buffer(bufnr)
end
local my_winid = api.nvim_get_current_win()
local my_winid = vim.api.nvim_get_current_win()
local aer_winid
if not existing_win then
if direction == "float" then
local rel = config.float.relative
@ -87,10 +109,10 @@ local function create_aerial_window(bufnr, aer_bufnr, direction, existing_win)
win_config.win = vim.api.nvim_get_current_win()
end
local new_config = config.float.override(win_config) or win_config
local winid = vim.api.nvim_open_win(aer_bufnr, true, new_config)
aer_winid = vim.api.nvim_open_win(aer_bufnr, false, new_config)
-- We store this as a window variable because relative=cursor gets
-- turned into relative=win when checking nvim_win_get_config()
vim.api.nvim_win_set_var(winid, "relative", new_config.relative)
vim.api.nvim_win_set_var(aer_winid, "relative", new_config.relative)
else
local modifier
if config.layout.placement == "edge" then
@ -111,39 +133,44 @@ local function create_aerial_window(bufnr, aer_bufnr, direction, existing_win)
modifier = direction == "left" and "leftabove" or "rightbelow"
end
vim.cmd(string.format("noau vertical %s split", modifier))
aer_winid = vim.api.nvim_get_current_win()
util.go_win_no_au(my_winid)
end
else
util.go_win_no_au(existing_win)
aer_winid = existing_win
end
util.go_buf_no_au(aer_bufnr)
api.nvim_win_set_option(0, "listchars", "tab:> ")
api.nvim_win_set_option(0, "winfixwidth", true)
api.nvim_win_set_option(0, "number", false)
api.nvim_win_set_option(0, "signcolumn", "no")
api.nvim_win_set_option(0, "foldcolumn", "0")
api.nvim_win_set_option(0, "relativenumber", false)
api.nvim_win_set_option(0, "wrap", false)
api.nvim_win_set_option(0, "spell", false)
api.nvim_win_set_var(0, "is_aerial_win", true)
-- Set the filetype only after we enter the buffer so that FileType autocmds
-- behave properly
api.nvim_buf_set_option(aer_bufnr, "filetype", "aerial")
vim.api.nvim_win_set_buf(aer_winid, aer_bufnr)
local aer_winid = api.nvim_get_current_win()
util.go_win_no_au(my_winid)
render.update_aerial_buffer(aer_bufnr)
setup_aerial_win(my_winid, aer_winid)
return aer_winid
end
M.is_open = function(bufnr)
local aer_bufnr = util.get_aerial_buffer(bufnr)
---@param src_bufnr integer source buffer
---@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)
local aer_bufnr = util.get_aerial_buffer(src_bufnr)
if aer_bufnr == -1 then
return false
else
local winid = util.buf_first_win_in_tabpage(aer_bufnr)
return winid ~= nil
aer_bufnr = create_aerial_buffer(src_bufnr)
end
vim.api.nvim_win_set_buf(aer_winid, aer_bufnr)
setup_aerial_win(src_winid, aer_winid)
end
---@param bufnr? integer
---@return integer|nil
M.get_aerial_win = function(bufnr)
local aer_bufnr = util.get_aerial_buffer(bufnr)
if aer_bufnr ~= -1 then
return util.buf_first_win_in_tabpage(aer_bufnr)
end
end
---@param bufnr? integer
---@return boolean
M.is_open = function(bufnr)
return M.get_aerial_win(bufnr) ~= nil
end
M.close = function()
@ -192,14 +219,11 @@ M.close_all_but_current = function()
end
end
---@param bufnr? integer
---@return boolean
M.maybe_open_automatic = function(bufnr)
if config.open_automatic(bufnr or 0) then
local opts = {}
local orphans = util.get_aerial_orphans()
if orphans[1] then
opts.winid = orphans[1]
end
M.open(false, nil, opts)
M.open(false)
return true
else
return false
@ -216,10 +240,10 @@ M.open = function(focus, direction, opts)
return
end
local bufnr, aer_bufnr = util.get_buffers()
if M.is_open() then
local aerial_win = M.get_aerial_win(bufnr)
if aerial_win then
if focus then
local winid = util.buf_first_win_in_tabpage(aer_bufnr)
api.nvim_set_current_win(winid)
vim.api.nvim_set_current_win(aerial_win)
end
return
end
@ -228,15 +252,15 @@ M.open = function(focus, direction, opts)
if not data:has_symbols(bufnr) then
backend.fetch_symbols(bufnr)
end
local my_winid = api.nvim_get_current_win()
local my_winid = vim.api.nvim_get_current_win()
M.update_position(nil, my_winid)
if focus then
api.nvim_set_current_win(aer_winid)
vim.api.nvim_set_current_win(aer_winid)
end
end
M.open_all = function()
if config.close_behavior == "global" then
if config.attach_mode == "global" then
return M.open()
end
for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
@ -252,10 +276,10 @@ M.focus = function()
if not M.is_open() then
return
end
local bufnr = api.nvim_get_current_buf()
local bufnr = vim.api.nvim_get_current_buf()
local aer_bufnr = util.get_aerial_buffer(bufnr)
local winid = util.buf_first_win_in_tabpage(aer_bufnr)
api.nvim_set_current_win(winid)
vim.api.nvim_set_current_win(winid)
end
M.toggle = function(focus, direction)
@ -277,7 +301,7 @@ end
---@param winid? integer
---@return aerial.CursorPosition
M.get_position_in_win = function(bufnr, winid)
local cursor = api.nvim_win_get_cursor(winid or 0)
local cursor = vim.api.nvim_win_get_cursor(winid or 0)
local lnum = cursor[1]
local col = cursor[2]
local bufdata = data:get_or_create(bufnr)
@ -367,14 +391,14 @@ M.update_position = function(winids, last_focused_win)
return
end
if winids == nil or winids == 0 then
winids = { api.nvim_get_current_win() }
winids = { vim.api.nvim_get_current_win() }
elseif type(winids) ~= "table" then
winids = { winids }
end
if #winids == 0 then
return
end
local win_bufnr = api.nvim_win_get_buf(winids[1])
local win_bufnr = vim.api.nvim_win_get_buf(winids[1])
local bufnr, aer_bufnr = util.get_buffers(win_bufnr)
if not data:has_symbols(bufnr) then
return
@ -399,13 +423,13 @@ M.update_position = function(winids, last_focused_win)
local aer_winid = util.buf_first_win_in_tabpage(aer_bufnr)
if aer_winid then
local last_position = bufdata.positions[bufdata.last_win]
local lines = api.nvim_buf_line_count(aer_bufnr)
local lines = vim.api.nvim_buf_line_count(aer_bufnr)
-- When aerial window is global, the items can change and cursor will move
-- before the symbols are published, which causes the line number to be
-- invalid.
if last_position and lines >= last_position.lnum then
api.nvim_win_set_cursor(aer_winid, { last_position.lnum, 0 })
vim.api.nvim_win_set_cursor(aer_winid, { last_position.lnum, 0 })
end
end
end

View file

@ -12,7 +12,7 @@ describe("config", function()
it("falls back to default options", function()
config.setup()
assert.equals(config.close_behavior, "auto")
assert.equals(config.attach_mode, "window")
end)
-- Filetype maps