mirror of
https://github.com/lotabout/skim.git
synced 2026-09-10 07:16:23 -04:00
103 lines
3.3 KiB
Rust
103 lines
3.3 KiB
Rust
use ratatui::text::Line;
|
|
use std::borrow::Cow;
|
|
use std::fmt::{Debug, Display};
|
|
|
|
use crate::{AsAny, DisplayContext, ItemPreview, PreviewContext};
|
|
|
|
/// 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.
|
|
///
|
|
/// ```rust
|
|
/// 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)
|
|
/// ```
|
|
pub trait SkimItem: AsAny + Send + Sync + 'static {
|
|
/// The string to be used for matching (without color)
|
|
fn text(&self) -> Cow<'_, str>;
|
|
|
|
/// The content to be displayed on the item list, could contain ANSI properties
|
|
fn display(&self, context: DisplayContext) -> Line<'_> {
|
|
context.to_line(self.text())
|
|
}
|
|
|
|
/// Custom preview content, default to `ItemPreview::Global` which will use global preview
|
|
/// setting(i.e. the command set by `preview` option)
|
|
fn preview(&self, _context: PreviewContext) -> ItemPreview {
|
|
ItemPreview::Global
|
|
}
|
|
|
|
/// 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.
|
|
fn output(&self) -> Cow<'_, str> {
|
|
self.text()
|
|
}
|
|
|
|
/// Limit the matching ranges of the `get_text` of the item.
|
|
/// providing (`start_byte`, `end_byte`) of the range
|
|
fn get_matching_ranges(&self) -> Option<&[(usize, usize)]> {
|
|
None
|
|
}
|
|
|
|
/// Returns true if the item should be disabled
|
|
/// Disabled items cannot be selected
|
|
fn disabled(&self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Implement SkimItem for raw strings
|
|
|
|
impl<T: AsRef<str> + Send + Sync + 'static> SkimItem for T {
|
|
fn text(&self) -> Cow<'_, str> {
|
|
Cow::Borrowed(self.as_ref())
|
|
}
|
|
}
|
|
|
|
impl Display for dyn SkimItem {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_str(&self.text())
|
|
}
|
|
}
|
|
impl Debug for dyn SkimItem {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_fmt(format_args!("SkimItem {{ text: {} }}", self.text()))
|
|
}
|
|
}
|