diff --git a/src/app/file_finder.rs b/src/app/file_finder.rs new file mode 100644 index 0000000..75d2682 --- /dev/null +++ b/src/app/file_finder.rs @@ -0,0 +1,78 @@ +use std::path::{Path, PathBuf}; + +use crossterm::event::Event; +use jocalsend::error::Result; +use ratatui::widgets::WidgetRef; +use ratatui_explorer::FileExplorer; +use simsearch::{SearchOptions, SimSearch}; +use tui_input::Input; + +#[derive(Clone)] +pub(crate) struct FileFinder { + pub explorer: FileExplorer, + pub fuzzy: SimSearch, + pub working_dir: Option, + pub input: Input, +} + +fn searcher() -> SimSearch { + SimSearch::new_with( + SearchOptions::new() + .stop_words(vec![std::path::MAIN_SEPARATOR_STR.to_string()]) + .stop_whitespace(false) + .threshold(0.0), + ) +} + +impl FileFinder { + pub fn new() -> Result { + Ok(Self { + explorer: FileExplorer::new()?, + fuzzy: searcher(), + working_dir: None, + input: Default::default(), + }) + } + + pub fn handle(&mut self, event: &Event) -> Result<()> { + self.index(); + Ok(self.explorer.handle(event)?) + } + + pub fn cwd(&self) -> &Path { + self.explorer.cwd() + } + + pub fn set_cwd(&mut self, cwd: &Path) -> Result<()> { + self.explorer.set_cwd(cwd)?; + self.index(); + Ok(()) + } + + pub fn widget(&self) -> impl WidgetRef { + self.explorer.widget() + } + + pub fn reset_fuzzy(&mut self) { + self.clear_fuzzy(); + self.input.reset(); + } + + fn clear_fuzzy(&mut self) { + self.fuzzy = searcher(); + } + + pub fn index(&mut self) { + if let Some(owd) = self.working_dir.as_ref() + && owd == self.cwd() + { + return; + } + self.working_dir = Some(self.cwd().to_path_buf()); + self.clear_fuzzy(); + + for (i, f) in self.explorer.files().iter().enumerate() { + self.fuzzy.insert(i, f.name()); + } + } +} diff --git a/src/app/mod.rs b/src/app/mod.rs index 80c46a8..8f06714 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,8 +1,4 @@ -use std::{ - collections::BTreeMap, - net::SocketAddr, - path::{Path, PathBuf}, -}; +use std::{collections::BTreeMap, net::SocketAddr}; use crossterm::event::{Event, EventStream, KeyEventKind}; use futures::{FutureExt, StreamExt}; @@ -11,15 +7,16 @@ use julid::Julid; use log::LevelFilter; use ratatui::{ Frame, - widgets::{ListState, TableState, WidgetRef}, + widgets::{ListState, TableState}, }; use ratatui_explorer::FileExplorer; -use simsearch::{SearchOptions, SimSearch}; use tokio::sync::mpsc::UnboundedReceiver; use tui_input::Input; pub mod widgets; +mod file_finder; +use file_finder::FileFinder; mod handle; #[derive(Debug, Clone, PartialEq, Eq)] @@ -29,26 +26,9 @@ pub struct Peer { pub addr: SocketAddr, } -#[derive(Clone)] -struct FileFinder { - explorer: FileExplorer, - fuzzy: SimSearch, - working_dir: Option, - input: Input, -} - -fn searcher() -> SimSearch { - SimSearch::new_with( - SearchOptions::new() - .stop_words(vec![std::path::MAIN_SEPARATOR_STR.to_string()]) - .stop_whitespace(false) - .threshold(0.0), - ) -} - pub struct App { pub service: JocalService, - pub events: EventStream, + pub terminal_events: EventStream, pub peers: Vec, pub peer_state: ListState, pub receive_requests: BTreeMap, @@ -56,7 +36,7 @@ pub struct App { receiving_state: TableState, // for getting messages back from the web server or web client about things we've done; the // other end is held by the service - event_listener: UnboundedReceiver, + jocal_event_rx: UnboundedReceiver, file_finder: FileFinder, text: Option, input: Input, @@ -89,11 +69,11 @@ impl App { pub fn new(service: JocalService, event_listener: UnboundedReceiver) -> Self { App { service, - event_listener, + jocal_event_rx: event_listener, screen: vec![CurrentScreen::Main], file_finder: FileFinder::new().expect("could not create file explorer"), text: None, - events: Default::default(), + terminal_events: Default::default(), peers: Default::default(), peer_state: Default::default(), receive_requests: Default::default(), @@ -104,7 +84,7 @@ impl App { pub async fn handle_events(&mut self) -> Result<()> { tokio::select! { - event = self.events.next().fuse() => { + event = self.terminal_events.next().fuse() => { if let Some(Ok(evt)) = event { match evt { Event::Key(key) @@ -116,7 +96,7 @@ impl App { } } } - transfer_event = self.event_listener.recv().fuse() => { + transfer_event = self.jocal_event_rx.recv().fuse() => { if let Some(event) = transfer_event { log::trace!("got JocalEvent {event:?}"); match event { @@ -163,59 +143,6 @@ impl App { } } -impl FileFinder { - pub fn new() -> Result { - Ok(Self { - explorer: FileExplorer::new()?, - fuzzy: searcher(), - working_dir: None, - input: Default::default(), - }) - } - - pub fn handle(&mut self, event: &Event) -> Result<()> { - self.index(); - Ok(self.explorer.handle(event)?) - } - - pub fn cwd(&self) -> &Path { - self.explorer.cwd() - } - - pub fn set_cwd(&mut self, cwd: &Path) -> Result<()> { - self.explorer.set_cwd(cwd)?; - self.index(); - Ok(()) - } - - pub fn widget(&self) -> impl WidgetRef { - self.explorer.widget() - } - - pub fn reset_fuzzy(&mut self) { - self.clear_fuzzy(); - self.input.reset(); - } - - fn clear_fuzzy(&mut self) { - self.fuzzy = searcher(); - } - - fn index(&mut self) { - if let Some(owd) = self.working_dir.as_ref() - && owd == self.cwd() - { - return; - } - self.working_dir = Some(self.cwd().to_path_buf()); - self.clear_fuzzy(); - - for (i, f) in self.explorer.files().iter().enumerate() { - self.fuzzy.insert(i, f.name()); - } - } -} - fn change_log_level(delta: isize) { let level = log::max_level() as isize; let max = log::LevelFilter::max() as isize;