stylish_stringlike/widget/
text_widget.rs1use crate::text::{HasWidth, Width};
2use crate::widget::{Truncateable, TruncationStrategy};
3use std::borrow::Cow;
4use std::ops::Deref;
5
6pub trait Fitable<T: Truncateable>: HasWidth {
8 fn truncate(&self, width: usize) -> Option<T>;
10}
11
12pub 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}