aboutsummaryrefslogtreecommitdiff
path: root/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'init.lua')
-rw-r--r--init.lua142
1 files changed, 110 insertions, 32 deletions
diff --git a/init.lua b/init.lua
index 8953847..d01969c 100644
--- a/init.lua
+++ b/init.lua
@@ -1610,9 +1610,8 @@ local function recursive_bfs_symbols_flatten(symbols, indent)
for _, s in ipairs(symbols) do
local range = s.selectionRange or s.location.range
table.insert(ranges, range)
- str = str ..
- string.format('%s%s %s %d:%d\n', indent, lsp_symbol_kinds[s.kind], s.name,
- range.start.line + 1, range.start.character + 1)
+ str = str .. string.format(lspc.navwin_symbol_format, indent, lsp_symbol_kinds[s.kind], s.name,
+ range.start.line + 1, range.start.character + 1)
-- Remember DocumentSymbol.selectionRange or SymbolInformation.location.range
if s.children then
local cstr, cranges = recursive_bfs_symbols_flatten(s.children, indent .. ' ')
@@ -1625,60 +1624,115 @@ local function recursive_bfs_symbols_flatten(symbols, indent)
return str, ranges
end
+--- Scroll the code window to the definition of the symbol selected in the navigation window.
+local function lspc_navwin_scroll_codewin(switch_win)
+ local line = lspc.navctx.navwin.selection.line
+ -- No valid selection in the navigation window
+ if line > #lspc.navctx.ranges then
+ return
+ end
+ local sel = lsp_pos_to_vis_sel(lspc.navctx.ranges[line].start)
+
+ -- Set the selection in the code window to the selected symbol
+ lspc.navctx.codewin.selection:to(sel.line, sel.col)
+
+ if switch_win then
+ vis.win = lspc.navctx.codewin
+ end
+end
+
+--- Instantiate a new navigation context from the received symbols.
local function lspc_navwin_from_symbols(symbols, ctx)
local symbols_outline, ranges = recursive_bfs_symbols_flatten(symbols, '')
local old_layout = vis.ui.layout
- vis:command('vsplit')
- local navwin = ctx.win
- local codewin = vis.win
+ if lspc.navwin_layout:sub(1, 1) == 'v' then
+ vis.ui.layout = vis.ui.layouts.VERTICAL
+ elseif lspc.navwin_layout:sub(1, 1) == 'h' then
+ vis.ui.layout = vis.ui.layouts.HORIZONTAL
+ end
+
+ local navwin
+ local codewin
+ -- The right or bottom (old) window is our navigation window
+ if lspc.navwin_layout:sub(2) == 'r' or lspc.navwin_layout:sub(2) == 'b' then
+ vis:command('o ' .. ctx.win.file.path)
+ navwin = ctx.win
+ navwin.file = ''
+ navwin.file:delete(0, navwin.file.size)
+ codewin = vis.win
+ -- The new (old) window is our navigation window
+ else
+ vis:command('o')
+ navwin = vis.win
+ codewin = ctx.win
+ end
+
+ assert(navwin)
+ assert(codewin)
+ lspc.navctx = {
+ navwin = navwin,
+ codewin = codewin,
+ ranges = ranges,
+ old_layout = old_layout,
+ }
-- Prepare window to be our symbol navigation window
- navwin.file = 'symbols'
- local navfile = navwin.file
- navfile:delete(0, navfile.size)
- navfile:insert(0, symbols_outline)
+ navwin.file:insert(0, symbols_outline)
navwin:draw()
+
-- Jump to navigation window
vis.win = navwin
- -- Create event handlers to connect the position in the navigation window to
- -- the original window.
- local function nav_win_win_highlight_handler(win)
- -- This is not the navigation window
- if win ~= navwin then
- return true
- end
+ -- Follow the position in the navigation window
+ local nav_win_win_highlight_handler
+ if lspc.navwin_auto_scroll then
+ -- Create event handlers to connect the position in the navigation window to
+ -- the original window.
+ nav_win_win_highlight_handler = function(win)
+ -- This is not the navigation window
+ if win ~= lspc.navctx.navwin then
+ return true
+ end
- -- No valid selection in the navigation window
- local line = navwin.selection.line
- if line > #ranges then
+ -- scroll the code window without switching to it.
+ lspc_navwin_scroll_codewin(false)
return true
end
- local sel = lsp_pos_to_vis_sel(ranges[navwin.selection.line].start)
-
- -- Set the selection in the code window to the selected symbol
- codewin.selection:to(sel.line, sel.col)
- return true
+ vis.events.subscribe(vis.events.WIN_HIGHLIGHT, nav_win_win_highlight_handler)
+ else
+ navwin:map(vis.modes.NORMAL, ' j', function()
+ lspc_navwin_scroll_codewin(true)
+ end, 'jump to the selected symbol')
+ navwin:map(vis.modes.NORMAL, ' s', function()
+ lspc_navwin_scroll_codewin(false)
+ end, 'scroll to the selected symbol')
+ navwin:map(vis.modes.NORMAL, ' x', function()
+ lspc.navctx.navwin:close(true)
+ end, 'close the navgation window')
end
- vis.events.subscribe(vis.events.WIN_HIGHLIGHT, nav_win_win_highlight_handler)
-- Remove the event handlers.
local nav_win_close_handler
nav_win_close_handler = function(win)
- if win ~= navwin and win ~= codewin then
+ if win ~= lspc.navctx.navwin and win ~= lspc.navctx.codewin then
return true
-- The code windows was closed, therefore we can also close the navigation window
- elseif win == codewin then
- navwin:close(true)
+ elseif win == lspc.navctx.codewin then
+ lspc:log('Code window closed. Force close the navigation window.')
+ lspc.navctx.navwin:close(true)
-- Reset everything after closing the navigation window
else
-- reset vis' layout
- vis.ui.layout = old_layout
- vis.ui.layout = vis.ui.layouts.HORIZONTAL
+ vis.ui.layout = lspc.navctx.old_layout
-- remove the navigation window event handlers
- vis.events.unsubscribe(vis.events.UI_DRAW, nav_win_win_highlight_handler)
+ if lspc.navwin_auto_jump then
+ vis.events.unsubscribe(vis.events.UI_DRAW, nav_win_win_highlight_handler)
+ end
+
+ -- remove the navigation context
+ lspc.navctx = nil
vis.events.unsubscribe(vis.events.WIN_CLOSE, nav_win_close_handler)
end
return true
@@ -1928,9 +1982,33 @@ vis:command_register('lspc-navigate-symbols', function(argv, _, win)
if not ls:is_file_opened(win.file.path) then
lspc_open(ls, win, win.file)
end
+ if lspc.navctx then
+ lspc:err('navigation window already active')
+ return
+ end
lspc_nav_symbols(ls, win)
end, 'navigate the file by its symbols')
+vis:command_register('lspc-navigate-close', function()
+ if not lspc.navctx then
+ lspc:err('no navigation window active')
+ return
+ end
+ lspc.navctx.navwin:close(true)
+end, 'close the navigation window')
+
+vis:command_register('lspc-navigate-jump', function(_, _, win)
+ if not lspc.navctx then
+ lspc:err('no navigation window active')
+ return
+ end
+ if win ~= lspc.navctx.navwin then
+ lspc:err('not in navigation window')
+ return
+ end
+
+end, 'navigate to the selected symbol')
+
-- vis-lspc event hooks
vis.events.subscribe(vis.events.WIN_OPEN, function(win)
if lspc.autostart and win.syntax then