Skip to content

Commit

Permalink
feat: emit YaziRenamedOrMoved event when files are renamed or moved
Browse files Browse the repository at this point in the history
Problem
=======

When files are renamed or moved in yazi, there is no way for other
plugins to know about this. If the user uses yazi.nvim along with other
plugins that need to react to files being renamed or moved, it cannot be
done. This means that other plugins that depend on yazi cannot react to
these changes.

Currently yazi.nvim can only react to LSP delete/rename events, but
plugins that operate outside of the LSP protocol are not supported.

Solution
========

Add a new Neovim autocmd/event called `YaziRenamedOrMoved` that is
emitted when files are renamed or moved. This event will contain a table
of the paths that were renamed or moved.

Previously we were already emitting a Neovim event for `YaziDDSHover` -
now we have two custom events.

Closes #494
  • Loading branch information
mikavilpas committed Oct 4, 2024
1 parent b6ac040 commit 3f434d2
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 3 deletions.
26 changes: 24 additions & 2 deletions lua/yazi/event_handling/nvim_event_handling.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
-- This file is about emitting events to other Neovim plugins
-- This file is about emitting events to other Neovim plugins so that they can
-- react to things that happen in this plugin.

local M = {}

---@alias YaziNeovimEvent
---| "'YaziDDSHover'" A file was hovered over in yazi
---| "'YaziRenamedOrMoved'" Files were renamed or moved

---@alias YaziNeovimEvent.YaziRenamedOrMovedData {changes: table<string, string>} # a table of old paths to new paths

---Emit and event when files are renamed or moved.
---@param event YaziRenameEvent | YaziMoveEvent | YaziBulkEvent
---@see YaziNeovimEvent.YaziRenamedOrMovedData
function M.emit_renamed_or_moved_event(event)
---@type YaziNeovimEvent.YaziRenamedOrMovedData
local event_data = {
changes = {},
}

if event.type == "move" or event.type == "rename" then
event_data.changes[event.data.from] = event.data.to
elseif event.type == "bulk" then
event_data.changes = event.changes
end

M.emit("YaziRenamedOrMoved", event_data)
end

---@param event_name YaziNeovimEvent
---@param event_data table
---@param event_data table<string, unknown>
function M.emit(event_name, event_data)
vim.api.nvim_exec_autocmds("User", {
pattern = event_name,
Expand Down
15 changes: 14 additions & 1 deletion lua/yazi/process/ya_process.lua
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,23 @@ function YaProcess:process_events(events)
event_handling.emit("YaziDDSHover", event)
end)
elseif event.type == "cd" then
---@cast event YaziChangeDirectoryEvent
---@cast event YaziHoverEvent
self.cwd = event.url
else
self.events[#self.events + 1] = event

if
event.type == "rename"
or event.type == "move"
or event.type == "bulk"
then
local event_handling =
require("yazi.event_handling.nvim_event_handling")

pcall(function()
event_handling.emit_renamed_or_moved_event(event)
end)
end
end
end
end
Expand Down
130 changes: 130 additions & 0 deletions spec/yazi/ya_process_spec.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
local assert = require("luassert")
local ya_process = require("yazi.process.ya_process")
local spy = require("luassert.spy")

describe("the get_yazi_command() function", function()
it("specifies opening multiple tabs when enabled in the config", function()
Expand Down Expand Up @@ -113,4 +114,133 @@ describe("process_events()", function()
assert.are.same("/tmp/directory", ya.cwd)
end)
end)

describe("YaziRenamedOrMoved events", function()
before_each(function()
-- delete the autocmd to prevent it from being called multiple times
vim.api.nvim_command("silent! autocmd! YaziRenamedOrMoved")
end)

it(
"gets published when YaziRenameEvent events are received from yazi",
function()
local config = require("yazi.config").default()
local ya = ya_process.new(config, "yazi_id_123")

---@type YaziRenameEvent[]
local events = {
{
type = "rename",
timestamp = "2021-09-01T12:00:00Z",
id = "rename_123",
data = {
from = "/tmp/old_path",
to = "/tmp/new_path",
},
},
}

local event_callback = spy.new()
vim.api.nvim_create_autocmd("User", {
pattern = "YaziRenamedOrMoved",
callback = function(...)
event_callback(...)
end,
})

ya:process_events(events)

assert.spy(event_callback).was_called()
assert.same(#event_callback.calls, 1)

local event = event_callback.calls[1].vals[1]
assert.same({
changes = {
["/tmp/old_path"] = "/tmp/new_path",
},
}, event.data)
end
)

it(
"gets published when YaziMoveEvent events are received from yazi",
function()
local config = require("yazi.config").default()
local ya = ya_process.new(config, "yazi_id_123")

---@type YaziMoveEvent[]
local events = {
{
type = "move",
timestamp = "2021-09-01T12:00:00Z",
id = "rename_123",
data = {
from = "/tmp/old_path",
to = "/tmp/new_path",
},
},
}

local event_callback = spy.new()
vim.api.nvim_create_autocmd("User", {
pattern = "YaziRenamedOrMoved",
callback = function(...)
event_callback(...)
end,
})

ya:process_events(events)

assert.spy(event_callback).was_called()
assert.same(#event_callback.calls, 1)

local event = event_callback.calls[1].vals[1]
assert.same({
changes = {
["/tmp/old_path"] = "/tmp/new_path",
},
}, event.data)
end
)

it(
"gets published when YaziBulkEvent events are received from yazi",
function()
local config = require("yazi.config").default()
local ya = ya_process.new(config, "yazi_id_123")

---@type YaziBulkEvent[]
local events = {
{
type = "bulk",
changes = {
["/tmp/old_path1"] = "/tmp/new_path1",
["/tmp/old_path2"] = "/tmp/new_path2",
},
},
}

local event_callback = spy.new()
vim.api.nvim_create_autocmd("User", {
pattern = "YaziRenamedOrMoved",
callback = function(...)
event_callback(...)
end,
})

ya:process_events(events)

assert.spy(event_callback).was_called()
assert.same(#event_callback.calls, 1)

local event = event_callback.calls[1].vals[1]
assert.same({
changes = {
["/tmp/old_path1"] = "/tmp/new_path1",
["/tmp/old_path2"] = "/tmp/new_path2",
},
}, event.data)
end
)
end)
end)

0 comments on commit 3f434d2

Please sign in to comment.