diff --git a/Cargo.lock b/Cargo.lock index 6c14d02..c15dcd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,9 +67,9 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "autotools" @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -171,9 +171,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck", "proc-macro2", @@ -322,9 +322,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "j9" @@ -350,7 +350,7 @@ dependencies = [ [[package]] name = "jnv" -version = "0.2.0" +version = "0.2.1" dependencies = [ "anyhow", "clap", @@ -503,9 +503,9 @@ dependencies = [ [[package]] name = "promkit" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa31233c1a91cf9b5e8753a57b59a3bcca559f45f38da508857fb866635ab92" +checksum = "a5d06099a0a47b6bd7414d6692596b754a12ec4537fc46b72c7363a88fee66d9" dependencies = [ "anyhow", "crossterm", @@ -570,9 +570,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rustc-hash" @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "indexmap", "itoa", diff --git a/Cargo.toml b/Cargo.toml index 4139a9e..2b39a57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jnv" -version = "0.2.0" +version = "0.2.1" authors = ["ynqa "] edition = "2021" description = "JSON navigator and interactive filter leveraging jq" @@ -10,10 +10,10 @@ readme = "README.md" [dependencies] anyhow = "1.0.80" -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5.4", features = ["derive"] } gag = "1.0.0" j9 = "0.1.3" -promkit = "0.3.2" +promkit = "0.3.3" radix_trie = "0.2.1" # The profile that 'cargo dist' will build with diff --git a/README.md b/README.md index 143c6bb..1270956 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # jnv +[![ci](https://github.com/ynqa/jnv/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/ynqa/jnv/actions/workflows/ci.yml) + *jnv* is designed for navigating JSON, offering an interactive JSON viewer and `jq` filter editor. @@ -87,6 +89,10 @@ jnv data.json | Enter | Toggle expand/collapse in JSON viewer | Ctrl + P | Expand all folds in JSON viewer | Ctrl + N | Collapse all folds in JSON viewer +| Alt + B | Move the cursor to the previous nearest character within set(`.`,`\|`,`(`,`)`,`[`,`]`) +| Alt + F | Move the cursor to the next nearest character within set(`.`,`\|`,`(`,`)`,`[`,`]`) +| Ctrl + W | Erase to the previous nearest character within set(`.`,`\|`,`(`,`)`,`[`,`]`) +| Alt + D | Erase to the next nearest character within set(`.`,`\|`,`(`,`)`,`[`,`]`) ## Usage diff --git a/src/jnv.rs b/src/jnv.rs index a5aacbf..4ab8ebf 100644 --- a/src/jnv.rs +++ b/src/jnv.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, collections::HashSet, rc::Rc}; use anyhow::Result; use gag::Gag; @@ -90,6 +90,7 @@ impl Jnv { active_char_style: StyleBuilder::new().bgc(Color::Magenta).build(), inactive_char_style: StyleBuilder::new().build(), edit_mode, + word_break_chars: HashSet::from(['.', '|', '(', ')', '[', ']']), lines: Default::default(), }, hint_message_renderer: text::Renderer { diff --git a/src/jnv/keymap.rs b/src/jnv/keymap.rs index cc48bab..34d3f61 100644 --- a/src/jnv/keymap.rs +++ b/src/jnv/keymap.rs @@ -69,6 +69,24 @@ pub fn default(event: &Event, renderer: &mut crate::jnv::render::Renderer) -> Re state: KeyEventState::NONE, }) => query_editor_after_mut.texteditor.move_to_tail(), + Event::Key(KeyEvent { + code: KeyCode::Char('b'), + modifiers: KeyModifiers::ALT, + kind: KeyEventKind::Press, + state: KeyEventState::NONE, + }) => query_editor_after_mut + .texteditor + .move_to_previous_nearest(&query_editor_after_mut.word_break_chars), + + Event::Key(KeyEvent { + code: KeyCode::Char('f'), + modifiers: KeyModifiers::ALT, + kind: KeyEventKind::Press, + state: KeyEventState::NONE, + }) => query_editor_after_mut + .texteditor + .move_to_next_nearest(&query_editor_after_mut.word_break_chars), + // Erase char(s). Event::Key(KeyEvent { code: KeyCode::Backspace, @@ -83,6 +101,25 @@ pub fn default(event: &Event, renderer: &mut crate::jnv::render::Renderer) -> Re state: KeyEventState::NONE, }) => query_editor_after_mut.texteditor.erase_all(), + // Erase to the nearest character. + Event::Key(KeyEvent { + code: KeyCode::Char('w'), + modifiers: KeyModifiers::CONTROL, + kind: KeyEventKind::Press, + state: KeyEventState::NONE, + }) => query_editor_after_mut + .texteditor + .erase_to_previous_nearest(&query_editor_after_mut.word_break_chars), + + Event::Key(KeyEvent { + code: KeyCode::Char('d'), + modifiers: KeyModifiers::ALT, + kind: KeyEventKind::Press, + state: KeyEventState::NONE, + }) => query_editor_after_mut + .texteditor + .erase_to_next_nearest(&query_editor_after_mut.word_break_chars), + // Move up. Event::Key(KeyEvent { code: KeyCode::Up,