Skip to content

Commit 9c9e15c

Browse files
committed
feat: add Skim::run_items API
1 parent 396f295 commit 9c9e15c

File tree

4 files changed

+77
-1
lines changed

4 files changed

+77
-1
lines changed

examples/base.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use skim::prelude::*;
2+
3+
fn main() -> color_eyre::Result<()> {
4+
let opts = SkimOptionsBuilder::default().multi(true).reverse(true).build()?;
5+
let res = Skim::run_items(opts, ["hello", "world"])?;
6+
7+
for item in res.selected_items {
8+
println!("Selected {} (id {})", item.output(), item.get_index());
9+
}
10+
11+
Ok(())
12+
}

src/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub use crate::helper::selector::DefaultSkimSelector;
1313
pub use crate::options::{SkimOptions, SkimOptionsBuilder};
1414
pub use crate::output::SkimOutput;
1515
pub use crate::reader::CommandCollector;
16+
pub use crate::skim_item::Item;
1617
pub use crate::tui::{Event, PreviewCallback, event::Action};
1718
pub use crate::*;
1819
pub use kanal::{Receiver, Sender, bounded, unbounded};

src/skim.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use tokio::{runtime::Handle, select, task::block_in_place};
1111

1212
use crate::reader::{Reader, ReaderControl};
1313
use crate::tui::{App, Event, Size, Tui, event::Action};
14-
use crate::{SkimItemReceiver, SkimOptions, SkimOutput};
14+
use crate::{SkimItem, SkimItemReceiver, SkimOptions, SkimOutput};
1515

1616
/// Main entry point for running skim
1717
pub struct Skim<Backend = ratatui::backend::CrosstermBackend<BufWriter<Stderr>>>
@@ -79,6 +79,28 @@ impl Skim {
7979
Ok(output)
8080
}
8181

82+
/// Run skim with a Vec of items
83+
pub fn run_items<I, T>(options: SkimOptions, items: I) -> Result<SkimOutput>
84+
where
85+
I: IntoIterator<Item = T>,
86+
T: SkimItem,
87+
{
88+
const BATCH_SIZE: usize = 1024;
89+
let (tx, rx) = crate::prelude::unbounded();
90+
let mut batch: Vec<Arc<dyn SkimItem>> = Vec::with_capacity(BATCH_SIZE);
91+
for (idx, raw_item) in items.into_iter().enumerate() {
92+
if batch.len() == 1024 {
93+
tx.send(batch)?;
94+
batch = Vec::with_capacity(BATCH_SIZE);
95+
}
96+
let mut item = crate::prelude::Item::from(raw_item);
97+
item.set_index(idx);
98+
batch.push(Arc::new(item) as Arc<dyn SkimItem>);
99+
}
100+
tx.send(batch)?;
101+
Self::run_with(options, Some(rx))
102+
}
103+
82104
/// Initialize the TUI with the default crossterm backend, but do not enter it yet
83105
pub fn init_tui(&mut self) -> Result<()> {
84106
self.tui = Some(Tui::new_with_height(self.height)?);

src/skim_item.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,47 @@ impl<T: AsRef<str> + Send + Sync + 'static> SkimItem for T {
9797
}
9898
}
9999

100+
/// A basic SkimItem implementation for basic types
101+
pub struct Item<T: SkimItem> {
102+
inner: T,
103+
index: usize,
104+
}
105+
106+
impl<T: SkimItem> SkimItem for Item<T> {
107+
fn text(&self) -> Cow<'_, str> {
108+
self.inner.text()
109+
}
110+
fn display<'a>(&'a self, context: DisplayContext) -> Line<'a> {
111+
self.inner.display(context)
112+
}
113+
114+
fn preview(&self, context: PreviewContext) -> ItemPreview {
115+
self.inner.preview(context)
116+
}
117+
118+
fn output(&self) -> Cow<'_, str> {
119+
self.inner.output()
120+
}
121+
122+
fn get_matching_ranges(&self) -> Option<&[(usize, usize)]> {
123+
self.inner.get_matching_ranges()
124+
}
125+
126+
fn get_index(&self) -> usize {
127+
self.index
128+
}
129+
130+
fn set_index(&mut self, index: usize) {
131+
self.index = index;
132+
}
133+
}
134+
135+
impl<T: SkimItem> From<T> for Item<T> {
136+
fn from(value: T) -> Self {
137+
Self { inner: value, index: 0 }
138+
}
139+
}
140+
100141
impl Display for dyn SkimItem {
101142
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102143
f.write_str(&self.text())

0 commit comments

Comments
 (0)