feat: trash support for linux and mac (#165)
* wip: skeleton code for trash adapter * refactor: split trash implementation for mac and linux * fix: ensure we create the .Trash/$uid dir * feat: code complete linux trash implementation * doc: write up trash features * feat: code complete mac trash implementation * cleanup: remove previous, terrible, undocumented trash feature * fix: always disabled trash * feat: show original path of trashed files * doc: add a note about calling actions directly * fix: bugs in trash implementation * fix: schedule_wrap in mac trash * doc: fix typo and line wrapping * fix: parsing of arguments to :Oil command * doc: small documentation tweaks * doc: fix awkward wording in the toggle_trash action * fix: warning on Windows when delete_to_trash = true * feat: :Oil --trash can open specific trash directories * fix: show all trash files in device root * fix: trash mtime should be sortable * fix: shorten_path handles optional trailing slash * refactor: overhaul the UI * fix: keep trash original path vtext from stacking * refactor: replace disable_changes with an error filter * fix: shorten path names in home directory relative to root * doc: small README format changes * cleanup: remove unnecessary preserve_undo logic * test: add a functional test for the freedesktop trash adapter * test: more functional tests for trash * fix: schedule a callback to avoid main loop error * refactor: clean up mutator logic * doc: some comments and type annotations
This commit is contained in:
parent
d8f0d91b10
commit
6175bd6462
27 changed files with 1580 additions and 229 deletions
164
tests/trash_spec.lua
Normal file
164
tests/trash_spec.lua
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
local uv = vim.uv or vim.loop
|
||||
require("plenary.async").tests.add_to_env()
|
||||
local TmpDir = require("tests.tmpdir")
|
||||
local fs = require("oil.fs")
|
||||
local test_util = require("tests.test_util")
|
||||
|
||||
---Get the raw list of filenames from an unmodified oil buffer
|
||||
---@param bufnr? integer
|
||||
---@return string[]
|
||||
local function parse_entries(bufnr)
|
||||
bufnr = bufnr or 0
|
||||
if vim.bo[bufnr].modified then
|
||||
error("parse_entries doesn't work on a modified oil buffer")
|
||||
end
|
||||
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
|
||||
return vim.tbl_map(function(line)
|
||||
return line:match("^/%d+ +(.+)$")
|
||||
end, lines)
|
||||
end
|
||||
|
||||
a.describe("freedesktop", function()
|
||||
local tmpdir
|
||||
a.before_each(function()
|
||||
require("oil.config").delete_to_trash = true
|
||||
tmpdir = TmpDir.new()
|
||||
package.loaded["oil.adapters.trash"] = require("oil.adapters.trash.freedesktop")
|
||||
local trash_dir = string.format(".Trash-%d", uv.getuid())
|
||||
tmpdir:create({ fs.join(trash_dir, "__dummy__") })
|
||||
end)
|
||||
a.after_each(function()
|
||||
if tmpdir then
|
||||
tmpdir:dispose()
|
||||
end
|
||||
test_util.reset_editor()
|
||||
package.loaded["oil.adapters.trash"] = nil
|
||||
end)
|
||||
|
||||
a.it("files can be moved to the trash", function()
|
||||
tmpdir:create({ "a.txt", "foo/b.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
vim.api.nvim_feedkeys("p", "x", true)
|
||||
test_util.actions.save()
|
||||
tmpdir:assert_not_exists("a.txt")
|
||||
tmpdir:assert_exists("foo/b.txt")
|
||||
test_util.actions.reload()
|
||||
assert.are.same({ "a.txt" }, parse_entries(0))
|
||||
end)
|
||||
|
||||
a.it("deleting a file moves it to trash", function()
|
||||
tmpdir:create({ "a.txt", "foo/b.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
tmpdir:assert_not_exists("a.txt")
|
||||
tmpdir:assert_exists("foo/b.txt")
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
assert.are.same({ "a.txt" }, parse_entries(0))
|
||||
end)
|
||||
|
||||
a.it("deleting a directory moves it to trash", function()
|
||||
tmpdir:create({ "a.txt", "foo/b.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("foo/")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
tmpdir:assert_not_exists("foo")
|
||||
tmpdir:assert_exists("a.txt")
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
assert.are.same({ "foo/" }, parse_entries(0))
|
||||
end)
|
||||
|
||||
a.it("deleting a file from trash deletes it permanently", function()
|
||||
tmpdir:create({ "a.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.reload()
|
||||
tmpdir:assert_not_exists("a.txt")
|
||||
assert.are.same({}, parse_entries(0))
|
||||
end)
|
||||
|
||||
a.it("cannot create files in the trash", function()
|
||||
tmpdir:create({ "a.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
vim.api.nvim_feedkeys("onew_file.txt", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.reload()
|
||||
assert.are.same({ "a.txt" }, parse_entries(0))
|
||||
end)
|
||||
|
||||
a.it("cannot rename files in the trash", function()
|
||||
tmpdir:create({ "a.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
vim.api.nvim_feedkeys("0facwnew_name", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.reload()
|
||||
assert.are.same({ "a.txt" }, parse_entries(0))
|
||||
end)
|
||||
|
||||
a.it("cannot copy files in the trash", function()
|
||||
tmpdir:create({ "a.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
vim.api.nvim_feedkeys("yypp", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.reload()
|
||||
assert.are.same({ "a.txt" }, parse_entries(0))
|
||||
end)
|
||||
|
||||
a.it("can restore files from trash", function()
|
||||
tmpdir:create({ "a.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
test_util.actions.focus("a.txt")
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
vim.api.nvim_feedkeys("p", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.reload()
|
||||
assert.are.same({ "a.txt" }, parse_entries(0))
|
||||
local uid = uv.getuid()
|
||||
tmpdir:assert_fs({
|
||||
["a.txt"] = "a.txt",
|
||||
[".Trash-" .. uid .. "/__dummy__"] = ".Trash-" .. uid .. "/__dummy__",
|
||||
[".Trash-" .. uid .. "/files/"] = true,
|
||||
[".Trash-" .. uid .. "/info/"] = true,
|
||||
})
|
||||
end)
|
||||
|
||||
a.it("can have multiple files with the same name in trash", function()
|
||||
tmpdir:create({ "a.txt" })
|
||||
test_util.actions.open({ tmpdir.path })
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
tmpdir:create({ "a.txt" })
|
||||
test_util.actions.reload()
|
||||
vim.api.nvim_feedkeys("dd", "x", true)
|
||||
test_util.actions.save()
|
||||
test_util.actions.open({ "--trash", tmpdir.path })
|
||||
assert.are.same({ "a.txt", "a.txt" }, parse_entries(0))
|
||||
end)
|
||||
end)
|
||||
Loading…
Add table
Add a link
Reference in a new issue