use std::io::Write;
use super::Row;
pub(super) fn print_rows(out: &mut dyn Write, rows: &[Row], json: bool) -> std::io::Result<()> {
if json {
let obj = serde_json::json!({ "providers": rows });
return writeln!(out, "{obj}");
}
let tunings: Vec<String> = rows.iter().map(tuning_cell).collect();
let shapes: Vec<String> = rows.iter().map(shapes_cell).collect();
let devices: Vec<String> = rows.iter().map(device_cell).collect();
let (name, protocol, auth) = (
width(rows, |r| &r.name),
width(rows, |r| &r.protocol),
width(rows, |r| &r.auth),
);
let tuning = cell_width(&tunings);
let shape = cell_width(&shapes);
let device = cell_width(&devices);
for (((r, t), s), d) in rows.iter().zip(&tunings).zip(&shapes).zip(&devices) {
writeln!(
out,
"{:name$} {:protocol$} {:auth$} {:tuning$} {:shape$} {:device$} {}",
r.name, r.protocol, r.auth, t, s, d, r.credential
)?;
}
Ok(())
}
fn tuning_cell(r: &Row) -> String {
named(&[("effort", r.effort), ("priority", r.priority)])
}
fn shapes_cell(r: &Row) -> String {
named(&[("tools", r.tools), ("multi_turn", r.multi_turn)])
}
fn device_cell(r: &Row) -> String {
r.device.clone().unwrap_or_else(|| "-".to_owned())
}
fn named(members: &[(&str, bool)]) -> String {
let held: Vec<&str> = members
.iter()
.filter_map(|(name, yes)| yes.then_some(*name))
.collect();
if held.is_empty() {
return "-".to_owned();
}
held.join(",")
}
fn width(rows: &[Row], field: impl Fn(&Row) -> &String) -> usize {
rows.iter().map(|r| field(r).len()).max().unwrap_or(0)
}
fn cell_width(cells: &[String]) -> usize {
cells.iter().map(String::len).max().unwrap_or(0)
}