stylish_stringlike/widget/
text_widget.rs

1use crate::text::{HasWidth, Width};
2use crate::widget::{Truncateable, TruncationStrategy};
3use std::borrow::Cow;
4use std::ops::Deref;
5
6/// Widgets that can be truncated to fit in a provided width.
7pub trait Fitable<T: Truncateable>: HasWidth {
8    /// Truncate self to fit in a given width.
9    fn truncate(&self, width: usize) -> Option<T>;
10}
11
12/// A widget that can be truncated
13pub struct TextWidget<'a, T: Clone, U: Clone> {
14    text: Cow<'a, T>,
15    truncation_strategy: Cow<'a, U>,
16}
17
18impl<'a, T: Clone, U: Clone> TextWidget<'a, T, U> {
19    pub fn new(text: Cow<'a, T>, truncation_strategy: Cow<'a, U>) -> Self {
20        TextWidget {
21            text,
22            truncation_strategy,
23        }
24    }
25}
26
27impl<'a, T: Clone, U: Clone> Fitable<T::Output> for TextWidget<'a, T, U>
28where
29    T: Truncateable,
30    U: TruncationStrategy<T>,
31    T::Output: Truncateable,
32{
33    fn truncate(&self, width: usize) -> Option<T::Output> {
34        self.truncation_strategy.truncate(self.text.deref(), width)
35    }
36}
37
38impl<'a, T: Clone, U: Clone> HasWidth for TextWidget<'a, T, U>
39where
40    T: HasWidth,
41{
42    fn width(&self) -> Width {
43        self.text.width()
44    }
45}
46
47#[cfg(test)]
48mod test {
49    use super::*;
50    use crate::text::*;
51    use crate::widget::TruncationStyle;
52    use std::borrow::Cow;
53    #[test]
54    fn truncate_widget() {
55        let fmt_1 = Tag::new("<1>", "</1>");
56        let fmt_2 = Tag::new("<2>", "</2>");
57        let fmt_3 = Tag::new("<3>", "</3>");
58        let mut spans: Spans<Tag> = Default::default();
59        spans.push(&Span::new(Cow::Borrowed(&fmt_2), Cow::Borrowed("01234")));
60        spans.push(&Span::new(Cow::Borrowed(&fmt_3), Cow::Borrowed("56789")));
61        let truncator = {
62            let mut ellipsis = Spans::<Tag>::default();
63            ellipsis.push(&Span::new(Cow::Borrowed(&fmt_1), Cow::Borrowed("...")));
64            TruncationStyle::Left(ellipsis)
65        };
66        let widget = TextWidget::new(Cow::Borrowed(&spans), Cow::Borrowed(&truncator));
67        let actual = format!("{}", widget.truncate(9).unwrap());
68        let expected = String::from("<2>01234</2><3>5</3><1>...</1>");
69        assert_eq!(expected, actual);
70    }
71}