pub trait SkimItem:
AsAny
+ Send
+ Sync
+ 'static {
// Required method
fn text(&self) -> Cow<'_, str>;
// Provided methods
fn display(&self, context: DisplayContext<'_>) -> AnsiString { ... }
fn preview(&self, _context: PreviewContext<'_>) -> ItemPreview { ... }
fn output(&self) -> Cow<'_, str> { ... }
fn get_matching_ranges(&self) -> Option<&[(usize, usize)]> { ... }
}Expand description
A SkimItem defines what’s been processed(fetched, matched, previewed and returned) by skim
§Downcast Example
Skim will return the item back, but in Arc<dyn SkimItem> form. We might want a reference
to the concrete type instead of trait object. Skim provide a somehow “complicated” way to
downcast it back to the reference of the original concrete type.
use skim::prelude::*;
struct MyItem {}
impl SkimItem for MyItem {
fn text(&self) -> Cow<str> {
unimplemented!()
}
}
impl MyItem {
pub fn mutable(&mut self) -> i32 {
1
}
pub fn immutable(&self) -> i32 {
0
}
}
let mut ret: Arc<dyn SkimItem> = Arc::new(MyItem{});
let mutable: &mut MyItem = Arc::get_mut(&mut ret)
.expect("item is referenced by others")
.as_any_mut() // cast to Any
.downcast_mut::<MyItem>() // downcast to (mut) concrete type
.expect("something wrong with downcast");
assert_eq!(mutable.mutable(), 1);
let immutable: &MyItem = (*ret).as_any() // cast to Any
.downcast_ref::<MyItem>() // downcast to concrete type
.expect("something wrong with downcast");
assert_eq!(immutable.immutable(), 0)Required Methods§
Provided Methods§
sourcefn display(&self, context: DisplayContext<'_>) -> AnsiString
fn display(&self, context: DisplayContext<'_>) -> AnsiString
The content to be displayed on the item list, could contain ANSI properties
sourcefn preview(&self, _context: PreviewContext<'_>) -> ItemPreview
fn preview(&self, _context: PreviewContext<'_>) -> ItemPreview
Custom preview content, default to ItemPreview::Global which will use global preview
setting(i.e. the command set by preview option)
sourcefn output(&self) -> Cow<'_, str>
fn output(&self) -> Cow<'_, str>
Get output text(after accept), default to text()
Note that this function is intended to be used by the caller of skim and will not be used by
skim. And since skim will return the item back in SkimOutput, if string is not what you
want, you could still use downcast to retain the pointer to the original struct.
Examples found in repository?
More examples
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
pub fn main() {
let input = "foo 123";
let options = SkimOptionsBuilder::default().query(Some("f")).build().unwrap();
let item_reader = SkimItemReader::new(SkimItemReaderOption::default().nth("2").build());
let (items, opt_ingest_handle) = item_reader.of_bufread(Box::new(Cursor::new(input)));
let selected_items = Skim::run_with(&options, Some(items))
.map(|out| out.selected_items)
.unwrap_or_else(Vec::new);
for item in selected_items.iter() {
println!("{}", item.output());
}
if let Some(handle) = opt_ingest_handle {
let _ = handle.join();
}
}22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
pub fn main() {
let options = SkimOptionsBuilder::default()
.height(Some("50%"))
.multi(true)
.preview(Some("")) // preview should be specified to enable preview window
.build()
.unwrap();
let (tx_item, rx_item): (SkimItemSender, SkimItemReceiver) = unbounded();
let _ = tx_item.send(Arc::new(MyItem {
inner: "color aaaa".to_string(),
}));
let _ = tx_item.send(Arc::new(MyItem {
inner: "bbbb".to_string(),
}));
let _ = tx_item.send(Arc::new(MyItem {
inner: "ccc".to_string(),
}));
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_else(Vec::new);
for item in selected_items.iter() {
println!("{}", item.output());
}
}5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
pub fn main() {
let options = SkimOptionsBuilder::default()
.height(Some("50%"))
.multi(true)
.build()
.unwrap();
let item_reader = SkimItemReader::default();
//==================================================
// first run
let input = "aaaaa\nbbbb\nccc";
let (items, opt_ingest_handle) = item_reader.of_bufread(Box::new(Cursor::new(input)));
let selected_items = Skim::run_with(&options, Some(items))
.map(|out| out.selected_items)
.unwrap_or_else(Vec::new);
for item in selected_items.iter() {
println!("{}", item.output());
}
if let Some(handle) = opt_ingest_handle {
let _ = handle.join();
}
//==================================================
// second run
let input = "11111\n22222\n333333333";
let (items, opt_ingest_handle) = item_reader.of_bufread(Box::new(Cursor::new(input)));
let selected_items = Skim::run_with(&options, Some(items))
.map(|out| out.selected_items)
.unwrap_or_else(Vec::new);
for item in selected_items.iter() {
println!("{}", item.output());
}
if let Some(handle) = opt_ingest_handle {
let _ = handle.join();
}
}sourcefn get_matching_ranges(&self) -> Option<&[(usize, usize)]>
fn get_matching_ranges(&self) -> Option<&[(usize, usize)]>
we could limit the matching ranges of the get_text of the item.
providing (start_byte, end_byte) of the range