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}