105 lines
3.1 KiB
Lua
105 lines
3.1 KiB
Lua
local M = {}
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
---Requests a 'workspace/willRenameFiles' on any running LSP client, that supports it
|
|
---SOURCE https://github.com/LazyVim/LazyVim/blob/ac092289f506052cfdd1879f462be05075fe3081/lua/lazyvim/util/lsp.lua#L99-L119
|
|
---@param fromName string
|
|
---@param toName string
|
|
function M.sendWillRenameToLsp(fromName, toName)
|
|
local clients = vim.lsp.get_clients { bufnr = 0 }
|
|
for _, client in ipairs(clients) do
|
|
if client.supports_method("workspace/willRenameFiles") then
|
|
local response = client.request_sync("workspace/willRenameFiles", {
|
|
files = {
|
|
{ oldUri = vim.uri_from_fname(fromName), newUri = vim.uri_from_fname(toName) },
|
|
},
|
|
}, 1000, 0)
|
|
if response and response.result ~= nil then
|
|
vim.lsp.util.apply_workspace_edit(response.result, client.offset_encoding)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---@nodiscard
|
|
---@return boolean
|
|
function M.lspSupportsRenaming()
|
|
-- INFO `client.supports_method()` seems often falsely returning true. This
|
|
-- does not affect `onRename`, but here we need to check for the server
|
|
-- capabilities to properly identify whether our LSP supports renaming or not.
|
|
local clients = vim.lsp.get_clients { bufnr = 0 }
|
|
for _, client in ipairs(clients) do
|
|
local workspaceCap = client.server_capabilities.workspace
|
|
local supports = workspaceCap
|
|
and workspaceCap.fileOperations
|
|
and workspaceCap.fileOperations.willRename
|
|
if supports then return true end
|
|
end
|
|
return false
|
|
end
|
|
|
|
---@param filePath string
|
|
local function isGitManagedFile(filePath)
|
|
local obj = vim.system({ "git", "ls-files", "--error-unmatch", filePath }, { text = true })
|
|
:wait()
|
|
if obj.code == 0 then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
---@param oldFilePath string
|
|
---@param newFilePath string
|
|
local function git_mv(oldFilePath, newFilePath)
|
|
local obj = vim.system({ "git", "mv", oldFilePath, newFilePath }, { text = true }):wait()
|
|
if obj.code == 0 then
|
|
return true, obj.stderr
|
|
else
|
|
return false, obj.stderr
|
|
end
|
|
end
|
|
|
|
---@param oldFilePath string
|
|
---@param newFilePath string
|
|
function M.moveFile(oldFilePath, newFilePath)
|
|
local u = require("genghis.support.utils")
|
|
if isGitManagedFile(oldFilePath) then
|
|
local renamed, git_mv_error = git_mv(oldFilePath, newFilePath)
|
|
if renamed then
|
|
return true
|
|
else
|
|
u.notify(
|
|
("File managed by git.\nFailed to rename using git mv %q:\n%q\nAttempting to rename using fs."):format(
|
|
oldFilePath,
|
|
git_mv_error
|
|
),
|
|
"error"
|
|
)
|
|
end
|
|
else
|
|
local renamed, _ = vim.uv.fs_rename(oldFilePath, newFilePath)
|
|
if renamed then return true end
|
|
end
|
|
|
|
---try `fs_copyfile` to support moving across partitions
|
|
local copied, copiedError = vim.uv.fs_copyfile(oldFilePath, newFilePath)
|
|
if copied then
|
|
local deleted, deletedError = vim.uv.fs_unlink(oldFilePath)
|
|
if deleted then
|
|
return true
|
|
else
|
|
u.notify(("Failed to delete %q: %q"):format(oldFilePath, deletedError), "error")
|
|
return false
|
|
end
|
|
else
|
|
local msg = ("Failed to copy %q to %q: %q"):format(oldFilePath, newFilePath, copiedError)
|
|
u.notify(msg, "error")
|
|
return false
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
return M
|