extern crate skim;
use skim::prelude::*;

struct MyItem {
    inner: String,
}

impl SkimItem for MyItem {
    fn text(&self) -> Cow<'_, str> {
        Cow::Borrowed(&self.inner)
    }

    fn preview(&self, _context: PreviewContext) -> ItemPreview {
        if self.inner.starts_with("color") {
            ItemPreview::AnsiText(format!("\x1b[31mhello:\x1b[m\n{}", self.inner))
        } else {
            ItemPreview::Text(format!("hello:\n{}", self.inner))
        }
    }
}

fn main() {
    let options = SkimOptionsBuilder::default()
        .height(String::from("50%"))
        .multi(true)
        .preview(Some(String::new())) // preview should be specified to enable preview window
        .build()
        .unwrap();

    let (tx_item, rx_item): (SkimItemSender, SkimItemReceiver) = unbounded();
    let _ = tx_item.send(vec![
        Arc::new(MyItem {
            inner: "color aaaa".to_string(),
        }) as Arc<dyn SkimItem>,
        Arc::new(MyItem {
            inner: "bbbb".to_string(),
        }) as Arc<dyn SkimItem>,
        Arc::new(MyItem {
            inner: "ccc".to_string(),
        }) as Arc<dyn SkimItem>,
    ]);
    drop(tx_item); // so that skim could know when to stop waiting for more items.

    let selected_items = Skim::run_with(options, Some(rx_item))
        .map(|out| out.selected_items)
        .unwrap_or_default();

    for item in selected_items.iter() {
        println!("{}", item.output());
    }
}
