Rework and simplify configuration options

This commit is contained in:
Steven Arcangeli 2021-06-17 09:54:37 -07:00
parent 81a4fe010c
commit 639ffe285b
11 changed files with 256 additions and 183 deletions

111
README.md
View file

@ -23,7 +23,7 @@ and [vim-plug](https://github.com/junegunn/vim-plug)
Plug 'stevearc/aerial.nvim'
```
## Configuration
## Setup
Step one is to get a Neovim LSP set up, which is beyond the scope of this guide.
See [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) for instructions.
@ -31,9 +31,6 @@ See [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig) for instructions.
After you have a functioning LSP setup, you will need to customize the
`on_attach` callback.
XXX Update all docs to remove prev_item/scroll_to_loc/jump_to_loc
XXX Remove the code too
```lua
local aerial = require'aerial'
@ -58,12 +55,95 @@ require'lspconfig'.vimls.setup{
}
```
A full list of commands and options can be found [in the
docs](https://github.com/stevearc/aerial.nvim/blob/master/doc/aerial.txt)
## Options
```lua
vim.g.aerial = {
-- Enum: prefer_right, prefer_left, right, left
-- 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
default_direction = 'prefer_right',
-- Fetch document symbols when LSP diagnostics change.
-- If you set this to false, you will need to manually fetch symbols
diagnostics_trigger_update = true,
-- Enum: split_width, full_width, last
-- Determines line highlighting mode when multiple buffers are visible
highlight_mode = 'split_width',
-- When jumping to a symbol, highlight the line for this many ms
-- Set to 0 or false to disable
highlight_on_jump = 300,
-- The maximum width of the aerial window
max_width = 40,
-- The minimum width of the aerial window.
-- To disable dynamic resizing, set this to be equal to max_width
min_width = 10,
-- Set default symbol icons to use Nerd Font icons (see https://www.nerdfonts.com/)
nerd_font = 'auto',
-- Whether to open aerial automatically when entering a buffer.
-- Can also be specified per-filetype as a map (see below)
open_automatic = false,
-- If open_automatic is true, only open aerial if the source buffer is at
-- least this long
open_automatic_min_lines = 0,
-- If open_automatic is true, only open aerial if there are at least this many symbols
open_automatic_min_symbols = 0,
-- Set to false to not update the symbols when there are LSP errors
update_when_errors = true,
-- A list of all symbols to display
filter_kind = {
"Class",
"Constructor",
"Enum",
"Function",
"Interface",
"Method",
"Struct",
},
}
-- open_automatic can be specified as a filetype map. For example, the below
-- configuration will open automatically in all filetypes except python and rust
vim.g.aerial = {
open_automatic = {
-- use underscore to specify the default behavior
['_'] = true,
python = false,
rust = false,
}
}
-- You can also override the default icons.
vim.g.aerial = {
icons = {
Class = '';
-- The icon to use when a class has been collapsed in the tree
ClassCollapsed = '喇';
Function = '';
Constant = '[c]'
-- The default icon to use when any symbol is collapsed in the tree
Collapsed = '▶';
}
}
```
Setting options in vimscript works the same way
```vim
" You can specify with global variables prefixed with 'aerial_'
let g:aerial_default_direction = 'left'
" Or you can set the g:aerial dict all at once
let g:aerial = {
\ 'default_direction': 'left',
\}
```
All possible SymbolKind values can be found [in the LSP
spec](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#symbolKind).
These are the values used for configuring icons, highlight groups, and
filtering.
## Default Keybindings
The default keybindings in the aerial window are [in the
ftplugin](https://github.com/stevearc/aerial.nvim/blob/master/ftplugin/aerial.vim)
The default keybindings in the aerial window are
Key | Command
--- | -------
@ -85,11 +165,12 @@ There are highlight groups created for each `SymbolKind`. There will be one for
the name of the symbol (`Aerial<SymbolKind>`, and one for the icon
(`Aerial<SymbolKind>Icon`). For example:
`AerialClass` \
`AerialClassIcon` \
`AerialFunction` \
`AerialFunctionIcon`
```vim
hi link AerialClass Type
hi link AerialClassIcon Special
hi link AerialFunction Special
hi AerialFunctionIcon guifg=#cb4b16 guibg=NONE guisp=NONE gui=NONE cterm=NONE
The [LSP spec](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol) has the authoritative list of valid `SymbolKind`s.
Additionally, there is an `AerialLine` group that is used to indicate cursor position.
" There's also this group for the cursor position
hi link AerialLine QuickFixLine
```

View file

@ -123,20 +123,6 @@ g:aerial_highlight_mode *g:aerial_highlight_mode
g:aerial_default_bindings *g:aerial_default_bindings*
If false, don't set up the default keybindings in the aerial buffer.
aerial.set_open_automatic({filetype}, {bool}) *aerial.set_open_automatic()*
aerial.set_open_automatic({mapping})
This is used to automatically open aerial when a new buffer is loaded.
Disabled by default. The options are set per-filetype like so:
>
aerial.set_open_automatic('vim', true)
aerial.set_open_automatic('rust', false)
-- Or you can specify the mapping
aerial.set_open_automatic{
['_'] = true, -- use underscore to set the default behavior
['vim'] = false,
['lua'] = false,
}
g:aerial_open_automatic_min_lines *g:aerial_open_automatic_min_lines*
When using |aerial.set_open_automatic()|, you can set this value to only
automatically open aerial on files greater than a certain length.
@ -171,19 +157,5 @@ aerial.set_icon({mapping})
aerial.set_icon('Collapsed', '---')
aerial.set_filter_kind({kinds}) *aerial.set_filter_kind()*
Only display these SymbolKind symbols in the aerial buffer. {kinds} is a
list-like table.
>
-- These are the default values
aerial.set_filter_kind{
'Function',
'Class',
'Constructor',
'Method',
'Struct',
'Enum',
}
===============================================================================
vim:ft=help:et:ts=2:sw=2:sts=2:norl

View file

@ -10,9 +10,7 @@ aerial.is_open() aerial.txt /*aerial.is_open()*
aerial.nvim aerial.txt /*aerial.nvim*
aerial.on_attach() aerial.txt /*aerial.on_attach()*
aerial.open() aerial.txt /*aerial.open()*
aerial.set_filter_kind() aerial.txt /*aerial.set_filter_kind()*
aerial.set_icon() aerial.txt /*aerial.set_icon()*
aerial.set_open_automatic() aerial.txt /*aerial.set_open_automatic()*
aerial.toggle() aerial.txt /*aerial.toggle()*
aerial.txt aerial.txt /*aerial.txt*
g:aerial_default_bindings aerial.txt /*g:aerial_default_bindings*

View file

@ -48,14 +48,14 @@ M.on_attach = function(client, opts)
end
vim.lsp.handlers['textDocument/documentSymbol'] = new_callback
if config.get_diagnostics_trigger_update() then
if config.diagnostics_trigger_update then
vim.cmd("autocmd User LspDiagnosticsChanged lua require'aerial.autocommands'.on_diagnostics_changed()")
end
vim.cmd("autocmd CursorMoved <buffer> lua require'aerial.autocommands'.on_cursor_move()")
vim.cmd("autocmd BufLeave <buffer> lua require'aerial.autocommands'.on_buf_leave()")
vim.cmd([[autocmd BufDelete <buffer> call luaeval("require'aerial.autocommands'.on_buf_delete(_A)", expand('<abuf>'))]])
if config.get_open_automatic() then
if config.open_automatic() then
vim.lsp.buf.document_symbol()
vim.cmd("autocmd BufWinEnter <buffer> lua require'aerial.autocommands'.on_buf_win_enter()")
end
@ -73,24 +73,36 @@ M.tree_cmd = function(action, opts)
end
end
-- @deprecated
M.set_open_automatic = function(ft_or_mapping, bool)
config.set_open_automatic(ft_or_mapping, bool)
end
M.set_icon = function(kind_or_mapping, icon)
config.set_icon(kind_or_mapping, icon)
end
M.set_filter_kind = function(list)
config.filter_kind = {}
for _,kind in pairs(list) do
config.filter_kind[kind] = true
local opts = vim.g.aerial or {}
if type(ft_or_mapping) == 'table' then
opts.open_automatic = ft_or_mapping
else
opts.open_automatic[ft_or_mapping] = bool
end
vim.g.aerial = opts
end
-- @deprecated. use set_icon() instead
-- @deprecated.
M.set_filter_kind = function(list)
local opts = vim.g.aerial or {}
opts.filter_kind = list
vim.g.aerial = opts
end
-- @deprecated.
M.set_kind_abbr = function(kind_or_mapping, abbr)
config.set_icon(kind_or_mapping, abbr)
local opts = vim.g.aerial or {}
if type(kind_or_mapping) == 'table' then
opts.icons = kind_or_mapping
else
if not opts.icons then
opts.icons = {}
end
opts.icons[kind_or_mapping] = abbr
end
vim.g.aerial = opts
end
-- @deprecated. Use select()

View file

@ -59,7 +59,7 @@ end
M.on_diagnostics_changed = function()
local errors = vim.lsp.diagnostic.get_count(0, 'Error')
-- if no errors, refresh symbols
if config.get_update_when_errors()
if config.update_when_errors
or errors == 0
or not data:has_symbols() then
vim.lsp.buf.document_symbol()
@ -67,7 +67,7 @@ M.on_diagnostics_changed = function()
end
M.on_buf_win_enter = function()
if not config.get_open_automatic() then
if not config.open_automatic() then
return
end

View file

@ -21,7 +21,7 @@ local function process_symbols(symbols)
elseif symbol.range then -- DocumentSymbol type
range = symbol.range
end
local include_item = range and config.filter_kind[kind]
local include_item = range and config.include_kind(kind)
if include_item then
local item = {
@ -58,7 +58,7 @@ M.symbol_callback = function(_, _, result, _, bufnr)
-- Don't update if there are diagnostics errors (or override by setting)
local error_count = vim.lsp.diagnostic.get_count(bufnr, 'Error')
local has_symbols = data:has_symbols(bufnr)
if not config.get_update_when_errors() and error_count > 0 and has_symbols then
if not config.update_when_errors and error_count > 0 and has_symbols then
return
end

View file

@ -1,21 +1,102 @@
local M = {}
local has_devicons = pcall(require, 'nvim-web-devicons')
local open_automatic = {
['_'] = false,
-- Copy this to the README after modification
local default_options = {
-- Enum: prefer_right, prefer_left, right, left
-- 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
default_direction = 'prefer_right',
-- Fetch document symbols when LSP diagnostics change.
-- If you set this to false, you will need to manually fetch symbols
diagnostics_trigger_update = true,
-- Enum: split_width, full_width, last
-- Determines line highlighting mode when multiple buffers are visible
highlight_mode = 'split_width',
-- When jumping to a symbol, highlight the line for this many ms
-- Set to 0 or false to disable
highlight_on_jump = 300,
-- The maximum width of the aerial window
max_width = 40,
-- The minimum width of the aerial window.
-- To disable dynamic resizing, set this to be equal to max_width
min_width = 10,
-- Set default symbol icons to use Nerd Font icons (see https://www.nerdfonts.com/)
nerd_font = 'auto',
-- Whether to open aerial automatically when entering a buffer.
-- Can also be specified per-filetype as a map (see below)
open_automatic = false,
-- If open_automatic is true, only open aerial if the source buffer is at
-- least this long
open_automatic_min_lines = 0,
-- If open_automatic is true, only open aerial if there are at least this many symbols
open_automatic_min_symbols = 0,
-- Set to false to not update the symbols when there are LSP errors
update_when_errors = true,
-- A list of all symbols to display
filter_kind = {
"Class",
"Constructor",
"Enum",
"Function",
"Interface",
"Method",
"Struct",
},
}
M.filter_kind = {
Class = true,
Constructor = true,
Enum = true,
Function = true,
Interface = true,
Method = true,
Struct = true,
}
local function get_option(opt)
local ret = vim.g[string.format('aerial_%s', opt)]
if ret == nil then
ret = (vim.g.aerial or {})[opt]
end
-- People are used to using 0 for v:false in vimscript
if ret == 0 and (default_options[opt] == true or default_options[opt] == false) then
ret = false
end
if ret == nil then
return default_options[opt]
else
return ret
end
end
local icons = nil
setmetatable(M, {
__index = function(_, opt)
return get_option(opt)
end
})
local function get_table_default(table, key, default_key, default)
if type(table) ~= 'table' then
return table
end
local ret = table[key]
if ret == nil and default_key then
ret = table[default_key]
end
if ret == nil then
return default
else
return ret
end
end
local function get_table_opt(opt, key, default_key, default)
return get_table_default(get_option(opt) or {}, key, default_key, default)
end
M.include_kind = function(kind)
return vim.tbl_contains(M.filter_kind, kind)
end
M.open_automatic = function()
local ft = vim.api.nvim_buf_get_option(0, 'filetype')
local ret = get_table_opt('open_automatic', ft, '_', false)
-- People are used to using 0 for v:false in vimscript
return ret and ret ~= 0
end
local plain_icons = {
Array = '[arr]';
@ -58,104 +139,31 @@ local nerd_icons = {
Collapsed = '';
}
M.get_highlight_on_jump = function()
local value = vim.g.aerial_highlight_on_jump
if value == nil then return true else return value end
end
M.get_update_when_errors = function()
local val = vim.g.aerial_update_when_errors
if val == nil then return true else return val end
end
M.set_open_automatic = function(ft_or_mapping, bool)
if type(ft_or_mapping) == 'table' then
open_automatic = ft_or_mapping
else
open_automatic[ft_or_mapping] = bool
end
end
M.get_open_automatic = function(bufnr)
local ft = vim.api.nvim_buf_get_option(bufnr or 0, 'filetype')
local ret = open_automatic[ft]
return ret == nil and open_automatic['_'] or ret
end
M.get_default_direction = function()
local dir = vim.g.aerial_default_direction
return dir == nil and 'prefer_right' or dir
end
M.get_open_automatic_min_lines = function()
local min_lines = vim.g.aerial_open_automatic_min_lines
if min_lines == nil then return 0 else return min_lines end
end
M.get_open_automatic_min_symbols = function()
local min_symbols = vim.g.aerial_open_automatic_min_symbols
if min_symbols == nil then return 0 else return min_symbols end
end
M.get_diagnostics_trigger_update = function()
local update = vim.g.aerial_diagnostics_trigger_update
if update == nil then return true else return update end
end
M.get_highlight_mode = function()
local mode = vim.g.aerial_highlight_mode
if mode == nil then
return 'split_width'
elseif mode == 'last' or mode == 'full_width' or mode == 'split_width' then
return mode
end
error("Unrecognized highlight mode '" .. mode .. "'")
return 'split_width'
end
M.get_min_width = function()
local width = vim.g.aerial_min_width
if width == nil then return 10 else return width end
end
M.get_max_width = function()
local width = vim.g.aerial_max_width
if width == nil then return 40 else return width end
end
M.get_use_icons = function()
local use_icons = vim.g.aerial_use_icons
if use_icons == nil then return has_devicons else return use_icons end
end
local function get_icons()
if not icons then
if M.get_use_icons() then
icons = vim.tbl_extend('keep', nerd_icons, plain_icons)
else
icons = plain_icons
end
end
return icons
end
M.set_icon = function(kind_or_mapping, icon)
if type(kind_or_mapping) == 'table' then
icons = vim.tbl_extend('keep', kind_or_mapping, get_icons())
else
get_icons()[kind_or_mapping] = icon
end
end
local _last_checked = 0
local _last_icons = {}
M.get_icon = function(kind, collapsed)
local abbrs = get_icons()
local abbr
if collapsed then
abbr = abbrs[kind .. 'Collapsed'] or abbrs['Collapsed']
else
abbr = abbrs[kind]
local icons = _last_icons
if vim.fn.localtime() - _last_checked > 5 then
local default
local nerd_font = get_option('nerd_font')
if nerd_font == 'auto' then
nerd_font = has_devicons
end
if nerd_font then
default = vim.tbl_extend('keep', nerd_icons, plain_icons)
else
default = plain_icons
end
icons = vim.tbl_extend('keep', M.icons or {}, default)
_last_icons = icons
_last_checked = vim.fn.localtime()
end
if collapsed then
return get_table_default(icons, kind..'Collapsed', 'Collapsed', kind)
else
return get_table_default(icons, kind, nil, kind)
end
return abbr and abbr or kind
end
return M

View file

@ -133,8 +133,8 @@ M.select = function(opts)
else
window.update_position(target_win)
end
if config.get_highlight_on_jump() then
util.flash_highlight(bufnr, item.lnum)
if config.highlight_on_jump then
util.flash_highlight(bufnr, item.lnum, config.highlight_on_jump)
end
end

View file

@ -38,7 +38,7 @@ M.update_aerial_buffer = function(buf)
row = row + 1
end)
local width = math.min(config.get_max_width(), math.max(config.get_min_width(), max_len))
local width = math.min(config.max_width, math.max(config.min_width, max_len))
util.set_width(aer_bufnr, width)
-- Insert lines into buffer
@ -77,7 +77,7 @@ M.update_highlights = function(buf)
return
end
local hl_width = math.floor(util.get_width(aer_bufnr) / #winids)
local hl_mode = config.get_highlight_mode()
local hl_mode = config.highlight_mode
if hl_mode == 'last' then
local row = data[bufnr].last_position

View file

@ -21,7 +21,7 @@ M.get_width = function(bufnr)
if ok then
return width
end
return config.get_min_width()
return config.min_width
end
M.set_width = function(bufnr, width)
@ -67,9 +67,11 @@ M.get_buffer_from_var = function(bufnr, varname)
return vim.fn.bufnr(result_bufnr)
end
M.flash_highlight = function(bufnr, lnum, hl_group, durationMs)
M.flash_highlight = function(bufnr, lnum, durationMs, hl_group)
hl_group = hl_group or 'AerialLine'
durationMs = durationMs or 300
if durationMs == true or durationMs == 1 then
durationMs = 300
end
local ns = vim.api.nvim_buf_add_highlight(bufnr, 0, hl_group, lnum - 1, 0, -1)
local remove_highlight = function()
vim.api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
@ -98,7 +100,7 @@ M.is_floating_win = function(winid)
end
M.detect_split_direction = function(bufnr)
local default = config.get_default_direction()
local default = config.default_direction
if default == 'left' then
return 'left'
elseif default == 'right' then

View file

@ -89,13 +89,13 @@ M.close = function()
end
M.maybe_open_automatic = function()
if not config.get_open_automatic() then
if not config.open_automatic() then
return false
end
if data[0]:count() < config.get_open_automatic_min_symbols() then
if data[0]:count() < config.open_automatic_min_symbols then
return false
end
if vim.fn.line('$') < config.get_open_automatic_min_lines() then
if vim.fn.line('$') < config.open_automatic_min_lines then
return false
end
M.open(false)