diff --git a/cli/src/main.rs b/cli/src/main.rs index e88c0e7..f78bb9b 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -40,7 +40,7 @@ impl Input { #[derive(Debug, Parser)] struct Args { - #[arg(long, default_value_t = fuk::output::Format::JSONPretty)] + #[arg(long, default_value_t = fuk::output::Format::JSON)] format: fuk::output::Format, /// File containing list of keys to be fetched #[arg(value_hint = clap::ValueHint::FilePath)] @@ -54,7 +54,9 @@ fn main() -> Result<()> { let output = fuk::fuk(config); - println!("{}", args.format.render(&output)); + let out = std::io::stdout(); + let mut out = out.lock(); + args.format.render(&output, &mut out)?; Ok(()) } diff --git a/cli/src/output/mod.rs b/cli/src/output/mod.rs index 70ae75a..96daff6 100644 --- a/cli/src/output/mod.rs +++ b/cli/src/output/mod.rs @@ -3,22 +3,24 @@ // SPDX-License-Identifier: EUPL-1.2 use std::collections::HashMap; +use std::io::{self, prelude::*}; #[derive(PartialEq, Eq, Debug, Copy, Clone)] pub enum Format { JSON, - JSONPretty, TOML, - TOMLPretty, + CSV, } impl Format { - pub fn render(self, output: &Output) -> String { + pub fn render(self, output: &Output, w: &mut W) -> io::Result<()> { match self { - Format::JSON => serde_json::to_string(&output.keys).unwrap(), - Format::JSONPretty => serde_json::to_string_pretty(&output.keys).unwrap(), - Format::TOML => toml::to_string(&output.keys).unwrap(), - Format::TOMLPretty => toml::to_string_pretty(&output.keys).unwrap(), + Format::JSON => { + serde_json::to_writer_pretty(&mut *w, &output.keys).map_err(io::Error::other)?; + writeln!(w, "") + } + Format::TOML => write!(w, "{}", toml::to_string_pretty(&output.keys).unwrap()), + Format::CSV => as_csv(w, &output), } } } @@ -27,9 +29,8 @@ impl std::fmt::Display for Format { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match *self { Format::JSON => f.write_str("json"), - Format::JSONPretty => f.write_str("json-pretty"), Format::TOML => f.write_str("toml"), - Format::TOMLPretty => f.write_str("toml-pretty"), + Format::CSV => f.write_str("csv"), } } } @@ -38,10 +39,8 @@ impl<'a> From<&'a str> for Format { fn from(s: &'a str) -> Format { match s { "json" => Format::JSON, - "pretty" => Format::JSONPretty, - "json-pretty" => Format::JSONPretty, "toml" => Format::TOML, - "toml-pretty" => Format::TOMLPretty, + "csv" => Format::CSV, _ => unreachable!(), } } @@ -51,3 +50,14 @@ impl<'a> From<&'a str> for Format { pub struct Output { pub keys: HashMap>, } + +// TODO: proper escaping +fn as_csv(w: &mut W, output: &Output) -> io::Result<()> { + for (name, keys) in &output.keys { + for key in keys { + writeln!(w, "{name},{}", key.to_string())?; + } + } + + Ok(()) +} diff --git a/docs/fuk.1.scd b/docs/fuk.1.scd index ea1a878..d9998fb 100644 --- a/docs/fuk.1.scd +++ b/docs/fuk.1.scd @@ -7,7 +7,8 @@ fuk - Fetch User Keys # SYNOPSIS *fuk* -h++ -*fuk* [--format (json|json-pretty|toml|toml-pretty)] _config.toml_ +*fuk* --help++ +*fuk* [--format (json|toml|csv)] _config.toml_ # DESCRIPTION @@ -68,11 +69,13 @@ keys = [ # OUTPUT -_fuk_ prints result to stdout in JSON format. Keys will be deduplicated by +_fuk_ prints result to stdout in selected format. Keys will be deduplicated by algorithm and key, but the comment *will* be ignored when comparing for equality. If comments for duplicated keys are different, then there is no guarantee about comment content. +Possible formats - JSON, TOML, CSV. + Example output: ```