use clap::Command;
use clap::builder::CommandExt;
use crate::model::OutputEncoding;
use crate::model::OutputMode;
use crate::model::OutputSchema;
use crate::model::OutputSpec;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct OutputContracts {
contracts: Vec<OutputContract>,
}
impl CommandExt for OutputContracts {}
impl OutputContracts {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with(mut self, contract: OutputContract) -> Self {
self.contracts.push(contract);
self
}
#[must_use]
pub fn with_all(mut self, contracts: OutputContracts) -> Self {
self.contracts.extend(contracts.contracts);
self
}
#[must_use]
pub fn json(type_name: impl Into<String>) -> Self {
Self::new().with(OutputContract::json(type_name))
}
#[must_use]
pub fn json_lines(type_name: impl Into<String>) -> Self {
Self::new().with(OutputContract::json_lines(type_name))
}
#[must_use]
pub fn text(type_name: impl Into<String>) -> Self {
Self::new().with(OutputContract::text(type_name))
}
pub(crate) fn iter(&self) -> impl Iterator<Item = &OutputContract> {
self.contracts.iter()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OutputContract {
pub encoding: OutputEncoding,
pub mode: OutputMode,
pub type_name: String,
pub schema: Option<OutputSchema>,
}
impl OutputContract {
#[must_use]
pub fn json(type_name: impl Into<String>) -> Self {
Self {
encoding: OutputEncoding::Json,
mode: OutputMode::Buffered,
type_name: type_name.into(),
schema: None,
}
}
#[must_use]
pub fn json_lines(type_name: impl Into<String>) -> Self {
Self {
encoding: OutputEncoding::JsonLines,
mode: OutputMode::Streaming,
type_name: type_name.into(),
schema: None,
}
}
#[must_use]
pub fn text(type_name: impl Into<String>) -> Self {
Self {
encoding: OutputEncoding::Text,
mode: OutputMode::Buffered,
type_name: type_name.into(),
schema: None,
}
}
#[must_use]
pub fn interactive(mut self) -> Self {
self.mode = OutputMode::Interactive;
self
}
#[must_use]
pub fn json_schema(mut self, schema: impl Into<String>) -> Self {
self.schema = Some(OutputSchema::JsonSchema(schema.into()));
self
}
pub(crate) fn to_spec(&self, command_path: Vec<String>) -> OutputSpec {
OutputSpec {
command_path,
encoding: self.encoding,
mode: self.mode,
type_name: self.type_name.clone(),
schema: self.schema.clone(),
}
}
}
pub trait ClapTypesCommandExt {
fn output_contract(self, contract: OutputContract) -> Self;
fn output_contracts(self, contracts: OutputContracts) -> Self;
}
impl ClapTypesCommandExt for Command {
fn output_contract(self, contract: OutputContract) -> Self {
let contracts = self
.get::<OutputContracts>()
.cloned()
.unwrap_or_default()
.with(contract);
self.add(contracts)
}
fn output_contracts(self, contracts: OutputContracts) -> Self {
let contracts = self
.get::<OutputContracts>()
.cloned()
.unwrap_or_default()
.with_all(contracts);
self.add(contracts)
}
}