Repository: ynqa/jnv (language: rust)

Issue:
How about replacement `jq` with `jaq`?
At the time of v0.1.0, the author deemed it most appropriate to use the original jq.

However, managing C-related stuff during build time had to be undertaken, and this was underestimated at the release of v0.1.0. After actually releasing and taking a look the installation error issues that were raised, it became apparent that continuing to use jq might not be the best decision.

Then, there is a project in Rust called [jaq](https://github.com/01mf02/jaq), which is a jq-clone. I hope to discuss whether or not to replace jq with jaq, and whether it is feasible to do so.

Here's a rough outline of the pros and cons:

[jq](https://github.com/jqlang/jq) ([j9](https://github.com/ynqa/j9))
- pros
  - As an original implementation, all filters defined here are, of course, available for use
- cons
  - Requires management of C dependencies, which might pose issues during build phase
    - https://github.com/ynqa/jnv/issues/6
    - https://github.com/ynqa/jnv/issues/13
    - https://github.com/ynqa/jnv/issues/1

[jaq](https://github.com/01mf02/jaq)
- pros
  - pure Rust, there is no need to manage C dependencies
- cons
  - jq-clone, not all filters may be supported
     - e.g. https://github.com/01mf02/jaq/issues/112
     - My concern is with this point. Ideally, it would be better if all features were available for use (Or maybe it's sufficient if only the basic filters are available...?)


Discussion / hints:
I say it’s okay to have *jaq*’s reduced set of available filters, if more people can build and use *jnv*. 😊
I agree with @dwvisser and would personally prefer an easy-to-build pure rust tool over packaging C deps. `ripgrep` took a similar approach where the rust `regex` crate they use lacks some features (eg look-ahead/behind is not supported) but in return doesn't depend on C.
I would like to start using this tool if it was pure Rust. Even if there weren't a complete match of filters.

jq was unmaintained entirely for a number of years, which should be considered under Cons. They had to make a point release to fix a security issue in the update they made. 

At least if you only have Rust dependencies it will be easier to manage if such a situation happens again.
Can you maybe try out how it works with jaq, allowing choice of jaq and jaq, then deprecate jq if jaq is good enough.
I'm also having some issues compiling j9-sys

https://github.com/conda-forge/staged-recipes/pull/25806#issuecomment-2041434460

```
checking host system type... 
  --- stderr
  configure.ac:11: installing 'config/ar-lib'
  configure.ac:8: installing 'config/compile'
  configure.ac:19: installing 'config/config.guess'
  configure.ac:19: installing 'config/config.sub'
  configure.ac:9: installing 'config/install-sh'
  configure.ac:9: installing 'config/missing'
  Makefile.am: installing 'config/depcomp'
  configure.ac: installing 'config/ylwrap'
  parallel-tests: installing 'config/test-driver'
  Invalid configuration `/home/conda/staged-recipes/build_artifacts/jnv_1712488275842/_build_env/bin/x86_64-conda-linux-gnu': more than four components
  configure: error: /bin/sh /home/conda/staged-recipes/build_artifacts/jnv_1712488275842/work/target/x86_64-unknown-linux-gnu/release/build/j9-sys-b50a7ed31c9b8fd9/out/jq_build/config/config.sub /home/conda/staged-recipes/build_artifacts/jnv_1712488275842/_build_env/bin/x86_64-conda-linux-gnu failed
  thread 'main' panicked at /home/conda/staged-recipes/build_artifacts/jnv_1712488275842/_build_env/.cargo/registry/src/index.crates.io-6f17d22bba15001f/autotools-0.2.6/src/lib.rs:781:5:
```

Switching to `jaq` would fix this 😅 

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 924e7c9..84ffca2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -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
diff --git a/Cargo.lock b/Cargo.lock
index f8624ef..6c4778c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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 = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
+name = "dyn-clone"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
+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"
@@ -312,66 +286,87 @@ dependencies = [
 ]
 
 [[package]]
-name = "itertools"
-version = "0.12.1"
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "jaq-core"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+checksum = "03d6a5713b8f33675abfac79d1db0022a3f28764b2a6b96a185c199ad8dab86d"
 dependencies = [
- "either",
+ "aho-corasick",
+ "base64",
+ "hifijson",
+ "jaq-interpret",
+ "libm",
+ "log",
+ "regex",
+ "time",
+ "urlencoding",
 ]
 
 [[package]]
-name = "itoa"
-version = "1.0.11"
+name = "jaq-interpret"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+checksum = "f569e38e5fc677db8dfda89ee0b4c25b3f53e811b16434fd14bdc5b43fc362ac"
+dependencies = [
+ "ahash",
+ "dyn-clone",
+ "hifijson",
+ "indexmap",
+ "jaq-syn",
+ "once_cell",
+ "serde_json",
+]
 
 [[package]]
-name = "j9"
-version = "0.1.3"
+name = "jaq-parse"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c2876f6d536ef88276de82d5c4c76a463b9f7ebaee288b49284aeacfca7b699"
+checksum = "ef6f8beb9f9922546419e774e24199e8a968f54c63a5a2323c8f3ef3321ace14"
 dependencies = [
- "j9-sys",
- "thiserror",
+ "chumsky",
+ "jaq-syn",
 ]
 
 [[package]]
-name = "j9-sys"
-version = "0.1.3"
+name = "jaq-std"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe8caa9c5f8d1b56e4191614bed237d2f9081d933ac3884cafab1100f37d0afd"
+checksum = "5d7871c59297cbfdd18f6f1bbbafaad24e97fd555ee1e2a1be7a40a5a20f551a"
 dependencies = [
- "anyhow",
- "autotools",
- "bindgen",
- "walkdir",
+ "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"
-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"
+name = "libm"
+version = "0.2.8"
 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",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 3a95a03..c89c896 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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 = '*'
diff --git a/README.md b/README.md
index 305a2d2..7de78ac 100644
--- a/README.md
+++ b/README.md
@@ -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
 ```
diff --git a/src/jnv.rs b/src/jnv.rs
index 4bd5c88..792b921 100644
--- a/src/jnv.rs
+++ b/src/jnv.rs
@@ -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;
                                 }
                             }
                         }
diff --git a/src/main.rs b/src/main.rs
index 70064aa..d575c92 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -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()?;


Test patch: