From e97bfc69f9e1d3c98d3f6883bec49cecea7578cf Mon Sep 17 00:00:00 2001 From: tinaxd <31384595+tinaxd@users.noreply.github.com> Date: Mon, 9 Dec 2019 18:46:59 +0900 Subject: [PATCH] pretty print --- src/lib.rs | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 17 ++++++++-- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 50c77ef..5fb1617 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,4 +29,102 @@ pub fn minimize_json(json: &str) -> String { } } result +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum JsonContext { + Object, Array, String, +} + +pub fn pretty_json(json: &str, setting: &PrettySetting) -> String { + let compressed = minimize_json(json); + let dirty = &compressed; + + let mut curr_indentlv = 0; + let mut result = String::new(); + let mut ctx: Vec = vec![JsonContext::Object]; // Used as stack + let mut skip_char = false; + let mut last_comma = false; + + for ch in dirty.chars() { + if skip_char { + skip_char = false; + result.push(ch); + last_comma = false; + continue; + } + + if ctx[0] == JsonContext::String { + if ch == '\\' { + skip_char = true; + } else if ch == '\"' { + ctx.pop(); + } + result.push(ch); + last_comma = false; + continue; + } + + if ch == '\"' { + result.push(ch); + ctx.push(JsonContext::String); + last_comma = false; + continue; + } + + if ch == ',' { + result.push(ch); + result.push('\n'); + for _ in 0..(curr_indentlv * setting.indent_width) { + result.push(' '); + } + last_comma = true; + continue; + } + + if ch == '[' || ch == '{' { + result.push(ch); + result.push('\n'); + curr_indentlv += 1; + for _ in 0..(curr_indentlv * setting.indent_width) { + result.push(' '); + } + ctx.push(match ch { + '[' => JsonContext::Array, + '{' => JsonContext::Object, + _ => unreachable!(), + }); + last_comma = false; + continue; + } + + if ch == ']' || ch == '}' { + curr_indentlv -= 1; + if !last_comma { + result.push('\n'); + for _ in 0..(curr_indentlv * setting.indent_width) { + result.push(' '); + } + } + result.push(ch); + ctx.pop(); + continue; + } + + if ch == ':' { + result.push(ch); + result.push(' '); + continue; + } + + result.push(ch); + } + result.push('\n'); + + result +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct PrettySetting { + pub indent_width: u32, } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 0d56de4..a55b131 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,28 @@ extern crate minjson; - +use std::env; use std::io::Read; use std::io; fn main() -> () { + let args: Vec = env::args().collect(); + if args.len() != 2 || (args[1] != "minify" && args[1] != "pretty") { + eprintln!("Wrong number of arguments"); + eprintln!("Usage: minjson "); + eprintln!(" := minify | pretty"); + return; + } + let mut strbuf = String::new(); io::stdin().read_to_string(&mut strbuf).expect("Unable to read json"); - let res = minjson::minimize_json(&strbuf); + let res: String; + if args[1] == "minify" { + res = minjson::minimize_json(&strbuf); + } else { + res = minjson::pretty_json(&strbuf, &minjson::PrettySetting{indent_width: 2}); + } print!("{}", res); }