use crate::error;
use crate::models;
use crate::picker;
use error::PickerError;
use models::ResultWithDefaultError;
use picker::{ItemPicker, PickableItem, PickableItemKey};
use skim::prelude::*;
pub struct SkimPicker;
fn get_skim_configuration(items: Vec<PickableItem>) -> (SkimOptions<'static>, SkimItemReceiver) {
let options = SkimOptionsBuilder::default()
.height(Some("100%"))
.multi(false)
.build()
.unwrap();
let (sender, source): (SkimItemSender, SkimItemReceiver) = unbounded();
for item in items {
let _ = sender.send(Arc::new(item));
}
drop(sender);
(options, source)
}
impl SkimItem for PickableItem {
fn text(&self) -> Cow<str> {
Cow::from(self.formatted.as_str())
}
fn output(&self) -> Cow<str> {
Cow::from(self.key.to_string())
}
}
impl ItemPicker for SkimPicker {
fn pick(&self, items: Vec<PickableItem>) -> ResultWithDefaultError<PickableItemKey> {
let (options, source) = get_skim_configuration(items);
let output = Skim::run_with(&options, Some(source));
match output {
None => Err(Box::new(PickerError::Cancelled)),
Some(item) => {
if item.is_abort {
Err(Box::new(PickerError::Cancelled))
} else {
let selectable_items = item
.selected_items
.iter()
.map(|selected_items| {
selected_items.output().parse::<PickableItemKey>().unwrap()
})
.collect::<Vec<PickableItemKey>>();
match selectable_items.first() {
None => Err(Box::new(PickerError::Generic)),
Some(id) => Ok(id.clone()),
}
}
}
}
}
}