use std::{
io::{self, stdout},
path::PathBuf,
process,
};
use crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{backend::CrosstermBackend, Terminal};
use tui_file_explorer::{render_themed, ExplorerOutcome, FileExplorer, Theme};
fn main() {
let extensions: Vec<String> = std::env::args().skip(1).collect();
match run(extensions) {
Ok(Some(path)) => {
println!("{}", path.display());
process::exit(0);
}
Ok(None) => {
process::exit(1);
}
Err(e) => {
eprintln!("error: {e}");
process::exit(2);
}
}
}
fn run(extensions: Vec<String>) -> io::Result<Option<PathBuf>> {
let start = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("/"));
let mut explorer = FileExplorer::builder(start)
.extension_filter(extensions)
.build();
let theme = Theme::grape();
enable_raw_mode()?;
let mut stdout = stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let result = event_loop(&mut terminal, &mut explorer, &theme);
let _ = disable_raw_mode();
let _ = execute!(
terminal.backend_mut(),
LeaveAlternateScreen,
DisableMouseCapture,
);
let _ = terminal.show_cursor();
result
}
fn event_loop(
terminal: &mut Terminal<CrosstermBackend<std::io::Stdout>>,
explorer: &mut FileExplorer,
theme: &Theme,
) -> io::Result<Option<PathBuf>> {
loop {
terminal.draw(|frame| {
render_themed(explorer, frame, frame.area(), theme);
})?;
let Event::Key(key) = event::read()? else {
continue;
};
match explorer.handle_key(key) {
ExplorerOutcome::Selected(path) => return Ok(Some(path)),
ExplorerOutcome::Dismissed => return Ok(None),
ExplorerOutcome::Pending | ExplorerOutcome::Unhandled => {}
}
}
}