Skip to main content

futucli/
output.rs

1//! 输出格式化:table / json / jsonl
2
3use std::io::{self, Write};
4
5use clap::ValueEnum;
6use serde::Serialize;
7use tabled::{Table, Tabled, settings::Style};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
10pub enum OutputFormat {
11    /// 人类可读表格
12    Table,
13    /// 单个 JSON 数组
14    Json,
15    /// 每行一个 JSON 对象(适合管道处理)
16    Jsonl,
17}
18
19impl OutputFormat {
20    /// 以 table 优先输出;如果 fmt != Table 则走 json/jsonl。
21    pub fn print_rows<R, S>(&self, rows: &[R], serializable: &[S]) -> io::Result<()>
22    where
23        R: Tabled,
24        S: Serialize,
25    {
26        match self {
27            OutputFormat::Table => {
28                if rows.is_empty() {
29                    println!("(empty)");
30                    return Ok(());
31                }
32                let mut table = Table::new(rows);
33                table.with(Style::rounded());
34                println!("{table}");
35                Ok(())
36            }
37            OutputFormat::Json => {
38                let s = serde_json::to_string_pretty(serializable).map_err(io::Error::other)?;
39                println!("{s}");
40                Ok(())
41            }
42            OutputFormat::Jsonl => {
43                let stdout = io::stdout();
44                let mut lock = stdout.lock();
45                for item in serializable {
46                    let s = serde_json::to_string(item).map_err(io::Error::other)?;
47                    writeln!(lock, "{s}")?;
48                }
49                Ok(())
50            }
51        }
52    }
53}