Skip to main content

indieweb_cli_common/
output.rs

1use clap::ValueEnum;
2use serde::Serialize;
3use std::io::{self, Write};
4
5#[derive(Debug, Clone, Copy, Default, ValueEnum)]
6pub enum OutputFormat {
7    #[default]
8    Json,
9    Table,
10}
11
12pub trait CliOutput: Serialize {
13    fn print(&self, format: OutputFormat) -> io::Result<()> {
14        match format {
15            OutputFormat::Json => {
16                let json = serde_json::to_string_pretty(self)?;
17                println!("{}", json);
18            }
19            OutputFormat::Table => {
20                self.print_table()?;
21            }
22        }
23        Ok(())
24    }
25
26    fn print_table(&self) -> io::Result<()> {
27        let json = serde_json::to_string_pretty(self)?;
28        println!("{}", json);
29        Ok(())
30    }
31}
32
33pub fn print_json<T: Serialize>(value: &T) -> io::Result<()> {
34    let json = serde_json::to_string_pretty(value)?;
35    println!("{}", json);
36    Ok(())
37}
38
39pub fn print_error(error: &str) {
40    eprintln!("error: {}", error);
41}
42
43pub fn print_success(message: &str) {
44    println!("{}", message);
45}
46
47pub fn print_table(headers: &[&str], rows: &[Vec<String>]) -> io::Result<()> {
48    let mut widths: Vec<usize> = headers.iter().map(|h| h.len()).collect();
49
50    for row in rows {
51        for (i, cell) in row.iter().enumerate() {
52            if i < widths.len() {
53                widths[i] = widths[i].max(cell.len());
54            }
55        }
56    }
57
58    let separator: String = widths
59        .iter()
60        .map(|w| "-".repeat(*w + 2))
61        .collect::<Vec<_>>()
62        .join("+");
63
64    let header_row: String = headers
65        .iter()
66        .enumerate()
67        .map(|(i, h)| {
68            format!(
69                " {:width$} ",
70                h,
71                width = widths.get(i).copied().unwrap_or(0)
72            )
73        })
74        .collect::<Vec<_>>()
75        .join("|");
76
77    println!("+{}+", separator);
78    println!("|{}|", header_row);
79    println!("+{}+", separator);
80
81    for row in rows {
82        let row_str: String = row
83            .iter()
84            .enumerate()
85            .map(|(i, cell)| {
86                format!(
87                    " {:width$} ",
88                    cell,
89                    width = widths.get(i).copied().unwrap_or(0)
90                )
91            })
92            .collect::<Vec<_>>()
93            .join("|");
94        println!("|{}|", row_str);
95    }
96
97    println!("+{}+", separator);
98    io::stdout().flush()
99}