diff options
-rw-r--r-- | Cargo.lock | 112 | ||||
-rw-r--r-- | Cargo.toml | 4 | ||||
-rw-r--r-- | docs/configuration/keymap.toml.md | 8 | ||||
-rw-r--r-- | src/commands/delete_files.rs | 13 | ||||
-rw-r--r-- | src/commands/file_ops.rs | 26 | ||||
-rw-r--r-- | src/context/worker_context.rs | 6 | ||||
-rw-r--r-- | src/error/error_kind.rs | 3 | ||||
-rw-r--r-- | src/error/error_type.rs | 11 | ||||
-rw-r--r-- | src/event/app_event.rs | 3 | ||||
-rw-r--r-- | src/event/process_event.rs | 3 | ||||
-rw-r--r-- | src/io/io_worker.rs | 72 |
11 files changed, 82 insertions, 179 deletions
@@ -306,15 +306,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] name = "fsevent-sys" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -391,7 +382,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows 0.48.0", + "windows", ] [[package]] @@ -404,16 +395,6 @@ dependencies = [ ] [[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] name = "indexmap" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -497,7 +478,6 @@ dependencies = [ "structopt", "termion", "toml", - "trash", "unicode-segmentation", "unicode-width", "uuid", @@ -560,15 +540,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -657,15 +628,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" [[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -710,12 +672,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] name = "phf" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1160,21 +1116,6 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] name = "toml" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1209,43 +1150,12 @@ dependencies = [ ] [[package]] -name = "trash" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af3663fb8f476d674b9c61d1d2796acec725bef6bec4b41402a904252a25971e" -dependencies = [ - "chrono", - "libc", - "log", - "objc", - "once_cell", - "scopeguard", - "url", - "windows 0.44.0", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] name = "unicode-segmentation" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1258,17 +1168,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] -name = "url" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1437,15 +1336,6 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" @@ -32,7 +32,6 @@ signal-hook = "^0" structopt = "^0" termion = "^2" toml = "^0" -trash = { version = "^3", optional = true } unicode-segmentation = "^1" unicode-width = "^0" whoami = "^1" @@ -58,6 +57,5 @@ features = ["v4", "fast-rng", "macro-diagnostics"] devicons = ["phf"] file_mimetype = [] mouse = [] -recycle_bin = ["trash"] syntax_highlight = ["ansi-to-tui"] -default = ["devicons", "mouse", "recycle_bin", "syntax_highlight"] +default = ["devicons", "mouse", "syntax_highlight"] diff --git a/docs/configuration/keymap.toml.md b/docs/configuration/keymap.toml.md index 6ef8dbf..bc50909 100644 --- a/docs/configuration/keymap.toml.md +++ b/docs/configuration/keymap.toml.md @@ -271,8 +271,12 @@ function joshuto() { - `--permanently`: force permanent deletion regardless of `use_trash` value. - will **_permanently_** delete files if `use_trash` is `false` in [joshuto.toml](https://github.com/kamiyaa/joshuto)/wiki/Configuration#joshutotoml) -- if `use_trash` is `true`, this might cause issues with deleting files - on mounted filesystems such as on an external hard drive or tmpfs +- if `use_trash` is `true`, `joshuto` will try to use + the following command-line tools to try to put the files in the trash can instead + of permanently deleting them + - `gio trash` + - `trash-put`: https://github.com/andreafrancia/trash-cli + - `trash` ### `rename`: rename the current file the cursor is on diff --git a/src/commands/delete_files.rs b/src/commands/delete_files.rs index 496bbc1..4f062bc 100644 --- a/src/commands/delete_files.rs +++ b/src/commands/delete_files.rs @@ -4,7 +4,7 @@ use std::sync::mpsc; use termion::event::Key; use crate::context::AppContext; -use crate::error::JoshutoResult; +use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult}; use crate::history::DirectoryHistory; use crate::io::{FileOperation, FileOperationOptions, IoWorkerThread}; use crate::ui::widgets::TuiPrompt; @@ -15,7 +15,7 @@ fn delete_files( backend: &mut AppBackend, background: bool, permanently: bool, -) -> std::io::Result<()> { +) -> JoshutoResult<()> { let paths = context .tab_context_ref() .curr_tab_ref() @@ -24,10 +24,11 @@ fn delete_files( .unwrap_or_default(); let paths_len = paths.len(); if paths_len == 0 { - return Err(std::io::Error::new( - std::io::ErrorKind::Other, - "no files selected", - )); + let err = JoshutoError::new( + JoshutoErrorKind::InvalidParameters, + "no files selected".to_string(), + ); + return Err(err); } let ch = { diff --git a/src/commands/file_ops.rs b/src/commands/file_ops.rs index e9d889a..f289323 100644 --- a/src/commands/file_ops.rs +++ b/src/commands/file_ops.rs @@ -1,5 +1,5 @@ use std::io; -use std::process::Command; +use std::process::{Command, Stdio}; use crate::context::{AppContext, LocalStateContext}; use crate::error::{JoshutoError, JoshutoErrorKind, JoshutoResult}; @@ -129,27 +129,27 @@ fn copy_string_to_buffer(string: String) -> JoshutoResult { let clipboards = [ ( "wl-copy", - format!("printf '%s' '{}' | {} 2> /dev/null", string, "wl-copy"), - ), - ( - "xsel", - format!("printf '%s' '{}' | {} -ib 2> /dev/null", string, "xsel"), - ), - ( - "pbcopy", - format!("printf '%s' '{}' | {} 2> /dev/null", string, "pbcopy"), + format!("printf '%s' '{}' | {}", string, "wl-copy"), ), + ("xsel", format!("printf '%s' '{}' | {} -ib", string, "xsel")), + ("pbcopy", format!("printf '%s' '{}' | {}", string, "pbcopy")), ( "xclip", format!( - "printf '%s' '{}' | {} -selection clipboard 2> /dev/null", + "printf '%s' '{}' | {} -selection clipboard", string, "xclip" ), ), ]; - for (_, command) in clipboards.iter() { - match Command::new("sh").args(["-c", command.as_str()]).status() { + for (_, cmd) in clipboards.iter() { + let status = Command::new("sh") + .args(["-c", cmd.as_str()]) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status(); + + match status { Ok(s) if s.success() => return Ok(()), _ => {} } diff --git a/src/context/worker_context.rs b/src/context/worker_context.rs index 5bdf055..be6329b 100644 --- a/src/context/worker_context.rs +++ b/src/context/worker_context.rs @@ -3,6 +3,7 @@ use std::collections::{HashMap, VecDeque}; use std::sync::mpsc; use std::thread; +use crate::error::{JoshutoError, JoshutoErrorKind}; use crate::event::AppEvent; use crate::io::{FileOperationProgress, IoWorkerObserver, IoWorkerThread}; @@ -86,7 +87,10 @@ impl WorkerContext { let _ = tx.send(AppEvent::IoWorkerResult(res)); } Err(_) => { - let err = std::io::Error::new(std::io::ErrorKind::Other, "Sending Error"); + let err = JoshutoError::new( + JoshutoErrorKind::UnknownError, + "Sending Error".to_string(), + ); let _ = tx.send(AppEvent::IoWorkerResult(Err(err))); } } diff --git a/src/error/error_kind.rs b/src/error/error_kind.rs index 7260e2d..9afab66 100644 --- a/src/error/error_kind.rs +++ b/src/error/error_kind.rs @@ -14,7 +14,6 @@ pub enum JoshutoErrorKind { ClipboardError, TomlDeError(toml::de::Error), - #[cfg(feature = "recycle_bin")] TrashError, Glob, @@ -23,6 +22,8 @@ pub enum JoshutoErrorKind { UnrecognizedArgument, UnrecognizedCommand, + + UnknownError, } impl From<io::ErrorKind> for JoshutoErrorKind { diff --git a/src/error/error_type.rs b/src/error/error_type.rs index 4e2eaad..a195ef6 100644 --- a/src/error/error_type.rs +++ b/src/error/error_type.rs @@ -56,17 +56,6 @@ impl From<std::env::VarError> for JoshutoError { } } -#[cfg(feature = "recycle_bin")] -impl From<trash::Error> for JoshutoError { - fn from(err: trash::Error) -> Self { - let cause = err.to_string(); - Self { - _kind: JoshutoErrorKind::TrashError, - _cause: cause, - } - } -} - impl From<toml::de::Error> for JoshutoError { fn from(err: toml::de::Error) -> Self { let cause = err.to_string(); diff --git a/src/event/app_event.rs b/src/event/app_event.rs index fd36224..c50a195 100644 --- a/src/event/app_event.rs +++ b/src/event/app_event.rs @@ -12,6 +12,7 @@ use termion::input::TermRead; use uuid::Uuid; +use crate::error::JoshutoResult; use crate::fs::JoshutoDirList; use crate::io::FileOperationProgress; use crate::preview::preview_file::FilePreview; @@ -24,7 +25,7 @@ pub enum AppEvent { // background IO worker events IoWorkerCreate, FileOperationProgress(FileOperationProgress), - IoWorkerResult(io::Result<FileOperationProgress>), + IoWorkerResult(JoshutoResult<FileOperationProgress>), // forked process events ChildProcessComplete(u32), diff --git a/src/event/process_event.rs b/src/event/process_event.rs index f215d9a..2b6b0ae 100644 --- a/src/event/process_event.rs +++ b/src/event/process_event.rs @@ -10,6 +10,7 @@ use uuid::Uuid; use crate::commands::{cursor_move, parent_cursor_move, reload}; use crate::config::{AppKeyMapping, KeyMapping}; use crate::context::AppContext; +use crate::error::JoshutoResult; use crate::event::AppEvent; use crate::fs::JoshutoDirList; use crate::history::DirectoryHistory; @@ -90,7 +91,7 @@ pub fn process_worker_progress(context: &mut AppContext, res: FileOperationProgr pub fn process_finished_worker( context: &mut AppContext, - res: std::io::Result<FileOperationProgress>, + res: JoshutoResult<FileOperationProgress>, ) { let worker_context = context.worker_context_mut(); let observer = worker_context.remove_worker().unwrap(); diff --git a/src/io/io_worker.rs b/src/io/io_worker.rs index b8d5113..298c464 100644 --- a/src/io/io_worker.rs +++ b/src/io/io_worker.rs @@ -1,11 +1,15 @@ use std::fs; use std::io; use std::path; +use std::process::{Command, Stdio}; use std::sync::mpsc; #[cfg(unix)] use std::os::unix; +use crate::error::JoshutoError; +use crate::error::JoshutoErrorKind; +use crate::error::JoshutoResult; use crate::io::{FileOperation, FileOperationOptions, FileOperationProgress}; use crate::util::fs::query_number_of_items; use crate::util::name_resolution::rename_filename_conflict; @@ -40,7 +44,7 @@ impl IoWorkerThread { pub fn start( &self, tx: mpsc::Sender<FileOperationProgress>, - ) -> io::Result<FileOperationProgress> { + ) -> JoshutoResult<FileOperationProgress> { match self.kind() { FileOperation::Cut => self.paste_cut(tx), FileOperation::Copy => self.paste_copy(tx), @@ -53,7 +57,7 @@ impl IoWorkerThread { fn paste_copy( &self, tx: mpsc::Sender<FileOperationProgress>, - ) -> io::Result<FileOperationProgress> { + ) -> JoshutoResult<FileOperationProgress> { let (total_files, total_bytes) = query_number_of_items(&self.paths)?; let mut progress = FileOperationProgress::new( self.kind(), @@ -79,7 +83,7 @@ impl IoWorkerThread { fn paste_cut( &self, tx: mpsc::Sender<FileOperationProgress>, - ) -> io::Result<FileOperationProgress> { + ) -> JoshutoResult<FileOperationProgress> { let (total_files, total_bytes) = query_number_of_items(&self.paths)?; let mut progress = FileOperationProgress::new( self.kind(), @@ -105,7 +109,7 @@ impl IoWorkerThread { fn paste_link_absolute( &self, tx: mpsc::Sender<FileOperationProgress>, - ) -> io::Result<FileOperationProgress> { + ) -> JoshutoResult<FileOperationProgress> { let total_files = self.paths.len(); let total_bytes = total_files as u64; let mut progress = FileOperationProgress::new( @@ -137,7 +141,7 @@ impl IoWorkerThread { fn paste_link_relative( &self, tx: mpsc::Sender<FileOperationProgress>, - ) -> io::Result<FileOperationProgress> { + ) -> JoshutoResult<FileOperationProgress> { let total_files = self.paths.len(); let total_bytes = total_files as u64; let mut progress = FileOperationProgress::new( @@ -190,7 +194,7 @@ impl IoWorkerThread { fn delete( &self, _tx: mpsc::Sender<FileOperationProgress>, - ) -> io::Result<FileOperationProgress> { + ) -> JoshutoResult<FileOperationProgress> { let (total_files, total_bytes) = query_number_of_items(&self.paths)?; let progress = FileOperationProgress::new( self.kind(), @@ -200,16 +204,12 @@ impl IoWorkerThread { total_bytes, total_bytes, ); - #[cfg(feature = "recycle_bin")] + if self.options.permanently { remove_files(&self.paths)?; } else { trash_files(&self.paths)?; } - #[cfg(not(feature = "recycle_bin"))] - { - remove_files(&self.paths)?; - } Ok(progress) } @@ -329,19 +329,6 @@ pub fn recursive_cut( } } -#[cfg(feature = "recycle_bin")] -fn trash_error_to_io_error(err: trash::Error) -> std::io::Error { - match err { - trash::Error::Unknown { description } => { - std::io::Error::new(std::io::ErrorKind::Other, description) - } - trash::Error::TargetedRoot => { - std::io::Error::new(std::io::ErrorKind::Other, "Targeted Root") - } - _ => std::io::Error::new(std::io::ErrorKind::Other, "Unknown Error"), - } -} - fn remove_files<P>(paths: &[P]) -> std::io::Result<()> where P: AsRef<path::Path>, @@ -358,15 +345,42 @@ where Ok(()) } -#[cfg(feature = "recycle_bin")] -fn trash_files<P>(paths: &[P]) -> std::io::Result<()> +fn trash_files<P>(paths: &[P]) -> JoshutoResult where P: AsRef<path::Path>, { for path in paths { - if let Err(e) = trash::delete(path) { - return Err(trash_error_to_io_error(e)); - } + trash_file(path)?; } Ok(()) } + +fn trash_file<P>(file_path: P) -> JoshutoResult +where + P: AsRef<path::Path>, +{ + let file_path_str = file_path.as_ref().as_os_str().to_string_lossy(); + + let clipboards = [ + ("gio trash", format!("gio trash '{}'", file_path_str)), + ("trash-put", format!("trash-put '{}'", file_path_str)), + ("trash", format!("trash '{}'", file_path_str)), + ]; + + for (_, cmd) in clipboards.iter() { + let status = Command::new("sh") + .args(["-c", cmd.as_str()]) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status(); + + match status { + Ok(s) if s.success() => return Ok(()), + _ => {} + } + } + Err(JoshutoError::new( + JoshutoErrorKind::TrashError, + "Failed to trash file".to_string(), + )) +} |