Skip to main content

envvault/cli/
output.rs

1//! Colored terminal output helpers.
2//!
3//! All user-facing output goes through these functions so we get
4//! consistent styling across every command.
5
6use comfy_table::{ContentArrangement, Table};
7use console::style;
8
9use crate::vault::SecretMetadata;
10
11/// Print a green success message: "check_mark {msg}"
12pub fn success(msg: &str) {
13    println!("{} {}", style("\u{2713}").green().bold(), msg);
14}
15
16/// Print a red error message: "x_mark {msg}"
17pub fn error(msg: &str) {
18    eprintln!("{} {}", style("\u{2717}").red().bold(), msg);
19}
20
21/// Print a yellow warning: "warning_sign {msg}"
22pub fn warning(msg: &str) {
23    eprintln!("{} {}", style("\u{26a0}").yellow().bold(), msg);
24}
25
26/// Print a blue info message: "info_sign {msg}"
27pub fn info(msg: &str) {
28    println!("{} {}", style("\u{2139}").blue().bold(), msg);
29}
30
31/// Print a dim tip/hint: "arrow {msg}"
32pub fn tip(msg: &str) {
33    println!("{} {}", style("\u{2192}").dim(), style(msg).dim());
34}
35
36/// Print a table of secret metadata (Name, Created, Updated).
37pub fn print_secrets_table(secrets: &[SecretMetadata]) {
38    if secrets.is_empty() {
39        info("No secrets in this vault yet.");
40        tip("Run `envvault set <KEY>` to add your first secret.");
41        return;
42    }
43
44    let mut table = Table::new();
45    table.set_content_arrangement(ContentArrangement::Dynamic);
46    table.set_header(vec!["Name", "Created", "Updated"]);
47
48    for s in secrets {
49        table.add_row(vec![
50            s.name.clone(),
51            s.created_at.format("%Y-%m-%d %H:%M:%S").to_string(),
52            s.updated_at.format("%Y-%m-%d %H:%M:%S").to_string(),
53        ]);
54    }
55
56    println!("{table}");
57}