use ratatui::text::Line;
use std::borrow::Cow;
use std::fmt::{Debug, Display};
use crate::{AsAny, DisplayContext, ItemPreview, PreviewContext};
pub trait SkimItem: AsAny + Send + Sync + 'static {
fn text(&self) -> Cow<'_, str>;
fn display(&self, context: DisplayContext) -> Line<'_> {
context.to_line(self.text())
}
fn preview(&self, _context: PreviewContext) -> ItemPreview {
ItemPreview::Global
}
fn output(&self) -> Cow<'_, str> {
self.text()
}
fn get_matching_ranges(&self) -> Option<&[(usize, usize)]> {
None
}
fn disabled(&self) -> bool {
false
}
}
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()))
}
}
#[cfg(test)]
#[cfg_attr(coverage, coverage(off))]
mod tests {
use super::*;
use std::sync::Arc;
#[test]
fn blanket_impl_default_methods() {
let item = "hello".to_string();
assert_eq!(item.text(), "hello");
assert_eq!(item.output(), "hello");
assert!(item.get_matching_ranges().is_none());
assert!(!item.disabled());
}
#[test]
fn display_and_debug_for_trait_object() {
let item: Arc<dyn SkimItem> = Arc::new("world".to_string());
let as_dyn: &dyn SkimItem = &*item;
assert_eq!(format!("{as_dyn}"), "world");
assert!(format!("{as_dyn:?}").contains("world"));
}
}