use std::io::IsTerminal; use std::str::FromStr; /// Output format for all commands. #[derive(Debug, Clone, Default, PartialEq)] pub enum OutputMode { /// Human-readable text (default when stdout is a TTY) #[default] Text, /// Pretty-printed JSON Json, /// Single-line JSON (default when stdout is NOT a TTY, e.g. piped to jq) JsonCompact, /// KEY=VALUE pairs suitable for `source` or `.env` files Env, } impl FromStr for OutputMode { type Err = anyhow::Error; fn from_str(s: &str) -> Result { match s { "text" => Ok(Self::Text), "json" => Ok(Self::Json), "json-compact" => Ok(Self::JsonCompact), "env" => Ok(Self::Env), other => Err(anyhow::anyhow!( "Unknown output format '{}'. Valid: text, json, json-compact, env", other )), } } } /// Resolve the effective output mode. /// - Explicit value from `--output` takes priority. /// - TTY → text; non-TTY (piped/redirected) → json-compact. pub fn resolve_output_mode(explicit: Option<&str>) -> anyhow::Result { if let Some(s) = explicit { return s.parse(); } if std::io::stdout().is_terminal() { Ok(OutputMode::Text) } else { Ok(OutputMode::JsonCompact) } }