Skip to content

Commit

Permalink
Move TerminalApp to separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrwach committed Jan 7, 2024
1 parent cf3c507 commit 5123cf5
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 163 deletions.
162 changes: 1 addition & 161 deletions src/interactive/app/eventloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,166 +337,6 @@ where
Ok(())
}

/// State and methods representing the interactive disk usage analyser for the terminal
pub struct TerminalApp {
pub traversal: Traversal,
pub display: DisplayOptions,
pub state: AppState,
pub window: MainWindow,
}

type KeyboardInputAndApp = (crossbeam::channel::Receiver<Event>, TerminalApp);

impl TerminalApp {
pub fn refresh_view<B>(&mut self, terminal: &mut Terminal<B>)
where
B: Backend,
{
// Use an event that does nothing to trigger a refresh
self.state
.process_events(
&mut self.window,
&mut self.traversal,
&mut self.display,
terminal,
std::iter::once(Event::Key(refresh_key())),
)
.ok();
}

pub fn process_events<B>(
&mut self,
terminal: &mut Terminal<B>,
events: impl Iterator<Item = Event>,
) -> Result<WalkResult>
where
B: Backend,
{
match self.state.process_events(
&mut self.window,
&mut self.traversal,
&mut self.display,
terminal,
events,
)? {
ProcessingResult::Finished(res) | ProcessingResult::ExitRequested(res) => Ok(res),
}
}

pub fn initialize<B>(
terminal: &mut Terminal<B>,
options: WalkOptions,
input_paths: Vec<PathBuf>,
keys_rx: Receiver<Event>,
) -> Result<Option<KeyboardInputAndApp>>
where
B: Backend,
{
terminal.hide_cursor()?;
terminal.clear()?;

let mut display: DisplayOptions = options.clone().into();
display.byte_vis = ByteVisualization::PercentageAndBar;

let mut window = MainWindow::default();

// #[inline]
// fn fetch_buffered_key_events(keys_rx: &Receiver<Event>) -> Vec<Event> {
// let mut keys = Vec::new();
// while let Ok(key) = keys_rx.try_recv() {
// keys.push(key);
// }
// keys
// }

let mut state = AppState {
is_scanning: false,
..Default::default()
};

// let mut received_events = false;
// let traversal =
// Traversal::from_walk(options, input_paths, &keys_rx, |traversal, event| {
// if !received_events {
// state.navigation_mut().view_root = traversal.root_index;
// }
// state.entries = sorted_entries(
// &traversal.tree,
// state.navigation().view_root,
// state.sorting,
// state.glob_root(),
// );
// if !received_events {
// state.navigation_mut().selected = state.entries.first().map(|b| b.index);
// }
// state.reset_message(); // force "scanning" to appear

// let mut events = fetch_buffered_key_events(&keys_rx);
// if let Some(event) = event {
// // This update is triggered by a user event, insert it
// // before any events fetched later.
// events.insert(0, event);
// }
// received_events |= !events.is_empty();

// let should_exit = match state.process_events(
// &mut window,
// traversal,
// &mut display,
// terminal,
// events.into_iter(),
// )? {
// ProcessingResult::ExitRequested(_) => true,
// ProcessingResult::Finished(_) => false,
// };

// Ok(should_exit)
// })?;

// let traversal = match traversal {
// Some(t) => t,
// None => return Ok(None),
// };

// state.is_scanning = false;
// if !received_events {
// }

let traversal = {
let mut tree = Tree::new();
let root_index = tree.add_node(EntryData::default());
Traversal {
tree,
root_index,
entries_traversed: 0,
start: std::time::Instant::now(),
elapsed: None,
io_errors: 0,
total_bytes: None,
}
};

state.navigation_mut().view_root = traversal.root_index;
state.entries = sorted_entries(
&traversal.tree,
state.navigation().view_root,
state.sorting,
state.glob_root(),
);
state.navigation_mut().selected = state.entries.first().map(|b| b.index);

let mut app = TerminalApp {
state,
display,
traversal,
window,
};
app.refresh_view(terminal);

Ok(Some((keys_rx, app)))
}
}

fn refresh_key() -> KeyEvent {
pub fn refresh_key() -> KeyEvent {
KeyEvent::new(KeyCode::Char('\r'), KeyModifiers::ALT)
}
1 change: 1 addition & 0 deletions src/interactive/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod handlers;
pub mod input;
mod navigation;
pub mod tree_view;
pub mod terminal_app;

pub use bytevis::*;
pub use common::*;
Expand Down
173 changes: 173 additions & 0 deletions src/interactive/app/terminal_app.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
use std::path::PathBuf;

use crossbeam::channel::Receiver;
use crosstermion::input::Event;
use dua::{traverse::{Traversal, Tree, EntryData}, WalkResult, WalkOptions};
use tui::prelude::Backend;
use tui_react::Terminal;
use anyhow::Result;

use crate::interactive::widgets::MainWindow;

use super::{DisplayOptions, AppState, ProcessingResult, ByteVisualization, sorted_entries, refresh_key};


/// State and methods representing the interactive disk usage analyser for the terminal
pub struct TerminalApp {
pub traversal: Traversal,
pub display: DisplayOptions,
pub state: AppState,
pub window: MainWindow,
}

type KeyboardInputAndApp = (crossbeam::channel::Receiver<Event>, TerminalApp);

impl TerminalApp {
pub fn refresh_view<B>(&mut self, terminal: &mut Terminal<B>)
where
B: Backend,
{
// Use an event that does nothing to trigger a refresh
self.state
.process_events(
&mut self.window,
&mut self.traversal,
&mut self.display,
terminal,
std::iter::once(Event::Key(refresh_key())),
)
.ok();
}

pub fn process_events<B>(
&mut self,
terminal: &mut Terminal<B>,
events: impl Iterator<Item = Event>,
) -> Result<WalkResult>
where
B: Backend,
{
match self.state.process_events(
&mut self.window,
&mut self.traversal,
&mut self.display,
terminal,
events,
)? {
ProcessingResult::Finished(res) | ProcessingResult::ExitRequested(res) => Ok(res),
}
}

pub fn initialize<B>(
terminal: &mut Terminal<B>,
options: WalkOptions,
input_paths: Vec<PathBuf>,
keys_rx: Receiver<Event>,
) -> Result<Option<KeyboardInputAndApp>>
where
B: Backend,
{
terminal.hide_cursor()?;
terminal.clear()?;

let mut display: DisplayOptions = options.clone().into();
display.byte_vis = ByteVisualization::PercentageAndBar;

let mut window = MainWindow::default();

// #[inline]
// fn fetch_buffered_key_events(keys_rx: &Receiver<Event>) -> Vec<Event> {
// let mut keys = Vec::new();
// while let Ok(key) = keys_rx.try_recv() {
// keys.push(key);
// }
// keys
// }

let mut state = AppState {
is_scanning: false,
..Default::default()
};

// let mut received_events = false;
// let traversal =
// Traversal::from_walk(options, input_paths, &keys_rx, |traversal, event| {
// if !received_events {
// state.navigation_mut().view_root = traversal.root_index;
// }
// state.entries = sorted_entries(
// &traversal.tree,
// state.navigation().view_root,
// state.sorting,
// state.glob_root(),
// );
// if !received_events {
// state.navigation_mut().selected = state.entries.first().map(|b| b.index);
// }
// state.reset_message(); // force "scanning" to appear

// let mut events = fetch_buffered_key_events(&keys_rx);
// if let Some(event) = event {
// // This update is triggered by a user event, insert it
// // before any events fetched later.
// events.insert(0, event);
// }
// received_events |= !events.is_empty();

// let should_exit = match state.process_events(
// &mut window,
// traversal,
// &mut display,
// terminal,
// events.into_iter(),
// )? {
// ProcessingResult::ExitRequested(_) => true,
// ProcessingResult::Finished(_) => false,
// };

// Ok(should_exit)
// })?;

// let traversal = match traversal {
// Some(t) => t,
// None => return Ok(None),
// };

// state.is_scanning = false;
// if !received_events {
// }

let traversal = {
let mut tree = Tree::new();
let root_index = tree.add_node(EntryData::default());
Traversal {
tree,
root_index,
entries_traversed: 0,
start: std::time::Instant::now(),
elapsed: None,
io_errors: 0,
total_bytes: None,
}
};

state.navigation_mut().view_root = traversal.root_index;
state.entries = sorted_entries(
&traversal.tree,
state.navigation().view_root,
state.sorting,
state.glob_root(),
);
state.navigation_mut().selected = state.entries.first().map(|b| b.index);

let mut app = TerminalApp {
state,
display,
traversal,
window,
};
app.refresh_view(terminal);

Ok(Some((keys_rx, app)))
}
}
2 changes: 1 addition & 1 deletion src/interactive/app/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::{
use tui::backend::TestBackend;
use tui_react::Terminal;

use crate::interactive::{app::tests::FIXTURE_PATH, TerminalApp};
use crate::interactive::{app::tests::FIXTURE_PATH, terminal_app::TerminalApp};

pub fn into_keys<'a>(
codes: impl IntoIterator<Item = KeyCode> + 'a,
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::fs::OpenOptions;
use std::{fs, io, io::Write, path::PathBuf, process};

use crate::interactive::input::input_channel;
use crate::interactive::terminal_app::TerminalApp;

mod crossdev;
#[cfg(feature = "tui-crossplatform")]
Expand Down Expand Up @@ -53,7 +54,6 @@ fn main() -> Result<()> {
let res = match opt.command {
#[cfg(feature = "tui-crossplatform")]
Some(Interactive { input }) => {
use crate::interactive::{TerminalApp};
use anyhow::{anyhow, Context};
use crosstermion::terminal::{tui::new_terminal, AlternateRawScreen};

Expand Down

0 comments on commit 5123cf5

Please sign in to comment.