From 9e8d774db0835aed3fe744cb001117ec54281d0a Mon Sep 17 00:00:00 2001 From: Mika Vilpas Date: Fri, 12 Jul 2024 19:44:45 +0300 Subject: [PATCH] fix: not handling bulk renaming events correctly This commit fixes a bug where yazi.nvim would not handle bulk renaming events like rename,move,delete events are handled. This bug had the following impact: - open buffers would not be renamed after a bulk rename operation - LSP servers would not be notified of the rename operation --- .../opening-files.cy.ts | 74 ++++++++++++++----- lua/yazi/event_handling.lua | 14 ++++ lua/yazi/process/ya_process.lua | 2 +- lua/yazi/types.lua | 6 +- lua/yazi/utils.lua | 12 ++- 5 files changed, 85 insertions(+), 23 deletions(-) diff --git a/integration-tests/cypress/e2e/using-ya-to-read-events/opening-files.cy.ts b/integration-tests/cypress/e2e/using-ya-to-read-events/opening-files.cy.ts index 2a10fbbd..d0da4042 100644 --- a/integration-tests/cypress/e2e/using-ya-to-read-events/opening-files.cy.ts +++ b/integration-tests/cypress/e2e/using-ya-to-read-events/opening-files.cy.ts @@ -65,30 +65,64 @@ describe("opening files", () => { }) }) - it("can bulk rename files", () => { - startNeovimWithYa().then((_dir) => { - // in yazi, bulk renaming is done by - // - selecting files and pressing "r". - // - It opens the editor with the names of the selected files. - // - Next, the editor must make changes to the file names and save the - // file. - // - Finally, yazi should rename the files to match the new names. - cy.typeIntoTerminal("{upArrow}") - cy.typeIntoTerminal("{control+a}r") + describe("bulk renaming", () => { + it("can bulk rename files", () => { + startNeovimWithYa().then((_dir) => { + // in yazi, bulk renaming is done by + // - selecting files and pressing "r". + // - It opens the editor with the names of the selected files. + // - Next, the editor must make changes to the file names and save the + // file. + // - Finally, yazi should rename the files to match the new names. + cy.typeIntoTerminal("{upArrow}") + cy.typeIntoTerminal("{control+a}r") + + // yazi should now have opened an embedded Neovim. The file name should say + // "bulk" somewhere to indicate this + cy.contains(new RegExp("yazi/bulk-\\d+")) + + // edit the name of the first file + cy.typeIntoTerminal("xxx") + cy.typeIntoTerminal(":xa{enter}") + + // yazi must now ask for confirmation + cy.contains("Continue to rename? (y/N):") + + // answer yes + cy.typeIntoTerminal("y{enter}") + }) + }) + + it("can rename a buffer that's open in Neovim", () => { + startNeovimWithYa().then((_dir) => { + cy.typeIntoTerminal("{upArrow}") + // select only the current file to make the test easier + cy.typeIntoTerminal("v") + cy.typeIntoTerminal("r") // start renaming + + // yazi should now have opened an embedded Neovim. The file name should say + // "bulk" somewhere to indicate this + cy.contains(new RegExp("yazi/bulk-\\d+")) + + // edit the name of the file + cy.typeIntoTerminal("cc") + cy.typeIntoTerminal("renamed-file.txt{esc}") + cy.typeIntoTerminal(":xa{enter}") + + // yazi must now ask for confirmation + cy.contains("Continue to rename? (y/N):") - // yazi should now have opened an embedded Neovim. The file name should say - // "bulk" somewhere to indicate this - cy.contains(new RegExp("yazi/bulk-\\d+")) + // answer yes + cy.typeIntoTerminal("y{enter}") - // edit the name of the first file - cy.typeIntoTerminal("xxx") - cy.typeIntoTerminal(":xa{enter}") + // close yazi + cy.typeIntoTerminal("q") - // yazi must now ask for confirmation - cy.contains("Continue to rename? (y/N):") + // the file should now be renamed - ask neovim to confirm this + cy.typeIntoTerminal(":buffers{enter}") - // answer yes - cy.typeIntoTerminal("y{enter}") + cy.contains("renamed-file.txt") + }) }) }) diff --git a/lua/yazi/event_handling.lua b/lua/yazi/event_handling.lua index 52204d2c..8be934fa 100644 --- a/lua/yazi/event_handling.lua +++ b/lua/yazi/event_handling.lua @@ -94,6 +94,20 @@ function M.process_events_emitted_from_yazi(events) utils.rename_or_close_buffer(instruction) end end + elseif event.type == 'bulk' then + ---@cast event YaziBulkEvent + for from, to in pairs(event.changes) do + lsp_rename.file_renamed(from, to) + + local rename_instructions = + M.get_buffers_that_need_renaming_after_yazi_exited({ + from = from, + to = to, + }) + for _, instruction in ipairs(rename_instructions) do + utils.rename_or_close_buffer(instruction) + end + end elseif event.type == 'delete' then local remaining_events = vim.list_slice(events, i) ---@cast event YaziDeleteEvent diff --git a/lua/yazi/process/ya_process.lua b/lua/yazi/process/ya_process.lua index 1ee2bcf4..df4b3ddc 100644 --- a/lua/yazi/process/ya_process.lua +++ b/lua/yazi/process/ya_process.lua @@ -49,7 +49,7 @@ function YaProcess:wait(timeout) end function YaProcess:start() - local ya_command = { 'ya', 'sub', 'rename,delete,trash,move,cd,hover' } + local ya_command = { 'ya', 'sub', 'rename,delete,trash,move,cd,hover,bulk' } Log:debug( string.format( 'Opening ya with the command: (%s), attempt %s', diff --git a/lua/yazi/types.lua b/lua/yazi/types.lua index f6302128..22f77559 100644 --- a/lua/yazi/types.lua +++ b/lua/yazi/types.lua @@ -29,7 +29,7 @@ ---@class (exact) YaziConfigHighlightGroups # Defines the highlight groups that will be used in yazi ---@field public hovered_buffer_background? vim.api.keyset.highlight # the color of the background of buffer that is hovered over ----@alias YaziEvent YaziRenameEvent | YaziMoveEvent | YaziDeleteEvent | YaziTrashEvent | YaziChangeDirectoryEvent | YaziHoverEvent +---@alias YaziEvent YaziRenameEvent | YaziMoveEvent | YaziDeleteEvent | YaziTrashEvent | YaziChangeDirectoryEvent | YaziHoverEvent | YaziBulkEvent ---@class (exact) YaziClosedState # describes the state of yazi when it was closed; the last known state ---@field public last_directory Path # the last directory that yazi was in before it was closed @@ -72,6 +72,10 @@ ---@field public type "hover" ---@field public url string +---@class (exact) YaziBulkEvent "Like `rename` and `move` but for bulk renaming" +---@field public type "bulk" +---@field public changes table # a table of old paths to new paths + ---@class (exact) yazi.AutoCmdEvent # the nvim_create_autocmd() event object copied from the nvim help docs ---@field public id number ---@field public event string diff --git a/lua/yazi/utils.lua b/lua/yazi/utils.lua index 70bb4a8a..03e23db0 100644 --- a/lua/yazi/utils.lua +++ b/lua/yazi/utils.lua @@ -80,10 +80,20 @@ function M.parse_events(events_file_lines) data = vim.json.decode(data_string), } table.insert(events, event) + elseif type == 'bulk' then + -- example of a bulk event: + -- bulk,0,1720800121065599,{"changes":{"/tmp/test-directory/test":"/tmp/test-directory/test2"}} + local data = vim.json.decode(table.concat(parts, ',', 4, #parts)) + + ---@type YaziBulkEvent + local event = { + type = 'bulk', + changes = data['changes'], + } + table.insert(events, event) elseif type == 'delete' then -- example of a delete event: -- delete,1712766606832135,1712766606832135,{"urls":["/tmp/test-directory/test_2"]} - local timestamp = parts[2] local id = parts[3] local data_string = table.concat(parts, ',', 4, #parts)