@@ -3,6 +3,10 @@ local luv = vim.loop
33local open_mode = luv .constants .O_CREAT + luv .constants .O_WRONLY + luv .constants .O_TRUNC
44
55local M = {}
6+ local clipboard = {
7+ move = {},
8+ copy = {}
9+ }
610
711local function clear_prompt ()
812 vim .api .nvim_command (' normal :esc<CR>' )
@@ -109,6 +113,88 @@ local function remove_dir(cwd)
109113 return luv .fs_rmdir (cwd )
110114end
111115
116+ local function do_copy (source , destination )
117+ local source_stats = luv .fs_stat (source )
118+
119+ if source_stats and source_stats .type == ' file' then
120+ return luv .fs_copyfile (source , destination )
121+ end
122+
123+ local handle = luv .fs_scandir (source )
124+ if type (handle ) == ' string' then
125+ return api .nvim_err_writeln (handle )
126+ end
127+
128+ luv .fs_mkdir (destination , source_stats .mode )
129+
130+ while true do
131+ local name , t = luv .fs_scandir_next (handle )
132+ if not name then break end
133+
134+ local new_name = source .. ' /' .. name
135+ local new_destination = destination .. ' /' .. name
136+ if t == ' directory' then
137+ local success = do_copy (new_name , new_destination )
138+ if not success then return false end
139+ else
140+ local success = luv .fs_copyfile (new_name , new_destination )
141+ if not success then return false end
142+ end
143+ end
144+
145+ return true
146+ end
147+
148+ local function do_paste (node , action_type , action_fn )
149+ local clip = clipboard [action_type ]
150+ if # clip == 0 then return end
151+
152+ local destination = node .absolute_path
153+ local stats = luv .fs_stat (destination )
154+ local is_dir = stats and stats .type == ' directory'
155+
156+ if not is_dir then
157+ destination = vim .fn .fnamemodify (destination , ' :p:h' )
158+ elseif not node .open then
159+ destination = vim .fn .fnamemodify (destination , ' :p:h:h' )
160+ end
161+
162+ local msg = # clip .. ' entries'
163+
164+ if # clip == 1 then
165+ msg = clip [1 ].absolute_path
166+ end
167+
168+ local ans = vim .fn .input (action_type .. ' ' .. msg .. ' to ' .. destination .. ' ? y/n: ' )
169+ clear_prompt ()
170+ if not ans :match (' ^y' ) then
171+ return api .nvim_out_write (' Canceled.\n ' )
172+ end
173+
174+ for _ , entry in ipairs (clip ) do
175+ local dest = destination .. ' /' .. entry .name
176+ local success = action_fn (entry .absolute_path , dest )
177+ if not success then
178+ api .nvim_err_writeln (' Could not ' .. action_type .. ' ' .. entry .absolute_path )
179+ end
180+ end
181+ clipboard [action_type ] = {}
182+ return refresh_tree ()
183+ end
184+
185+ local function add_to_clipboard (node , clip )
186+ if node .name == ' ..' then return end
187+
188+ for idx , entry in ipairs (clip ) do
189+ if entry .absolute_path == node .absolute_path then
190+ table.remove (clip , idx )
191+ return api .nvim_out_write (node .absolute_path .. ' removed to clipboard.\n ' )
192+ end
193+ end
194+ table.insert (clip , node )
195+ api .nvim_out_write (node .absolute_path .. ' added to clipboard.\n ' )
196+ end
197+
112198function M .remove (node )
113199 if node .name == ' ..' then return end
114200
@@ -153,4 +239,20 @@ function M.rename(node)
153239 refresh_tree ()
154240end
155241
242+ function M .copy (node )
243+ add_to_clipboard (node , clipboard .copy )
244+ end
245+
246+ function M .cut (node )
247+ add_to_clipboard (node , clipboard .move )
248+ end
249+
250+ function M .paste (node )
251+ if clipboard .move [1 ] ~= nil then
252+ return do_paste (node , ' move' , luv .fs_rename )
253+ end
254+
255+ return do_paste (node , ' copy' , do_copy )
256+ end
257+
156258return M
0 commit comments