mirror of
https://github.com/ynqa/jnv.git
synced 2026-01-07 11:49:30 -06:00
reconsider terminology
This commit is contained in:
60
src/jnv.rs
60
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<Vec<
|
||||
}
|
||||
|
||||
pub struct Jnv {
|
||||
input_stream: Vec<serde_json::Value>,
|
||||
|
||||
// Keybindings
|
||||
keymap: RefCell<ActiveKeySwitcher<keymap::Keymap>>,
|
||||
query_editor_snapshot: Snapshot<text_editor::State>,
|
||||
hint_message_snapshot: Snapshot<text::State>,
|
||||
suggest: Suggest,
|
||||
suggest_state: listbox::State,
|
||||
|
||||
// For Rendering
|
||||
filter_editor: Snapshot<text_editor::State>,
|
||||
hint_message: Snapshot<text::State>,
|
||||
suggestions: listbox::State,
|
||||
json_state: json::State,
|
||||
trie: QueryTrie,
|
||||
input_json_stream: Vec<serde_json::Value>,
|
||||
|
||||
// Store the filter history
|
||||
trie: FilterTrie,
|
||||
// Store the filter suggestions
|
||||
suggest: Suggest,
|
||||
|
||||
expand_depth: Option<usize>,
|
||||
no_hint: bool,
|
||||
}
|
||||
|
||||
impl Jnv {
|
||||
pub fn try_new(
|
||||
input_json_str: String,
|
||||
input: String,
|
||||
expand_depth: Option<usize>,
|
||||
no_hint: bool,
|
||||
edit_mode: text_editor::Mode,
|
||||
indent: usize,
|
||||
suggestion_list_length: usize,
|
||||
) -> Result<Prompt<Self>> {
|
||||
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::<text_editor::State>::new(text_editor::State {
|
||||
filter_editor: Snapshot::<text_editor::State>::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::<text::State>::new(text::State {
|
||||
hint_message: Snapshot::<text::State>::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::<String>::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<Self::Return> {
|
||||
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<Pane> {
|
||||
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(
|
||||
|
||||
@@ -7,7 +7,7 @@ use promkit::{
|
||||
pub type Keymap = fn(&Event, &mut crate::jnv::Jnv) -> anyhow::Result<PromptSignal>;
|
||||
|
||||
pub fn default(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result<PromptSignal> {
|
||||
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<Promp
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => {
|
||||
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<Promp
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => {
|
||||
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<Promp
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => {
|
||||
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<Promp
|
||||
modifiers: KeyModifiers::NONE,
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => 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<Promp
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => 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<Promp
|
||||
modifiers: KeyModifiers::SHIFT,
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => 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<Promp
|
||||
}
|
||||
|
||||
pub fn on_suggest(event: &Event, jnv: &mut crate::jnv::Jnv) -> anyhow::Result<PromptSignal> {
|
||||
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<Pr
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => {
|
||||
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<Pr
|
||||
kind: KeyEventKind::Press,
|
||||
state: KeyEventState::NONE,
|
||||
}) => {
|
||||
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::<String>::new());
|
||||
jnv.suggestions.listbox = Listbox::from_iter(Vec::<String>::new());
|
||||
jnv.keymap.borrow_mut().switch("default");
|
||||
|
||||
// This block is specifically designed to prevent the default action of toggling collapse/expand
|
||||
|
||||
@@ -3,9 +3,9 @@ use radix_trie::{Trie, TrieCommon};
|
||||
use promkit::serde_json;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct QueryTrie(Trie<String, Vec<serde_json::Value>>);
|
||||
pub struct FilterTrie(Trie<String, Vec<serde_json::Value>>);
|
||||
|
||||
impl QueryTrie {
|
||||
impl FilterTrie {
|
||||
pub fn insert(&mut self, query: &str, json_nodes: Vec<serde_json::Value>) {
|
||||
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"})]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user