diff options
| author | Steven Sojka <Steven.Sojka@tdameritrade.com> | 2020-06-26 13:57:23 -0500 |
|---|---|---|
| committer | Kiyan Yazdani <yazdani.kiyan@protonmail.com> | 2020-06-30 08:21:01 +0200 |
| commit | 6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a (patch) | |
| tree | 8b49bdf8651b54b0ff398af254c026cb303347fc | |
| parent | feat(refactor): add smart rename module (diff) | |
| download | nvim-treesitter-6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a.tar nvim-treesitter-6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a.tar.gz nvim-treesitter-6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a.tar.bz2 nvim-treesitter-6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a.tar.lz nvim-treesitter-6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a.tar.xz nvim-treesitter-6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a.tar.zst nvim-treesitter-6f8e4c97a4f99b1a04cca5c41c333ffb5337d84a.zip | |
feat(refactor): add definition navigation module
| -rw-r--r-- | lua/nvim-treesitter/configs.lua | 9 | ||||
| -rw-r--r-- | lua/nvim-treesitter/refactor/navigation.lua | 87 | ||||
| -rw-r--r-- | lua/nvim-treesitter/ts_utils.lua | 34 |
3 files changed, 123 insertions, 7 deletions
diff --git a/lua/nvim-treesitter/configs.lua b/lua/nvim-treesitter/configs.lua index 595c2e759..1d3e1c75e 100644 --- a/lua/nvim-treesitter/configs.lua +++ b/lua/nvim-treesitter/configs.lua @@ -39,6 +39,15 @@ local config = { keymaps = { smart_rename = "grr" } + }, + navigation = { + enable = false, + disable = {}, + is_supported = queries.has_locals, + keymaps = { + goto_definition = "gnd", + list_definitions = "gnD" + } } } }, diff --git a/lua/nvim-treesitter/refactor/navigation.lua b/lua/nvim-treesitter/refactor/navigation.lua new file mode 100644 index 000000000..9c439179c --- /dev/null +++ b/lua/nvim-treesitter/refactor/navigation.lua @@ -0,0 +1,87 @@ +-- Definition based navigation module + +local ts_utils = require'nvim-treesitter.ts_utils' +local locals = require'nvim-treesitter.locals' +local configs = require'nvim-treesitter.configs' +local api = vim.api + +local M = {} + +local function node_to_qf(node, kind) + local lnum, col, _ = def.node:start() + + return { + bufnr = bufnr, + lnum = lnum + 1, + col = col + 1, + text = ts_utils.get_node_text(def.node)[1] or '', + kind = kind + } +end + +function M.goto_definition(bufnr) + local bufnr = bufnr or api.nvim_get_current_buf() + local node_at_point = ts_utils.get_node_at_cursor() + + if not node_at_point then return end + + local definition, _ = ts_utils.find_definition(node_at_point, bufnr) + + if not definition then + print('No definition found') + return + end + + local start_row, start_col, _ = definition:start() + + api.nvim_win_set_cursor(0, { start_row + 1, start_col }) +end + +function M.list_definitions(bufnr) + local bufnr = bufnr or api.nvim_get_current_buf() + local definitions = locals.get_definitions(bufnr) + + if #definitions < 1 then return end + + local qf_list = {} + + for _, def in ipairs(definitions) do + ts_utils.recurse_local_nodes(def, function(_, node, _, match) + local lnum, col, _ = node:start() + + table.insert(qf_list, { + bufnr = bufnr, + lnum = lnum + 1, + col = col + 1, + text = ts_utils.get_node_text(node)[1] or "", + kind = match and match:sub(1, 1) or "" + }) + end) + end + + vim.fn.setqflist(qf_list, 'r') + api.nvim_command('copen') +end + +function M.attach(bufnr) + local bufnr = bufnr or api.nvim_get_current_buf() + + local config = configs.get_module('refactor.navigation') + + for fn_name, mapping in pairs(config.keymaps) do + local cmd = string.format([[:lua require'nvim-treesitter.refactor.navigation'.%s(%d)<CR>]], fn_name, bufnr) + + api.nvim_buf_set_keymap(bufnr, 'n', mapping, cmd, { silent = true }) + end +end + +function M.detach(bufnr) + local buf = bufnr or api.nvim_get_current_buf() + local config = configs.get_module('refactor.navigation') + + for fn_name, mapping in pairs(config.keymaps) do + api.nvim_buf_del_keymap(bufnr, 'n', mapping) + end +end + +return M diff --git a/lua/nvim-treesitter/ts_utils.lua b/lua/nvim-treesitter/ts_utils.lua index 90dc3d262..9720be7bf 100644 --- a/lua/nvim-treesitter/ts_utils.lua +++ b/lua/nvim-treesitter/ts_utils.lua @@ -252,16 +252,36 @@ end -- @param local_def the local list result -- @returns a list of nodes function M.get_local_nodes(local_def) + local result = {} + + M.recurse_local_nodes(local_def, function(_, node) + table.insert(result, node) + end) + + return result +end + +-- Recurse locals results until a node is found. +-- The accumulator function is given +-- * The table of the node +-- * The node +-- * The full definition match `@definition.var.something` -> 'var.something' +-- * The last definition match `@definition.var.something` -> 'something' +-- @param The locals result +-- @param The accumulator function +-- @param The full match path to append to +-- @param The last match +function M.recurse_local_nodes(local_def, accumulator, full_match, last_match) if local_def.node then - return { local_def.node } + accumulator(local_def, local_def.node, full_match, last_match) else - local result = {} - - for _, def in pairs(local_def) do - vim.list_extend(result, M.get_local_nodes(def)) + for match_key, def in pairs(local_def) do + M.recurse_local_nodes( + def, + accumulator, + full_match and (full_match..'.'..match_key) or match_key, + match_key) end - - return result end end |
