diff --git a/src/jnv.rs b/src/jnv.rs index ae45e11..5c65815 100644 --- a/src/jnv.rs +++ b/src/jnv.rs @@ -19,7 +19,7 @@ use promkit::{ text, text_editor, PaneFactory, Prompt, PromptSignal, }; -use crate::trie::QueryTrie; +use crate::trie::FilterTrie; mod keymap; @@ -67,29 +67,37 @@ fn run_jq(query: &str, json_stream: &[serde_json::Value]) -> anyhow::Result, + + // Keybindings keymap: RefCell>, - query_editor_snapshot: Snapshot, - hint_message_snapshot: Snapshot, - suggest: Suggest, - suggest_state: listbox::State, + + // For Rendering + filter_editor: Snapshot, + hint_message: Snapshot, + suggestions: listbox::State, json_state: json::State, - trie: QueryTrie, - input_json_stream: Vec, + + // Store the filter history + trie: FilterTrie, + // Store the filter suggestions + suggest: Suggest, + expand_depth: Option, no_hint: bool, } impl Jnv { pub fn try_new( - input_json_str: String, + input: String, expand_depth: Option, no_hint: bool, edit_mode: text_editor::Mode, indent: usize, suggestion_list_length: usize, ) -> Result> { - let stream = deserialize_json(&input_json_str)?; - let all_kinds = JsonStream::new(stream.clone(), None).flatten_kinds(); + let input_stream = deserialize_json(&input)?; + let all_kinds = JsonStream::new(input_stream.clone(), None).flatten_kinds(); let suggestions = all_kinds .iter() .filter_map(|kind| kind.path()) @@ -126,7 +134,7 @@ impl Jnv { ActiveKeySwitcher::new("default", self::keymap::default as keymap::Keymap) .register("on_suggest", self::keymap::on_suggest), ), - query_editor_snapshot: Snapshot::::new(text_editor::State { + filter_editor: Snapshot::::new(text_editor::State { texteditor: Default::default(), history: Default::default(), prefix: String::from("❯❯ "), @@ -138,15 +146,14 @@ impl Jnv { word_break_chars: HashSet::from(['.', '|', '(', ')', '[', ']']), lines: Default::default(), }), - hint_message_snapshot: Snapshot::::new(text::State { + hint_message: Snapshot::::new(text::State { text: Default::default(), style: StyleBuilder::new() .fgc(Color::Green) .attrs(Attributes::from(Attribute::Bold)) .build(), }), - suggest: Suggest::from_iter(suggestions), - suggest_state: listbox::State { + suggestions: listbox::State { listbox: listbox::Listbox::from_iter(Vec::::new()), cursor: String::from("❯ "), active_item_style: StyleBuilder::new() @@ -157,7 +164,7 @@ impl Jnv { lines: Some(suggestion_list_length), }, json_state: json::State { - stream: JsonStream::new(stream.clone(), expand_depth), + stream: JsonStream::new(input_stream.clone(), expand_depth), theme: json::Theme { curly_brackets_style: StyleBuilder::new() .attrs(Attributes::from(Attribute::Bold)) @@ -176,17 +183,18 @@ impl Jnv { indent, }, }, - trie: QueryTrie::default(), - input_json_stream: stream, + trie: FilterTrie::default(), + suggest: Suggest::from_iter(suggestions), expand_depth, no_hint, + input_stream, }, }) } fn update_hint_message(&mut self, text: String, style: ContentStyle) { if !self.no_hint { - self.hint_message_snapshot + self.hint_message .after_mut() .replace(text::State { text, style }) } @@ -198,7 +206,7 @@ impl promkit::Finalizer for Jnv { fn finalize(&self) -> anyhow::Result { Ok(self - .query_editor_snapshot + .filter_editor .after() .texteditor .text_without_cursor() @@ -209,9 +217,9 @@ impl promkit::Finalizer for Jnv { impl promkit::Renderer for Jnv { fn create_panes(&self, width: u16, height: u16) -> Vec { vec![ - self.query_editor_snapshot.create_pane(width, height), - self.hint_message_snapshot.create_pane(width, height), - self.suggest_state.create_pane(width, height), + self.filter_editor.create_pane(width, height), + self.hint_message.create_pane(width, height), + self.suggestions.create_pane(width, height), self.json_state.create_pane(width, height), ] } @@ -220,7 +228,7 @@ impl promkit::Renderer for Jnv { let keymap = *self.keymap.borrow_mut().get(); let signal = keymap(event, self); let completed = self - .query_editor_snapshot + .filter_editor .after() .texteditor .text_without_cursor() @@ -229,15 +237,15 @@ impl promkit::Renderer for Jnv { // Check if the query has changed if completed != self - .query_editor_snapshot + .filter_editor .borrow_before() .texteditor .text_without_cursor() .to_string() { - self.hint_message_snapshot.reset_after_to_init(); + self.hint_message.reset_after_to_init(); - match run_jq(&completed, &self.input_json_stream) { + match run_jq(&completed, &self.input_stream) { Ok(ret) => { if ret.is_empty() { self.update_hint_message( diff --git a/src/jnv/keymap.rs b/src/jnv/keymap.rs index e2993e2..317db63 100644 --- a/src/jnv/keymap.rs +++ b/src/jnv/keymap.rs @@ -7,7 +7,7 @@ use promkit::{ pub type Keymap = fn(&Event, &mut crate::jnv::Jnv) -> anyhow::Result; pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result { - let query_editor_after_mut = jnv.query_editor_snapshot.after_mut(); + let filter_editor = jnv.filter_editor.after_mut(); match event { Event::Key(KeyEvent { @@ -16,17 +16,14 @@ pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result { - let query = query_editor_after_mut - .texteditor - .text_without_cursor() - .to_string(); + let query = filter_editor.texteditor.text_without_cursor().to_string(); if let Some(mut candidates) = jnv.suggest.prefix_search(query) { candidates.sort_by(|a, b| a.len().cmp(&b.len()).then_with(|| a.cmp(b))); - jnv.suggest_state.listbox = Listbox::from_iter(candidates); - query_editor_after_mut + jnv.suggestions.listbox = Listbox::from_iter(candidates); + filter_editor .texteditor - .replace(&jnv.suggest_state.listbox.get()); + .replace(&jnv.suggestions.listbox.get()); jnv.keymap.borrow_mut().switch("on_suggest"); } @@ -46,7 +43,7 @@ pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result { - query_editor_after_mut.texteditor.backward(); + filter_editor.texteditor.backward(); } Event::Key(KeyEvent { code: KeyCode::Right, @@ -54,38 +51,38 @@ pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result { - query_editor_after_mut.texteditor.forward(); + filter_editor.texteditor.forward(); } Event::Key(KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::CONTROL, kind: KeyEventKind::Press, state: KeyEventState::NONE, - }) => query_editor_after_mut.texteditor.move_to_head(), + }) => filter_editor.texteditor.move_to_head(), Event::Key(KeyEvent { code: KeyCode::Char('e'), modifiers: KeyModifiers::CONTROL, kind: KeyEventKind::Press, state: KeyEventState::NONE, - }) => query_editor_after_mut.texteditor.move_to_tail(), + }) => filter_editor.texteditor.move_to_tail(), Event::Key(KeyEvent { code: KeyCode::Char('b'), modifiers: KeyModifiers::ALT, kind: KeyEventKind::Press, state: KeyEventState::NONE, - }) => query_editor_after_mut + }) => filter_editor .texteditor - .move_to_previous_nearest(&query_editor_after_mut.word_break_chars), + .move_to_previous_nearest(&filter_editor.word_break_chars), Event::Key(KeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::ALT, kind: KeyEventKind::Press, state: KeyEventState::NONE, - }) => query_editor_after_mut + }) => filter_editor .texteditor - .move_to_next_nearest(&query_editor_after_mut.word_break_chars), + .move_to_next_nearest(&filter_editor.word_break_chars), // Erase char(s). Event::Key(KeyEvent { @@ -93,13 +90,13 @@ pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result query_editor_after_mut.texteditor.erase(), + }) => filter_editor.texteditor.erase(), Event::Key(KeyEvent { code: KeyCode::Char('u'), modifiers: KeyModifiers::CONTROL, kind: KeyEventKind::Press, state: KeyEventState::NONE, - }) => query_editor_after_mut.texteditor.erase_all(), + }) => filter_editor.texteditor.erase_all(), // Erase to the nearest character. Event::Key(KeyEvent { @@ -107,18 +104,18 @@ pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result query_editor_after_mut + }) => filter_editor .texteditor - .erase_to_previous_nearest(&query_editor_after_mut.word_break_chars), + .erase_to_previous_nearest(&filter_editor.word_break_chars), Event::Key(KeyEvent { code: KeyCode::Char('d'), modifiers: KeyModifiers::ALT, kind: KeyEventKind::Press, state: KeyEventState::NONE, - }) => query_editor_after_mut + }) => filter_editor .texteditor - .erase_to_next_nearest(&query_editor_after_mut.word_break_chars), + .erase_to_next_nearest(&filter_editor.word_break_chars), // Move up. Event::Key(KeyEvent { @@ -212,9 +209,9 @@ pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result match query_editor_after_mut.edit_mode { - text_editor::Mode::Insert => query_editor_after_mut.texteditor.insert(*ch), - text_editor::Mode::Overwrite => query_editor_after_mut.texteditor.overwrite(*ch), + }) => match filter_editor.edit_mode { + text_editor::Mode::Insert => filter_editor.texteditor.insert(*ch), + text_editor::Mode::Overwrite => filter_editor.texteditor.overwrite(*ch), }, _ => (), @@ -223,7 +220,7 @@ pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result anyhow::Result { - let query_editor_after_mut = jnv.query_editor_snapshot.after_mut(); + let query_editor_after_mut = jnv.filter_editor.after_mut(); match event { Event::Key(KeyEvent { @@ -245,10 +242,10 @@ pub fn on_suggest(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result { - jnv.suggest_state.listbox.forward(); + jnv.suggestions.listbox.forward(); query_editor_after_mut .texteditor - .replace(&jnv.suggest_state.listbox.get()); + .replace(&jnv.suggestions.listbox.get()); } Event::Key(KeyEvent { @@ -257,14 +254,14 @@ pub fn on_suggest(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result { - jnv.suggest_state.listbox.backward(); + jnv.suggestions.listbox.backward(); query_editor_after_mut .texteditor - .replace(&jnv.suggest_state.listbox.get()); + .replace(&jnv.suggestions.listbox.get()); } _ => { - jnv.suggest_state.listbox = Listbox::from_iter(Vec::::new()); + jnv.suggestions.listbox = Listbox::from_iter(Vec::::new()); jnv.keymap.borrow_mut().switch("default"); // This block is specifically designed to prevent the default action of toggling collapse/expand diff --git a/src/trie.rs b/src/trie.rs index b21c042..ced2b46 100644 --- a/src/trie.rs +++ b/src/trie.rs @@ -3,9 +3,9 @@ use radix_trie::{Trie, TrieCommon}; use promkit::serde_json; #[derive(Default, Clone)] -pub struct QueryTrie(Trie>); +pub struct FilterTrie(Trie>); -impl QueryTrie { +impl FilterTrie { pub fn insert(&mut self, query: &str, json_nodes: Vec) { self.0.insert(query.to_string(), json_nodes); } @@ -27,7 +27,7 @@ mod tests { #[test] fn test() { - let mut trie = QueryTrie::default(); + let mut trie = FilterTrie::default(); trie.insert("apple", vec![json!({"type": "fruit"})]); trie.insert("app", vec![json!({"type": "abbreviation"})]);