mirror of
https://github.com/Noratrieb/jsonformat.git
synced 2026-01-14 22:25:01 +01:00
options
This commit is contained in:
parent
d0733b1a7c
commit
9b7260660e
5 changed files with 320 additions and 30 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -3,4 +3,7 @@
|
|||
*.iml
|
||||
|
||||
# test data
|
||||
*.json
|
||||
*.json
|
||||
|
||||
# local install script
|
||||
install.sh
|
||||
248
Cargo.lock
generated
248
Cargo.lock
generated
|
|
@ -1,5 +1,253 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.0-beta.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonformat"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ description = "Reads raw json from stdin and formats it to stdout"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = "3.0.0-beta.2"
|
||||
70
src/lib.rs
70
src/lib.rs
|
|
@ -1,5 +1,14 @@
|
|||
pub fn format_json(json: &str, indent_str: &str) -> String {
|
||||
let mut out = String::with_capacity(json.len()); // at least as big as the input
|
||||
///
|
||||
/// # Formats a json string
|
||||
///
|
||||
/// The indentation can be set to any custom value
|
||||
/// The default value is two spaces
|
||||
/// The default indentation is faster than a custom one
|
||||
///
|
||||
pub fn format_json(json: &str, indentation: Option<&str>) -> String {
|
||||
// at least as big as the input to avoid resizing
|
||||
// this might be too big if the input string is formatted in a weird way, but that's not expected
|
||||
let mut out = String::with_capacity(json.len());
|
||||
|
||||
let mut escaped = false;
|
||||
let mut in_string = false;
|
||||
|
|
@ -42,9 +51,9 @@ pub fn format_json(json: &str, indent_str: &str) -> String {
|
|||
'}' | ']' => {
|
||||
indent_level -= 1;
|
||||
if !newline_requested {
|
||||
// see comment above
|
||||
// see comment below about newline_requested
|
||||
out.push('\n');
|
||||
indent(&mut out, indent_level, indent_str);
|
||||
indent(&mut out, indent_level, indentation);
|
||||
}
|
||||
}
|
||||
':' => {
|
||||
|
|
@ -59,8 +68,10 @@ pub fn format_json(json: &str, indent_str: &str) -> String {
|
|||
}
|
||||
if newline_requested && char != ']' && char != '}' {
|
||||
// newline only happens after { [ and ,
|
||||
// this means we can safely assume that it being followed up by } or ]
|
||||
// means an empty object/array
|
||||
out.push('\n');
|
||||
indent(&mut out, old_level, indent_str);
|
||||
indent(&mut out, old_level, indentation);
|
||||
}
|
||||
|
||||
if auto_push {
|
||||
|
|
@ -74,76 +85,83 @@ pub fn format_json(json: &str, indent_str: &str) -> String {
|
|||
out
|
||||
}
|
||||
|
||||
fn indent(buf: &mut String, level: usize, indent_str: &str) {
|
||||
fn indent(buf: &mut String, level: usize, indent_str: Option<&str>) {
|
||||
for _ in 0..level {
|
||||
buf.push_str(indent_str);
|
||||
match indent_str {
|
||||
None => {
|
||||
buf.push(' ');
|
||||
buf.push(' ');
|
||||
}
|
||||
Some(indent) => {
|
||||
buf.push_str(indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
const INDENT: &str = " ";
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn echoes_primitive() {
|
||||
let json = "1.35";
|
||||
assert_eq!(json, format_json(json, INDENT));
|
||||
assert_eq!(json, format_json(json, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_whitespace_in_string() {
|
||||
let json = "\" hallo \"";
|
||||
assert_eq!(json, format_json(json, INDENT));
|
||||
assert_eq!(json, format_json(json, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_leading_whitespace() {
|
||||
let json = " 0";
|
||||
let expected = "0";
|
||||
assert_eq!(expected, format_json(json, INDENT));
|
||||
assert_eq!(expected, format_json(json, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handle_escaped_strings() {
|
||||
let json = " \" hallo \\\" \" ";
|
||||
let expected = "\" hallo \\\" \"";
|
||||
assert_eq!(expected, format_json(json, INDENT));
|
||||
assert_eq!(expected, format_json(json, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_object() {
|
||||
let json = "{\"a\":0}";
|
||||
let expected = "{
|
||||
\"a\": 0
|
||||
\"a\": 0
|
||||
}";
|
||||
assert_eq!(expected, format_json(json, INDENT));
|
||||
assert_eq!(expected, format_json(json, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_array() {
|
||||
let json = "[1,2,null]";
|
||||
let expected = "[
|
||||
1,
|
||||
2,
|
||||
null
|
||||
1,
|
||||
2,
|
||||
null
|
||||
]";
|
||||
assert_eq!(expected, format_json(json, INDENT));
|
||||
assert_eq!(expected, format_json(json, None));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_of_object() {
|
||||
let json = "[{\"a\": 0}, {}, {\"a\": null}]";
|
||||
let expected = "[
|
||||
{
|
||||
\"a\": 0
|
||||
},
|
||||
{},
|
||||
{
|
||||
\"a\": null
|
||||
}
|
||||
{
|
||||
\"a\": 0
|
||||
},
|
||||
{},
|
||||
{
|
||||
\"a\": null
|
||||
}
|
||||
]";
|
||||
|
||||
assert_eq!(expected, format_json(json, INDENT));
|
||||
assert_eq!(expected, format_json(json, None));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
src/main.rs
26
src/main.rs
|
|
@ -1,12 +1,21 @@
|
|||
use clap::clap_app;
|
||||
use jsonformat::format_json;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
|
||||
fn main() -> Result<(), io::Error> {
|
||||
let filename = std::env::args().skip(1).next();
|
||||
let matches = clap_app!(jsonformat =>
|
||||
(version: "1.0")
|
||||
(author: "nilstrieb <nilstrieb@gmail.com>")
|
||||
(about: "Formats json")
|
||||
(@arg indentation: -i --indent +takes_value "Set the indentation used (\\s for space, \\t for tab)")
|
||||
(@arg output: -o --output +takes_value "The output file for the formatted json")
|
||||
(@arg input: "The input file to format")
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let str = match filename {
|
||||
let str = match matches.value_of("input") {
|
||||
Some(path) => fs::read_to_string(path)?,
|
||||
None => {
|
||||
let mut buf = String::new();
|
||||
|
|
@ -16,7 +25,18 @@ fn main() -> Result<(), io::Error> {
|
|||
}
|
||||
};
|
||||
|
||||
println!("{}", format_json(&str, " "));
|
||||
let replaced_indent = matches
|
||||
.value_of("indentation")
|
||||
.map(|value| value.replace("s", " ").replace("t", "\t"));
|
||||
|
||||
let formatted = format_json(&str, replaced_indent.as_deref());
|
||||
|
||||
match matches.value_of("output") {
|
||||
Some(file) => {
|
||||
fs::write(file, formatted)?;
|
||||
}
|
||||
None => println!("{}", formatted),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue