Skip to main content

cargo_airbender/
ui.rs

1use crate::error::CliError;
2use anstyle::{AnsiColor, Effects, Style};
3use std::fmt::Display;
4use std::io::Write;
5
6pub fn success(message: impl AsRef<str>) {
7    if !should_emit() {
8        return;
9    }
10    print_stdout_line("success", AnsiColor::Green, message.as_ref());
11}
12
13pub fn info(message: impl AsRef<str>) {
14    if !should_emit() {
15        return;
16    }
17    print_stdout_line("info", AnsiColor::Blue, message.as_ref());
18}
19
20pub fn field(key: &str, value: impl Display) {
21    if !should_emit() {
22        return;
23    }
24    let mut stream = anstream::stdout();
25    let _ = writeln!(stream, "  {key}: {value}");
26}
27
28pub fn command(command: impl AsRef<str>) {
29    if !should_emit() {
30        return;
31    }
32    let style = label_style(AnsiColor::Cyan);
33    let mut stream = anstream::stdout();
34    let _ = writeln!(
35        stream,
36        "  {style}$ {command}{style:#}",
37        command = command.as_ref()
38    );
39}
40
41pub fn blank_line() {
42    if !should_emit() {
43        return;
44    }
45    let mut stream = anstream::stdout();
46    let _ = writeln!(stream);
47}
48
49pub fn render_error(err: &CliError) {
50    if !should_emit() {
51        return;
52    }
53    print_stderr_line("error", AnsiColor::Red, err.to_string());
54
55    if let Some(source) = err.source_error() {
56        if let Some(root_cause) = source.chain().last() {
57            print_stderr_detail("cause", root_cause);
58        }
59    }
60
61    if let Some(hint) = err.hint() {
62        print_stderr_line("hint", AnsiColor::Yellow, hint);
63    }
64}
65
66fn print_stdout_line(label: &str, color: AnsiColor, message: &str) {
67    let style = label_style(color);
68    let mut stream = anstream::stdout();
69    let _ = writeln!(stream, "{style}{label}{style:#}: {message}");
70}
71
72fn print_stderr_line(label: &str, color: AnsiColor, message: impl Display) {
73    let style = label_style(color);
74    let mut stream = anstream::stderr();
75    let _ = writeln!(stream, "{style}{label}{style:#}: {message}");
76}
77
78fn print_stderr_detail(label: &str, message: impl Display) {
79    let mut stream = anstream::stderr();
80    let _ = writeln!(stream, "  {label}: {message}");
81}
82
83fn label_style(color: AnsiColor) -> Style {
84    Style::new()
85        .fg_color(Some(color.into()))
86        .effects(Effects::BOLD)
87}
88
89fn should_emit() -> bool {
90    !cfg!(test)
91}