fix: Preview window position based on outline split position

- preview window can adapt based on position of outline window, and not
  based on config value of `position` left/right
- it can also properly vertically center-align, even when there are
  horizontal splits below the outline
- fixed a few bugs associated with previous rewrite commits in init.lua

config:
- Added min_height for preview window
This commit is contained in:
hedy
2023-11-18 15:04:26 +08:00
parent 62183f9d51
commit 090da7633b
6 changed files with 112 additions and 102 deletions

View File

@@ -50,6 +50,9 @@ local function wipe_state()
}
end
---Calls writer.make_outline and then calls M.update_cursor_pos if update_cursor is not false
---@param update_cursor boolean?
---@param set_cursor_to_node outline.SymbolNode|outline.FlatSymbolNode?
local function _update_lines(update_cursor, set_cursor_to_node)
local current
M.state.flattened_outline_items, current =
@@ -64,6 +67,35 @@ local function _merge_items(items)
utils.merge_items_rec({ children = items }, { children = M.state.outline_items })
end
---Setup autocmds for the buffer that the outline attached to
---@param code_win integer Must be valid
---@param code_buf integer Must be valid
local function setup_attached_buffer_autocmd(code_win, code_buf)
local events = cfg.o.outline_items.auto_update_events
if
cfg.o.outline_items.highlight_hovered_item
or cfg.o.symbol_folding.auto_unfold_hover
then
if M.state.autocmds[code_win] then
vim.api.nvim_del_autocmd(M.state.autocmds[code_win])
M.state.autocmds[code_win] = nil
end
if utils.str_or_nonempty_table(events.follow) then
M.state.autocmds[code_win] =
vim.api.nvim_create_autocmd(events.follow, {
buffer = code_buf,
callback = function()
M._highlight_current_item(
code_win,
cfg.o.outline_items.auto_set_cursor
)
end,
})
end
end
end
local function __refresh()
local current_buffer_is_outline = M.view.bufnr == vim.api.nvim_get_current_buf()
if M.view:is_open() and not current_buffer_is_outline then
@@ -82,29 +114,16 @@ local function __refresh()
M.state.autocmds[M.state.code_win] = nil
end
end
M.state.code_win = curwin
M.state.code_buf = curbuf
if cfg.o.outline_items.highlight_hovered_item or cfg.o.symbol_folding.auto_unfold_hover then
if M.state.autocmds[curwin] then
vim.api.nvim_del_autocmd(M.state.autocmds[curwin])
M.state.autocmds[curwin] = nil
end
if utils.str_or_nonempty_table(cfg.o.outline_items.auto_update_events.follow) then
M.state.autocmds[curwin] =
vim.api.nvim_create_autocmd(cfg.o.outline_items.auto_update_events.follow, {
buffer = curbuf,
callback = function()
M._highlight_current_item(nil, cfg.o.outline_items.auto_follow_cursor)
end,
})
end
end
setup_attached_buffer_autocmd(curwin, curbuf)
local items = parser.parse(response, vim.api.nvim_get_current_buf())
_merge_items(items)
local update_cursor = newbuf or cfg.o.outline_items.auto_follow_cursor
local update_cursor = newbuf or cfg.o.outline_items.auto_set_cursor
_update_lines(update_cursor)
end
@@ -326,13 +345,22 @@ function M._highlight_current_item(winnr, update_cursor)
return
end
-- TODO: Find an efficient way to:
-- 1) Set highlight for all nodes in range (regardless of visibility)
-- 2) Find the line number of the deepest node in range, that is visible (no
-- parents folded)
-- In one go
local valid_code_win = vim.api.nvim_win_is_valid(M.state.code_win)
local valid_winnr = winnr and vim.api.nvim_win_is_valid(winnr)
-- XXX: Could current win ~= M.state.code_win here?
if not valid_code_win then
-- Definetely don't attempt to update anything if code win is no longer valid
return
end
if not valid_winnr then
return
elseif winnr ~= M.state.code_win then
-- Both valid, but given winnr ~= known code_win.
-- Best not to handle this situation at all to prevent any unwanted side
-- effects
return
end
_update_lines(update_cursor)
end
@@ -421,35 +449,16 @@ local function handler(response, opts)
return
end
if not opts then
opts = {}
end
M.state.code_win = vim.api.nvim_get_current_win()
M.state.code_buf = vim.api.nvim_get_current_buf()
M.state.opened_first_outline = true
if opts and opts.on_symbols then
opts.on_symbols()
end
M.view:setup_view()
if opts and opts.on_outline_setup then
opts.on_outline_setup()
end
if cfg.o.outline_items.highlight_hovered_item or cfg.o.symbol_folding.auto_unfold_hover then
if M.state.autocmds[M.state.code_win] then
vim.api.nvim_del_autocmd(M.state.autocmds[M.state.code_win])
M.state.autocmds[M.state.code_win] = nil
end
if utils.str_or_nonempty_table(cfg.o.outline_items.auto_update_events.follow) then
M.state.autocmds[M.state.code_win] =
vim.api.nvim_create_autocmd(cfg.o.outline_items.auto_update_events.follow, {
buffer = M.state.code_buf,
callback = function()
M._highlight_current_item(nil, cfg.o.outline_items.auto_follow_cursor)
end,
})
end
end
local sc = opts.split_command or cfg.get_split_command()
M.view:setup_view(sc)
-- clear state when buffer is closed
vim.api.nvim_buf_attach(M.view.bufnr, false, {
@@ -460,6 +469,7 @@ local function handler(response, opts)
setup_keymaps(M.view.bufnr)
setup_buffer_autocmd()
setup_attached_buffer_autocmd(M.state.code_win, M.state.code_buf)
local items = parser.parse(response, M.state.code_buf)
@@ -470,7 +480,7 @@ local function handler(response, opts)
M.update_cursor_pos(current)
if not cfg.o.outline_window.focus_on_open or (opts and not opts.focus_outline) then
if not cfg.o.outline_window.focus_on_open or not opts.focus_outline then
vim.fn.win_gotoid(M.state.code_win)
end
end
@@ -531,26 +541,13 @@ end
local function _cmd_open_with_mods(fn)
return function(opts)
local old_sc, use_old_sc
local split = opts.smods.split
if split ~= '' then
old_sc = cfg.o.outline_window.split_command
use_old_sc = true
cfg.o.outline_window.split_command = split .. ' vsplit'
local fnopts = { focus_outline = not opts.bang }
local sc = opts.smods.split
if sc ~= '' then
fnopts.split_command = sc .. ' vsplit'
end
local function on_outline_setup()
if use_old_sc then
cfg.o.outline_window.split_command = old_sc
-- the old option should already have been resolved during set up
end
end
if opts.bang then
fn({ focus_outline = false, on_outline_setup = on_outline_setup })
else
fn({ focus_outline = true, on_outline_setup = on_outline_setup })
end
fn(fnopts)
end
end