Skip to content

Commit 1fab54c

Browse files
authored
feat(filesystem): add BEFORE_FILE_{ADD/DELETE} events (#1657)
1 parent 5d172e8 commit 1fab54c

File tree

2 files changed

+91
-58
lines changed

2 files changed

+91
-58
lines changed

lua/neo-tree/events/init.lua

+7-5
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@ local utils = require("neo-tree.utils")
55

66
local M = {
77
-- Well known event names, you can make up your own
8-
STATE_CREATED = "state_created",
9-
BEFORE_RENDER = "before_render",
108
AFTER_RENDER = "after_render",
9+
BEFORE_FILE_ADD = "before_file_add",
10+
BEFORE_FILE_DELETE = "before_file_delete",
11+
BEFORE_FILE_MOVE = "before_file_move",
12+
BEFORE_FILE_RENAME = "before_file_rename",
13+
BEFORE_RENDER = "before_render",
1114
FILE_ADDED = "file_added",
1215
FILE_DELETED = "file_deleted",
13-
BEFORE_FILE_MOVE = "before_file_move",
1416
FILE_MOVED = "file_moved",
15-
FILE_OPEN_REQUESTED = "file_open_requested",
1617
FILE_OPENED = "file_opened",
17-
BEFORE_FILE_RENAME = "before_file_rename",
18+
FILE_OPEN_REQUESTED = "file_open_requested",
1819
FILE_RENAMED = "file_renamed",
1920
FS_EVENT = "fs_event",
2021
GIT_EVENT = "git_event",
2122
GIT_STATUS_CHANGED = "git_status_changed",
23+
STATE_CREATED = "state_created",
2224
NEO_TREE_BUFFER_ENTER = "neo_tree_buffer_enter",
2325
NEO_TREE_BUFFER_LEAVE = "neo_tree_buffer_leave",
2426
NEO_TREE_LSP_UPDATE = "neo_tree_lsp_update",

lua/neo-tree/sources/filesystem/lib/fs_actions.lua

+84-53
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
-- Permalink: https://github.com/mhartington/dotfiles/blob/7560986378753e0c047d940452cb03a3b6439b11/config/nvim/lua/mh/filetree/init.lua
77
local vim = vim
88
local api = vim.api
9-
local loop = vim.loop
9+
local loop = vim.uv or vim.loop
1010
local scan = require("plenary.scandir")
1111
local utils = require("neo-tree.utils")
1212
local inputs = require("neo-tree.ui.inputs")
@@ -253,6 +253,12 @@ M.copy_node = function(source, _destination, callback, using_root_directory)
253253
log.warn("Cannot copy a file/folder to itself")
254254
return
255255
end
256+
257+
local event_result = events.fire_event(events.BEFORE_FILE_ADD, destination) or {}
258+
if event_result.handled then
259+
return
260+
end
261+
256262
local source_path = Path:new(source)
257263
if source_path:is_file() then
258264
-- When the source is a file, then Path.copy() currently doesn't create
@@ -321,6 +327,11 @@ M.create_directory = function(in_directory, callback, using_root_directory)
321327
destination = vim.fn.fnamemodify(destination, ":p")
322328
end
323329

330+
local event_result = events.fire_event(events.BEFORE_FILE_ADD, destination) or {}
331+
if event_result.handled then
332+
return
333+
end
334+
324335
if loop.fs_stat(destination) then
325336
log.warn("Directory already exists")
326337
return
@@ -378,14 +389,24 @@ M.create_node = function(in_directory, callback, using_root_directory)
378389
destination = vim.fn.fnamemodify(destination, ":p")
379390
end
380391

381-
if utils.is_windows then
382-
destination = utils.windowize_path(destination)
383-
end
392+
destination = utils.normalize_path(destination)
384393
if loop.fs_stat(destination) then
385394
log.warn("File already exists")
386395
return
387396
end
388397

398+
local complete = vim.schedule_wrap(function()
399+
events.fire_event(events.FILE_ADDED, destination)
400+
if callback then
401+
callback(destination)
402+
end
403+
end)
404+
local event_result = events.fire_event(events.BEFORE_FILE_ADD, destination) or {}
405+
if event_result.handled then
406+
complete()
407+
return
408+
end
409+
389410
create_all_parents(destination)
390411
if is_dir then
391412
loop.fs_mkdir(destination, 493)
@@ -403,17 +424,50 @@ M.create_node = function(in_directory, callback, using_root_directory)
403424
loop.fs_close(fd)
404425
end
405426
end
406-
407-
vim.schedule(function()
408-
events.fire_event(events.FILE_ADDED, destination)
409-
if callback then
410-
callback(destination)
411-
end
412-
end)
427+
complete()
413428
end
414429
end)
415430
end
416431

432+
---Recursively delete a directory and its children.
433+
---@param dir_path string Directory to delete.
434+
---@return boolean success Whether the directory was deleted.
435+
local function delete_dir(dir_path)
436+
local handle = loop.fs_scandir(dir_path)
437+
if type(handle) == "string" then
438+
api.nvim_err_writeln(handle)
439+
return false
440+
end
441+
442+
if not handle then
443+
log.error("could not scan dir " .. dir_path)
444+
return false
445+
end
446+
447+
while true do
448+
local child_name, t = loop.fs_scandir_next(handle)
449+
if not child_name then
450+
break
451+
end
452+
453+
local child_path = dir_path .. "/" .. child_name
454+
if t == "directory" then
455+
local success = delete_dir(child_path)
456+
if not success then
457+
log.error("failed to delete ", child_path)
458+
return false
459+
end
460+
else
461+
local success = loop.fs_unlink(child_path)
462+
if not success then
463+
return false
464+
end
465+
clear_buffer(child_path)
466+
end
467+
end
468+
return loop.fs_rmdir(dir_path) or false
469+
end
470+
417471
-- Delete Node
418472
M.delete_node = function(path, callback, noconfirm)
419473
local _, name = utils.split_path(path)
@@ -454,39 +508,18 @@ M.delete_node = function(path, callback, noconfirm)
454508
return
455509
end
456510

457-
local do_delete = function(confirmed)
458-
if not confirmed then
459-
return
460-
end
461-
462-
local function delete_dir(dir_path)
463-
local handle = loop.fs_scandir(dir_path)
464-
if type(handle) == "string" then
465-
return api.nvim_err_writeln(handle)
511+
local do_delete = function()
512+
local complete = vim.schedule_wrap(function()
513+
events.fire_event(events.FILE_DELETED, path)
514+
if callback then
515+
callback(path)
466516
end
517+
end)
467518

468-
while true do
469-
local child_name, t = loop.fs_scandir_next(handle)
470-
if not child_name then
471-
break
472-
end
473-
474-
local child_path = dir_path .. "/" .. child_name
475-
if t == "directory" then
476-
local success = delete_dir(child_path)
477-
if not success then
478-
log.error("failed to delete ", child_path)
479-
return false
480-
end
481-
else
482-
local success = loop.fs_unlink(child_path)
483-
if not success then
484-
return false
485-
end
486-
clear_buffer(child_path)
487-
end
488-
end
489-
return loop.fs_rmdir(dir_path)
519+
local event_result = events.fire_event(events.BEFORE_FILE_DELETE, path) or {}
520+
if event_result.handled then
521+
complete()
522+
return
490523
end
491524

492525
if _type == "directory" then
@@ -526,19 +559,17 @@ M.delete_node = function(path, callback, noconfirm)
526559
end
527560
clear_buffer(path)
528561
end
529-
530-
vim.schedule(function()
531-
events.fire_event(events.FILE_DELETED, path)
532-
if callback then
533-
callback(path)
534-
end
535-
end)
562+
complete()
536563
end
537564

538565
if noconfirm then
539-
do_delete(true)
566+
do_delete()
540567
else
541-
inputs.confirm(msg, do_delete)
568+
inputs.confirm(msg, function(confirmed)
569+
if confirmed then
570+
do_delete()
571+
end
572+
end)
542573
end
543574
end
544575

@@ -593,9 +624,8 @@ local rename_node = function(msg, name, get_destination, path, callback)
593624
if err then
594625
log.warn("Could not rename the files")
595626
return
596-
else
597-
complete()
598627
end
628+
complete()
599629
end)
600630
end
601631

@@ -605,6 +635,7 @@ local rename_node = function(msg, name, get_destination, path, callback)
605635
callback = fs_rename,
606636
}) or {}
607637
if event_result.handled then
638+
complete()
608639
return
609640
end
610641
fs_rename()

0 commit comments

Comments
 (0)