aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Sojka <Steven.Sojka@tdameritrade.com>2020-06-26 11:11:21 -0500
committerKiyan Yazdani <yazdani.kiyan@protonmail.com>2020-06-30 08:21:01 +0200
commit64838e51c0fcb9def4be912391a1544b4d9a9d27 (patch)
treee2a66a26be775d27a74e916dabfc66664a99644b
parentfeat(refactor): highlight usages module (diff)
downloadnvim-treesitter-64838e51c0fcb9def4be912391a1544b4d9a9d27.tar
nvim-treesitter-64838e51c0fcb9def4be912391a1544b4d9a9d27.tar.gz
nvim-treesitter-64838e51c0fcb9def4be912391a1544b4d9a9d27.tar.bz2
nvim-treesitter-64838e51c0fcb9def4be912391a1544b4d9a9d27.tar.lz
nvim-treesitter-64838e51c0fcb9def4be912391a1544b4d9a9d27.tar.xz
nvim-treesitter-64838e51c0fcb9def4be912391a1544b4d9a9d27.tar.zst
nvim-treesitter-64838e51c0fcb9def4be912391a1544b4d9a9d27.zip
feat(refactor): add smart rename module
-rw-r--r--lua/nvim-treesitter/configs.lua8
-rw-r--r--lua/nvim-treesitter/query.lua8
-rw-r--r--lua/nvim-treesitter/refactor/highlight_definitions.lua20
-rw-r--r--lua/nvim-treesitter/refactor/smart_rename.lua75
-rw-r--r--lua/nvim-treesitter/ts_utils.lua28
5 files changed, 115 insertions, 24 deletions
diff --git a/lua/nvim-treesitter/configs.lua b/lua/nvim-treesitter/configs.lua
index 30c2114ce..595c2e759 100644
--- a/lua/nvim-treesitter/configs.lua
+++ b/lua/nvim-treesitter/configs.lua
@@ -31,6 +31,14 @@ local config = {
enable = false,
disable = {},
is_supported = queries.has_locals
+ },
+ smart_rename = {
+ enable = false,
+ disable = {},
+ is_supported = queries.has_locals,
+ keymaps = {
+ smart_rename = "grr"
+ }
}
}
},
diff --git a/lua/nvim-treesitter/query.lua b/lua/nvim-treesitter/query.lua
index d04e368a6..6c76fc237 100644
--- a/lua/nvim-treesitter/query.lua
+++ b/lua/nvim-treesitter/query.lua
@@ -13,7 +13,9 @@ local function read_query_files(filenames)
return table.concat(contents, '\n')
end
-local function get_query_gaurd(query)
+-- Creates a function that checks whether a certain query exists
+-- for a specific language.
+local function get_query_guard(query)
return function(lang)
return M.get_query(lang, query) ~= nil
end
@@ -27,8 +29,8 @@ M.base_language_map = {
tsx = {'typescript', 'javascript'},
}
-M.has_locals = get_query_gaurd('locals')
-M.has_highlights = get_query_gaurd('highlights')
+M.has_locals = get_query_guard('locals')
+M.has_highlights = get_query_guard('highlights')
function M.get_query(lang, query_name)
local query_files = api.nvim_get_runtime_file(string.format('queries/%s/%s.scm', lang, query_name), true)
diff --git a/lua/nvim-treesitter/refactor/highlight_definitions.lua b/lua/nvim-treesitter/refactor/highlight_definitions.lua
index ef415bb77..6279e4708 100644
--- a/lua/nvim-treesitter/refactor/highlight_definitions.lua
+++ b/lua/nvim-treesitter/refactor/highlight_definitions.lua
@@ -11,24 +11,6 @@ local M = {}
local usage_namespace = api.nvim_create_namespace('nvim-treesitter-usages')
-local function find_usages(node, scope_node)
- local usages = {}
- local node_text = ts_utils.get_node_text(node)[1]
-
- if not node_text or #node_text < 1 then return end
-
- for _, def in ipairs(locals.collect_locals(bufnr, scope_node)) do
- if def.reference
- and def.reference.node
- and ts_utils.get_node_text(def.reference.node)[1] == node_text then
-
- table.insert(usages, def.reference.node)
- end
- end
-
- return usages
-end
-
function M.highlight_usages(bufnr)
M.clear_usage_highlights(bufnr)
@@ -37,7 +19,7 @@ function M.highlight_usages(bufnr)
if not node_at_point then return end
local def_node, scope = ts_utils.find_definition(node_at_point, bufnr)
- local usages = find_usages(node_at_point, scope)
+ local usages = ts_utils.find_usages(node_at_point, scope)
for _, usage_node in ipairs(usages) do
local start_row, start_col, _, end_col = usage_node:range()
diff --git a/lua/nvim-treesitter/refactor/smart_rename.lua b/lua/nvim-treesitter/refactor/smart_rename.lua
new file mode 100644
index 000000000..5b7562eb4
--- /dev/null
+++ b/lua/nvim-treesitter/refactor/smart_rename.lua
@@ -0,0 +1,75 @@
+-- Binds a keybinding to smart rename definitions and usages.
+-- Can be used directly using the `smart_rename` function.
+
+local ts_utils = require'nvim-treesitter.ts_utils'
+local configs = require'nvim-treesitter.configs'
+local api = vim.api
+
+local M = {}
+
+function M.smart_rename(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
+ print('No node to rename!')
+ return
+ end
+
+ local node_text = ts_utils.get_node_text(node_at_point)[1]
+ local new_name = vim.fn.input('New name: ', node_text or '')
+
+ -- Empty name cancels the interaction or ESC
+ if not new_name or #new_name < 1 then return end
+
+ local definition, scope = ts_utils.find_definition(node_at_point, bufnr)
+ local nodes_to_rename = ts_utils.find_usages(node_at_point, scope)
+
+ if not vim.tbl_contains(nodes_to_rename, node_at_point) then
+ table.insert(nodes_to_rename, node_at_point)
+ end
+
+ if definition and not vim.tbl_contains(nodes_to_rename, definition) then
+ table.insert(nodes_to_rename, definition)
+ end
+
+ if #nodes_to_rename < 1 then
+ print('No nodes to rename!')
+ return
+ end
+
+ for _, node in ipairs(nodes_to_rename) do
+ local start_row, start_col, end_row, end_col = node:range()
+
+ local line = api.nvim_buf_get_lines(bufnr, start_row, start_row + 1, false)[1]
+
+ if line then
+ local new_line = line:sub(1, start_col) .. new_name .. line:sub(end_col + 1, -1)
+
+ api.nvim_buf_set_lines(bufnr, start_row, start_row + 1, false, { new_line })
+ end
+ end
+end
+
+function M.attach(bufnr)
+ local bufnr = bufnr or api.nvim_get_current_buf()
+
+ local config = configs.get_module('refactor.smart_rename')
+
+ for fn_name, mapping in pairs(config.keymaps) do
+ local cmd = string.format([[:lua require'nvim-treesitter.refactor.smart_rename'.%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.smart_rename')
+
+ 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 363d26374..90dc3d262 100644
--- a/lua/nvim-treesitter/ts_utils.lua
+++ b/lua/nvim-treesitter/ts_utils.lua
@@ -15,14 +15,16 @@ function M.get_node_text(node, bufnr)
-- We have to remember that end_col is end-exclusive
local start_row, start_col, end_row, end_col = node:range()
+
if start_row ~= end_row then
local lines = api.nvim_buf_get_lines(bufnr, start_row, end_row+1, false)
lines[1] = string.sub(lines[1], start_col+1)
lines[#lines] = string.sub(lines[#lines], 1, end_col)
return lines
else
- local line = api.nvim_buf_get_lines(bufnr, start_row, start_row+1, true)[1]
- return { string.sub(line, start_col+1, end_col) }
+ local line = api.nvim_buf_get_lines(bufnr, start_row, start_row+1, false)[1]
+ -- If line is nil then the line is empty
+ return line and { string.sub(line, start_col+1, end_col) } or {}
end
end
@@ -263,4 +265,26 @@ function M.get_local_nodes(local_def)
end
end
+-- Finds usages of a node in a particula scope
+-- @param node the node to find usages for
+-- @param scope_node the node to look within
+-- @returns a list of nodes
+function M.find_usages(node, scope_node)
+ local usages = {}
+ local node_text = M.get_node_text(node)[1]
+
+ if not node_text or #node_text < 1 then return {} end
+
+ for _, def in ipairs(locals.collect_locals(bufnr, scope_node)) do
+ if def.reference
+ and def.reference.node
+ and M.get_node_text(def.reference.node)[1] == node_text then
+
+ table.insert(usages, def.reference.node)
+ end
+ end
+
+ return usages
+end
+
return M