diff options
Diffstat (limited to 'init.lua')
| -rw-r--r-- | init.lua | 142 |
1 files changed, 110 insertions, 32 deletions
@@ -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 |
