diff --git a/lua/yazi.lua b/lua/yazi.lua index 5468e081..e7caf17f 100644 --- a/lua/yazi.lua +++ b/lua/yazi.lua @@ -47,7 +47,8 @@ function M.yazi(config, path) utils.on_yazi_exited(prev_win, win, yazi_buffer, config) - event_handling.process_events_emitted_from_yazi(config) + local events = utils.read_events_file(config.events_file_path) + event_handling.process_events_emitted_from_yazi(events) end, }) diff --git a/lua/yazi/event_handling.lua b/lua/yazi/event_handling.lua index 6f19f719..f4573c41 100644 --- a/lua/yazi/event_handling.lua +++ b/lua/yazi/event_handling.lua @@ -30,15 +30,17 @@ function M.process_delete_event(event, remaining_events) end end ----@param rename_event YaziEventDataRenameOrMove +---@param rename_or_move_event YaziEventDataRenameOrMove ---@return RenameableBuffer[] "instructions for renaming the buffers (command pattern)" -function M.get_buffers_that_need_renaming_after_yazi_exited(rename_event) +function M.get_buffers_that_need_renaming_after_yazi_exited( + rename_or_move_event +) local open_buffers = utils.get_open_buffers() ---@type table local renamed_buffers = {} - local event = rename_event + local event = rename_or_move_event for _, buffer in ipairs(open_buffers) do if buffer:matches_exactly(event.from) then buffer:rename(event.to) @@ -52,10 +54,9 @@ function M.get_buffers_that_need_renaming_after_yazi_exited(rename_event) return vim.tbl_values(renamed_buffers) end ----@param config YaziConfig -function M.process_events_emitted_from_yazi(config) +---@param events YaziEvent[] +function M.process_events_emitted_from_yazi(events) -- process events emitted from yazi - local events = utils.read_events_file(config.events_file_path) for i, event in ipairs(events) do if event.type == 'rename' then @@ -63,7 +64,7 @@ function M.process_events_emitted_from_yazi(config) local rename_instructions = M.get_buffers_that_need_renaming_after_yazi_exited(event.data) for _, instruction in ipairs(rename_instructions) do - vim.api.nvim_buf_set_name(instruction.bufnr, instruction.path.filename) + utils.rename_or_close_buffer(instruction) end elseif event.type == 'move' then ---@cast event YaziMoveEvent @@ -71,10 +72,7 @@ function M.process_events_emitted_from_yazi(config) local rename_instructions = M.get_buffers_that_need_renaming_after_yazi_exited(item) for _, instruction in ipairs(rename_instructions) do - vim.api.nvim_buf_set_name( - instruction.bufnr, - instruction.path.filename - ) + utils.rename_or_close_buffer(instruction) end end elseif event.type == 'delete' then diff --git a/lua/yazi/utils.lua b/lua/yazi/utils.lua index 082acb99..34de7e54 100644 --- a/lua/yazi/utils.lua +++ b/lua/yazi/utils.lua @@ -149,6 +149,31 @@ function M.get_open_buffers() return open_buffers end +---@param path string +---@return boolean +function M.is_buffer_open(path) + local open_buffers = M.get_open_buffers() + for _, buffer in ipairs(open_buffers) do + if buffer:matches_exactly(path) then + return true + end + end + + return false +end + +---@param instruction RenameableBuffer +---@return nil +function M.rename_or_close_buffer(instruction) + -- If the target buffer is already open in neovim, just close the old buffer. + -- It causes an error to try to rename to a buffer that's already open. + if M.is_buffer_open(instruction.path.filename) then + vim.api.nvim_buf_delete(instruction.bufnr, {}) + else + vim.api.nvim_buf_set_name(instruction.bufnr, instruction.path.filename) + end +end + ---@param prev_win integer ---@param floating_window_id integer ---@param floating_window_buffer integer diff --git a/tests/yazi/rename_spec.lua b/tests/yazi/rename_spec.lua index 2c497952..bcf88127 100644 --- a/tests/yazi/rename_spec.lua +++ b/tests/yazi/rename_spec.lua @@ -1,5 +1,6 @@ local assert = require('luassert') local event_handling = require('yazi.event_handling') +local utils = require('yazi.utils') describe('get_buffers_that_need_renaming_after_yazi_exited', function() before_each(function() @@ -73,3 +74,62 @@ describe('get_buffers_that_need_renaming_after_yazi_exited', function() assert.is_equal(vim.tbl_count(rename_instructions), 0) end) end) + +describe('process_events_emitted_from_yazi', function() + before_each(function() + -- clear all buffers + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + vim.api.nvim_buf_delete(buf, { force = true }) + end + end) + + it('closes a buffer that was renamed to another open buffer', function() + vim.fn.bufadd('/my-tmp/file1') + vim.fn.bufadd('/my-tmp/file2') + + ---@type YaziRenameEvent + local event = { + type = 'rename', + data = { + from = '/my-tmp/file1', + to = '/my-tmp/file2', + }, + timestamp = '2021-09-01T00:00:00Z', + id = '123', + } + + event_handling.process_events_emitted_from_yazi({ event }) + + local open_buffers = utils.get_open_buffers() + for _, buffer in ipairs(open_buffers) do + assert.is_not_equal('/my-tmp/file1', buffer.path.filename) + end + end) + + it('closes a buffer that was moved to another open buffer', function() + vim.fn.bufadd('/my-tmp/file1') + vim.fn.bufadd('/my-tmp/file2') + + ---@type YaziMoveEvent + local event = { + type = 'move', + id = '123', + timestamp = '2021-09-01T00:00:00Z', + data = { + items = { + { + from = '/my-tmp/file1', + to = '/my-tmp/file2', + }, + }, + }, + } + + event_handling.process_events_emitted_from_yazi({ event }) + + local open_buffers = utils.get_open_buffers() + for _, buffer in ipairs(open_buffers) do + assert.is_not_equal('/my-tmp/file1', buffer.path.filename) + end + end) +end)