mirror of
https://github.com/ItsDrike/dotfiles.git
synced 2024-12-26 13:14:35 +00:00
Manually implement auto mass-renaming using LSP
This commit is contained in:
parent
bd3ece59b7
commit
f0fbf261ec
|
@ -1,3 +1,160 @@
|
||||||
-- Nvim's LSP lacks rename-all functionality which plugins like Coc provide
|
-- Nvim's LSP lacks rename-all functionality which plugins like Coc provide
|
||||||
-- this is a manual implementation of this feature
|
-- this is a manual implementation of this feature
|
||||||
-- TODO: Actually implement this
|
local vim = require("vim")
|
||||||
|
local api = vim.api
|
||||||
|
local cmd = vim.cmd
|
||||||
|
local lsp = vim.lsp
|
||||||
|
local fn = vim.fn
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- Unique name for the rename window, so we can access it
|
||||||
|
-- from close_rename_win function.
|
||||||
|
local unique_name = "lsp-rename-win"
|
||||||
|
|
||||||
|
-- File require string. Neede because we will be defining keymaps
|
||||||
|
-- applied only to the rename window buffer which will refer to
|
||||||
|
-- functions within this file, for that, they need to call require
|
||||||
|
local file_require_string = "lsp.rename"
|
||||||
|
|
||||||
|
-- Check whether LSP is actually active.
|
||||||
|
local function check_lsp_active()
|
||||||
|
local active_clients = lsp.get_active_clients()
|
||||||
|
if next(active_clients) == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Once in the rename window buffer, apply specific mappings to confirm or
|
||||||
|
-- cancel renaming, and define a specific autocmd to close the window if
|
||||||
|
-- we leave it.
|
||||||
|
local function apply_actions()
|
||||||
|
local prefix = string.format("lua require('%s')", file_require_string)
|
||||||
|
local close_win_s = prefix .. ".close_rename_win()"
|
||||||
|
local do_rename_s = prefix .. ".do_rename()"
|
||||||
|
-- Automatically close the window if it's escaped
|
||||||
|
api.nvim_command("autocmd QuitPre <buffer> ++nested ++once :silent " .. close_win_s)
|
||||||
|
-- Define confirm and exit buffer-specific keymaps
|
||||||
|
api.nvim_command("inoremap <buffer><nowait><silent><CR> <cmd>" .. do_rename_s .. "<CR>")
|
||||||
|
api.nvim_command("nnoremap <buffer><silent>q <cmd>" .. close_win_s .. "<CR>")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Closes the rename window (identified by the `unique_name`)
|
||||||
|
function M.close_rename_win()
|
||||||
|
if fn.mode() == "1" then
|
||||||
|
cmd[[stopinsert]]
|
||||||
|
end
|
||||||
|
|
||||||
|
local exists, winid = pcall(api.nvim_win_get_var, 0, unique_name)
|
||||||
|
if exists then
|
||||||
|
api.nvim_win_close(winid, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function dump(o)
|
||||||
|
if type(o) == 'table' then
|
||||||
|
local s = '{ '
|
||||||
|
for k,v in pairs(o) do
|
||||||
|
if type(k) ~= 'number' then k = '"'..k..'"' end
|
||||||
|
s = s .. '['..k..'] = ' .. dump(v) .. ','
|
||||||
|
end
|
||||||
|
return s .. '} '
|
||||||
|
else
|
||||||
|
return tostring(o)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Trigger renaming
|
||||||
|
function M.do_rename()
|
||||||
|
local new_name = vim.trim(fn.getline('.'))
|
||||||
|
M.close_rename_win()
|
||||||
|
local current_name = fn.expand("<cword>")
|
||||||
|
|
||||||
|
if not new_name or #new_name == 0 or new_name == current_name then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local params = lsp.util.make_position_params()
|
||||||
|
params.newName = new_name
|
||||||
|
lsp.buf_request(0, "textDocument/rename", params, function(_, result, _, _)
|
||||||
|
if not result then
|
||||||
|
-- If the server returns an empty result, don't do anything
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The result contains all places we need to update the name
|
||||||
|
-- of the identifier, so we apply those edits.
|
||||||
|
lsp.util.apply_workspace_edit(result)
|
||||||
|
|
||||||
|
if not result.changes then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local total_files = 0
|
||||||
|
local total_renames = 0
|
||||||
|
for _, renames in pairs(result.changes) do
|
||||||
|
total_files = total_files + 1
|
||||||
|
for _ in pairs(renames) do
|
||||||
|
total_renames = total_renames + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Once the changes were applied, these files won't be saved
|
||||||
|
-- automatically, let's remind ourselves to save those...
|
||||||
|
print(string.format(
|
||||||
|
"Changed %s file%s (%s rename%s). To save %s, run ':w%s'",
|
||||||
|
total_files,
|
||||||
|
total_files > 1 and "s" or "",
|
||||||
|
total_renames,
|
||||||
|
total_renames > 1 and "s" or "",
|
||||||
|
total_files > 1 and "them" or "it",
|
||||||
|
total_files > 1 and "a" or ""
|
||||||
|
))
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the rename window
|
||||||
|
function M.rename()
|
||||||
|
if not check_lsp_active() then
|
||||||
|
print("No LSP client available, can't rename!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- In case there already is another rename window opened, close it
|
||||||
|
M.close_rename_win()
|
||||||
|
|
||||||
|
|
||||||
|
-- Read the current name here, before we're in the rename window
|
||||||
|
local current_name = fn.expand('<cword>')
|
||||||
|
|
||||||
|
-- Create a window within our buffer with our `unique_name` so that it
|
||||||
|
-- can be found from the close fucntion and automatically enter it
|
||||||
|
local win_opts = {
|
||||||
|
relative = 'cursor',
|
||||||
|
row = 0,
|
||||||
|
col = 0,
|
||||||
|
width = 30,
|
||||||
|
height = 1,
|
||||||
|
style = 'minimal',
|
||||||
|
border = 'single'
|
||||||
|
}
|
||||||
|
local buf = api.nvim_create_buf(false, true)
|
||||||
|
local win = api.nvim_open_win(buf, true, win_opts)
|
||||||
|
api.nvim_win_set_var(0, unique_name, win)
|
||||||
|
|
||||||
|
-- Automatically enter insert mode
|
||||||
|
cmd[[startinsert]]
|
||||||
|
|
||||||
|
-- Pre-write the current name of given object into the rename window
|
||||||
|
-- and set cursor behind it
|
||||||
|
api.nvim_buf_set_lines(buf, 0, -1, false, {current_name})
|
||||||
|
api.nvim_win_set_cursor(win, {1, #current_name})
|
||||||
|
|
||||||
|
-- Set actions for auto-closing the window and buffer-specific mappings
|
||||||
|
-- to confirm or close rename
|
||||||
|
apply_actions()
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
|
|
Loading…
Reference in a new issue