-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: LSP renaming did not work in some cases
There were some edge cases that caused issues when renaming files with LSP servers. Hopefully fix all of them by using the implementation that's also shared by neotree and nvim-tree: https://github.com/antosha417/nvim-lsp-file-operations Thanks @chaozwn for suggesting the fix! Closes <#80> This work was started in #190 where the idea is to add a dependency on nvim-lsp-file-operations, but that PR has become slightly stalled for now. This PR is a temporary fix to this stalling by simply embedding the new package inside yazi.nvim for now. When the issues in the PR have been resolved, the embedding can be removed.
- Loading branch information
1 parent
a197e9a
commit ac990c1
Showing
19 changed files
with
515 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,14 @@ | ||
local M = {} | ||
|
||
---@param path string | ||
local function notify_file_was_deleted(path) | ||
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_willDeleteFiles | ||
local method = 'workspace/willDeleteFiles' | ||
|
||
local clients = vim.lsp.get_clients({ | ||
method = method, | ||
bufnr = vim.api.nvim_get_current_buf(), | ||
}) | ||
|
||
for _, client in ipairs(clients) do | ||
local resp = client.request_sync(method, { | ||
files = { | ||
{ | ||
uri = vim.uri_from_fname(path), | ||
}, | ||
}, | ||
}, 1000, 0) | ||
|
||
if resp and resp.result ~= nil then | ||
vim.lsp.util.apply_workspace_edit(resp.result, client.offset_encoding) | ||
end | ||
end | ||
end | ||
|
||
---@param path string | ||
local function notify_delete_complete(path) | ||
-- https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didDeleteFiles | ||
local method = 'workspace/didDeleteFiles' | ||
local will_delete = require('yazi.lsp.embedded.lsp-file-operations.will-delete') | ||
local did_delete = require('yazi.lsp.embedded.lsp-file-operations.did-delete') | ||
|
||
local clients = vim.lsp.get_clients({ | ||
method = method, | ||
bufnr = vim.api.nvim_get_current_buf(), | ||
}) | ||
|
||
for _, client in ipairs(clients) do | ||
-- NOTE: this returns nothing, so no need to do anything with the response | ||
client.request_sync(method, { | ||
files = { | ||
{ | ||
uri = vim.uri_from_fname(path), | ||
}, | ||
}, | ||
}, 1000, 0) | ||
end | ||
end | ||
local M = {} | ||
|
||
-- Send a notification to LSP servers, letting them know that yazi just deleted some files | ||
-- Send a notification to LSP servers, letting them know that yazi just deleted | ||
-- some files. Execute any changes that the LSP says are needed in other files. | ||
---@param path string | ||
function M.file_deleted(path) | ||
notify_file_was_deleted(path) | ||
notify_delete_complete(path) | ||
will_delete.callback({ fname = path }) | ||
did_delete.callback({ fname = path }) | ||
end | ||
|
||
return M |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
local M = {} | ||
|
||
local log = require('yazi.lsp.embedded.lsp-file-operations.log') | ||
|
||
local default_config = { | ||
debug = false, | ||
timeout_ms = 10000, | ||
operations = { | ||
willRenameFiles = true, | ||
didRenameFiles = true, | ||
willCreateFiles = true, | ||
didCreateFiles = true, | ||
willDeleteFiles = true, | ||
didDeleteFiles = true, | ||
}, | ||
} | ||
|
||
local modules = { | ||
willRenameFiles = 'yazi.lsp.embedded.lsp-file-operations.will-rename', | ||
didRenameFiles = 'yazi.lsp.embedded.lsp-file-operations.did-rename', | ||
willCreateFiles = 'yazi.lsp.embedded.lsp-file-operations.will-create', | ||
didCreateFiles = 'yazi.lsp.embedded.lsp-file-operations.did-create', | ||
willDeleteFiles = 'yazi.lsp.embedded.lsp-file-operations.will-delete', | ||
didDeleteFiles = 'yazi.lsp.embedded.lsp-file-operations.did-delete', | ||
} | ||
|
||
local capabilities = { | ||
willRenameFiles = 'willRename', | ||
didRenameFiles = 'didRename', | ||
willCreateFiles = 'willCreate', | ||
didCreateFiles = 'didCreate', | ||
willDeleteFiles = 'willDelete', | ||
didDeleteFiles = 'didDelete', | ||
} | ||
|
||
---@alias HandlerMap table<string, string[]> a mapping from modules to events that trigger it | ||
|
||
--- helper function to subscribe events to a given module callback | ||
---@param op_events HandlerMap the table that maps modules to event strings | ||
---@param subscribe fun(module: string, event: string) the function for how to subscribe a module to an event | ||
local function setup_events(op_events, subscribe) | ||
for operation, enabled in pairs(M.config.operations) do | ||
if enabled then | ||
local module, events = modules[operation], op_events[operation] | ||
if module and events then | ||
vim.tbl_map(function(event) | ||
subscribe(module, event) | ||
end, events) | ||
end | ||
end | ||
end | ||
end | ||
|
||
M.setup = function(opts) | ||
M.config = vim.tbl_deep_extend('force', default_config, opts or {}) | ||
if M.config.debug then | ||
log.level = 'debug' | ||
end | ||
|
||
-- nvim-tree integration | ||
local ok_nvim_tree, nvim_tree_api = pcall(require, 'nvim-tree.api') | ||
if ok_nvim_tree then | ||
log.debug('Setting up nvim-tree integration') | ||
|
||
---@type HandlerMap | ||
local nvim_tree_event = nvim_tree_api.events.Event | ||
local events = { | ||
willRenameFiles = { nvim_tree_event.WillRenameNode }, | ||
didRenameFiles = { nvim_tree_event.NodeRenamed }, | ||
willCreateFiles = { nvim_tree_event.WillCreateFile }, | ||
didCreateFiles = { | ||
nvim_tree_event.FileCreated, | ||
nvim_tree_event.FolderCreated, | ||
}, | ||
willDeleteFiles = { nvim_tree_event.WillRemoveFile }, | ||
didDeleteFiles = { | ||
nvim_tree_event.FileRemoved, | ||
nvim_tree_event.FolderRemoved, | ||
}, | ||
} | ||
setup_events(events, function(module, event) | ||
nvim_tree_api.events.subscribe(event, function(args) | ||
require(module).callback(args) | ||
end) | ||
end) | ||
end | ||
|
||
-- neo-tree integration | ||
local ok_neo_tree, neo_tree_events = pcall(require, 'neo-tree.events') | ||
if ok_neo_tree then | ||
log.debug('Setting up neo-tree integration') | ||
|
||
---@type HandlerMap | ||
local events = { | ||
willRenameFiles = { | ||
neo_tree_events.BEFORE_FILE_RENAME, | ||
neo_tree_events.BEFORE_FILE_MOVE, | ||
}, | ||
didRenameFiles = { | ||
neo_tree_events.FILE_RENAMED, | ||
neo_tree_events.FILE_MOVED, | ||
}, | ||
didCreateFiles = { neo_tree_events.FILE_ADDED }, | ||
didDeleteFiles = { neo_tree_events.FILE_DELETED }, | ||
-- currently no events in neo-tree for before creating or deleting, so unable to support those file operations | ||
-- Issue to add the missing events: https://github.com/nvim-neo-tree/neo-tree.nvim/issues/1276 | ||
} | ||
setup_events(events, function(module, event) | ||
-- create an event name based on the module and the event | ||
local id = ('%s.%s'):format(module, event) | ||
-- just in case setup is called twice, unsubscribe from event | ||
neo_tree_events.unsubscribe({ id = id }) | ||
neo_tree_events.subscribe({ | ||
id = id, | ||
event = event, | ||
handler = function(args) | ||
-- translate neo-tree arguemnts to the same format as nvim-tree | ||
if type(args) == 'table' then | ||
args = { old_name = args.source, new_name = args.destination } | ||
else | ||
args = { fname = args } | ||
end | ||
-- load module and call the callback | ||
require(module).callback(args) | ||
end, | ||
}) | ||
end) | ||
log.debug('Neo-tree integration setup complete') | ||
end | ||
end | ||
|
||
--- The extra client capabilities provided by this plugin. To be merged with | ||
--- vim.lsp.protocol.make_client_capabilities() and sent to the LSP server. | ||
M.default_capabilities = function() | ||
local config = M.config or default_config | ||
local result = { | ||
workspace = { | ||
fileOperations = {}, | ||
}, | ||
} | ||
for operation, capability in pairs(capabilities) do | ||
result.workspace.fileOperations[capability] = config.operations[operation] | ||
end | ||
return result | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
local utils = require('yazi.lsp.embedded.lsp-file-operations.utils') | ||
local log = require('yazi.lsp.embedded.lsp-file-operations.log') | ||
|
||
local M = {} | ||
|
||
M.callback = function(data) | ||
for _, client in pairs(vim.lsp.get_active_clients()) do | ||
local did_create = utils.get_nested_path( | ||
client, | ||
{ 'server_capabilities', 'workspace', 'fileOperations', 'didCreate' } | ||
) | ||
if did_create ~= nil then | ||
local filters = did_create.filters or {} | ||
if utils.matches_filters(filters, data.fname) then | ||
local params = { | ||
files = { | ||
{ uri = vim.uri_from_fname(data.fname) }, | ||
}, | ||
} | ||
client.notify('workspace/didCreateFiles', params) | ||
log.debug('Sending workspace/didCreateFiles notification', params) | ||
end | ||
end | ||
end | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
local utils = require('yazi.lsp.embedded.lsp-file-operations.utils') | ||
local log = require('yazi.lsp.embedded.lsp-file-operations.log') | ||
|
||
local M = {} | ||
|
||
M.callback = function(data) | ||
for _, client in pairs(vim.lsp.get_active_clients()) do | ||
local did_delete = utils.get_nested_path( | ||
client, | ||
{ 'server_capabilities', 'workspace', 'fileOperations', 'didDelete' } | ||
) | ||
if did_delete ~= nil then | ||
local filters = did_delete.filters or {} | ||
if utils.matches_filters(filters, data.fname) then | ||
local params = { | ||
files = { | ||
{ uri = vim.uri_from_fname(data.fname) }, | ||
}, | ||
} | ||
client.notify('workspace/didDeleteFiles', params) | ||
log.debug('Sending workspace/didDeleteFiles notification', params) | ||
end | ||
end | ||
end | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
local utils = require('yazi.lsp.embedded.lsp-file-operations.utils') | ||
local log = require('yazi.lsp.embedded.lsp-file-operations.log') | ||
|
||
local M = {} | ||
|
||
M.callback = function(data) | ||
for _, client in pairs(vim.lsp.get_active_clients()) do | ||
local did_rename = utils.get_nested_path( | ||
client, | ||
{ 'server_capabilities', 'workspace', 'fileOperations', 'didRename' } | ||
) | ||
if did_rename ~= nil then | ||
local filters = did_rename.filters or {} | ||
if utils.matches_filters(filters, data.old_name) then | ||
local params = { | ||
files = { | ||
{ | ||
oldUri = vim.uri_from_fname(data.old_name), | ||
newUri = vim.uri_from_fname(data.new_name), | ||
}, | ||
}, | ||
} | ||
client.notify('workspace/didRenameFiles', params) | ||
log.debug('Sending workspace/didRenameFiles notification', params) | ||
end | ||
end | ||
end | ||
end | ||
|
||
return M |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
local log = require('plenary.log') | ||
|
||
return log.new({ | ||
plugin = 'nvim-yazi.lsp.embedded.lsp-file-operations', | ||
}, false) |
Oops, something went wrong.