From dd1aca9ad2f19c6116f4fc8c8a7651b2b7742cbf Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Wed, 30 Jul 2025 19:36:09 +0200 Subject: improve navigation windows Remove broken autoscrolling. Add commands to control a code/navigation window pair. Support multiple navigation window pairs. Improve default navigation window keybindings. --- init.lua | 131 +++++++++++++++++++++++++++++---------------------------------- 1 file changed, 60 insertions(+), 71 deletions(-) (limited to 'init.lua') diff --git a/init.lua b/init.lua index d01969c..0819cb6 100644 --- a/init.lua +++ b/init.lua @@ -1625,19 +1625,19 @@ local function recursive_bfs_symbols_flatten(symbols, indent) 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 +local function navwin_scroll_codewin(self, switch_win) + local line = self.navwin.selection.line -- No valid selection in the navigation window - if line > #lspc.navctx.ranges then + if line > #self.ranges then return end - local sel = lsp_pos_to_vis_sel(lspc.navctx.ranges[line].start) + local sel = lsp_pos_to_vis_sel(self.ranges[line].start) -- Set the selection in the code window to the selected symbol - lspc.navctx.codewin.selection:to(sel.line, sel.col) + self.codewin.selection:to(sel.line, sel.col) if switch_win then - vis.win = lspc.navctx.codewin + vis.win = self.codewin end end @@ -1670,71 +1670,53 @@ local function lspc_navwin_from_symbols(symbols, ctx) assert(navwin) assert(codewin) - lspc.navctx = { + ctx = { navwin = navwin, codewin = codewin, ranges = ranges, old_layout = old_layout, } + lspc.navwins[navwin] = ctx + lspc.navwins[codewin] = ctx + -- Prepare window to be our symbol navigation window navwin.file:insert(0, symbols_outline) navwin:draw() + navwin:map(vis.modes.NORMAL, '', function() + navwin_scroll_codewin(ctx, true) + end, 'jump to the selected symbol') + navwin:map(vis.modes.NORMAL, 'p', function() + navwin_scroll_codewin(ctx, false) + end, 'scroll to the selected symbol') + navwin:map(vis.modes.NORMAL, 'q', function() + navwin:close(true) + end, 'close this window') + -- Jump to navigation window vis.win = navwin - -- 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 - - -- scroll the code window without switching to it. - lspc_navwin_scroll_codewin(false) - return true - end - 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 - -- Remove the event handlers. local nav_win_close_handler nav_win_close_handler = function(win) - if win ~= lspc.navctx.navwin and win ~= lspc.navctx.codewin then + -- Not our windows + if win ~= navwin and win ~= codewin then return true -- The code windows was closed, therefore we can also close the navigation window - elseif win == lspc.navctx.codewin then + elseif win == 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 = lspc.navctx.old_layout - - -- remove the navigation window event handlers - 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) + navwin:close(true) + return end + -- reset vis' layout + vis.ui.layout = lspc.navwins[codewin].old_layout + + -- remove the navigation window + lspc.navwins[navwin] = nil + lspc.navwins[codewin] = nil + lspc:log('unsubscribe navwin event handler') + vis.events.unsubscribe(vis.events.WIN_CLOSE, nav_win_close_handler) return true end @@ -1982,32 +1964,39 @@ 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 + if lspc.navwins[win] then + lspc.navwins[win].navwin:close(true) + else + lspc_nav_symbols(ls, win) end - lspc_nav_symbols(ls, win) -end, 'navigate the file by its symbols') +end, 'toggle the symbol navigation') -vis:command_register('lspc-navigate-close', function() - if not lspc.navctx then - lspc:err('no navigation window active') - return +vis:command_register('lspc-navwin-jump', function(_, _, win) + local navwin = lspc.navwins[win] + if not navwin then + lspc:err('no associated navigation window') + else + navwin_scroll_codewin(navwin, true) end - lspc.navctx.navwin:close(true) -end, 'close the navigation window') +end, 'jump to the selected symbol') -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 +vis:command_register('lspc-navwin-scroll', function(_, _, win) + local navwin = lspc.navwins[win] + if not navwin then + lspc:err('no associated navigation window') + else + navwin_scroll_codewin(navwin, false) end +end, 'scroll the code window to the selected symbol') -end, 'navigate to the selected symbol') +vis:command_register('lspc-navwin-close', function(_, _, win) + local navwin = lspc.navwins[win] + if not navwin then + lspc:err('no associated navigation window') + else + navwin.navwin:close(true) + end +end, 'close the navigation window') -- vis-lspc event hooks vis.events.subscribe(vis.events.WIN_OPEN, function(win) -- cgit v1.2.3