aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/args.rs23
-rw-r--r--src/config.rs5
-rw-r--r--src/output.rs41
3 files changed, 56 insertions, 13 deletions
diff --git a/src/args.rs b/src/args.rs
index f54025e..758af8c 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -16,6 +16,9 @@ pub struct Args {
/// Disables the cache for all secrets.
#[structopt(long, global = true)]
pub no_cache: bool,
+ /// Selects the output format.
+ #[structopt(long, global = true, possible_values = &OutputFormat::all_str())]
+ pub output_format: Option<OutputFormat>,
#[structopt(subcommand)]
pub cmd: Command,
}
@@ -68,6 +71,26 @@ impl<'de> serde::Deserialize<'de> for DeviceModel {
}
}
+Enum! {
+ /// The format for the nitrocli output.
+ OutputFormat, [
+ Text => "text",
+ ]
+}
+
+impl<'de> serde::Deserialize<'de> for OutputFormat {
+ fn deserialize<D>(deserializer: D) -> Result<OutputFormat, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ use serde::de::Error as _;
+ use std::str::FromStr as _;
+
+ let s = String::deserialize(deserializer)?;
+ OutputFormat::from_str(&s).map_err(D::Error::custom)
+ }
+}
+
Command! {
/// A top-level command for nitrocli.
Command, [
diff --git a/src/config.rs b/src/config.rs
index aceda38..b96d071 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -32,6 +32,8 @@ pub struct Config {
#[merge(strategy = merge::num::overwrite_zero)]
#[serde(default)]
pub verbosity: u8,
+ /// The output format.
+ pub output_format: Option<args::OutputFormat>,
}
impl Config {
@@ -57,6 +59,9 @@ impl Config {
if args.verbose > 0 {
self.verbosity = args.verbose;
}
+ if args.output_format.is_some() {
+ self.output_format = args.output_format;
+ }
}
}
diff --git a/src/output.rs b/src/output.rs
index 77fb93b..7c85a82 100644
--- a/src/output.rs
+++ b/src/output.rs
@@ -7,19 +7,28 @@
use std::fmt;
+use crate::args;
use crate::Context;
/// A trait for objects that can be printed as nitrocli’s output.
pub trait Output {
- /// Formats this object as a string that can be printed to the standard output.
- fn format(&self) -> anyhow::Result<String>;
+ /// Formats this object using the given output format.
+ fn format(&self, format: args::OutputFormat) -> anyhow::Result<String>;
- /// Prints this object to the output set in the given context.
+ /// Prints this object to the output set in the given context using the output format set in the
+ /// context configuration.
///
/// The default implementation for this method prints the return value of `format` to
/// `ctx.stdout`.
fn print(&self, ctx: &mut Context<'_>) -> anyhow::Result<()> {
- println!(ctx, "{}", self.format()?.trim_end()).map_err(From::from)
+ println!(
+ ctx,
+ "{}",
+ self
+ .format(ctx.config.output_format.unwrap_or(args::OutputFormat::Text))?
+ .trim_end()
+ )
+ .map_err(From::from)
}
}
@@ -54,8 +63,10 @@ impl<T: fmt::Display> Value<T> {
}
impl<T: fmt::Display> Output for Value<T> {
- fn format(&self) -> anyhow::Result<String> {
- Ok(self.0.to_string())
+ fn format(&self, format: args::OutputFormat) -> anyhow::Result<String> {
+ match format {
+ args::OutputFormat::Text => Ok(self.0.to_string()),
+ }
}
}
@@ -77,13 +88,17 @@ impl<T: TableItem> Table<T> {
}
impl<T: TableItem> Output for Table<T> {
- fn format(&self) -> anyhow::Result<String> {
- if self.items.is_empty() {
- Ok(self.empty_message.clone())
- } else {
- let headers = T::headers().into_iter().map(ToOwned::to_owned).collect();
- let values = self.items.iter().map(TableItem::values);
- Ok(print_table(headers, values))
+ fn format(&self, format: args::OutputFormat) -> anyhow::Result<String> {
+ match format {
+ args::OutputFormat::Text => {
+ if self.items.is_empty() {
+ Ok(self.empty_message.clone())
+ } else {
+ let headers = T::headers().into_iter().map(ToOwned::to_owned).collect();
+ let values = self.items.iter().map(TableItem::values);
+ Ok(print_table(headers, values))
+ }
+ }
}
}
}