Skip to content

Commit

Permalink
Merge pull request #318 from Bnyro/format-options
Browse files Browse the repository at this point in the history
add format options: json indentation
  • Loading branch information
ducaale committed Jul 20, 2023
2 parents 4b16f73 + 2ce5cc6 commit d6bc539
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 11 deletions.
45 changes: 44 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::time::Duration;

use anyhow::anyhow;
use anyhow::{anyhow, Context};
use clap::{self, AppSettings, ArgEnum, Error, ErrorKind, FromArgMatches, Result};
use encoding_rs::Encoding;
use once_cell::sync::OnceCell;
Expand Down Expand Up @@ -83,6 +83,15 @@ Defaults to \"format\" if the NO_COLOR env is set and to \"none\" if stdout is n
)]
pub pretty: Option<Pretty>,

/// Set output formatting options. The only currently implemented option
/// is json.indent.
///
/// Different options need to be separated by a comma.
///
/// Example: --format-options=json.indent:2
#[clap(long, value_name = "FORMAT_OPTIONS")]
pub format_options: Option<FormatOptions>,

/// Output coloring style.
#[clap(short = 's', long, arg_enum, value_name = "THEME")]
pub style: Option<Theme>,
Expand Down Expand Up @@ -949,6 +958,40 @@ impl Pretty {
}
}

#[derive(Debug)]
pub struct FormatOptions {
pub json_indent: usize,
}

impl Default for FormatOptions {
fn default() -> Self {
Self { json_indent: 4 }
}
}

impl FromStr for FormatOptions {
type Err = anyhow::Error;
fn from_str(options: &str) -> anyhow::Result<FormatOptions> {
let mut format_options = FormatOptions::default();

// generate a map of the specified options
for argument in options.split(',') {
let (key, value) = argument
.split_once(':')
.context("Format options consist of a key and a value, separated by a \":\".")?;
match key {
"json.indent" => {
format_options.json_indent = value.parse().context("Invalid indent value")?;
}
_ => {
return Err(anyhow!("Unknown option '{key}'"));
}
}
}
Ok(format_options)
}
}

#[derive(ArgEnum, Debug, PartialEq, Eq, Clone, Copy)]
pub enum Theme {
Auto,
Expand Down
9 changes: 6 additions & 3 deletions src/formatting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ use syntect::parsing::SyntaxSet;
use syntect::util::LinesWithEndings;
use termcolor::WriteColor;

use crate::{buffer::Buffer, cli::Theme};
use crate::{
buffer::Buffer,
cli::{FormatOptions, Theme},
};

pub fn get_json_formatter() -> jsonxf::Formatter {
pub fn get_json_formatter(format_options: &FormatOptions) -> jsonxf::Formatter {
let mut fmt = jsonxf::Formatter::pretty_printer();
fmt.indent = String::from(" ");
fmt.indent = " ".repeat(format_options.json_indent);
fmt.record_separator = String::from("\n\n");
fmt.eager_record_separators = true;
fmt
Expand Down
9 changes: 8 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use std::sync::Arc;

use anyhow::{anyhow, Context, Result};
use atty::Stream;
use cli::FormatOptions;
use network_interface::{NetworkInterface, NetworkInterfaceConfig};
use redirect::RedirectFollower;
use reqwest::blocking::Client;
Expand Down Expand Up @@ -484,7 +485,13 @@ fn run(args: Cli) -> Result<i32> {
),
};
let pretty = args.pretty.unwrap_or_else(|| buffer.guess_pretty());
let mut printer = Printer::new(pretty, args.style, args.stream, buffer);
let mut printer = Printer::new(
pretty,
args.style,
args.stream,
buffer,
args.format_options.unwrap_or(FormatOptions::default()),
);

let response_charset = args.response_charset;
let response_mime = args.response_mime.as_deref();
Expand Down
24 changes: 18 additions & 6 deletions src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use reqwest::header::{
use reqwest::Version;
use url::Url;

use crate::cli::FormatOptions;
use crate::decoder::{decompress, get_compression_type};
use crate::{
buffer::Buffer,
Expand Down Expand Up @@ -114,10 +115,17 @@ pub struct Printer {
sort_headers: bool,
stream: bool,
buffer: Buffer,
format_options: FormatOptions,
}

impl Printer {
pub fn new(pretty: Pretty, theme: Option<Theme>, stream: bool, buffer: Buffer) -> Self {
pub fn new(
pretty: Pretty,
theme: Option<Theme>,
stream: bool,
buffer: Buffer,
format_options: FormatOptions,
) -> Self {
let theme = theme.unwrap_or(Theme::Auto);

Printer {
Expand All @@ -127,6 +135,7 @@ impl Printer {
stream,
theme,
buffer,
format_options,
}
}

Expand Down Expand Up @@ -159,15 +168,16 @@ impl Printer {
return self.print_syntax_text(text, "json");
}

let mut formatter = get_json_formatter(&self.format_options);
if self.color {
let mut buf = Vec::new();
get_json_formatter().format_buf(text.as_bytes(), &mut buf)?;
formatter.format_buf(text.as_bytes(), &mut buf)?;
// in principle, buf should already be valid UTF-8,
// because JSONXF doesn't mangle it
let text = String::from_utf8_lossy(&buf);
self.print_colorized_text(&text, "json")
} else {
get_json_formatter().format_buf(text.as_bytes(), &mut self.buffer)
formatter.format_buf(text.as_bytes(), &mut self.buffer)
}
}

Expand Down Expand Up @@ -234,7 +244,7 @@ impl Printer {
self.print_syntax_stream(stream, "json")
} else if self.color {
let mut guard = BinaryGuard::new(stream, self.buffer.is_terminal());
let mut formatter = get_json_formatter();
let mut formatter = get_json_formatter(&self.format_options);
let mut highlighter = self.get_highlighter("json");
let mut buf = Vec::new();
while let Some(lines) = guard.read_lines()? {
Expand All @@ -247,7 +257,7 @@ impl Printer {
}
Ok(())
} else {
let mut formatter = get_json_formatter();
let mut formatter = get_json_formatter(&self.format_options);
if !self.buffer.is_terminal() {
let mut buf = vec![0; BUFFER_SIZE];
loop {
Expand Down Expand Up @@ -717,7 +727,8 @@ mod tests {
let args = Cli::try_parse_from(args).unwrap();
let buffer = Buffer::new(args.download, args.output.as_deref(), is_stdout_tty).unwrap();
let pretty = args.pretty.unwrap_or_else(|| buffer.guess_pretty());
Printer::new(pretty, args.style, false, buffer)
let format_options = FormatOptions::default();
Printer::new(pretty, args.style, false, buffer, format_options)
}

fn temp_path() -> String {
Expand Down Expand Up @@ -805,6 +816,7 @@ mod tests {
sort_headers: false,
stream: false,
buffer: Buffer::new(false, None, false).unwrap(),
format_options: FormatOptions::default(),
};

let mut headers = HeaderMap::new();
Expand Down

0 comments on commit d6bc539

Please sign in to comment.