summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Thiel <sebastian.thiel@icloud.com>2020-03-29 13:53:09 +0800
committerSebastian Thiel <sebastian.thiel@icloud.com>2020-03-29 13:53:09 +0800
commit758ea32b90547c9f9c8f3135f3e7fa422111e44a (patch)
tree41c2de282558ae6f907fd333ec291a585261e047
parent00e70066ea495af9464b9d12cfd8ef15a40c6584 (diff)
phase one of refactoring nearly complete
-rw-r--r--src/interactive/app/eventloop.rs125
-rw-r--r--src/interactive/app/handlers.rs305
-rw-r--r--src/traverse.rs4
3 files changed, 306 insertions, 128 deletions
diff --git a/src/interactive/app/eventloop.rs b/src/interactive/app/eventloop.rs
index c81960c..7dbe9f3 100644
--- a/src/interactive/app/eventloop.rs
+++ b/src/interactive/app/eventloop.rs
@@ -37,7 +37,113 @@ pub struct AppState {
pub bookmarks: BTreeMap<TreeIndex, TreeIndex>,
}
-impl AppState {}
+impl AppState {
+ pub fn draw<B>(
+ &mut self,
+ window: &mut MainWindow,
+ traversal: &Traversal,
+ display: DisplayOptions,
+ terminal: &mut Terminal<B>,
+ ) -> Result<(), Error>
+ where
+ B: Backend,
+ {
+ let props = MainWindowProps {
+ traversal: &traversal,
+ display,
+ state: &self,
+ };
+ draw_window(window, props, terminal)
+ }
+
+ pub fn process_events<B>(
+ &mut self,
+ window: &mut MainWindow,
+ traversal: &mut Traversal,
+ mut display: DisplayOptions,
+ mut terminal: Terminal<B>,
+ keys: impl Iterator<Item = Result<Key, io::Error>>,
+ ) -> Result<WalkResult, Error>
+ where
+ B: Backend,
+ {
+ use termion::event::Key::*;
+ use FocussedPane::*;
+
+ fn exit_now<B: Backend>(terminal: Terminal<B>) -> ! {
+ drop(terminal);
+ io::stdout().flush().ok();
+ // Exit 'quickly' to avoid having to wait for all memory to be freed by us.
+ // Let the OS do it - we have nothing to lose, literally.
+ std::process::exit(0);
+ }
+
+ self.draw(window, traversal, display, &mut terminal)?;
+ for key in keys.filter_map(Result::ok) {
+ match key {
+ Char('?') => self.toggle_help_pane(window),
+ Char('\t') => {
+ self.cycle_focus(window);
+ }
+ Ctrl('c') => exit_now(terminal),
+ Char('q') | Esc => match self.focussed {
+ Main => exit_now(terminal),
+ Mark => self.focussed = Main,
+ Help => {
+ self.focussed = Main;
+ window.help_pane = None
+ }
+ },
+ _ => {}
+ }
+
+ match self.focussed {
+ FocussedPane::Mark => {
+ self.dispatch_to_mark_pane(key, window, traversal, display, &mut terminal)
+ }
+ FocussedPane::Help => {
+ window.help_pane.as_mut().expect("help pane").key(key);
+ }
+ FocussedPane::Main => match key {
+ Char('O') => self.open_that(traversal),
+ Char(' ') => self.mark_entry(false, window, traversal),
+ Char('d') => self.mark_entry(true, window, traversal),
+ Char('u') | Char('h') | Backspace | Left => {
+ self.exit_node_with_traversal(traversal)
+ }
+ Char('o') | Char('l') | Char('\n') | Right => {
+ self.enter_node_with_traversal(traversal)
+ }
+ Ctrl('u') | PageUp => self.change_entry_selection(CursorDirection::PageUp),
+ Char('k') | Up => self.change_entry_selection(CursorDirection::Up),
+ Char('j') | Down => self.change_entry_selection(CursorDirection::Down),
+ Ctrl('d') | PageDown => self.change_entry_selection(CursorDirection::PageDown),
+ Char('s') => self.cycle_sorting(traversal),
+ Char('g') => display.byte_vis.cycle(),
+ _ => {}
+ },
+ };
+ self.draw(window, traversal, display, &mut terminal)?;
+ }
+ Ok(WalkResult {
+ num_errors: traversal.io_errors,
+ })
+ }
+}
+
+pub fn draw_window<B>(
+ window: &mut MainWindow,
+ props: MainWindowProps,
+ terminal: &mut Terminal<B>,
+) -> Result<(), Error>
+where
+ B: Backend,
+{
+ let area = terminal.pre_render()?;
+ window.render(props, area, terminal.current_buffer_mut());
+ terminal.post_render()?;
+ Ok(())
+}
/// State and methods representing the interactive disk usage analyser for the terminal
pub struct TerminalApp {
@@ -48,19 +154,6 @@ pub struct TerminalApp {
}
impl TerminalApp {
- pub fn draw_window<B>(
- window: &mut MainWindow,
- props: MainWindowProps,
- terminal: &mut Terminal<B>,
- ) -> Result<(), Error>
- where
- B: Backend,
- {
- let area = terminal.pre_render()?;
- window.render(props, area, terminal.current_buffer_mut());
- terminal.post_render()?;
- Ok(())
- }
pub fn draw<B>(&mut self, terminal: &mut Terminal<B>) -> Result<(), Error>
where
B: Backend,
@@ -70,7 +163,7 @@ impl TerminalApp {
display: self.display,
state: &self.state,
};
- Self::draw_window(&mut self.window, props, terminal)
+ draw_window(&mut self.window, props, terminal)
}
pub fn process_events<B>(
&mut self,
@@ -165,7 +258,7 @@ impl TerminalApp {
display: display_options,
state: &state,
};
- Self::draw_window(&mut window, props, terminal)
+ draw_window(&mut window, props, terminal)
})?;
let sorting = Default::default();
diff --git a/src/interactive/app/handlers.rs b/src/interactive/app/handlers.rs
index 103db4f..8c0df23 100644
--- a/src/interactive/app/handlers.rs
+++ b/src/interactive/app/handlers.rs
@@ -1,9 +1,10 @@
+use crate::interactive::widgets::MainWindow;
use crate::interactive::{
app::{FocussedPane::*, TerminalApp},
path_of, sorted_entries,
widgets::MarkMode,
widgets::{HelpPane, MarkPane},
- AppState, EntryDataBundle,
+ AppState, DisplayOptions, EntryDataBundle,
};
use dua::traverse::{Traversal, TreeIndex};
use itertools::Itertools;
@@ -39,6 +40,11 @@ impl AppState {
}
}
+ pub fn exit_node_with_traversal(&mut self, traversal: &Traversal) {
+ let entries = self.entries_for_exit_node(traversal);
+ self.exit_node(entries);
+ }
+
fn entries_for_exit_node(
&self,
traversal: &Traversal,
@@ -82,6 +88,11 @@ impl AppState {
})
}
+ pub fn enter_node_with_traversal(&mut self, traversal: &Traversal) {
+ let new_entries = self.entries_for_enter_node(traversal);
+ self.enter_node(new_entries)
+ }
+
pub fn enter_node(&mut self, entries_at_selected: Option<(TreeIndex, Vec<EntryDataBundle>)>) {
if let Some((previously_selected, new_entries)) = entries_at_selected {
match new_entries.get(
@@ -130,6 +141,175 @@ impl AppState {
self.sorting.toggle_size();
self.entries = sorted_entries(&traversal.tree, self.root, self.sorting);
}
+
+ pub fn reset_message(&mut self) {
+ self.message = None;
+ }
+
+ pub fn toggle_help_pane(&mut self, window: &mut MainWindow) {
+ self.focussed = match self.focussed {
+ Main | Mark => {
+ window.help_pane = Some(HelpPane::default());
+ Help
+ }
+ Help => {
+ window.help_pane = None;
+ Main
+ }
+ }
+ }
+ pub fn cycle_focus(&mut self, window: &mut MainWindow) {
+ if let Some(p) = window.mark_pane.as_mut() {
+ p.set_focus(false)
+ };
+ self.focussed = match (self.focussed, &window.help_pane, &mut window.mark_pane) {
+ (Main, Some(_), _) => Help,
+ (Help, _, Some(ref mut pane)) => {
+ pane.set_focus(true);
+ Mark
+ }
+ (Help, _, None) => Main,
+ (Mark, _, _) => Main,
+ (Main, None, None) => Main,
+ (Main, None, Some(ref mut pane)) => {
+ pane.set_focus(true);
+ Mark
+ }
+ };
+ }
+
+ pub fn dispatch_to_mark_pane<B>(
+ &mut self,
+ key: Key,
+ window: &mut MainWindow,
+ traversal: &mut Traversal,
+ display: DisplayOptions,
+ terminal: &mut Terminal<B>,
+ ) where
+ B: Backend,
+ {
+ let res = window.mark_pane.take().and_then(|p| p.key(key));
+ window.mark_pane = match res {
+ Some((pane, mode)) => match mode {
+ Some(MarkMode::Delete) => {
+ self.message = Some("Deleting entries...".to_string());
+ let mut entries_deleted = 0;
+ let res = pane.iterate_deletable_items(|mut pane, entry_to_delete| {
+ window.mark_pane = Some(pane);
+ self.draw(window, traversal, display, terminal).ok();
+ pane = window.mark_pane.take().expect("option to be filled");
+ match self.delete_entry(entry_to_delete, traversal) {
+ Ok(ed) => {
+ entries_deleted += ed;
+ self.message =
+ Some(format!("Deleted {} entries...", entries_deleted));
+ Ok(pane)
+ }
+ Err(c) => Err((pane, c)),
+ }
+ });
+ self.message = None;
+ res
+ }
+ None => Some(pane),
+ },
+ None => None,
+ };
+ if window.mark_pane.is_none() {
+ self.focussed = Main;
+ }
+ }
+
+ pub fn delete_entry(
+ &mut self,
+ index: TreeIndex,
+ traversal: &mut Traversal,
+ ) -> Result<usize, usize> {
+ let mut entries_deleted = 0;
+ if let Some(_entry) = traversal.tree.node_weight(index) {
+ let path_to_delete = path_of(&traversal.tree, index);
+ delete_directory_recursively(path_to_delete)?;
+ 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_deleted += 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_deleted)
+ }
+
+ fn set_root(&mut self, root: TreeIndex, traversal: &Traversal) {
+ self.root = root;
+ self.entries = sorted_entries(&traversal.tree, root, self.sorting);
+ }
+
+ fn recompute_sizes_recursively(&mut self, mut index: TreeIndex, traversal: &mut Traversal) {
+ loop {
+ traversal
+ .tree
+ .node_weight_mut(index)
+ .expect("valid index")
+ .size = traversal
+ .tree
+ .neighbors_directed(index, Direction::Outgoing)
+ .filter_map(|idx| traversal.tree.node_weight(idx).map(|w| w.size))
+ .sum();
+ match traversal
+ .tree
+ .neighbors_directed(index, Direction::Incoming)
+ .next()
+ {
+ None => break,
+ Some(parent) => index = parent,
+ }
+ }
+ traversal.total_bytes = traversal
+ .tree
+ .node_weight(traversal.root_index)
+ .map(|w| w.size);
+ }
+
+ pub fn mark_entry(
+ &mut self,
+ advance_cursor: bool,
+ window: &mut MainWindow,
+ traversal: &Traversal,
+ ) {
+ if let Some(index) = self.selected {
+ let is_dir = self
+ .entries
+ .iter()
+ .find(|e| e.index == index)
+ .unwrap()
+ .is_dir;
+ if let Some(pane) = window.mark_pane.take() {
+ window.mark_pane = pane.toggle_index(index, &traversal.tree, is_dir);
+ } else {
+ window.mark_pane = MarkPane::default().toggle_index(index, &traversal.tree, is_dir)
+ }
+ };
+ if advance_cursor {
+ self.change_entry_selection(CursorDirection::Down)
+ }
+ }
}
impl TerminalApp {
@@ -171,7 +351,7 @@ impl TerminalApp {
}
pub fn reset_message(&mut self) {
- self.state.message = None;
+ self.state.reset_message()
}
pub fn open_that(&self) {
@@ -197,129 +377,34 @@ impl TerminalApp {
}
pub fn mark_entry(&mut self, advance_cursor: bool) {
- if let Some(index) = self.state.selected {
- let is_dir = self
- .state
- .entries
- .iter()
- .find(|e| e.index == index)
- .unwrap()
- .is_dir;
- if let Some(pane) = self.window.mark_pane.take() {
- self.window.mark_pane = pane.toggle_index(index, &self.traversal.tree, is_dir);
- } else {
- self.window.mark_pane =
- MarkPane::default().toggle_index(index, &self.traversal.tree, is_dir)
- }
- };
- if advance_cursor {
- self.change_entry_selection(CursorDirection::Down)
- }
+ self.state
+ .mark_entry(advance_cursor, &mut self.window, &self.traversal)
}
fn set_root(&mut self, root: TreeIndex) {
- self.state.root = root;
- self.state.entries = sorted_entries(&self.traversal.tree, root, self.state.sorting);
+ self.state.set_root(root, &self.traversal);
}
pub fn delete_entry(&mut self, index: TreeIndex) -> Result<usize, usize> {
- let mut entries_deleted = 0;
- if let Some(_entry) = self.traversal.tree.node_weight(index) {
- let path_to_delete = path_of(&self.traversal.tree, index);
- delete_directory_recursively(path_to_delete)?;
- let parent_idx = self
- .traversal
- .tree
- .neighbors_directed(index, Direction::Incoming)
- .next()
- .expect("us being unable to delete the root index");
- let mut bfs = Bfs::new(&self.traversal.tree, index);
- while let Some(nx) = bfs.next(&self.traversal.tree) {
- self.traversal.tree.remove_node(nx);
- self.traversal.entries_traversed -= 1;
- entries_deleted += 1;
- }
- self.state.entries =
- sorted_entries(&self.traversal.tree, self.state.root, self.state.sorting);
- if self.traversal.tree.node_weight(self.state.root).is_none() {
- self.set_root(self.traversal.root_index);
- }
- if self
- .state
- .selected
- .and_then(|selected| self.state.entries.iter().find(|e| e.index == selected))
- .is_none()
- {
- self.state.selected = self.state.entries.get(0).map(|e| e.index);
- }
- self.recompute_sizes_recursively(parent_idx);
- }
- Ok(entries_deleted)
+ self.state.delete_entry(index, &mut self.traversal)
}
fn recompute_sizes_recursively(&mut self, mut index: TreeIndex) {
- loop {
- self.traversal
- .tree
- .node_weight_mut(index)
- .expect("valid index")
- .size = self
- .traversal
- .tree
- .neighbors_directed(index, Direction::Outgoing)
- .filter_map(|idx| self.traversal.tree.node_weight(idx).map(|w| w.size))
- .sum();
- match self
- .traversal
- .tree
- .neighbors_directed(index, Direction::Incoming)
- .next()
- {
- None => break,
- Some(parent) => index = parent,
- }
- }
- self.traversal.total_bytes = self
- .traversal
- .tree
- .node_weight(self.traversal.root_index)
- .map(|w| w.size);
+ self.state
+ .recompute_sizes_recursively(index, &mut self.traversal)
}
pub fn dispatch_to_mark_pane<B>(&mut self, key: Key, terminal: &mut Terminal<B>)
where
B: Backend,
{
- let res = self.window.mark_pane.take().and_then(|p| p.key(key));
- self.window.mark_pane = match res {
- Some((pane, mode)) => match mode {
- Some(MarkMode::Delete) => {
- self.state.message = Some("Deleting entries...".to_string());
- let mut entries_deleted = 0;
- let res = pane.iterate_deletable_items(|mut pane, entry_to_delete| {
- self.window.mark_pane = Some(pane);
- self.draw(terminal).ok();
- pane = self.window.mark_pane.take().expect("option to be filled");
- match self.delete_entry(entry_to_delete) {
- Ok(ed) => {
- entries_deleted += ed;
- self.state.message =
- Some(format!("Deleted {} entries...", entries_deleted));
- Ok(pane)
- }
- Err(c) => Err((pane, c)),
- }
- });
- self.state.message = None;
- res
- }
- None => Some(pane),
- },
- None => None,
- };
- if self.window.mark_pane.is_none() {
- self.state.focussed = Main;
- }
+ self.state.dispatch_to_mark_pane(
+ key,
+ &mut self.window,
+ &mut self.traversal,
+ self.display,
+ terminal,
+ );
}
}
diff --git a/src/traverse.rs b/src/traverse.rs
index ab4eff9..13e4761 100644
--- a/src/traverse.rs
+++ b/src/traverse.rs
@@ -37,7 +37,7 @@ impl Traversal {
pub fn from_walk(
mut walk_options: WalkOptions,
input: Vec<PathBuf>,
- mut update: impl FnMut(&Traversal) -> Result<(), Error>,
+ mut update: impl FnMut(&mut Traversal) -> Result<(), Error>,
) -> Result<Traversal, Error> {
fn set_size_or_panic(tree: &mut Tree, node_idx: TreeIndex, current_size_at_depth: u64) {
tree.node_weight_mut(node_idx)
@@ -178,7 +178,7 @@ impl Traversal {
last_seen_eid = eid;
last_checked = now;
- update(&t)?;
+ update(&mut t)?;
}
}
}