Skip to content

Commit

Permalink
feat: when files are deleted in yazi, they are closed in nvim
Browse files Browse the repository at this point in the history
  • Loading branch information
mikavilpas committed Apr 11, 2024
1 parent 39d0316 commit 7fe7761
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 21 deletions.
14 changes: 11 additions & 3 deletions lua/yazi.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ local window = require('yazi.window')
local utils = require('yazi.utils')
local vimfn = require('yazi.vimfn')
local configModule = require('yazi.config')
local renaming = require('yazi.renaming')
local event_handling = require('yazi.event_handling')

local M = {}

Expand All @@ -28,7 +28,7 @@ function M.yazi(config, path)

os.remove(config.chosen_file_path)
local cmd = string.format(
'yazi "%s" --local-events "rename" --chooser-file "%s" > %s',
'yazi "%s" --local-events "rename,delete,trash" --chooser-file "%s" > %s',
path,
config.chosen_file_path,
config.events_file_path
Expand Down Expand Up @@ -73,8 +73,9 @@ function M.yazi(config, path)

for _, event in ipairs(events) do
if event.type == 'rename' then
---@cast event YaziRenameEvent
local rename_instructions =
renaming.get_buffers_that_need_renaming_after_yazi_exited(
event_handling.get_buffers_that_need_renaming_after_yazi_exited(
event.data
)
for _, instruction in ipairs(rename_instructions) do
Expand All @@ -83,6 +84,13 @@ function M.yazi(config, path)
instruction.path.filename
)
end
elseif event.type == 'delete' then
---@cast event YaziDeleteEvent
event_handling.process_delete_event(event)
elseif event.type == 'trash' then
-- selene: allow(if_same_then_else)
---@cast event YaziTrashEvent
event_handling.process_delete_event(event)
end
end
end,
Expand Down
26 changes: 16 additions & 10 deletions lua/yazi/renaming.lua → lua/yazi/event_handling.lua
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
local RenameableBuffer = require('yazi.renameable_buffer')
local utils = require('yazi.utils')

local M = {}

---@param event YaziDeleteEvent | YaziTrashEvent
function M.process_delete_event(event)
local open_buffers = utils.get_open_buffers()

for _, buffer in ipairs(open_buffers) do
for _, url in ipairs(event.data.urls) do
if buffer:matches_exactly(url) or buffer:matches_parent(url) then
-- allow the user to cancel the deletion
vim.api.nvim_buf_delete(buffer.bufnr, { force = false })
end
end
end
end

---@param rename_event YaziEventDataRename
---@return RenameableBuffer[] "instructions for renaming the buffers (command pattern)"
function M.get_buffers_that_need_renaming_after_yazi_exited(rename_event)
---@type RenameableBuffer[]
local open_buffers = {}
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
local path = vim.api.nvim_buf_get_name(bufnr)
if path ~= '' and path ~= nil then
local renameable_buffer = RenameableBuffer.new(bufnr, path)
open_buffers[#open_buffers + 1] = renameable_buffer
end
end
local open_buffers = utils.get_open_buffers()

---@type table<integer, RenameableBuffer>
local renamed_buffers = {}
Expand Down
14 changes: 14 additions & 0 deletions lua/yazi/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
---@field public yazi_opened? fun(preselected_path: string | nil): nil
---@field public yazi_closed_successfully? fun(chosen_file: string | nil): nil

---@alias YaziEvent YaziRenameEvent | YaziDeleteEvent | YaziTrashEvent

---@class YaziRenameEvent
---@field public type "rename"
---@field public timestamp string
Expand All @@ -20,3 +22,15 @@
---@class YaziEventDataRename
---@field public from string
---@field public to string

---@class YaziDeleteEvent
---@field public type "delete"
---@field public timestamp string
---@field public id string
---@field public data {urls: string[]}

---@class YaziTrashEvent
---@field public type "trash"
---@field public timestamp string
---@field public id string
---@field public data {urls: string[]}
51 changes: 50 additions & 1 deletion lua/yazi/utils.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local fn = vim.fn
local RenameableBuffer = require('yazi.renameable_buffer')

local M = {}

Expand Down Expand Up @@ -44,6 +45,7 @@ function M.parse_events(events_file_lines)
local parts = vim.split(line, ',')
local type = parts[1]

-- selene: allow(if_same_then_else)
if type == 'rename' then
-- example of a rename event:

Expand All @@ -60,14 +62,46 @@ function M.parse_events(events_file_lines)
data = vim.fn.json_decode(data_string),
}
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)

---@type YaziDeleteEvent
local event = {
type = type,
timestamp = timestamp,
id = id,
data = vim.fn.json_decode(data_string),
}
table.insert(events, event)
elseif type == 'trash' then
-- example of a trash event:
-- trash,1712766606832135,1712766606832135,{"urls":["/tmp/test-directory/test_2"]}

local timestamp = parts[2]
local id = parts[3]
local data_string = table.concat(parts, ',', 4, #parts)

---@type YaziTrashEvent
local event = {
type = type,
timestamp = timestamp,
id = id,
data = vim.fn.json_decode(data_string),
}
table.insert(events, event)
end
end

return events
end

---@param path string
---@return YaziRenameEvent[]
---@return YaziEvent[]
function M.read_events_file(path)
local success, events_file_lines = pcall(vim.fn.readfile, path)
os.remove(path)
Expand All @@ -85,4 +119,19 @@ function M.read_events_file(path)
return events
end

---@return RenameableBuffer[]
function M.get_open_buffers()
---@type RenameableBuffer[]
local open_buffers = {}
for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
local path = vim.api.nvim_buf_get_name(bufnr)
if path ~= '' and path ~= nil then
local renameable_buffer = RenameableBuffer.new(bufnr, path)
open_buffers[#open_buffers + 1] = renameable_buffer
end
end

return open_buffers
end

return M
59 changes: 59 additions & 0 deletions tests/yazi/delete_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
local assert = require('luassert')
local event_handling = require('yazi.event_handling')

describe('process_delete_event', 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('deletes a buffer that matches the delete event exactly', function()
local buffer = vim.fn.bufadd('/abc/def')

---@type YaziDeleteEvent
local event = {
type = 'delete',
timestamp = '1712766606832135',
id = '1712766606832135',
data = { urls = { '/abc/def' } },
}

event_handling.process_delete_event(event)

assert.is_false(vim.api.nvim_buf_is_valid(buffer))
end)

it('deletes a buffer that matches the parent directory', function()
local buffer = vim.fn.bufadd('/abc/def')

---@type YaziDeleteEvent
local event = {
type = 'delete',
timestamp = '1712766606832135',
id = '1712766606832135',
data = { urls = { '/abc' } },
}

event_handling.process_delete_event(event)

assert.is_false(vim.api.nvim_buf_is_valid(buffer))
end)

it("doesn't delete a buffer that doesn't match the delete event", function()
local buffer = vim.fn.bufadd('/abc/def')

---@type YaziDeleteEvent
local event = {
type = 'delete',
timestamp = '1712766606832135',
id = '1712766606832135',
data = { urls = { '/abc/ghi' } },
}

event_handling.process_delete_event(event)

assert.is_true(vim.api.nvim_buf_is_valid(buffer))
end)
end)
2 changes: 1 addition & 1 deletion tests/yazi/open_dir_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('when the user set open_for_directories = true', function()
vim.api.nvim_command('edit /')

assert.stub(api_mock.termopen).was_called_with(
'yazi "/" --local-events "rename" --chooser-file "/tmp/yazi_filechosen" > /tmp/yazi.nvim.events.txt',
'yazi "/" --local-events "rename,delete,trash" --chooser-file "/tmp/yazi_filechosen" > /tmp/yazi.nvim.events.txt',
match.is_table()
)
end)
Expand Down
19 changes: 19 additions & 0 deletions tests/yazi/read_events_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,23 @@ describe('parsing yazi event file events', function()
},
})
end)

it('can parse delete events', function()
local data = {
'delete,1712766606832135,1712766606832135,{"urls":["/tmp/test-directory/test_2"]}',
}

local events = utils.parse_events(data)

assert.are.same(events, {
{
type = 'delete',
timestamp = '1712766606832135',
id = '1712766606832135',
data = {
urls = { '/tmp/test-directory/test_2' },
},
},
})
end)
end)
14 changes: 10 additions & 4 deletions tests/yazi/rename_spec.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
local assert = require('luassert')
local renaming = require('yazi.renaming')
local event_handning = require('yazi.event_handling')

describe('get_buffers_that_need_renaming_after_yazi_exited', function()
before_each(function()
Expand All @@ -21,7 +21,9 @@ describe('get_buffers_that_need_renaming_after_yazi_exited', function()
vim.fn.bufadd('/my-tmp/file_A')

local rename_instructions =
renaming.get_buffers_that_need_renaming_after_yazi_exited(rename_event)
event_handning.get_buffers_that_need_renaming_after_yazi_exited(
rename_event
)

assert.is_equal(vim.tbl_count(rename_instructions), 1)

Expand All @@ -43,7 +45,9 @@ describe('get_buffers_that_need_renaming_after_yazi_exited', function()
vim.fn.bufadd('/my-tmp/dir1/file')

local rename_instructions =
renaming.get_buffers_that_need_renaming_after_yazi_exited(rename_event)
event_handning.get_buffers_that_need_renaming_after_yazi_exited(
rename_event
)

assert.is_equal(vim.tbl_count(rename_instructions), 1)
local result = rename_instructions[1]
Expand All @@ -62,7 +66,9 @@ describe('get_buffers_that_need_renaming_after_yazi_exited', function()
vim.fn.bufadd('/my-tmp/dir1/file')

local rename_instructions =
renaming.get_buffers_that_need_renaming_after_yazi_exited(rename_event)
event_handning.get_buffers_that_need_renaming_after_yazi_exited(
rename_event
)

assert.is_equal(vim.tbl_count(rename_instructions), 0)
end)
Expand Down
59 changes: 59 additions & 0 deletions tests/yazi/trash_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
local assert = require('luassert')
local event_handling = require('yazi.event_handling')

describe('process_trash_event', 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('deletes a buffer that matches the trash event exactly', function()
local buffer = vim.fn.bufadd('/abc/def')

---@type YaziTrashEvent
local event = {
type = 'trash',
timestamp = '1712766606832135',
id = '1712766606832135',
data = { urls = { '/abc/def' } },
}

event_handling.process_delete_event(event)

assert.is_false(vim.api.nvim_buf_is_valid(buffer))
end)

it('deletes a buffer that matches the parent directory', function()
local buffer = vim.fn.bufadd('/abc/def')

---@type YaziTrashEvent
local event = {
type = 'trash',
timestamp = '1712766606832135',
id = '1712766606832135',
data = { urls = { '/abc' } },
}

event_handling.process_delete_event(event)

assert.is_false(vim.api.nvim_buf_is_valid(buffer))
end)

it("doesn't delete a buffer that doesn't match the trash event", function()
local buffer = vim.fn.bufadd('/abc/def')

---@type YaziTrashEvent
local event = {
type = 'trash',
timestamp = '1712766606832135',
id = '1712766606832135',
data = { urls = { '/abc/ghi' } },
}

event_handling.process_delete_event(event)

assert.is_true(vim.api.nvim_buf_is_valid(buffer))
end)
end)
4 changes: 2 additions & 2 deletions tests/yazi/yazi_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('opening a file', function()
plugin.yazi()

assert.stub(api_mock.termopen).was_called_with(
'yazi "/abc/test-file.txt" --local-events "rename" --chooser-file "/tmp/yazi_filechosen" > /tmp/yazi.nvim.events.txt',
'yazi "/abc/test-file.txt" --local-events "rename,delete,trash" --chooser-file "/tmp/yazi_filechosen" > /tmp/yazi.nvim.events.txt',
match.is_table()
)
end)
Expand All @@ -28,7 +28,7 @@ describe('opening a file', function()
plugin.yazi()

assert.stub(api_mock.termopen).was_called_with(
'yazi "/tmp/" --local-events "rename" --chooser-file "/tmp/yazi_filechosen" > /tmp/yazi.nvim.events.txt',
'yazi "/tmp/" --local-events "rename,delete,trash" --chooser-file "/tmp/yazi_filechosen" > /tmp/yazi.nvim.events.txt',
match.is_table()
)
end)
Expand Down

0 comments on commit 7fe7761

Please sign in to comment.