nossh/src/user_fuzzy_find.rs

62 lines
1.7 KiB
Rust

use skim::prelude::*;
use crate::{
ssh_config::{SshItem, SshItems},
state::State,
};
pub struct UserFuzzyFind {}
impl UserFuzzyFind {
pub async fn get_ssh_item_from_user<'a>(
&self,
items: &'a SshItems,
) -> anyhow::Result<&'a SshItem> {
let skim_options = SkimOptionsBuilder::default()
.no_multi(true)
.build()
.expect("failed to build skim config");
let (tx, rx): (SkimItemSender, SkimItemReceiver) = skim::prelude::unbounded();
for item in items.to_vec().into_iter().cloned() {
tx.send(Arc::new(item))
.expect("we should never have enough items that we exceed unbounded");
}
let chosen_items = Skim::run_with(&skim_options, Some(rx))
.and_then(|output| if output.is_abort { None } else { Some(output) })
.map(|item| item.selected_items)
.ok_or(anyhow::anyhow!("failed to find an ssh item"))?;
let chosen_item = chosen_items
.first()
.expect("there should never be more than 1 skip item");
let output = chosen_item.output();
let chosen_ssh_item = items
.get_choice(&output) // Cow, str, String
.expect("always find an ssh item from a choice");
tracing::debug!("the user chose item: {chosen_ssh_item:#?}");
Ok(chosen_ssh_item)
}
}
pub trait UserFuzzyFindState {
fn user_fuzzy_find(&self) -> UserFuzzyFind;
}
impl UserFuzzyFindState for State {
fn user_fuzzy_find(&self) -> UserFuzzyFind {
UserFuzzyFind {}
}
}
impl SkimItem for SshItem {
fn text(&'_ self) -> std::borrow::Cow<'_, str> {
format!("{self}").into()
}
}