use crate::ListOutputFormat;
use crate::cmd::output::{command_table, print_json, print_yaml};
use crate::diagnostic::{DiagnosticCode, DiagnosticResult};
use crate::theme::{SemanticColor, status_semantic};
use crate::ui::stdout_supports_color;
use comfy_table::{Attribute, Cell};
use serde::Serialize;
use std::io::IsTerminal;
fn cell(text: &str) -> Cell {
Cell::new(text)
}
fn id_cell(text: &str, use_colors: bool) -> Cell {
if use_colors {
Cell::new(text)
.fg(SemanticColor::Info.to_comfy())
.add_attribute(Attribute::Bold)
} else {
Cell::new(text)
}
}
fn status_cell(status: &str, use_colors: bool) -> Cell {
if use_colors {
Cell::new(status).fg(status_semantic(status).to_comfy())
} else {
Cell::new(status)
}
}
fn header_cell(text: &str, use_colors: bool) -> Cell {
if use_colors {
Cell::new(text).add_attribute(Attribute::Bold)
} else {
Cell::new(text)
}
}
pub(super) fn truncate_chars(s: &str, max: usize) -> String {
if s.chars().count() <= max {
s.to_string()
} else {
let truncated: String = s.chars().take(max).collect();
format!("{truncated}…")
}
}
pub(crate) fn resolve_list_output(output: Option<ListOutputFormat>) -> ListOutputFormat {
output.unwrap_or_else(|| {
if std::io::stdout().is_terminal() {
ListOutputFormat::Table
} else {
ListOutputFormat::Json
}
})
}
pub(super) fn output_list<T: Serialize>(
items: &[T],
headers: &[&str],
format: ListOutputFormat,
to_row: impl Fn(&T) -> Vec<String>,
) -> DiagnosticResult<()> {
match format {
ListOutputFormat::Json => {
print_json(
&items,
DiagnosticCode::E0903UnexpectedError,
"Failed to serialize resource list as JSON",
"list",
)?;
}
ListOutputFormat::Yaml => {
print_yaml(
&items,
DiagnosticCode::E0903UnexpectedError,
"Failed to serialize resource list as YAML",
"list",
)?;
}
ListOutputFormat::Table => {
let use_colors = stdout_supports_color();
let mut table = command_table();
table.set_header(
headers
.iter()
.map(|h| header_cell(h, use_colors))
.collect::<Vec<_>>(),
);
for item in items {
let row = to_row(item);
table.add_row(
row.iter()
.enumerate()
.map(|(i, v)| {
if i == 0 {
id_cell(v, use_colors)
} else if headers
.get(i)
.is_some_and(|h| *h == "Status" || *h == "Phase")
{
status_cell(v, use_colors)
} else {
cell(v)
}
})
.collect::<Vec<_>>(),
);
}
println!("{table}");
}
}
Ok(())
}