Merge pull request #45 from ynqa/v0.3.0/main

v0.3.0
This commit is contained in:
ynqa
2024-06-02 18:50:25 +09:00
committed by GitHub
6 changed files with 294 additions and 399 deletions

View File

@@ -15,27 +15,6 @@ jobs:
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install clang package
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
autoconf \
libtool \
git \
wget \
software-properties-common
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-add-repository "deb http://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-15 main"
sudo apt-get update
sudo apt-get install -y \
clang-15 \
lldb-15 \
lld-15
- name: Set default compiler to clang
run: |
echo "CC=clang-15" >> $GITHUB_ENV
echo "CXX=clang++-15" >> $GITHUB_ENV
- uses: actions-rs/toolchain@v1
with:
toolchain: stable

405
Cargo.lock generated
View File

@@ -2,6 +2,19 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"getrandom",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.3"
@@ -11,6 +24,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "anstream"
version = "0.6.13"
@@ -72,35 +91,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "autotools"
version = "0.2.7"
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef941527c41b0fc0dd48511a8154cd5fc7e29200a0ff8b7203c5d777dbc795cf"
dependencies = [
"cc",
]
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bindgen"
version = "0.69.4"
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"bitflags 2.5.0",
"cexpr",
"clang-sys",
"itertools",
"lazy_static",
"lazycell",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
"which",
"serde",
]
[[package]]
@@ -115,21 +117,6 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "cc"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -137,14 +124,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.7.0"
name = "chumsky"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
dependencies = [
"glob",
"libc",
"libloading",
"hashbrown",
]
[[package]]
@@ -220,10 +205,19 @@ dependencies = [
]
[[package]]
name = "either"
version = "1.11.0"
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "dyn-clone"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
[[package]]
name = "endian-type"
@@ -237,22 +231,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "fastrand"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
[[package]]
name = "filedescriptor"
version = "0.8.2"
@@ -265,26 +243,25 @@ dependencies = [
]
[[package]]
name = "gag"
version = "1.0.0"
name = "getrandom"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a713bee13966e9fbffdf7193af71d54a6b35a0bb34997cd6c9519ebeb5005972"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
dependencies = [
"filedescriptor",
"tempfile",
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "heck"
@@ -293,13 +270,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "home"
version = "0.5.9"
name = "hifijson"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
checksum = "18ae468bcb4dfecf0e4949ee28abbc99076b6a0077f51ddbc94dbfff8e6a870c"
[[package]]
name = "indexmap"
@@ -311,15 +285,6 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
@@ -327,51 +292,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "j9"
version = "0.1.3"
name = "jaq-core"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c2876f6d536ef88276de82d5c4c76a463b9f7ebaee288b49284aeacfca7b699"
checksum = "03d6a5713b8f33675abfac79d1db0022a3f28764b2a6b96a185c199ad8dab86d"
dependencies = [
"j9-sys",
"thiserror",
"aho-corasick",
"base64",
"hifijson",
"jaq-interpret",
"libm",
"log",
"regex",
"time",
"urlencoding",
]
[[package]]
name = "j9-sys"
version = "0.1.3"
name = "jaq-interpret"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe8caa9c5f8d1b56e4191614bed237d2f9081d933ac3884cafab1100f37d0afd"
checksum = "f569e38e5fc677db8dfda89ee0b4c25b3f53e811b16434fd14bdc5b43fc362ac"
dependencies = [
"anyhow",
"autotools",
"bindgen",
"walkdir",
"ahash",
"dyn-clone",
"hifijson",
"indexmap",
"jaq-syn",
"once_cell",
"serde_json",
]
[[package]]
name = "jaq-parse"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef6f8beb9f9922546419e774e24199e8a968f54c63a5a2323c8f3ef3321ace14"
dependencies = [
"chumsky",
"jaq-syn",
]
[[package]]
name = "jaq-std"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d7871c59297cbfdd18f6f1bbbafaad24e97fd555ee1e2a1be7a40a5a20f551a"
dependencies = [
"bincode",
"jaq-parse",
"jaq-syn",
]
[[package]]
name = "jaq-syn"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4d60101fb791b20c982731d848ed6e7d25363656497647c2093b68bd88398d6"
dependencies = [
"serde",
]
[[package]]
name = "jnv"
version = "0.2.3"
version = "0.3.0"
dependencies = [
"anyhow",
"clap",
"gag",
"j9",
"jaq-core",
"jaq-interpret",
"jaq-parse",
"jaq-std",
"promkit",
"radix_trie",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.153"
@@ -379,20 +374,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libloading"
version = "0.8.3"
name = "libm"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [
"cfg-if",
"windows-targets 0.52.5",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "lock_api"
@@ -416,12 +401,6 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "mio"
version = "0.8.11"
@@ -444,14 +423,10 @@ dependencies = [
]
[[package]]
name = "nom"
version = "7.1.3"
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "once_cell"
@@ -483,14 +458,10 @@ dependencies = [
]
[[package]]
name = "prettyplease"
version = "0.2.19"
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ac2cf0f2e4f42b49f5ffd07dae8d746508ef7526c13940e5f524012ae6c6550"
dependencies = [
"proc-macro2",
"syn",
]
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
@@ -573,40 +544,12 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89"
dependencies = [
"bitflags 2.5.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "ryu"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -645,12 +588,6 @@ dependencies = [
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
version = "0.3.17"
@@ -704,18 +641,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if",
"fastrand",
"rustix",
"windows-sys 0.52.0",
]
[[package]]
name = "thiserror"
version = "1.0.59"
@@ -736,6 +661,37 @@ dependencies = [
"syn",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
@@ -748,6 +704,12 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "utf8parse"
version = "0.2.1"
@@ -755,14 +717,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "walkdir"
version = "2.5.0"
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi-util",
]
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
@@ -770,18 +728,6 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "winapi"
version = "0.3.9"
@@ -798,15 +744,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -951,3 +888,23 @@ name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@@ -1,6 +1,6 @@
[package]
name = "jnv"
version = "0.2.3"
version = "0.3.0"
authors = ["ynqa <un.pensiero.vano@gmail.com>"]
edition = "2021"
description = "JSON navigator and interactive filter leveraging jq"
@@ -11,8 +11,10 @@ readme = "README.md"
[dependencies]
anyhow = "1.0.82"
clap = { version = "4.5.4", features = ["derive"] }
gag = "1.0.0"
j9 = "0.1.3"
jaq-core = "1.2.1"
jaq-interpret = "1.2.1"
jaq-parse = "1.0.2"
jaq-std = "1.2.1"
promkit = "0.4.3"
radix_trie = "0.2.1"
@@ -32,11 +34,8 @@ installers = ["homebrew"]
# A GitHub repo to push Homebrew formulas to
tap = "ynqa/homebrew-tap"
# Target platforms to build apps for (Rust target-triple syntax)
targets = ["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]
targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]
# Publish jobs to run in CI
publish-jobs = ["homebrew"]
# Publish jobs to run in CI
pr-run-mode = "plan"
[workspace.metadata.dist.dependencies.homebrew]
automake = '*'

View File

@@ -14,6 +14,22 @@ and [jiq](https://github.com/fiatjaf/jiq).
- Interactive JSON viewer and `jq` filter editor
- Syntax highlighting for JSON
- Use [jaq](https://github.com/01mf02/jaq) to apply `jq` filter
- This eliminates the need for users to prepare `jq` on their own.
> [!IMPORTANT]
> Starting from v0.3.0, the transition from libjq Rust binding
> [j9](https://github.com/ynqa/j9) to jq clone
> [jaq](https://github.com/01mf02/jaq) was made.
>
> This change eliminated the need to manage C-related dependencies
> that include external tools like autoconf, thus simplifying the build process.
> However, please note that some filters are not yet supported by jaq.
> For more details, refer to GitHub issue
> [#24](https://github.com/ynqa/jnv/issues/24).
>
> Please continue to provide feedback regarding this transition.
- Capable of accommodating various format
- Input: File, Stdin
- Data: A JSON or multiple JSON structures
@@ -61,21 +77,10 @@ nix-shell -p jnv
### Cargo
#### Requirements
- [autoconf](https://www.gnu.org/software/autoconf/)
- [automake](https://www.gnu.org/software/automake/)
- [libtool](https://www.gnu.org/software/libtool/)
- [clang](https://clang.llvm.org/)
```bash
cargo install jnv
```
> [!NOTE]
> *jnv* does not require users to install `jq` on their system,
> because it utilizes [j9](https://github.com/ynqa/j9) Rust bindings.
## Examples
```bash
@@ -127,39 +132,23 @@ Examples:
cat data.json | jnv
Arguments:
[INPUT]
Optional path to a JSON file. If not provided or if "-" is specified, reads from standard input
[INPUT] Optional path to a JSON file. If not provided or if "-" is specified, reads from standard input
Options:
-e, --edit-mode <EDIT_MODE>
Specifies the edit mode for the interface.
Acceptable values are "insert" or "overwrite".
- "insert" inserts a new input at the cursor's position.
- "overwrite" mode replaces existing characters with new input at the cursor's position.
[default: insert]
Edit mode for the interface ('insert' or 'overwrite'). [default: insert]
-i, --indent <INDENT>
Affect the formatting of the displayed JSON,
making it more readable by adjusting the indentation level.
[default: 2]
Number of spaces used for indentation in the visualized data. [default: 2]
-n, --no-hint
When this option is enabled, it prevents the display of
hints that typically guide or offer suggestions to the user.
-d, --expand-depth <EXPAND_DEPTH>
Specifies the initial depth to which JSON nodes are expanded in the visualization.
Note: Increasing this depth can significantly slow down the display for large datasets.
[default: 3]
Disables the display of hints.
-d, --expand-depth <JSON_EXPAND_DEPTH>
Initial depth to which JSON nodes are expanded in the visualization. [default: 3]
-s, --limit-length <JSON_LIMIT_LENGTH>
Limit length of JSON array in the visualization. [default: 50]
-l, --suggestion-list-length <SUGGESTION_LIST_LENGTH>
Controls the number of suggestions displayed in the list,
aiding users in making selections more efficiently.
[default: 3]
Number of suggestions visible in the list. [default: 3]
-h, --help
Print help (see a summary with '-h')
Print help (see more with '--help')
-V, --version
Print version
```

View File

@@ -1,7 +1,8 @@
use std::cell::RefCell;
use anyhow::Result;
use gag::Gag;
use jaq_interpret::{Ctx, FilterT, ParseCtx, RcIter, Val};
use promkit::{
crossterm::{
@@ -11,7 +12,7 @@ use promkit::{
json::{self, JsonNode, JsonPathSegment, JsonStream},
listbox,
pane::Pane,
serde_json::{self, Deserializer},
serde_json,
snapshot::Snapshot,
style::StyleBuilder,
suggest::Suggest,
@@ -23,64 +24,37 @@ use crate::trie::FilterTrie;
mod keymap;
/// Deserializes a JSON string into a vector of `serde_json::Value`.
///
/// This function takes a JSON string as input and attempts to parse it into a vector
/// of `serde_json::Value`, which represents any valid JSON value (e.g., object, array, string, number).
/// It leverages `serde_json::Deserializer` to parse the string and collect the results.
///
/// # Arguments
/// * `json_str` - A string slice that holds the JSON data to be deserialized.
///
/// # Returns
/// An `anyhow::Result` wrapping a vector of `serde_json::Value`. On success, it contains the parsed
/// JSON data. On failure, it contains an error detailing what went wrong during parsing.
fn deserialize_json(
json_str: &str,
limit_length: Option<usize>,
fn run_jaq(
query: &str,
json_stream: Vec<serde_json::Value>,
) -> anyhow::Result<Vec<serde_json::Value>> {
let deserializer = Deserializer::from_str(json_str).into_iter::<serde_json::Value>();
let results = match limit_length {
Some(l) => deserializer.take(l).collect::<Result<Vec<_>, _>>(),
None => deserializer.collect::<Result<Vec<_>, _>>(),
};
results.map_err(anyhow::Error::from)
}
let mut ret = Vec::<serde_json::Value>::new();
fn run_jq(query: &str, json_stream: &[serde_json::Value]) -> anyhow::Result<Vec<String>> {
// libjq writes to the console when an internal error occurs.
//
// e.g.
// ```
// let _ = j9::run(". | select(.number == invalid_no_quote)", "{}");
// jq: error: invalid_no_quote/0 is not defined at <top-level>, line 1:
// . | select(.number == invalid_no_quote)
// ```
//
// While errors themselves are not an issue,
// they interfere with the console output handling mechanism
// in promkit and qjq (e.g., causing line numbers to shift).
// Therefore, we'll ignore console output produced inside j9::run.
//
// It's possible that this could be handled
// within github.com/ynqa/j9, but for now,
// we'll proceed with this workaround.
//
// For reference, the functionality of a quiet mode in libjq is
// also being discussed at https://github.com/jqlang/jq/issues/1225.
let ignore_err = Gag::stderr().unwrap();
let mut jq_ret = Vec::<String>::new();
for v in json_stream.iter() {
let inner_ret: Vec<String> = match j9::run(query, &v.to_string()) {
Ok(ret) => ret,
Err(e) => {
return Err(anyhow::anyhow!(e));
}
};
jq_ret.extend(inner_ret);
for input in json_stream {
let mut ctx = ParseCtx::new(Vec::new());
ctx.insert_natives(jaq_core::core());
ctx.insert_defs(jaq_std::std());
let (f, errs) = jaq_parse::parse(query, jaq_parse::main());
if !errs.is_empty() {
let error_message = errs
.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(", ");
return Err(anyhow::anyhow!(error_message));
}
let f = ctx.compile(f.unwrap());
let inputs = RcIter::new(core::iter::empty());
let mut out = f.run((Ctx::new([], &inputs), Val::from(input)));
while let Some(Ok(val)) = out.next() {
ret.push(val.into());
}
}
drop(ignore_err);
Ok(jq_ret)
Ok(ret)
}
pub struct JsonTheme {
@@ -132,24 +106,20 @@ pub struct Jnv {
suggest: Suggest,
json_expand_depth: Option<usize>,
json_limit_length: Option<usize>,
no_hint: bool,
}
impl Jnv {
#[allow(clippy::too_many_arguments)]
pub fn try_new(
input: String,
input_stream: Vec<serde_json::Value>,
filter_editor: text_editor::State,
hint_message: text::State,
suggestions: listbox::State,
json_theme: JsonTheme,
json_expand_depth: Option<usize>,
json_limit_length: Option<usize>,
no_hint: bool,
) -> Result<Prompt<Self>> {
let input_stream = deserialize_json(&input, json_limit_length)?;
let mut trie = FilterTrie::default();
trie.insert(".", input_stream.clone());
@@ -209,7 +179,6 @@ impl Jnv {
trie,
suggest,
json_expand_depth,
json_limit_length,
no_hint,
input_stream,
},
@@ -284,7 +253,7 @@ impl promkit::Renderer for Jnv {
);
}
None => {
match run_jq(&filter, &self.input_stream) {
match run_jaq(&filter, self.input_stream.clone()) {
Ok(ret) => {
if ret.is_empty() {
self.update_hint_message(
@@ -302,53 +271,30 @@ impl promkit::Renderer for Jnv {
JsonStream::new(searched.clone(), self.json_expand_depth);
}
} else {
match deserialize_json(&ret.join("\n"), self.json_limit_length) {
Ok(jsonl) => {
let stream =
JsonStream::new(jsonl.clone(), self.json_expand_depth);
let stream = JsonStream::new(ret.clone(), self.json_expand_depth);
let is_null = stream.roots().iter().all(|node| {
node == &JsonNode::Leaf(serde_json::Value::Null)
});
if is_null {
self.update_hint_message(
format!("JSON query resulted in 'null', which may indicate a typo or incorrect query: '{}'", &filter),
StyleBuilder::new()
.fgc(Color::Yellow)
.attrs(Attributes::from(Attribute::Bold))
.build(),
);
if let Some(searched) = self.trie.prefix_search(&filter)
{
self.json.stream = JsonStream::new(
searched.clone(),
self.json_expand_depth,
);
}
} else {
// SUCCESS!
self.trie.insert(&filter, jsonl);
self.json.stream = stream;
}
}
Err(e) => {
self.update_hint_message(
format!(
"Failed to parse query result for viewing: {}",
e
),
StyleBuilder::new()
.fgc(Color::Red)
.attrs(Attributes::from(Attribute::Bold))
.build(),
let is_null = stream
.roots()
.iter()
.all(|node| node == &JsonNode::Leaf(serde_json::Value::Null));
if is_null {
self.update_hint_message(
format!("JSON query resulted in 'null', which may indicate a typo or incorrect query: '{}'", &filter),
StyleBuilder::new()
.fgc(Color::Yellow)
.attrs(Attributes::from(Attribute::Bold))
.build(),
);
if let Some(searched) = self.trie.prefix_search(&filter) {
self.json.stream = JsonStream::new(
searched.clone(),
self.json_expand_depth,
);
if let Some(searched) = self.trie.prefix_search(&filter) {
self.json.stream = JsonStream::new(
searched.clone(),
self.json_expand_depth,
);
}
}
} else {
// SUCCESS!
self.trie.insert(&filter, ret);
self.json.stream = stream;
}
}
}

View File

@@ -11,6 +11,7 @@ use clap::Parser;
use promkit::{
crossterm::style::{Attribute, Attributes, Color},
listbox,
serde_json::{self, Deserializer},
style::StyleBuilder,
text, text_editor,
};
@@ -158,10 +159,35 @@ fn parse_input(args: &Args) -> Result<String> {
Ok(ret)
}
/// Deserializes a JSON string into a vector of `serde_json::Value`.
///
/// This function takes a JSON string as input and attempts to parse it into a vector
/// of `serde_json::Value`, which represents any valid JSON value (e.g., object, array, string, number).
/// It leverages `serde_json::Deserializer` to parse the string and collect the results.
///
/// # Arguments
/// * `json_str` - A string slice that holds the JSON data to be deserialized.
///
/// # Returns
/// An `anyhow::Result` wrapping a vector of `serde_json::Value`. On success, it contains the parsed
/// JSON data. On failure, it contains an error detailing what went wrong during parsing.
fn deserialize_json(
json_str: &str,
limit_length: Option<usize>,
) -> anyhow::Result<Vec<serde_json::Value>> {
let deserializer = Deserializer::from_str(json_str).into_iter::<serde_json::Value>();
let results = match limit_length {
Some(l) => deserializer.take(l).collect::<Result<Vec<_>, _>>(),
None => deserializer.collect::<Result<Vec<_>, _>>(),
};
results.map_err(anyhow::Error::from)
}
fn main() -> Result<()> {
let args = Args::parse();
let input = parse_input(&args)?;
let input_stream = deserialize_json(&input, args.json_limit_length)?;
let filter_editor = text_editor::State {
texteditor: Default::default(),
@@ -216,13 +242,12 @@ fn main() -> Result<()> {
};
let mut prompt = Jnv::try_new(
input,
input_stream,
filter_editor,
hint_message,
suggestions,
json_theme,
args.json_expand_depth,
args.json_limit_length,
args.no_hint,
)?;
let _ = prompt.run()?;