Skip to main content

yuki_cli/
output.rs

1use comfy_table::{Cell, Color, Table, presets::UTF8_FULL_CONDENSED};
2use serde_json::{Map, Value, json};
3
4pub enum OutputFormat {
5    Table,
6    Json,
7}
8
9impl OutputFormat {
10    pub fn from_flag(flag: Option<&str>, is_tty: bool) -> Self {
11        match flag {
12            Some("json") => Self::Json,
13            Some("table") => Self::Table,
14            Some(_) => Self::Table,
15            None if is_tty => Self::Table,
16            None => Self::Json,
17        }
18    }
19}
20
21pub fn format_json(headers: &[String], rows: &[Vec<String>]) -> String {
22    let items: Vec<Value> = rows
23        .iter()
24        .map(|row| {
25            let mut map = Map::new();
26            for (i, header) in headers.iter().enumerate() {
27                let val = row.get(i).cloned().unwrap_or_default();
28                map.insert(header.clone(), Value::String(val));
29            }
30            Value::Object(map)
31        })
32        .collect();
33    serde_json::to_string_pretty(&items).unwrap_or_else(|_| "[]".into())
34}
35
36pub fn format_table(headers: &[String], rows: &[Vec<String>]) -> String {
37    let mut table = Table::new();
38    table.load_preset(UTF8_FULL_CONDENSED);
39    let header_cells: Vec<Cell> = headers
40        .iter()
41        .map(|h| {
42            Cell::new(h)
43                .fg(Color::White)
44                .add_attribute(comfy_table::Attribute::Bold)
45        })
46        .collect();
47    table.set_header(header_cells);
48    for row in rows {
49        table.add_row(row);
50    }
51    table.to_string()
52}
53
54pub fn format_error_json(message: &str, code: &str) -> String {
55    serde_json::to_string_pretty(&json!({
56        "error": message,
57        "code": code,
58    }))
59    .unwrap_or_else(|_| format!(r#"{{"error":"{message}","code":"{code}"}}"#))
60}
61
62pub fn is_tty() -> bool {
63    std::io::IsTerminal::is_terminal(&std::io::stdout())
64}