Skip to main content

git_worktree_manager/
console.rs

1/// Console output formatting utilities.
2///
3/// Provides styled terminal output using the `console` crate.
4use console::{style, Style, Term};
5
6/// Print a styled header line.
7pub fn print_header(text: &str) {
8    let term = Term::stdout();
9    let _ = term.write_line(&format!("{}", style(text).cyan().bold()));
10}
11
12/// Print a styled success message.
13pub fn print_success(text: &str) {
14    let _ = Term::stdout().write_line(&format!("{}", style(text).green()));
15}
16
17/// Print a styled warning message.
18pub fn print_warning(text: &str) {
19    let _ = Term::stderr().write_line(&format!("{}", style(text).yellow()));
20}
21
22/// Print a styled error message.
23pub fn print_error(text: &str) {
24    let _ = Term::stderr().write_line(&format!("{}", style(text).red()));
25}
26
27/// Print dimmed text.
28pub fn print_dim(text: &str) {
29    let _ = Term::stdout().write_line(&format!("{}", style(text).dim()));
30}
31
32/// Status → color mapping used by list, tree, global_ops.
33pub fn status_style(status: &str) -> Style {
34    match status {
35        "active" => Style::new().green().bold(),
36        "clean" => Style::new().green(),
37        "modified" => Style::new().yellow(),
38        "merged" => Style::new().magenta(),
39        "pr-open" => Style::new().cyan(),
40        "busy" => Style::new().red().bold(),
41        "stale" => Style::new().red(),
42        _ => Style::new(),
43    }
44}
45
46/// Map worktree status string to a display icon.
47pub fn status_icon(status: &str) -> &'static str {
48    match status {
49        "active" => "●",
50        "clean" => "○",
51        "modified" => "◉",
52        "merged" => "✓",
53        "pr-open" => "⬆",
54        "busy" => "🔒",
55        "stale" => "x",
56        _ => "○",
57    }
58}
59
60/// Get current terminal width (fallback 80).
61pub fn terminal_width() -> usize {
62    Term::stdout().size().1 as usize
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_status_icon_all_variants() {
71        assert_eq!(status_icon("active"), "●");
72        assert_eq!(status_icon("clean"), "○");
73        assert_eq!(status_icon("modified"), "◉");
74        assert_eq!(status_icon("stale"), "x");
75    }
76
77    #[test]
78    fn test_status_icon_unknown_fallback() {
79        assert_eq!(status_icon("unknown"), "○");
80        assert_eq!(status_icon(""), "○");
81        assert_eq!(status_icon("something_else"), "○");
82    }
83
84    #[test]
85    fn test_status_style_known() {
86        // Just ensure no panic for all known statuses
87        let _ = status_style("active");
88        let _ = status_style("clean");
89        let _ = status_style("modified");
90        let _ = status_style("stale");
91        let _ = status_style("unknown");
92    }
93
94    #[test]
95    fn test_status_icon_merged() {
96        assert_eq!(status_icon("merged"), "✓");
97    }
98
99    #[test]
100    fn test_status_icon_pr_open() {
101        assert_eq!(status_icon("pr-open"), "⬆");
102    }
103
104    #[test]
105    fn test_status_style_new_statuses() {
106        // Ensure no panic
107        let _ = status_style("merged");
108        let _ = status_style("pr-open");
109    }
110}