summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFederico Stra <stra.federico@gmail.com>2021-06-27 15:30:35 +0200
committerFederico Stra <stra.federico@gmail.com>2021-06-27 15:41:39 +0200
commit00fae90e0dffc468c75bd362fa4220bc8650fb86 (patch)
treec84e4bdcd578f435ccc820d543e0546a2cae04a5 /src
parent5534cd7126eada8a040f00cd996295dfd42cb4c1 (diff)
Implement Ctrl+t move to trash
Diffstat (limited to 'src')
-rw-r--r--src/interactive/app/handlers.rs59
-rw-r--r--src/interactive/widgets/help.rs5
-rw-r--r--src/interactive/widgets/mark.rs9
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);