neo-tree.nvim icon indicating copy to clipboard operation
neo-tree.nvim copied to clipboard

Support trash instead of delete

Open mo8it opened this issue 3 years ago • 22 comments

Thanks for the awesome plugin!

Adding support for trash instead of rm would be awesome! Nvim-Tree does this with the D shortcut.

mo8it avatar Mar 25 '22 12:03 mo8it

This would be a simple one for a custom command. Take a look at :h neo-tree-custom-commands

Something like this should work (from memory, not tested):

   require("neo-tree").setup({
     filesystem = {
       window = {
         mappings = {
           ["D"] = functions(state)
             local node = state.tree:get_node()
             local path = node:get_id()
             vim.fn.system("trash " .. vim.fn.fnameescape(path))
           end
         }
       }
     }
   })

cseickel avatar Mar 25 '22 21:03 cseickel

Thanks for your answer, I did go with this:

require("neo-tree").setup({
	filesystem = {
		commands = {
			-- Override delete to use trash instead of rm
			delete = function(state)
				local path = state.tree:get_node().path
				vim.fn.system({ "trash", vim.fn.fnameescape(path) })
			end,
		},
	},
})

It did work and the docs in :h neo-tree-custom-commands were helpful, but now I have the problem that it does not refresh after sending to trash. I did take a look at the code, it does not seem very easy to try to copy everything is done when deleting. No conformation, no output, not sure about symlinks and directories. So, if would implement it, I would really appreciate it ^^

In the mean time: Can you please tell me how to refresh the tree after the operation is done?

Thank you a lot for the quick rely!

mo8it avatar Mar 25 '22 23:03 mo8it

You can use require("neo-tree.sources.manager").refresh(state.name) to refresh:

require("neo-tree").setup({
	filesystem = {
		commands = {
			-- Override delete to use trash instead of rm
			delete = function(state)
				local path = state.tree:get_node().path
				vim.fn.system({ "trash", vim.fn.fnameescape(path) })
                                require("neo-tree.sources.manager").refresh(state.name)
			end,
		},
	},
})

cseickel avatar Mar 26 '22 00:03 cseickel

Looking at the code now, there is some extra niceties happening that is worth having. I will leave this up as an enhancement, but since I don't use trash I'm not the best person to implement it. Hopefully someone else will pick it up.

cseickel avatar Mar 26 '22 00:03 cseickel

Refreshing did work. Thank you!

mo8it avatar Mar 26 '22 13:03 mo8it

To extend https://github.com/nvim-neo-tree/neo-tree.nvim/issues/202#issuecomment-1079531421 the example below adds a confirmation dialog.

What's still open is using the trash when deleting a range of files.

But usually git should lull one into safety without the need for a trash.

delete = function(state)
	local inputs = require "neo-tree.ui.inputs"
	local path = state.tree:get_node().path
	local msg = "Are you sure you want to delete " .. path
	inputs.confirm(msg, function(confirmed)
		if not confirmed then return end

		vim.fn.system { "trash", vim.fn.fnameescape(path) }
		require("neo-tree.sources.manager").refresh(state.name)
	end)
end,

ttytm avatar Nov 03 '22 21:11 ttytm

To work with multi selected nodes (in Visual mode), I also extended tobealive's code to below.

-- over write default 'delete' command to 'trash'.
delete = function(state)
	local inputs = require("neo-tree.ui.inputs")
	local path = state.tree:get_node().path
	local msg = "Are you sure you want to trash " .. path
	inputs.confirm(msg, function(confirmed)
		if not confirmed then return end

		vim.fn.system { "trash", vim.fn.fnameescape(path) }
		require("neo-tree.sources.manager").refresh(state.name)
	end)
end,

-- over write default 'delete_visual' command to 'trash' x n.
delete_visual = function(state, selected_nodes)
	local inputs = require("neo-tree.ui.inputs")

	-- get table items count
	function GetTableLen(tbl)
		local len = 0
		for n in pairs(tbl) do
			len = len + 1
		end
		return len
	end

	local count = GetTableLen(selected_nodes)
	local msg = "Are you sure you want to trash " .. count .. " files ?"
	inputs.confirm(msg, function(confirmed)
		if not confirmed then return end
		for _, node in ipairs(selected_nodes) do
			vim.fn.system { "trash", vim.fn.fnameescape(node.path) }
		end
		require("neo-tree.sources.manager").refresh(state.name)
	end)
end,

nvim's reboot is required for that 'refresh' command to work.

Thanks for all your advices.

riodelphino avatar Feb 13 '23 16:02 riodelphino

@riodelphino Thanks for sharing, helped me a lot. There is a built-in vim.tbl_count function, or #selected_nodes that can be used to simplify the GetTableLen. 😸

sxyazi avatar May 06 '23 13:05 sxyazi

I just deleted 18 hours of work by mistake. PLEASE, make this the default behavior

Its not reasonable to delete files forever with rm command when working with an editor

amitlevy21 avatar Nov 25 '23 10:11 amitlevy21

I just deleted 18 hours of work by mistake. PLEASE, make this the default behavior

Its not reasonable to delete files forever with rm command when working with an editor

I mean... You literally have to confirm you want to delete the thing. So while you may not like to hear this, this is purely on you.

If you select delete, and confirm you do want to delete, you cannot be upset that it was deleted. This idea that your editor should be responsible for the user's mistakes is incorrect. Additionally as was pointed out above, the support to do this is already built into neo-tree.

I will say we should probably put this recipe into the wiki, but IMO that is as far as this should go. Supporting trash is not as easy as it sounds (remember that there are 3 major operating systems, and 2 of them have completely different ways of doing trash support).

At the end of the day, Neovim and in extension Neo-tree are meant to be customized by you the user. Make it what you want. If you want the delete action to send to trash instead of deleting, then do it.

But we should not be changing the default simply because of a mistake confirmed by a few people.

I'm sorry you lost all that work. And I know this will read quite harsh. The intention is not to shame you, but simply to explain my position in saying we should not be changing the default on this behavior. Delete should be delete.

miversen33 avatar Nov 25 '23 15:11 miversen33

Thank you for addressing my comment, I appreciate your thoughts and words.

My mistake is that I used visual mode to delete 20+ files, mistakenly the cursor overlapped to the folder which I didn't want to deleted. I'm sure you can understand how easily this can happen to others.

I understand that this is not easy to add support for all OS's, and agree it should be added to the wiki. If this is not going to be supported out of the box it should be mentioned in the README with a big caution notice so each user can address it according to the OS he operates on.

amitlevy21 avatar Nov 25 '23 17:11 amitlevy21

So while you may not like to hear this, this is purely on you.

Just had a slightly different accident with deleting files #1090

Since shite like this and nasty bugs could happen and implementing a saver delete seems to be problematic, my (sad) solution is to switch back to the much saver nnn integration.

If this is not going to be supported out of the box it should be mentioned in the README with a big caution notice so each user can address it according to the OS he operates on.

@amitlevy21 Yep!

rafo avatar Dec 06 '23 12:12 rafo

I get this error: image

  {
    "nvim-neo-tree/neo-tree.nvim",
    opts = {
      filesystem = {
        commands = {
          -- Override delete to use trash instead of rm
          delete = function(state)
            local inputs = require("neo-tree.ui.inputs")
            local path = state.tree:get_node().path
            local msg = "Are you sure you want to delete "
              .. path
            inputs.confirm(msg, function(confirmed)
              if not confirmed then
                return
              end

              vim.fn.system({
                "trash",
                vim.fn.fnameescape(path),
              })
              require("neo-tree.sources.manager").refresh(
                state.name
              )
            end)
          end,
        },
      },
    },
  },

Mosazghi avatar Apr 22 '24 12:04 Mosazghi

Hi. I guess you just need trash command installed in your system(OS) by brew.

It passed long time, so now I'm not sure about my and your code.

riodelphino avatar Apr 22 '24 15:04 riodelphino

Worked!

Mosazghi avatar Apr 22 '24 15:04 Mosazghi