diff options
author | Federico Stra <stra.federico@gmail.com> | 2021-06-27 15:30:35 +0200 |
---|---|---|
committer | Federico Stra <stra.federico@gmail.com> | 2021-06-27 15:41:39 +0200 |
commit | 00fae90e0dffc468c75bd362fa4220bc8650fb86 (patch) | |
tree | c84e4bdcd578f435ccc820d543e0546a2cae04a5 /src | |
parent | 5534cd7126eada8a040f00cd996295dfd42cb4c1 (diff) |
Implement Ctrl+t move to trash
Diffstat (limited to 'src')
-rw-r--r-- | src/interactive/app/handlers.rs | 59 | ||||
-rw-r--r-- | src/interactive/widgets/help.rs | 5 | ||||
-rw-r--r-- | src/interactive/widgets/mark.rs | 9 |
3 files changed, 73 insertions, 0 deletions
diff --git a/src/interactive/app/handlers.rs b/src/interactive/app/handlers.rs index 2360aae..c15c764 100644 --- a/src/interactive/app/handlers.rs +++ b/src/interactive/app/handlers.rs @@ -9,6 +9,7 @@ use dua::traverse::{Traversal, TreeIndex}; use itertools::Itertools; use petgraph::{visit::Bfs, Direction}; use std::{fs, io, path::PathBuf}; +use trash; use tui::backend::Backend; use tui_react::Terminal; @@ -229,6 +230,26 @@ impl AppState { self.message = None; res } + Some(MarkMode::Trash) => { + self.message = Some("Trashing entries...".to_string()); + let mut entries_trashed = 0; + let res = pane.iterate_deletable_items(|mut pane, entry_to_trash| { + window.mark_pane = Some(pane); + self.draw(window, traversal, display, terminal).ok(); + pane = window.mark_pane.take().expect("option to be filled"); + match self.trash_entry(entry_to_trash, traversal) { + Ok(ed) => { + entries_trashed += ed; + self.message = + Some(format!("Trashed {} entries...", entries_trashed)); + Ok(pane) + } + Err(c) => Err((pane, c)), + } + }); + self.message = None; + res + } None => Some(pane), }, None => None, @@ -274,6 +295,44 @@ impl AppState { Ok(entries_deleted) } + pub fn trash_entry( + &mut self, + index: TreeIndex, + traversal: &mut Traversal, + ) -> Result<usize, usize> { + let mut entries_trashed = 0; + if let Some(_entry) = traversal.tree.node_weight(index) { + let path_to_delete = path_of(&traversal.tree, index); + if let Err(_) = trash::delete(path_to_delete) { + return Err(1); + } + let parent_idx = traversal + .tree + .neighbors_directed(index, Direction::Incoming) + .next() + .expect("us being unable to delete the root index"); + let mut bfs = Bfs::new(&traversal.tree, index); + while let Some(nx) = bfs.next(&traversal.tree) { + traversal.tree.remove_node(nx); + traversal.entries_traversed -= 1; + entries_trashed += 1; + } + self.entries = sorted_entries(&traversal.tree, self.root, self.sorting); + if traversal.tree.node_weight(self.root).is_none() { + self.set_root(traversal.root_index, traversal); + } + if self + .selected + .and_then(|selected| self.entries.iter().find(|e| e.index == selected)) + .is_none() + { + self.selected = self.entries.get(0).map(|e| e.index); + } + self.recompute_sizes_recursively(parent_idx, traversal); + } + Ok(entries_trashed) + } + fn set_root(&mut self, root: TreeIndex, traversal: &Traversal) { self.root = root; self.entries = sorted_entries(&traversal.tree, root, self.sorting); diff --git a/src/interactive/widgets/help.rs b/src/interactive/widgets/help.rs index 89678db..d410035 100644 --- a/src/interactive/widgets/help.rs +++ b/src/interactive/widgets/help.rs @@ -168,6 +168,11 @@ impl HelpPane { "Permanently delete all marked entries without prompt!", Some("This operation cannot be undone!"), ); + hotkey( + "Ctrl + t", + "Move all marked entries to the trash bin", + Some("The entries can be restored from the trash bin"), + ); spacer(); } title("Keys for application control"); diff --git a/src/interactive/widgets/mark.rs b/src/interactive/widgets/mark.rs index 4e5829a..e01604b 100644 --- a/src/interactive/widgets/mark.rs +++ b/src/interactive/widgets/mark.rs @@ -28,6 +28,7 @@ use unicode_segmentation::UnicodeSegmentation; pub enum MarkMode { Delete, + Trash, } pub type EntryMarkMap = BTreeMap<TreeIndex, EntryMark>; @@ -109,6 +110,7 @@ impl MarkPane { let action = None; match key { Ctrl('r') => return Some(self.prepare_deletion()), + Ctrl('t') => return Some(self.prepare_trashing()), Char('x') | Char('d') | Char(' ') => { return self.remove_selected().map(|s| (s, action)) } @@ -184,6 +186,13 @@ impl MarkPane { self.selected = Some(0); (self, Some(MarkMode::Delete)) } + fn prepare_trashing(mut self) -> (Self, Option<MarkMode>) { + for entry in self.marked.values_mut() { + entry.num_errors_during_deletion = 0; + } + self.selected = Some(0); + (self, Some(MarkMode::Trash)) + } fn remove_selected(mut self) -> Option<Self> { if let Some(mut selected) = self.selected { let idx = self.tree_index_by_list_position(selected); |