use crossterm::{
cursor,
event::{self, Event, KeyCode, KeyModifiers},
execute,
terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
};
use std::io;
use std::path::PathBuf;
use crate::app::App;
use crate::config::Config;
use crate::fs::EntryType;
use crate::ui;
pub fn path_finder(
current_dir: PathBuf,
entry_type: EntryType,
config: Config,
) -> io::Result<Option<PathBuf>> {
enable_raw_mode()?;
let mut stderr = io::stderr();
execute!(stderr, EnterAlternateScreen, cursor::Hide)?;
let result = path_finder_inner(&mut stderr, current_dir, entry_type, config);
execute!(stderr, cursor::Show, LeaveAlternateScreen)?;
disable_raw_mode()?;
result
}
fn path_finder_inner(
stderr: &mut io::Stderr,
current_dir: PathBuf,
entry_type: EntryType,
config: Config,
) -> io::Result<Option<PathBuf>> {
let mut app = App::new(current_dir, entry_type, config)?;
loop {
ui::render(stderr, &app)?;
match event::read()? {
Event::Key(key) => {
if key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL) {
return Ok(None);
}
if app.filtered_entries.is_empty() {
match key.code {
KeyCode::Esc => return Ok(None),
KeyCode::Char(ch) => app.push_input(ch),
KeyCode::Backspace => app.pop_input()?,
_ => {}
}
continue;
}
match key.code {
KeyCode::Esc => return Ok(None),
KeyCode::Up => app.move_up(),
KeyCode::Down => app.move_down(),
KeyCode::Tab => app.handle_tab()?,
KeyCode::Backspace | KeyCode::BackTab => app.pop_input()?,
KeyCode::Enter => {
if let Some(selected_path) = app.handle_enter() {
return Ok(Some(selected_path));
}
}
KeyCode::Char(ch) => app.push_input(ch),
_ => {}
}
}
Event::Resize(_, _) => {
continue;
}
_ => {}
}
}
}