Skip to content

Commit

Permalink
ui: unified panel
Browse files Browse the repository at this point in the history
this commit adds the ability to treat all calltree ui elements as a
unified panel similar to other IDEs.

the unified panel consists of a persistent symbol and call tree and both
UIs will stick together when the unified panel is toggled open or
closed.

this is an opt in feature and using each component separately is still
possible.

Signed-off-by: ldelossa <[email protected]>
  • Loading branch information
ldelossa committed Nov 30, 2021
1 parent 8a609c1 commit 4d71c36
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 11 deletions.
28 changes: 27 additions & 1 deletion doc/calltree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ This is what the "calltree.setup()" function does.
Once the calltree handlers are in place issuing the normal "vim.lsp.buf.incoming_calls"
and "vim.lsp.buf.outgoing_calls" will open the calltree window.

The calltree UI can be used as a unified panel or as individual elements.

A unified panel would feel similar to IDE's such as VSCode where you can "hide"
and "unhide" a persistent informational panel. Both the symbol tree and the call tree will
always be present in the toggled panel, unless you manually close a window.
Toggling the panel will recreate any closed windows. This functionality
is provided via the "CTToggle" command.

If you'd rather use each individual component separately this is possible
too. Utilize the "CTOpen/CTClose" and "STOpen/STClose" commands. These commands
will only open and close the respective UI components.

By default performing a "call-hierarchy" request for incoming or outgoing calls
does not assume a unified panel. If you'd like it to open the unified panel on LSP requests
then set "unified_panel" to true in the config. See *calltree-config*

From there check out *calltree-commands* to manipulate the calltree UI.

====================================================================================
Expand All @@ -76,8 +92,15 @@ Calltree exports several commands for manipulating the calltree UI.

*:CTClose*
:CTClose
Closes the calltree window
Closes the calltree window.
*:STOpen*

*:CTToggle*
:CTToggle
Treats calltree as a persistent panel and toggles it open or close.
Using this command will always toggle both the symboltree and calltree
components as if they were a single unified panel.

:STOpen
Open the symboltree window with the most recent outline tree present.

Expand Down Expand Up @@ -219,6 +242,9 @@ The config table is described below:
-- set this to false for large codebases to speed up opening
-- the calltree.
resolve_symbols = true
-- if set to true calling LSP functions which trigger calltree UI
-- will open the unified panel. see *calltree-usage* for details.
open_panel = false
}

====================================================================================
Expand Down
4 changes: 3 additions & 1 deletion lua/calltree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ M.config = {
indent_guides = true,
icon_highlights = {},
hls = {},
resolve_symbols = true
resolve_symbols = true,
unified_panel = false
}

function _setup_default_highlights()
Expand Down Expand Up @@ -148,6 +149,7 @@ function M.setup(user_config)
-- setup commands
vim.cmd("command! CTOpen lua require('calltree.ui').open_calltree()")
vim.cmd("command! STOpen lua require('calltree.ui').open_symboltree()")
vim.cmd("command! CTToggle lua require('calltree.ui').toggle_panel()")
vim.cmd("command! CTClose lua require('calltree.ui').close_calltree()")
vim.cmd("command! STClose lua require('calltree.ui').close_symboltree()")
vim.cmd("command! CTExpand lua require('calltree.ui').expand()")
Expand Down
26 changes: 19 additions & 7 deletions lua/calltree/lsp/handlers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,20 @@ M.ch_lsp_handler = function(direction)
if config.resolve_symbols then
lsp_util.gather_symbols_async(root, children, ui_state, function()
tree.add_node(ui_state.calltree_handle, root, children)
ui.open_calltree()
if config.unified_panel then
ui.toggle_panel(true)
else
ui.open_calltree()
end
end)
return
end
tree.add_node(ui_state.calltree_handle, root, children)
ui.open_calltree()
if config.unified_panel then
ui.toggle_panel(true)
else
ui.open_calltree()
end
end
end

Expand All @@ -86,14 +94,14 @@ M.ws_lsp_handler = function()
return
end

cur_win = vim.api.nvim_get_current_win()
local cur_win = vim.api.nvim_get_current_win()

cur_tabpage = vim.api.nvim_win_get_tabpage(cur_win)
local cur_tabpage = vim.api.nvim_win_get_tabpage(cur_win)

ui_state = ui.ui_state_registry[cur_tabpage]
local ui_state = ui.ui_state_registry[cur_tabpage]
if ui_state == nil then
ui_state = {}
ui.ui_state_registry[cur_tabpage] = ui_sate
ui.ui_state_registry[cur_tabpage] = ui_state
end

-- snag the lsp clients from the buffer issuing the
Expand Down Expand Up @@ -127,7 +135,11 @@ M.ws_lsp_handler = function()

tree.add_node(ui_state.symboltree_handle, root, nil, true)

ui.open_symboltree()
if config.unified_panel then
ui.toggle_panel(true)
else
ui.open_symboltree()
end
end
end

Expand Down
1 change: 0 additions & 1 deletion lua/calltree/lsp/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ function M.gather_symbols_async(root, children, ui_state, callback)
local params = {
query = node.name,
}
print(node.name)
M.multi_client_request(
ui_state.active_lsp_clients,
"workspace/symbol",
Expand Down
31 changes: 31 additions & 0 deletions lua/calltree/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,37 @@ M.close_calltree = function()
M.calltree_win = nil
end

M.toggle_panel = function(keep_open)
local win = vim.api.nvim_get_current_win()
local tab = vim.api.nvim_win_get_tabpage(win)
local ui_state = M.ui_state_registry[tab]
if ui_state == nil then
ui_state = {}
M.ui_state_registry[tab] = ui_state
end

local buf_name = "calltree: empty"
if ui_state.calltree_dir ~= nil then
buf_name = direction_map[ui_state.calltree_dir].buf_name
end

ui_state.calltree_buf =
ui_buf._setup_buffer(buf_name, ui_state.calltree_buf, tab)
if ui_state.calltree_handle ~= nil then
tree.write_tree(ui_state.calltree_handle, ui_state.calltree_buf)
end
ui_state.calltree_tab = tab

ui_state.symboltree_buf =
ui_buf._setup_buffer("documentSymbols", ui_state.symboltree_buf, tab)
if ui_state.symboltree_handle ~= nil then
tree.write_tree(ui_state.symboltree_handle, ui_state.symboltree_buf)
end

ui_state.symboltree_tab = tab
ui_win._toggle_panel(ui_state, keep_open)
end

-- open_symboltree will open a symboltree ui in the current tab.
--
-- if a valid tree handle and buffer exists in the tab's calltree
Expand Down
2 changes: 1 addition & 1 deletion lua/calltree/ui/marshal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ function M.marshal_node(node, final)

if ct.config.icons ~= "none" then
-- ▶  Func1
str = str .. M.glyphs.space .. icon .. M.glyphs.space .. M.glyphs.space .. name
str = str .. icon .. M.glyphs.space .. M.glyphs.space .. name
else
-- ▶ [Function] Func1
str = str .. M.glyphs.space .. "[" .. kind .. "]" .. M.glyphs.space .. M.glyphs.separator .. M.glyphs.space .. name
Expand Down
38 changes: 38 additions & 0 deletions lua/calltree/ui/window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,44 @@ function M._open_window(kind, ui_state)
M._setup_window(current_layout, desired_layout, ui_state)
end

-- toggle_panel is a helper function which will toggle
-- all calltree ui windows open or closed.
--
-- on toggle, only previously opened calltree ui windows
-- will be opened once again.
--
-- this is similar to having a collap
--
-- ui_state : table - the current ui_state table
-- provided by the ui module.
--
-- keep_open : bool - if true we do not close any
-- UI windows, effectivetly making this a no-op if
-- the panel is already open. Useful for LSP handlers
-- which want to refresh the state of the UI but not
-- close the panels.
function M._toggle_panel(ui_state, keep_open)
local open = true
if not keep_open then
for _, win_name in pairs(type_to_ui_state_win) do
local win = ui_state[win_name]
if win ~= nil and vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true)
ui_state[win_name] = nil
open = false
end
end
if not open then
return
end
end

-- we didn't find any open calltree windows, toggle
-- the pannel open
M._open_window("calltree", ui_state)
M._open_window("symboltree", ui_state)
end

-- setup_window evaluates the current layout and the desired layout
-- and opens the necessary windows to obtain the desired layout.
--
Expand Down

0 comments on commit 4d71c36

Please sign in to comment.