diff --git a/Cargo.lock b/Cargo.lock index 5d2de8d..6b6842b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "bitflags" version = "1.2.1" @@ -14,6 +20,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "const-sha1" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d" + [[package]] name = "edit" version = "0.1.3" @@ -30,6 +55,16 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + [[package]] name = "getrandom" version = "0.2.3" @@ -41,6 +76,17 @@ dependencies = [ "wasi", ] +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itertools" version = "0.8.2" @@ -56,12 +102,64 @@ version = "0.2.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + [[package]] name = "main_error" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb63bb1e282e0b6aba0addb1f0e87cb5181ea68142b2dfd21ba108f8e8088a64" +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "osstrtools" version = "0.2.2" @@ -71,6 +169,12 @@ dependencies = [ "itertools", ] +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + [[package]] name = "pico-args" version = "0.4.2" @@ -109,6 +213,7 @@ dependencies = [ "question", "rand", "thiserror", + "trash", ] [[package]] @@ -178,6 +283,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "syn" version = "1.0.73" @@ -223,12 +334,79 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "trash" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3ebb6cb2db7947ab9f65dec9f7c5dbe01042b708f564242dcfb6d5cb2957cbc" +dependencies = [ + "chrono", + "libc", + "log", + "objc", + "scopeguard", + "url", + "windows", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -266,3 +444,33 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361f3533a83ee1a28c9be59683f40043db02dbedf6479ce8795657386195c97f" +dependencies = [ + "const-sha1", + "windows_gen", + "windows_macros", +] + +[[package]] +name = "windows_gen" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54154dbc515d58723f6b6053c12f1065da7389f733660581b2391bd1af480452" +dependencies = [ + "syn", +] + +[[package]] +name = "windows_macros" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f7794c652845dc466cb8dc1b86c08345707c8144bc53e9086430047c7d33b76" +dependencies = [ + "syn", + "windows_gen", +] diff --git a/Cargo.toml b/Cargo.toml index 349ae4e..fe04a90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ main_error = "0.1.1" pico-args = "0.4.2" question = "0.2.2" rand = { version = "0.8", features = ["small_rng", "getrandom"], default_features = false } +trash = "2.0.2" diff --git a/src/main.rs b/src/main.rs index 237249b..8b6cc32 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,6 +21,7 @@ Options: -h, --help Prints help information -r, --retry Re-enters the editor after an error -n, --dry-run Show changes and ask for confirmation + -t, --trash Trash files instead of deleting them "; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -33,6 +34,7 @@ pub enum Mode { pub struct Args { mode: Mode, dryrun: bool, + trash: bool, } fn main() -> Result<(), main_error::MainError> { @@ -41,6 +43,7 @@ fn main() -> Result<(), main_error::MainError> { let help = pargs.contains(["-h", "--help"]); let retry = pargs.contains(["-r", "--retry"]); let dryrun = pargs.contains(["-n", "--dry-run"]); + let trash = pargs.contains(["-t", "--trash"]); let delete_mode = pargs.contains(["-d", "--delete-mode"]); @@ -65,7 +68,7 @@ fn main() -> Result<(), main_error::MainError> { use std::io::Read; let mut stdin = std::io::stdin(); - while let Err(err) = quiren(&dir, Args { mode, dryrun }) { + while let Err(err) = quiren(&dir, Args { mode, dryrun, trash }) { eprintln!("Error: {}", err); eprintln!("Press enter to retry"); @@ -74,7 +77,7 @@ fn main() -> Result<(), main_error::MainError> { return Ok(()); } - Ok(quiren(&dir, Args { mode, dryrun })?) + Ok(quiren(&dir, Args { mode, dryrun, trash })?) } #[derive(Error, Debug)] @@ -91,6 +94,8 @@ pub enum QuirenError { Tempfile, #[error("I/O error: {0}")] IoError(#[from] std::io::Error), + #[error("error when trashing: {0}")] + TrashError(#[from] trash::Error), } pub fn quiren(dir: &Path, args: Args) -> Result<(), QuirenError> { @@ -116,7 +121,7 @@ pub fn quiren(dir: &Path, args: Args) -> Result<(), QuirenError> { if args.dryrun { loop { - if confirm_changes(&changes) { + if confirm_changes(&changes, args.trash) { break; } @@ -168,6 +173,7 @@ pub fn quiren(dir: &Path, args: Args) -> Result<(), QuirenError> { fs::rename(a, b)? } + Change::Delete(a) if args.trash => trash::delete(a)?, Change::Delete(a) => fs::remove_file(a)?, } } @@ -251,14 +257,18 @@ fn extract_deletions<'a>( Ok(iter) } -fn confirm_changes(changes: &[Change]) -> bool { + +fn confirm_changes(changes: &[Change], trash: bool) -> bool { + let delete_action = if trash { "Trash" } else { "Delete" }; + for change in changes { match change { Change::Rename(a, b) => println!("Rename: {} -> {}", a.display(), b.display()), - Change::Delete(a) => println!("Delete: {}", a.display()), + Change::Delete(a) => println!("{}: {}", delete_action, a.display()), } } + if changes.is_empty() { println!("No changes."); return true;