diff --git a/lua/oil/lsp_helpers.lua b/lua/oil/lsp_helpers.lua index 70b0f2cc..b7feb783 100644 --- a/lua/oil/lsp_helpers.lua +++ b/lua/oil/lsp_helpers.lua @@ -3,6 +3,8 @@ local util = require("oil.util") local M = {} +---@alias oil.PathPair {src: string, dest: string} + ---@param filepath string ---@param pattern lsp.FileOperationPattern ---@return boolean @@ -48,10 +50,10 @@ local function any_match(filepath, filters) return false end ----@return nil|{src: string, dest: string} -local function get_matching_paths(client, path_pairs) +---@return nil|oil.PathPair[] +local function get_matching_paths(client, file_op, path_pairs) local filters = - vim.tbl_get(client.server_capabilities, "workspace", "fileOperations", "willRename", "filters") + vim.tbl_get(client.server_capabilities, "workspace", "fileOperations", file_op, "filters") if not filters then return nil end @@ -71,9 +73,10 @@ local function get_matching_paths(client, path_pairs) end end ----Process LSP rename in the background ---@param actions oil.MoveAction[] -M.will_rename_files = function(actions) +---@return oil.PathPair[] +local parse_pairs = function(actions) + ---@type oil.PathPair[] local path_pairs = {} for _, action in ipairs(actions) do local _, src_path = util.parse_url(action.src_url) @@ -84,10 +87,17 @@ M.will_rename_files = function(actions) local dest_file = fs.posix_to_os_path(dest_path) table.insert(path_pairs, { src = src_file, dest = dest_file }) end + return path_pairs +end + +---Process LSP will rename in the background +---@param actions oil.MoveAction[] +M.will_rename_files = function(actions) + local path_pairs = parse_pairs(actions) local clients = vim.lsp.get_active_clients() for _, client in ipairs(clients) do - local pairs = get_matching_paths(client, path_pairs) + local pairs = get_matching_paths(client, "willRename", path_pairs) if pairs then client.request("workspace/willRenameFiles", { files = vim.tbl_map(function(pair) @@ -105,6 +115,27 @@ M.will_rename_files = function(actions) end end +---Emit LSP did rename notification +---@param actions oil.MoveAction[] +M.did_rename_files = function(actions) + local path_pairs = parse_pairs(actions) + + local clients = vim.lsp.get_active_clients() + for _, client in ipairs(clients) do + local pairs = get_matching_paths(client, "didRename", path_pairs) + if pairs then + client.notify("workspace/didRenameFiles", { + files = vim.tbl_map(function(pair) + return { + oldUri = vim.uri_from_fname(pair.src), + newUri = vim.uri_from_fname(pair.dest), + } + end, pairs), + }) + end + end +end + -- LSP types from core Neovim ---A filter to describe in which file operation requests or notifications diff --git a/lua/oil/mutator/init.lua b/lua/oil/mutator/init.lua index 60a6ba67..b8621316 100644 --- a/lua/oil/mutator/init.lua +++ b/lua/oil/mutator/init.lua @@ -364,21 +364,22 @@ M.enforce_action_order = function(actions) return ret end +---@param action oil.Action +---@return boolean +local is_file_move = function(action) + if action.type == "move" then + local src_adapter = assert(config.get_adapter_by_scheme(action.src_url)) + local dest_adapter = assert(config.get_adapter_by_scheme(action.dest_url)) + return src_adapter.name == "files" and dest_adapter.name == "files" + end + return false +end + ---@param actions oil.Action[] ---@param cb fun(err: nil|string) M.process_actions = function(actions, cb) - -- send all renames to LSP servers - local moves = {} - for _, action in ipairs(actions) do - if action.type == "move" then - local src_adapter = assert(config.get_adapter_by_scheme(action.src_url)) - local dest_adapter = assert(config.get_adapter_by_scheme(action.dest_url)) - if src_adapter.name == "files" and dest_adapter.name == "files" then - table.insert(moves, action) - end - end - end - lsp_helpers.will_rename_files(moves) + -- send all file move actions to LSP servers + lsp_helpers.will_rename_files(vim.tbl_filter(is_file_move, actions)) -- Convert some cross-adapter moves to a copy + delete for _, action in ipairs(actions) do @@ -396,11 +397,13 @@ M.process_actions = function(actions, cb) end end + local moved = {} local finished = false local progress = Progress.new() local function finish(...) if not finished then finished = true + lsp_helpers.did_rename_files(moved) progress:close() cb(...) end @@ -443,6 +446,9 @@ M.process_actions = function(actions, cb) elseif err then finish(err) else + if is_file_move(action) then + table.insert(moved, action) + end cache.perform_action(action) next_action() end