Skip to main content

zlayer_tui/
icons.rs

1use ratatui::prelude::*;
2
3pub const PENDING: char = '\u{25CB}';
4pub const RUNNING: char = '\u{25B6}';
5pub const COMPLETE: char = '\u{2713}';
6pub const FAILED: char = '\u{2717}';
7pub const STOPPING: char = '\u{25BC}';
8pub const STOPPED: char = '\u{25A0}';
9pub const PROGRESS_FILLED: char = '\u{2588}';
10pub const PROGRESS_EMPTY: char = '\u{2591}';
11pub const ARROW_UP: char = '\u{2191}';
12pub const ARROW_DOWN: char = '\u{2193}';
13
14pub const SPINNER_FRAMES: &[char] = &['|', '/', '-', '\\'];
15
16#[must_use]
17pub fn status_icon(done: bool, running: bool, failed: bool) -> (char, Style) {
18    if failed {
19        (FAILED, Style::default().fg(Color::Red))
20    } else if done {
21        (COMPLETE, Style::default().fg(Color::Green))
22    } else if running {
23        (
24            RUNNING,
25            Style::default()
26                .fg(Color::Yellow)
27                .add_modifier(Modifier::BOLD),
28        )
29    } else {
30        (PENDING, Style::default().fg(Color::DarkGray))
31    }
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    #[test]
39    fn icon_characters_are_correct() {
40        assert_eq!(PENDING, '○');
41        assert_eq!(RUNNING, '▶');
42        assert_eq!(COMPLETE, '✓');
43        assert_eq!(FAILED, '✗');
44        assert_eq!(STOPPING, '▼');
45        assert_eq!(STOPPED, '■');
46        assert_eq!(PROGRESS_FILLED, '█');
47        assert_eq!(PROGRESS_EMPTY, '░');
48        assert_eq!(ARROW_UP, '↑');
49        assert_eq!(ARROW_DOWN, '↓');
50    }
51
52    #[test]
53    fn spinner_frames_has_four_entries() {
54        assert_eq!(SPINNER_FRAMES.len(), 4);
55        assert_eq!(SPINNER_FRAMES[0], '|');
56        assert_eq!(SPINNER_FRAMES[3], '\\');
57    }
58
59    #[test]
60    fn status_icon_failed_takes_priority() {
61        let (icon, style) = status_icon(true, true, true);
62        assert_eq!(icon, FAILED);
63        assert_eq!(style.fg, Some(Color::Red));
64    }
65
66    #[test]
67    fn status_icon_done() {
68        let (icon, style) = status_icon(true, false, false);
69        assert_eq!(icon, COMPLETE);
70        assert_eq!(style.fg, Some(Color::Green));
71    }
72
73    #[test]
74    fn status_icon_running() {
75        let (icon, style) = status_icon(false, true, false);
76        assert_eq!(icon, RUNNING);
77        assert_eq!(style.fg, Some(Color::Yellow));
78        assert!(style.add_modifier.contains(Modifier::BOLD));
79    }
80
81    #[test]
82    fn status_icon_pending() {
83        let (icon, style) = status_icon(false, false, false);
84        assert_eq!(icon, PENDING);
85        assert_eq!(style.fg, Some(Color::DarkGray));
86    }
87}