Skip to content

Commit

Permalink
Add CLI option -f, --file to read from file (#12)
Browse files Browse the repository at this point in the history
`-` will act like an alias for `-f -`
  • Loading branch information
sayanarijit authored May 28, 2023
1 parent 0f4b231 commit 241caaf
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jf"
version = "0.6.0"
version = "0.6.1"
edition = "2021"
authors = ["Arijit Basu <[email protected]>"]
description = 'A small utility to safely format and print JSON objects in the commandline'
Expand Down
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,25 @@ nix-env -f https://github.com/NixOS/nixpkgs/tarball/nixos-unstable -iA jf
### USAGE

```bash
jf [OPTION]... [--] TEMPLATE [VALUE]... [NAME=VALUE]... [NAME@FILE]...
jf [OPTION]... [--] TEMPLATE [VALUE]... [NAME=VALUE]... [NAME@FILE]...
```

### OPTIONS

| option | help |
| ------------- | ----------------------------------------------- |
| - | pass template via stdin |
| -- | stop parsing CLI options |
| -r, --raw | print the raw rendered value without formatting |
| -p, --pretty | pretty print the JSON formatted output |
| -y, --yaml | print the output as YAML instead of JSON |
| -h, --help | print this help message |
| -v, --version | print the version number |
| option | help |
| ------------- | -------------------------------------------------- |
| - | alias for `-f -`, i.e. read template from stdin |
| -- | stop parsing CLI options |
| -r, --raw | print the raw rendered value without formatting |
| -p, --pretty | pretty print the JSON formatted output |
| -y, --yaml | print the output as YAML instead of JSON |
| -h, --help | print this help message |
| -v, --version | print the version number |
| -f, --file | treat the template argument as a file to read from |

### TEMPLATE

A template is a string that should render into valid YAML. It can contain the
following placeholders:
Template should render into valid YAML. It can contain the following placeholders:

- `%%` a literal `%` character
- `%s` `%q` read positional argument
Expand Down
9 changes: 6 additions & 3 deletions assets/jf.1
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jf [OPTION]\.\.\. [--] TEMPLATE [VALUE]\.\.\. [NAME=VALUE]\.\.\. [NAME@FILE]\.\.
.TP
.B
-
pass template via stdin
alias for `\fB-f\fP -`, i.e. read template from stdin
.TP
.B
--
Expand All @@ -33,10 +33,13 @@ print this help message
.B
\fB-v\fP, \fB--version\fP
print the version number
.TP
.B
\fB-f\fP, \fB--file\fP
treat the template argument as a file to read from
.SH TEMPLATE

A template is a string that should render into valid YAML. It can contain the
following placeholders:
Template should render into valid YAML. It can contain the following placeholders:
.TP
.B
`%%`
Expand Down
57 changes: 39 additions & 18 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate as jf;
use crate::VERSION;
use std::env::Args;
use std::io;
use std::iter::{Peekable, Skip};
use std::iter::Skip;
use std::{fs, io};

#[derive(Debug)]
pub enum Format {
Expand All @@ -16,60 +16,81 @@ pub enum Format {
pub enum Cli {
Help,
Version,
Format(Format, Peekable<Skip<Args>>),
Format(Format, Option<String>, Skip<Args>),
}

impl Cli {
pub fn parse() -> Result<Self, jf::Error> {
pub fn parse() -> jf::Result<Self> {
let mut format = Format::Json;
let mut args = std::env::args().skip(1).peekable();
let mut template: Option<String> = None;
let mut args = std::env::args().skip(1);
let mut is_file = false;

while let Some(arg) = args.peek_mut() {
while let Some(arg) = args.next() {
match arg.as_str() {
"-h" | "--help" => return Ok(Self::Help),
"-v" | "--version" => return Ok(Self::Version),
"-r" | "--raw" => {
format = Format::Raw;
args.next();
}
"-p" | "--pretty" => {
format = Format::PrettyJson;
args.next();
}
"-y" | "--yaml" => {
format = Format::Yaml;
args.next();
}
"-f" | "--file" => {
is_file = true;
}
"-" => {
*arg = io::read_to_string(io::stdin().lock())?;
is_file = false;
template = Some(io::read_to_string(io::stdin().lock())?);
break;
}
"--" => {
args.next();
break;
}
a if a.starts_with('-') => {
return Err(format!("invalid argument {a}, try -h or --help")
.as_str()
.into())
}
_ => break,
_ => {
template = Some(arg);
break;
}
}
}

Ok(Self::Format(format, args))
if template.is_none() {
template = args.next()
}

if is_file {
if let Some(tmpl) = template.as_mut() {
*tmpl = fs::read_to_string(&tmpl)?;
}
}

Ok(Self::Format(format, template, args))
}

pub fn process(self) -> Result<String, jf::Error> {
match self {
Self::Help => Ok(jf::USAGE.into()),
Self::Version => Ok(format!("jf {VERSION}")),
Self::Format(Format::Raw, args) => jf::render(args.map(Into::into)),
Self::Format(Format::Json, args) => jf::format(args.map(Into::into)),
Self::Format(Format::PrettyJson, args) => {
jf::format_pretty(args.map(Into::into))
Self::Format(Format::Raw, template, args) => {
jf::render(template.iter().map(Into::into).chain(args.map(Into::into)))
}
Self::Format(Format::Json, template, args) => {
jf::format(template.iter().map(Into::into).chain(args.map(Into::into)))
}
Self::Format(Format::Yaml, args) => jf::format_yaml(args.map(Into::into)),
Self::Format(Format::PrettyJson, template, args) => jf::format_pretty(
template.iter().map(Into::into).chain(args.map(Into::into)),
),
Self::Format(Format::Yaml, template, args) => jf::format_yaml(
template.iter().map(Into::into).chain(args.map(Into::into)),
),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
/// To handle also the CLI options, use the `jf::cli` module.
pub mod cli;
pub mod error;
pub use error::{Error, Result};
pub use serde_json as json;
pub use serde_yaml as yaml;

use crate::error::{Error, Result};
use std::io::BufRead;
use std::{borrow::Cow, collections::HashMap};
use std::{fs, io};

pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const USAGE: &str = include_str!("./usage.txt");
pub const USAGE: &str = include_str!("usage.txt");

fn read_to_string<S>(path: &str, stdin: &mut S) -> Result<String>
where
Expand Down
6 changes: 3 additions & 3 deletions src/usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ USAGE

OPTIONS

- pass template via stdin
- alias for `-f -`, i.e. read template from stdin
-- stop parsing CLI options
-r, --raw print the raw rendered value without formatting
-p, --pretty pretty print the JSON formatted output
-y, --yaml print the output as YAML instead of JSON
-h, --help print this help message
-v, --version print the version number
-f, --file treat the template argument as a file to read from

TEMPLATE

A template is a string that should render into valid YAML. It can contain the
following placeholders:
Template should render into valid YAML. It can contain the following placeholders:

`%%` a literal `%` character
`%s` `%q` read positional argument
Expand Down

0 comments on commit 241caaf

Please sign in to comment.