Add scope-based selection and credits
- Selection keys (+/-/*) now work on current scope (parent dataset) - Add author credits: Florian Schermer, DATAZONE GmbH - Update help text and README with scope documentation
This commit is contained in:
parent
1bf3235f9e
commit
194b81bbcf
13
README.md
13
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.
|
||||
|
||||
50
src/app.rs
50
src/app.rs
@ -561,11 +561,23 @@ 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 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);
|
||||
@ -573,13 +585,28 @@ impl App {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.message = Some(format!("Selected {} snapshot(s)", count));
|
||||
}
|
||||
|
||||
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<String> = 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 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
|
||||
|
||||
@ -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<B: ratatui::backend::Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Result<()> {
|
||||
|
||||
11
src/ui.rs
11
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",
|
||||
];
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user