#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) enum OutputFormat {
#[default]
Human,
Json,
Yaml,
}
impl OutputFormat {
pub(crate) fn from_str(s: &str) -> Option<Self> {
match s {
"json" => Some(OutputFormat::Json),
"yaml" => Some(OutputFormat::Yaml),
"human" => Some(OutputFormat::Human),
_ => None,
}
}
pub(crate) fn is_structured(self) -> bool {
matches!(self, OutputFormat::Json | OutputFormat::Yaml)
}
}
pub(crate) fn render_structured<T: serde::Serialize>(value: &T, fmt: OutputFormat) {
use crate::infra::driving::cli::errors::{die1, CliError};
match fmt {
OutputFormat::Json => {
let out = serde_json::to_string_pretty(value).unwrap_or_else(|e| {
die1(
CliError::new(format!("JSON serialisation failed: {e}")).kind("internal"),
OutputFormat::Human,
);
});
println!("{out}");
}
OutputFormat::Yaml => {
let out = serde_yaml::to_string(value).unwrap_or_else(|e| {
die1(
CliError::new(format!("YAML serialisation failed: {e}")).kind("internal"),
OutputFormat::Human,
);
});
print!("{out}");
}
OutputFormat::Human => {
unreachable!("render_structured called with Human format");
}
}
}
pub(crate) fn extract_output_from_args() -> OutputFormat {
let args: Vec<String> = std::env::args().collect();
let mut iter = args.iter().skip(1).peekable();
while let Some(arg) = iter.next() {
if arg == "--output" || arg == "-o" {
if let Some(val) = iter.next() {
return OutputFormat::from_str(val).unwrap_or_default();
}
} else if let Some(val) = arg
.strip_prefix("--output=")
.or_else(|| arg.strip_prefix("-o="))
{
return OutputFormat::from_str(val).unwrap_or_default();
}
}
OutputFormat::Human
}