@@ -4,6 +4,7 @@ local utils = require "nvim-tree.utils"
4
4
local core = require " nvim-tree.core"
5
5
local events = require " nvim-tree.events"
6
6
local notify = require " nvim-tree.notify"
7
+ local async = require " nvim-tree.async"
7
8
8
9
local M = {}
9
10
@@ -12,9 +13,75 @@ local clipboard = {
12
13
copy = {},
13
14
}
14
15
16
+ local function do_copy_dir (source , destination , mode )
17
+ errmsg , handle = async .call (function (cb )
18
+ return vim .loop .fs_opendir (source , cb , 32 )
19
+ end )
20
+ if not handle then
21
+ log .line (" copy_paste" , " do_copy fs_scandir '%s' failed '%s'" , source , errmsg )
22
+ return false , errmsg
23
+ end
24
+
25
+ local _ , stats = async .call (vim .loop .fs_stat , destination )
26
+ if stats then
27
+ errMsg = async .call (vim .loop .fs_chmod , destination , mode )
28
+ if errMsg then
29
+ log .line (" copy_paste" , " do_copy fs_chmod '%s' failed '%s'" , destination , errmsg )
30
+ -- ignore error and continue, the dir exists
31
+ end
32
+ else
33
+ errmsg , success = async .call (vim .loop .fs_mkdir , destination , mode )
34
+ if not success then
35
+ log .line (" copy_paste" , " do_copy fs_mkdir '%s' failed '%s'" , destination , errmsg )
36
+ return false , errmsg
37
+ end
38
+ end
39
+
40
+ while true do
41
+ local _ , entries = async .call (vim .loop .fs_readdir , handle )
42
+ if not entries or # entries == 0 then
43
+ break
44
+ end
45
+ local cp_tasks = {}
46
+ for _ , entry in pairs (entries ) do
47
+ local name = entry .name
48
+ local type = entry .type
49
+ local new_name = utils .path_join { source , name }
50
+ local new_destination = utils .path_join { destination , name }
51
+
52
+ errMsg , stats = async .call (vim .loop .fs_stat , new_name )
53
+ if errMsg then
54
+ log .line (" copy_paste" , " do_copy fs_stat '%s' failed '%s'" , new_name , errmsg )
55
+ else
56
+ if type == " directory" then
57
+ success , errmsg = do_copy_dir (new_name , new_destination , stats .mode )
58
+ if not success then
59
+ return false , errmsg
60
+ end
61
+ else
62
+ table.insert (cp_tasks , function ()
63
+ errmsg , success = async .call (vim .loop .fs_copyfile , new_name , new_destination , nil )
64
+ if not success then
65
+ log .line (" copy_paste" , " do_copy fs_copyfile failed '%s'" , errmsg )
66
+ return false , errmsg
67
+ end
68
+ return true
69
+ end )
70
+ end
71
+ end
72
+ end
73
+ for _ , result in ipairs (async .all (unpack (cp_tasks ))) do
74
+ success = unpack (result )
75
+ if not success then
76
+ return false
77
+ end
78
+ end
79
+ end
80
+ return true
81
+ end
82
+
15
83
local function do_copy (source , destination )
16
- local source_stats , handle
17
- local success , errmsg
84
+ local source_stats , success , errmsg
18
85
19
86
source_stats , errmsg = vim .loop .fs_stat (source )
20
87
if not source_stats then
@@ -30,40 +97,16 @@ local function do_copy(source, destination)
30
97
end
31
98
32
99
if source_stats .type == " file" then
33
- success , errmsg = vim .loop .fs_copyfile ( source , destination )
100
+ errmsg , success = async . call ( vim .loop .fs_copyfile , source , destination )
34
101
if not success then
35
102
log .line (" copy_paste" , " do_copy fs_copyfile failed '%s'" , errmsg )
36
103
return false , errmsg
37
104
end
38
- return true
39
105
elseif source_stats .type == " directory" then
40
- handle , errmsg = vim .loop .fs_scandir (source )
41
- if type (handle ) == " string" then
42
- return false , handle
43
- elseif not handle then
44
- log .line (" copy_paste" , " do_copy fs_scandir '%s' failed '%s'" , source , errmsg )
45
- return false , errmsg
46
- end
47
-
48
- success , errmsg = vim .loop .fs_mkdir (destination , source_stats .mode )
106
+ success , errmsg = do_copy_dir (source , destination , source_stats .mode )
49
107
if not success then
50
- log .line (" copy_paste" , " do_copy fs_mkdir '%s' failed '%s'" , destination , errmsg )
51
108
return false , errmsg
52
109
end
53
-
54
- while true do
55
- local name , _ = vim .loop .fs_scandir_next (handle )
56
- if not name then
57
- break
58
- end
59
-
60
- local new_name = utils .path_join { source , name }
61
- local new_destination = utils .path_join { destination , name }
62
- success , errmsg = do_copy (new_name , new_destination )
63
- if not success then
64
- return false , errmsg
65
- end
66
- end
67
110
else
68
111
errmsg = string.format (" '%s' illegal file type '%s'" , source , source_stats .type )
69
112
log .line (" copy_paste" , " do_copy %s" , errmsg )
@@ -96,19 +139,17 @@ local function do_single_paste(source, dest, action_type, action_fn)
96
139
if dest_stats then
97
140
local prompt_select = " Overwrite " .. dest .. " ?"
98
141
local prompt_input = prompt_select .. " y/n/r(ename): "
99
- lib .prompt (prompt_input , prompt_select , { " y" , " n" , " r" }, { " Yes" , " No" , " Rename" }, function (item_short )
142
+ local item_short = async .call (lib .prompt , prompt_input , prompt_select , { " y" , " n" , " r" }, { " Yes" , " No" , " Rename" })
143
+ utils .clear_prompt ()
144
+ if item_short == " y" then
145
+ on_process ()
146
+ elseif item_short == " r" then
147
+ local new_dest = async .call (vim .ui .input , { prompt = " Rename to " , default = dest , completion = " dir" })
100
148
utils .clear_prompt ()
101
- if item_short == " y" then
102
- on_process ()
103
- elseif item_short == " r" then
104
- vim .ui .input ({ prompt = " Rename to " , default = dest , completion = " dir" }, function (new_dest )
105
- utils .clear_prompt ()
106
- if new_dest then
107
- do_single_paste (source , new_dest , action_type , action_fn )
108
- end
109
- end )
149
+ if new_dest then
150
+ do_single_paste (source , new_dest , action_type , action_fn )
110
151
end
111
- end )
152
+ end
112
153
else
113
154
on_process ()
114
155
end
@@ -184,24 +225,24 @@ local function do_cut(source, destination)
184
225
return true
185
226
end
186
227
187
- events ._dispatch_will_rename_node (source , destination )
188
- local success , errmsg = vim .loop .fs_rename (source , destination )
228
+ local errmsg , success = async .call (vim .loop .fs_rename , source , destination )
189
229
if not success then
190
230
log .line (" copy_paste" , " do_cut fs_rename failed '%s'" , errmsg )
191
231
return false , errmsg
192
232
end
233
+ async .schedule ()
193
234
utils .rename_loaded_buffers (source , destination )
194
235
events ._dispatch_node_renamed (source , destination )
195
236
return true
196
237
end
197
238
198
- function M .paste (node )
239
+ M .paste = async . wrap ( function (node )
199
240
if clipboard .move [1 ] ~= nil then
200
241
return do_paste (node , " move" , do_cut )
201
242
end
202
243
203
244
return do_paste (node , " copy" , do_copy )
204
- end
245
+ end )
205
246
206
247
function M .print_clipboard ()
207
248
local content = {}
0 commit comments