pub mod bar;
pub mod board;
pub mod bulk;
pub mod dict;
pub mod entity;
pub mod image;
pub mod markdown;
pub mod progress;
pub mod queue;
pub mod style;
pub mod table;
pub mod text;
pub mod untrusted;
pub mod user;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum Format {
#[default]
Text,
Json,
JsonRaw,
Toon,
}
impl FromStr for Format {
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"text" => Ok(Self::Text),
"json" => Ok(Self::Json),
"json-raw" => Ok(Self::JsonRaw),
"toon" => Ok(Self::Toon),
other => Err(format!(
"unknown format `{other}` (expected text, json, json-raw or toon)"
)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Audience {
Human,
Machine,
}
impl Audience {
#[must_use]
pub fn detect() -> Self {
use std::io::IsTerminal;
if std::io::stdout().is_terminal() {
Self::Human
} else {
Self::Machine
}
}
}
#[derive(Debug, Clone)]
pub struct Context {
pub format: Format,
pub audience: Audience,
pub description_lines: Option<usize>,
pub extra_fields: Vec<String>,
pub width: usize,
pub images: bool,
pub inline: image::Inline,
}
impl Context {
#[must_use]
pub fn is_human(&self) -> bool {
self.audience == Audience::Human
}
#[must_use]
pub fn painter(&self) -> style::Painter {
style::Painter::for_stream(self.is_human())
}
}
pub fn machine<T: serde::Serialize>(value: &T, format: Format) -> Result<String, RenderError> {
match format {
Format::Json | Format::JsonRaw => {
Ok(serde_json::to_string_pretty(value).map(|json| json + "\n")?)
}
Format::Toon => Ok(toon_format::encode_default(value)? + "\n"),
Format::Text => Err(RenderError::NotMachineReadable),
}
}
#[derive(Debug, thiserror::Error)]
pub enum RenderError {
#[error("could not serialise the result")]
Serialise(#[from] serde_json::Error),
#[error("text output is rendered per entity, not generically")]
NotMachineReadable,
#[error("could not encode as TOON")]
Toon(#[from] toon_format::ToonError),
}