diff --git a/README.md b/README.md index a59b09f..2682749 100644 --- a/README.md +++ b/README.md @@ -91,11 +91,11 @@ zfsdu | **Tree** | | | e | Expand all | | c | Collapse all | -| **Selection** | | +| **Selection (current scope)** | | | Space | Mark/unmark snapshot | -| + | Select all visible snapshots | -| - | Unselect all visible snapshots | -| * | Invert selection | +| + | Select all in scope | +| - | Unselect all in scope | +| * | Invert selection in scope | | **Search & Filter** | | | / | Search (n=next, N=prev) | | f | Filter visible items | @@ -141,6 +141,11 @@ search_match = "lightred" - Terminal with UTF-8 support - Root privileges (for snapshot deletion) +## Author + +**Florian Schermer** +[DATAZONE GmbH](https://datazone.de) + ## License CDDL (Common Development and Distribution License) - same as OpenZFS. diff --git a/src/app.rs b/src/app.rs index f85d8c8..eb5f466 100644 --- a/src/app.rs +++ b/src/app.rs @@ -561,15 +561,28 @@ impl App { self.search_matches.contains(&real_index) } - // Select/Unselect Group (like MC) + // Select/Unselect Group (like MC) - works in current scope pub fn select_group(&mut self) { + let current_parent = if let Some(real_idx) = self.nth_visible(self.selected) { + self.tree_items.get(real_idx).map(|ti| ti.parent_path.clone()) + } else { + None + }; + let mut count = 0; for ti in &self.tree_items { if ti.visible && ti.item.is_snapshot() { - let name = ti.item.full_name().to_string(); - if !self.marked.contains(&name) { - self.marked.push(name); - count += 1; + let in_scope = match ¤t_parent { + Some(parent) => &ti.parent_path == parent, + None => true, + }; + + if in_scope { + let name = ti.item.full_name().to_string(); + if !self.marked.contains(&name) { + self.marked.push(name); + count += 1; + } } } } @@ -577,9 +590,23 @@ impl App { } pub fn unselect_group(&mut self) { + let current_parent = if let Some(real_idx) = self.nth_visible(self.selected) { + self.tree_items.get(real_idx).map(|ti| ti.parent_path.clone()) + } else { + None + }; + let visible_names: Vec = self.tree_items .iter() - .filter(|ti| ti.visible && ti.item.is_snapshot()) + .filter(|ti| { + if !ti.visible || !ti.item.is_snapshot() { + return false; + } + match ¤t_parent { + Some(parent) => &ti.parent_path == parent, + None => true, + } + }) .map(|ti| ti.item.full_name().to_string()) .collect(); @@ -590,17 +617,34 @@ impl App { } pub fn invert_selection(&mut self) { + // Get current scope (parent dataset of selected item) + let current_parent = if let Some(real_idx) = self.nth_visible(self.selected) { + self.tree_items.get(real_idx).map(|ti| ti.parent_path.clone()) + } else { + None + }; + + let mut count = 0; for ti in &self.tree_items { + // Only invert in current scope (same parent) if ti.visible && ti.item.is_snapshot() { - let name = ti.item.full_name().to_string(); - if let Some(pos) = self.marked.iter().position(|x| x == &name) { - self.marked.remove(pos); - } else { - self.marked.push(name); + let in_scope = match ¤t_parent { + Some(parent) => &ti.parent_path == parent, + None => true, // If no parent, work on all visible + }; + + if in_scope { + let name = ti.item.full_name().to_string(); + if let Some(pos) = self.marked.iter().position(|x| x == &name) { + self.marked.remove(pos); + } else { + self.marked.push(name); + count += 1; + } } } } - self.message = Some(format!("{} snapshot(s) marked", self.marked.len())); + self.message = Some(format!("Inverted {} in scope", count)); } // Expand all datasets diff --git a/src/main.rs b/src/main.rs index 529293d..41a9ec5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,7 +75,7 @@ fn print_help() { println!(" ↑/k, ↓/j Navigate up/down"); println!(" Enter/l Expand/collapse dataset"); println!(" Space Mark/unmark snapshot"); - println!(" +/-/* Select/unselect/invert"); + println!(" +/-/* Select/unselect/invert (in scope)"); println!(" s Toggle sort (Size/Date/Name)"); println!(" / Search"); println!(" f Filter"); @@ -88,6 +88,9 @@ fn print_help() { println!(); println!("CONFIG:"); println!(" ~/.config/zfsdu/config.toml"); + println!(); + println!("(c) Florian Schermer - DATAZONE GmbH"); + println!("https://datazone.de"); } fn run_app(terminal: &mut Terminal, app: &mut App) -> Result<()> { diff --git a/src/ui.rs b/src/ui.rs index 8fa5d4a..aa3e063 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -407,11 +407,11 @@ fn draw_help(f: &mut Frame, app: &App) { " e Expand all", " c Collapse all", "", - " Selection:", + " Selection (current scope):", " Space Mark/unmark snapshot", - " + Select all visible snapshots", - " - Unselect all visible snapshots", - " * Invert selection", + " + Select all in scope", + " - Unselect all in scope", + " * Invert selection in scope", "", " Search & Filter:", " / Search (n=next, N=prev)", @@ -431,6 +431,9 @@ fn draw_help(f: &mut Frame, app: &App) { "", " Config: ~/.config/zfsdu/config.toml", "", + " (c) Florian Schermer - DATAZONE GmbH", + " https://datazone.de", + "", " Press any key to close", ];