use crossterm::event::{self, Event};
use std::collections::HashMap;
pub trait Provider {
type Item;
fn title(&self) -> &str;
fn collect(&self) -> HashMap<String, Self::Item>;
fn launch(&self, item: &Self::Item);
}
fn wait_for_key() {
match crossterm::terminal::enable_raw_mode() {
Ok(_) => (),
Err(_) => return,
}
loop {
if let Ok(Event::Key(_)) = event::read() {
break;
}
}
let _ = crossterm::terminal::disable_raw_mode();
}
pub fn run_provider<P: Provider>(provider: P) -> i32 {
let title = provider.title();
let history = crate::history::History::from_title(title);
let items = provider.collect();
if items.is_empty() {
eprintln!("{}: no items found", title);
eprint!("Press any key to close.");
let _ = std::io::Write::flush(&mut std::io::stderr());
wait_for_key();
return 1;
}
let mut names: Vec<String> = items.keys().cloned().collect();
names.sort_unstable();
if let Some(ref history) = history {
history.do_sort(&mut names);
};
let history_items = history.as_ref().map(|h| h.items()).unwrap_or(&[]);
if let Some(selected) = crate::tui::search(names, title, history_items)
&& let Some(item) = items.get(&selected)
{
if let Some(mut history) = history {
history.save(&selected);
}
provider.launch(item);
}
0
}