diff --git a/README.md b/README.md index d3b215c..2d967d1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ variable is: - Out of box experience. 10 lines of minimum vimrc can turn your neovim into a full-featured LSP & Treesitter powered IDE -- Unorthodox UI with floating windows, navigator provides a visual way to manage and navigate through symbols, diagnostic errors, reference etc. It covers +- UI with floating windows, navigator provides a visual way to manage and navigate through symbols, diagnostic errors, reference etc. It covers all features(handler) provided by LSP from commonly used search reference, to less commonly used search for interface implementation. @@ -69,6 +69,8 @@ variable is: - LSP multiple symbol highlight/marker and hop between document references +- Preview definination/references + - Better navigation for diagnostic errors, Navigate through all files/buffers that contain errors/warnings - Grouping references/implementation/incoming/outgoing based on file names. @@ -333,9 +335,10 @@ require'navigator'.setup({ | n | \ | signature help | | n | gW | workspace symbol | | n | gD | declaration | +| n | gd | definition | | n | g0 | document symbol | | n | \ | go to definition (if multiple show listview) | -| n | gp | definition | +| n | gp | definition preview (Go to Preview) | | n | \ | definition | | n | g\ | implementation | | n | gT | treesitter document symbol | @@ -485,6 +488,12 @@ colorscheme: [aurora](https://github.com/ray-x/aurora) Pls check the first part of README +### Definition preview + +Using treesitter and LSP to view the symbol definition + +![image](https://user-images.githubusercontent.com/1681295/139771978-bbc970a5-be9f-42cf-8942-3477485bd89c.png) + ### GUI and multigrid support You can load a different font size for floating win diff --git a/lua/navigator/definition.lua b/lua/navigator/definition.lua index 4301a16..1e175ae 100644 --- a/lua/navigator/definition.lua +++ b/lua/navigator/definition.lua @@ -62,7 +62,7 @@ local function def_preview(timeout_ms) return nil end - local range = data[1].targetRange or data[1].range + local range = data[1].targetRange or data[1].range or data[1].targetSelectionRange local row = range.start.line -- in case there are comments @@ -76,8 +76,22 @@ local function def_preview(timeout_ms) if not vim.api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end + + local ok, parsers = pcall(require, "nvim-treesitter.parsers") + local lines_num = 12 + if ok then + local ts = require 'navigator.treesitter' + local root = parsers.get_parser(bufnr) + log(range) + local def_node = ts.get_node_at_pos({range['start'].line, range['start'].character}, root) + + local sr, _, er, _ = ts.get_node_scope(def_node) + log(sr, er) + lines_num = math.max(lines_num, er - sr + 1) + end + -- TODO: 12 should be an option - local definition = vim.api.nvim_buf_get_lines(bufnr, row, range["end"].line + 12, false) + local definition = vim.api.nvim_buf_get_lines(bufnr, row, range["end"].line + lines_num, false) local def_line = vim.api.nvim_buf_get_lines(bufnr, range.start.line, range.start.line + 1, false) for _ = 1, math.min(3, #definition), 1 do if #definition[1] < 2 then @@ -89,7 +103,7 @@ local function def_preview(timeout_ms) end local width = 40 for key, value in pairs(definition) do - log(key, value, width) + -- log(key, value, width) width = math.max(width, #value) width = math.min(90, width) @@ -129,14 +143,12 @@ local def = function() local ref_params = vim.lsp.util.make_position_params() vim.lsp.for_each_buffer_client(bufnr, function(client, client_id, _bufnr) if client.resolved_capabilities.goto_definition then - client.request("textDocument/definition", ref_params, definition_hdlr , _bufnr) + client.request("textDocument/definition", ref_params, definition_hdlr, _bufnr) end end) end - - vim.lsp.handlers["textDocument/definition"] = definition_hdlr return { definition = def, diff --git a/lua/navigator/treesitter.lua b/lua/navigator/treesitter.lua index fe27bf5..4d2914b 100644 --- a/lua/navigator/treesitter.lua +++ b/lua/navigator/treesitter.lua @@ -315,6 +315,7 @@ local function get_all_nodes(bufnr, filter, summary) ["arrow_function"] = true, ["type"] = true, ["class"] = true, + ["struct"] = true, ["method"] = true } @@ -500,6 +501,8 @@ function M.buf_ts() }) end +M.get_all_nodes = get_all_nodes + function M.bufs_ts() if ts_locals == nil then error("treesitter not loaded") @@ -605,4 +608,50 @@ function M.clear_usage_highlights(bufnr) api.nvim_buf_clear_namespace(bufnr, usage_namespace, 0, -1) end +function M.get_node_at_pos(pos, parser) + -- local cursor = api.nvim_win_get_cursor(winnr or 0) + local cursor_range = {pos[1], pos[2]} + + log(cursor_range) + local root = ts_utils.get_root_for_position(unpack(cursor_range), parser) + + if not root then + return + end + + local node = root:named_descendant_for_range(cursor_range[1], cursor_range[2], cursor_range[1], cursor_range[2]) + log(node, node:range()) + return node +end + +function M.get_node_scope(node) + -- local + local n = node + if n == nil then + return 0, 0, 0, 0 + end + local sr, sc, er, ec = n:range() + + log(n:range()) + for _ = 1, 6 do + if n == nil then + return 0, 0, 0, 0 + end + + local nsr, nsc, ner, nec = n:range() + + if nsr < sr then + log(sr, er) + break + end + sr, sc, er, ec = nsr, nsc, ner, nec + if n:parent() then + n = n:parent() + end + end + + return sr, sc, er, ec + +end + return M