Skip to content

Commit

Permalink
Use Ctl-Up & Ctl-Down to navigate in lists.
Browse files Browse the repository at this point in the history
Say your prompt is something like this, with `^` indicating your cursor
position.
```
.[0].hosts[0]
        ^
```
if you type `Ctl-Down`, it will become

```
.[0].hosts[1]
        ^
```
  • Loading branch information
charbeljc committed Mar 26, 2024
1 parent c3f53a3 commit d3097b0
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/jnv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use promkit::{
text, text_editor, Prompt, PromptSignal, Renderer,
};

mod editing;
mod keymap;
mod render;
mod trie;
Expand Down
78 changes: 78 additions & 0 deletions src/jnv/editing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
pub fn add_to_nearest_integer(renderer: &mut promkit::text_editor::Renderer, value: isize) -> bool {
let cursor = renderer.texteditor.position();
let chars = renderer.texteditor.text_without_cursor().chars();
let mut previous = None;
let mut previous_distance = usize::MAX;
let mut pos = 0;
while pos < chars.len() {
match find_number(&chars, pos) {
Some((start, end)) => {
let distance = distance_from(start, end, cursor);
if distance < previous_distance {
previous = Some((start, end));
previous_distance = distance;
}
if distance == 0 {
pos = chars.len()
} else {
pos = end + 1;
}
}
None => pos = chars.len(),
}
}
match previous {
None => false,
Some((start, end)) => {
let before: String = chars[0..start].into_iter().collect();
let after: String = chars[end..].into_iter().collect();
let number: String = chars[start..end].into_iter().collect();
let current_value: isize = match number.parse() {
Ok(value) => value,
Err(_) => return false,
};
let new_value = current_value + value;
let new_query = format!("{before}{new_value}{after}");
renderer.texteditor.replace(&new_query);
let mut npos = renderer.texteditor.position();
while npos > cursor {
renderer.texteditor.backward();
npos = renderer.texteditor.position();
}
true
}
}
}

fn distance_from(start: usize, end: usize, cursor: usize) -> usize {
if start <= cursor && cursor < end {
0
} else if cursor < start {
start - cursor
} else {
cursor - end
}
}

fn find_number(chars: &Vec<char>, start: usize) -> Option<(usize, usize)> {
if start >= chars.len() {
return None;
}
match chars[start..]
.iter()
.position(|ch| *ch == '-' || ch.is_digit(10))
{
Some(num_start) => {
let ch = chars[num_start];
eprintln!("matched: {ch} at offset {num_start}");
let end = chars[start + num_start + 1..]
.iter()
.position(|ch| !ch.is_digit(10));
match end {
Some(end) => Some((start + num_start, start + num_start + 1 + end)),
None => Some((start + num_start, chars.len())),
}
}
None => None,
}
}
18 changes: 18 additions & 0 deletions src/jnv/keymap.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::editing::add_to_nearest_integer;
use promkit::{
crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers},
listbox::Listbox,
Expand Down Expand Up @@ -163,6 +164,23 @@ pub fn default(event: &Event, renderer: &mut crate::jnv::render::Renderer) -> Re
json_after_mut.stream.collapse_all();
}

Event::Key(KeyEvent {
code: KeyCode::Down,
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
state: KeyEventState::NONE,
}) => {
add_to_nearest_integer(query_editor_after_mut, 1);
}
Event::Key(KeyEvent {
code: KeyCode::Up,
modifiers: KeyModifiers::CONTROL,
kind: KeyEventKind::Press,
state: KeyEventState::NONE,
}) => {
add_to_nearest_integer(query_editor_after_mut, -1);
}

// Input char.
Event::Key(KeyEvent {
code: KeyCode::Char(ch),
Expand Down

0 comments on commit d3097b0

Please sign in to comment.