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        "stale" => Style::new().red(),
41        _ => Style::new(),
42    }
43}
44
45/// Map worktree status string to a display icon.
46pub fn status_icon(status: &str) -> &'static str {
47    match status {
48        "active" => "●",
49        "clean" => "○",
50        "modified" => "◉",
51        "merged" => "✓",
52        "pr-open" => "⬆",
53        "stale" => "x",
54        _ => "○",
55    }
56}
57
58/// Get current terminal width (fallback 80).
59pub fn terminal_width() -> usize {
60    Term::stdout().size().1 as usize
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn test_status_icon_all_variants() {
69        assert_eq!(status_icon("active"), "●");
70        assert_eq!(status_icon("clean"), "○");
71        assert_eq!(status_icon("modified"), "◉");
72        assert_eq!(status_icon("stale"), "x");
73    }
74
75    #[test]
76    fn test_status_icon_unknown_fallback() {
77        assert_eq!(status_icon("unknown"), "○");
78        assert_eq!(status_icon(""), "○");
79        assert_eq!(status_icon("something_else"), "○");
80    }
81
82    #[test]
83    fn test_status_style_known() {
84        // Just ensure no panic for all known statuses
85        let _ = status_style("active");
86        let _ = status_style("clean");
87        let _ = status_style("modified");
88        let _ = status_style("stale");
89        let _ = status_style("unknown");
90    }
91
92    #[test]
93    fn test_status_icon_merged() {
94        assert_eq!(status_icon("merged"), "✓");
95    }
96
97    #[test]
98    fn test_status_icon_pr_open() {
99        assert_eq!(status_icon("pr-open"), "⬆");
100    }
101
102    #[test]
103    fn test_status_style_new_statuses() {
104        // Ensure no panic
105        let _ = status_style("merged");
106        let _ = status_style("pr-open");
107    }
108}