Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ded8bf4
feat: view the initial pane on failure or null
ynqa Feb 20, 2026
cf41408
feat: replace stream with init on failure or null
ynqa Feb 22, 2026
af60522
fix: already could have generated jsonstream by given variables
ynqa Feb 22, 2026
ec189d2
on-err: use `termcfg` for configurations
ynqa Feb 23, 2026
25498ca
on-err: replace EventDefSet with HashSet<crossterm::Event>
ynqa Feb 23, 2026
5b79f19
chore: replace EventDefSet with HashSet<crossterm::Event>
ynqa Feb 23, 2026
c55ac10
feat: set style and keybind using easy readable strings
ynqa Feb 23, 2026
ac742b6
docs: update new syntax for configurations
ynqa Feb 23, 2026
4ea3ae8
chore: use official version for termcfg
ynqa Feb 24, 2026
5ee1d59
Merge pull request #106 from ynqa/termcfg
ynqa Feb 25, 2026
826ce64
debug: use local promkit-widgets
ynqa Feb 24, 2026
043e40d
chore: use promkit-widgets v0.2.0 => v0.3.0
ynqa Feb 24, 2026
472dfde
docs: how to set .toml configs
ynqa Feb 24, 2026
3be5b06
feat: use wrap for multiple lines for one field
ynqa Feb 25, 2026
9ca58ea
chore: use official v0.2.0 for termcfg
ynqa Feb 25, 2026
da3c871
docs: config.toml will be revamped in v0.7.0
ynqa Feb 25, 2026
310a843
FIX: apply keybinds for copies and switch-mode
ynqa Feb 25, 2026
c05b72d
feat: enable to scroll using mouse
ynqa Feb 25, 2026
3076255
chore: use official v0.3.0 for promkit-widgets
ynqa Feb 25, 2026
986c14b
fix: use dependencies.promkit-widgets instead
ynqa Feb 25, 2026
5cc5800
fix: use termcfg v0.2.0
ynqa Feb 25, 2026
aba9792
chore: move StdoutRedirect to stdout_redirect.rs
ynqa Feb 25, 2026
074eccf
docs: enable to write output to file
ynqa Feb 25, 2026
522d047
docs: what is stdout
ynqa Feb 25, 2026
0e8e2af
Merge pull request #107 from ynqa/promkit-widgets
ynqa Feb 26, 2026
0908e1a
feat: --write-to-stdout to write result to stdout (UNIX only)
ynqa Feb 25, 2026
d8686c3
chore: use rustix instead of libc
ynqa Feb 25, 2026
4f884f5
docs: configuration
ynqa Mar 1, 2026
1d2b1ec
chore: use promkit-widgets v0.3.1
ynqa Mar 1, 2026
7e78520
Update README.md
ynqa Mar 17, 2026
c32400d
Merge pull request #108 from ynqa/write-to-stdout
ynqa Mar 17, 2026
995f797
chore: bump up widget version to v0.5.0 (local)
ynqa Mar 16, 2026
b46252f
chore: use promkit spinner instead
ynqa Mar 16, 2026
39f8d89
chore: remove duplicated is_idle function
ynqa Mar 17, 2026
a31d4f0
chore: use official promkit versions
ynqa Mar 24, 2026
43a6072
cargo-fmt
ynqa Mar 24, 2026
4303712
Merge pull request #109 from ynqa/bump-up-promkit
ynqa Mar 25, 2026
c2431a2
bump up version to v0.7.0
ynqa Mar 25, 2026
972d5b6
cargo-update
ynqa Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 124 additions & 108 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "jnv"
version = "0.6.2"
version = "0.7.0"
authors = ["ynqa <un.pensiero.vano@gmail.com>"]
edition = "2021"
description = "JSON navigator and interactive filter leveraging jq"
Expand All @@ -12,14 +12,15 @@ readme = "README.md"
anyhow = "1.0.102"
arboard = { version = "3.6.1", features = ["wayland-data-control"] }
async-trait = "0.1.89"
clap = { version = "4.5.60", features = ["derive"] }
clap = { version = "4.6.0", features = ["derive"] }
duration-string = { version = "0.5.3", features = ["serde"] }
derive_builder = "0.20.2"
dirs = "6.0.0"
futures = "0.3.32"
promkit-widgets = { version = "0.2.0", features = ["jsonstream", "listbox", "text", "texteditor"] }
rustix = { version = "1.1.4", features = ["stdio"] }
serde = "1.0.228"
tokio = { version = "1.49.0", features = ["full"] }
termcfg = { version = "0.2.0", features = ["crossterm_0_29_0"] }
tokio = { version = "1.50.0", features = ["full"] }
tokio-stream = "0.1.18"
toml = "0.9.8"

Expand All @@ -28,6 +29,11 @@ jaq-core = "2.2.1"
jaq-json = { version = "1.1.3", features = ["serde_json"] }
jaq-std = "2.1.2"

[dependencies.promkit-widgets]
version = "0.5.0"
features = ["jsonstream", "listbox", "serde", "spinner", "status", "texteditor"]
default-features = false

# The profile that 'cargo dist' will build with
[profile.dist]
inherits = "release"
Expand Down
252 changes: 191 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,14 @@ cargo install jnv

```bash
cat data.json | jnv

# or
jnv data.json

# or write current result to stdout on exit (UNIX only)
cat data.json | jnv --write-to-stdout | some-command
# and also output to file
cat data.json | jnv -- --write-to-stdout > result.json
```

## Keymap
Expand Down Expand Up @@ -180,6 +186,7 @@ Arguments:
Options:
-c, --config <CONFIG_FILE> Path to the configuration file.
--default-filter <DEFAULT_FILTER> Default jq filter to apply to the input data
--write-to-stdout Write the current JSON result to stdout when exiting
-h, --help Print help (see more with '--help')
-V, --version Print version
```
Expand All @@ -204,99 +211,222 @@ the default configuration file location for each platform is as follows:
If the configuration file does not exist,
it will be automatically created on first run.

### Configuration Options
### Configuration

The following settings are available in `config.toml`:
> [!IMPORTANT]
> The syntax in TOML configurations
> like [default.toml](./default.toml) was revamped in v0.7.0,
> and the configuration shown below reflects the new format.
> A migration tool is not provided for this change.
> Please manually replace/update your local
> `config.toml` to match the new syntax.

> [!WARNING]
> Depending on the type of terminal and environment,
> characters and styles may not be displayed properly.
> Specific key bindings and decorative characters may not
> display or function correctly in certain terminal emulators.

<details>
<summary>The following settings are available in config.toml</summary>

```toml
# Whether to hide the hint message
# Whether to hide hint messages
no_hint = false

# Editor settings
[editor]
# Editor mode ("Insert" or "Overwrite")
mode = "Insert"
# Word break characters
# Uses promkit_widgets::text_editor::Config directly
[editor.on_focus]

# Editor mode
# "Insert": Insert characters at the cursor position
# "Overwrite": Replace characters at the cursor position with new ones
edit_mode = "Insert"

# Characters considered as word boundaries
# These are used to define word movement and deletion behavior in the editor
word_break_chars = [".", "|", "(", ")", "[", "]"]

# Theme when editor is focused
[editor.theme_on_focus]
# Style notation (termcfg)
# Format: "fg=<color>,bg=<color>,ul=<color>,attr=<token|token...>"
# Examples:
# - "fg=blue"
# - "fg=#00FF00,bg=black,attr=bold|underlined"
# - "attr=dim"
#
# Color tokens:
# - reset, black, red, green, yellow, blue, magenta, cyan, white
# - darkgrey, darkred, darkgreen, darkyellow, darkblue, darkmagenta, darkcyan, grey
# - #RRGGBB
#
# Attribute tokens (examples):
# - bold, italic, underlined, dim, reverse, crossedout, nounderline, nobold
#
# Notes:
# - ANSI 256-color index tokens (0..255, e.g. "200") are currently out of notation scope.
# - See termcfg notation reference for full token list.
#
# References:
# - https://github.com/ynqa/termcfg/blob/main/Notations.md
# - https://github.com/ynqa/termcfg

# Prefix shown before the cursor
prefix = "❯❯ "
prefix_style = { foreground = "blue" }
active_char_style = { background = "magenta" }
inactive_char_style = {}

# Theme when editor is not focused
[editor.theme_on_defocus]
# Style for the prefix
prefix_style = "fg=blue"
# Style for the character under the cursor
active_char_style = "bg=magenta"
# Style for all other characters
inactive_char_style = ""

# Theme settings when the editor is unfocused
[editor.on_defocus]
# Prefix shown when focus is lost
prefix = "▼ "
prefix_style = { foreground = "blue", attributes = ["Dim"] }
active_char_style = { attributes = ["Dim"] }
inactive_char_style = { attributes = ["Dim"] }
# Style for the prefix when unfocused
prefix_style = "fg=blue,attr=dim"
# Style for the character under the cursor when unfocused
active_char_style = "attr=dim"
# Style for all other characters when unfocused
inactive_char_style = "attr=dim"

# JSON display settings
[json]
# Maximum number of JSON objects to read from stream
# max_streams =
# Maximum number of JSON objects to read from streams (e.g., JSON Lines format)
# Limits how many objects are processed to reduce memory usage when handling large data streams
# No limit if unset
# max_streams =

# JSON theme settings
[json.theme]
# JSON display settings
# Uses promkit_widgets::jsonstream::Config directly
[json.stream]
# Number of spaces to use for indentation
indent = 2
curly_brackets_style = { attributes = ["Bold"] }
square_brackets_style = { attributes = ["Bold"] }
key_style = { foreground = "cyan" }
string_value_style = { foreground = "green" }
number_value_style = {}
boolean_value_style = {}
null_value_style = { foreground = "grey" }
# Style for curly brackets {}
curly_brackets_style = "attr=bold"
# Style for square brackets []
square_brackets_style = "attr=bold"
# Style for JSON keys
key_style = "fg=cyan"
# Style for string values
string_value_style = "fg=green"
# Style for number values
number_value_style = ""
# Style for boolean values
boolean_value_style = ""
# Style for null values
null_value_style = "fg=grey"
# Attribute for the selected row and unselected rows
active_item_attribute = "bold"
# Attribute for unselected rows
inactive_item_attribute = "dim"
# Behavior when JSON content exceeds the available width
# "Wrap": Wrap content to the next line
# "Truncate": Truncate content with an ellipsis (...)
overflow_mode = "Wrap"

# Completion feature settings
[completion]
lines = 3
cursor = "❯ "
active_item_style = { foreground = "grey", background = "yellow" }
inactive_item_style = { foreground = "grey" }
# Settings for background loading of completion candidates
#
# Number of candidates loaded per chunk for search results
# A larger value displays results faster but uses more memory
search_result_chunk_size = 100

# Number of items loaded per batch during background loading
# A larger value finishes loading sooner but uses more memory temporarily
search_load_chunk_size = 50000

# Keybind settings
# Completion UI settings
# Uses promkit_widgets::listbox::Config directly
[completion.listbox]
# Number of lines to display for completion candidates
lines = 3
# Cursor character shown before the selected candidate
cursor = "❯ "
# Style for the selected candidate
active_item_style = "fg=grey,bg=yellow"
# Style for unselected candidates
inactive_item_style = "fg=grey"

# Keybinding settings
[keybinds]
# Application exit key
exit = [{ Key = { modifiers = "CONTROL", code = { Char = "c" } } }]
# Copy query to clipboard key
copy_query = [{ Key = { modifiers = "CONTROL", code = { Char = "q" } } }]
# Copy result to clipboard key
copy_result = [{ Key = { modifiers = "CONTROL", code = { Char = "o" } } }]
# Mode switch keys
switch_mode = [
{ Key = { code = "Down", modifiers = "SHIFT" } },
{ Key = { code = "Up", modifiers = "SHIFT" } }
]

# Editor operation keybinds
# Key to exit the application
exit = ["Ctrl+C"]
# Key to copy the query to the clipboard
copy_query = ["Ctrl+Q"]
# Key to copy the result to the clipboard
copy_result = ["Ctrl+O"]
# Keys to switch focus between editor and JSON viewer
switch_mode = ["Shift+Down", "Shift+Up"]

# Keybindings for editor operations
[keybinds.on_editor]
# (Details omitted)

# JSON viewer keybinds
# Move cursor left
backward = ["Left"]

# Move cursor right
forward = ["Right"]

# Move cursor to beginning of line
move_to_head = ["Ctrl+A"]
# Move cursor to end of line
move_to_tail = ["Ctrl+E"]
# Move cursor to previous word boundary
move_to_previous_nearest = ["Alt+B"]
# Move cursor to next word boundary
move_to_next_nearest = ["Alt+F"]
# Delete character at the cursor
erase = ["Backspace"]

# Delete all input
erase_all = ["Ctrl+U"]

# Delete from cursor to previous word boundary
erase_to_previous_nearest = ["Ctrl+W"]
# Delete from cursor to next word boundary
erase_to_next_nearest = ["Alt+D"]
# Trigger completion
completion = ["Tab"]
# Move up in the completion list
on_completion.up = ["Up"]
# Move down in the completion list
on_completion.down = ["Down", "Tab"]

# Keybindings for JSON viewer operations
[keybinds.on_json_viewer]
# (Details omitted)
# Move up in JSON viewer
up = ["Up", "Ctrl+K", "ScrollUp"]
# Move down in JSON viewer
down = ["Down", "Ctrl+J", "ScrollDown"]
# Move to the top of JSON viewer
move_to_head = ["Ctrl+L"]
# Move to the bottom of JSON viewer
move_to_tail = ["Ctrl+H"]
# Toggle expand/collapse of JSON nodes
toggle = ["Enter"]
# Expand all JSON nodes
expand = ["Ctrl+P"]
# Collapse all JSON nodes
collapse = ["Ctrl+N"]

# Application reactivity settings
[reactivity_control]
# Delay time after query input
# Delay before processing query input
# Prevents excessive updates while user is typing
query_debounce_duration = "600ms"
# Redraw delay time after window resize

# Delay before redrawing after window resize
# Prevents frequent redraws during continuous resizing
resize_debounce_duration = "200ms"
# Spinner animation update interval

# Interval for spinner animation updates
# Controls the speed of the loading spinner
spin_duration = "300ms"
```

For more details on configuration, please refer to [default.toml](./default.toml)

> [!WARNING]
> Depending on the type of terminal and environment,
> characters and styles may not be displayed properly.
> Specific key bindings and decorative characters may not
> display or function correctly in certain terminal emulators.
</details>

## Stargazers over time

[![Stargazers over time](https://starchart.cc/ynqa/jnv.svg?variant=adaptive)](https://starchart.cc/ynqa/jnv)
Loading
Loading