wisp/components/
thought_message.rs1use tui::{Line, Style, Theme, ViewContext};
2
3pub struct ThoughtMessage<'a> {
4 pub text: &'a str,
5}
6
7impl ThoughtMessage<'_> {
8 fn format_line(text: &str, theme: &Theme) -> Line {
9 Line::with_style(text, Style::fg(theme.muted()).italic())
10 }
11
12 fn format_lines(text: &str, theme: &Theme) -> Vec<Line> {
13 text.lines().map(|line| Self::format_line(line, theme)).collect()
14 }
15}
16
17impl ThoughtMessage<'_> {
18 pub fn render(&self, context: &ViewContext) -> Vec<Line> {
19 if self.text.is_empty() {
20 return vec![];
21 }
22
23 Self::format_lines(self.text, &context.theme)
24 }
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30
31 #[test]
32 fn renders_italic_muted_thought_line() {
33 let component = ThoughtMessage { text: "check plan" };
34 let context = ViewContext::new((80, 24));
35 let lines = component.render(&context);
36 assert_eq!(lines.len(), 1);
37 assert_eq!(lines[0].plain_text(), "check plan");
38 let style = lines[0].spans()[0].style();
39 assert_eq!(style.fg, Some(context.theme.muted()));
40 assert!(style.italic);
41 }
42
43 #[test]
44 fn renders_all_lines_as_italic_muted() {
45 let component = ThoughtMessage { text: "line one\nline two" };
46 let context = ViewContext::new((80, 24));
47 let lines = component.render(&context);
48 assert_eq!(lines.len(), 2);
49 assert_eq!(lines[0].plain_text(), "line one");
50 assert_eq!(lines[1].plain_text(), "line two");
51 for line in &lines {
52 let style = line.spans()[0].style();
53 assert_eq!(style.fg, Some(context.theme.muted()));
54 assert!(style.italic);
55 }
56 }
57
58 #[test]
59 fn wrapped_continuation_rows_remain_italic_muted() {
60 let component = ThoughtMessage { text: "abcdefghijklmnopqrstuvwxyz" };
61 let context = ViewContext::new((80, 24));
62 let lines = component.render(&context);
63 let wrapped = lines[0].soft_wrap(12);
64 assert!(wrapped.len() > 1);
65
66 for row in wrapped.iter().skip(1) {
67 assert!(!row.spans().is_empty());
68 assert!(
69 row.spans()
70 .iter()
71 .all(|span| { span.style().fg == Some(context.theme.muted()) && span.style().italic })
72 );
73 }
74 }
75}