use clap::ValueEnum;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, ValueEnum)]
pub enum OutputMode {
#[default]
Text,
Json,
}
pub trait Render: serde::Serialize {
fn to_text(&self) -> String;
}
pub fn emit<T: Render>(value: &T, mode: OutputMode) -> eyre::Result<()> {
match mode {
OutputMode::Text => println!("{}", value.to_text()),
OutputMode::Json => println!("{}", serde_json::to_string_pretty(value)?),
}
Ok(())
}
pub fn progress(msg: impl std::fmt::Display) {
eprintln!("{}", msg);
}
const BOX_WIDTH: usize = 64;
pub fn newline() -> &'static str {
"\n"
}
pub fn boxed_header(title: &str) -> String {
let bar = "═".repeat(BOX_WIDTH);
let pad = BOX_WIDTH.saturating_sub(title.chars().count());
let left = pad / 2;
let right = pad - left;
format!(
"╔{bar}╗\n║{}{title}{}║\n╚{bar}╝\n",
" ".repeat(left),
" ".repeat(right),
)
}
pub fn field(label: &str, value: impl std::fmt::Display) -> String {
format!("{:<21}{}\n", format!("{label}:"), value)
}
pub fn subfield(label: &str, value: impl std::fmt::Display) -> String {
format!(" {:<19}{}\n", format!("{label}:"), value)
}
#[derive(serde::Serialize)]
pub struct NotFound {
pub found: bool,
pub pubkey: String,
#[serde(skip)]
pub label: String,
}
impl NotFound {
pub fn new(label: impl Into<String>, pubkey: impl Into<String>) -> Self {
Self {
found: false,
pubkey: pubkey.into(),
label: label.into(),
}
}
}
impl Render for NotFound {
fn to_text(&self) -> String {
format!("{} {} not found.", self.label, self.pubkey)
}
}
#[derive(Debug, serde::Serialize)]
#[serde(tag = "status", rename_all = "snake_case")]
pub enum TxOutputView {
Executed { signature: String },
ProposalCreated {
proposal: String,
transaction_index: u64,
signature: String,
},
}
impl Render for TxOutputView {
fn to_text(&self) -> String {
match self {
TxOutputView::Executed { signature } => {
let mut out = String::from("✅ Transaction executed\n");
out.push_str(&subfield("Signature", signature));
out
}
TxOutputView::ProposalCreated {
proposal,
transaction_index,
signature,
} => {
let mut out = String::from("✅ Proposal created\n");
out.push_str(&subfield("Proposal", proposal));
out.push_str(&subfield("Transaction Index", transaction_index));
out.push_str(&subfield("Signature", signature));
out
}
}
}
}