Skip to content

Commit

Permalink
Handle suffixes of cancelled keymaps in insert mode
Browse files Browse the repository at this point in the history
  • Loading branch information
kmicklas committed Oct 8, 2023
1 parent 93e54fa commit 957453e
Showing 1 changed file with 30 additions and 18 deletions.
48 changes: 30 additions & 18 deletions helix-term/src/ui/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use helix_view::{
keyboard::{KeyCode, KeyModifiers},
Document, Editor, Theme, View,
};
use std::{mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc, sync::Arc};
use std::{collections::VecDeque, mem::take, num::NonZeroUsize, path::PathBuf, rc::Rc, sync::Arc};

use tui::{buffer::Buffer as Surface, text::Span};

Expand Down Expand Up @@ -857,28 +857,40 @@ impl EditorView {
}

fn insert_mode(&mut self, cx: &mut commands::Context, event: KeyEvent) {
if let Some(keyresult) = self.handle_keymap_event(Mode::Insert, cx, event) {
match keyresult {
KeymapResult::NotFound => {
if let Some(ch) = event.char() {
commands::insert::insert_char(cx, ch)
let mut queue = VecDeque::from([event]);

while let Some(event) = queue.pop_front() {
if let Some(keyresult) = self.handle_keymap_event(Mode::Insert, cx, event) {
match keyresult {
KeymapResult::NotFound => {
if let Some(ch) = event.char() {
commands::insert::insert_char(cx, ch)
}
}
}
KeymapResult::Cancelled(pending) => {
for ev in pending {
match ev.char() {
Some(ch) => commands::insert::insert_char(cx, ch),
None => {
if let KeymapResult::Matched(command) =
self.keymaps.get(Mode::Insert, ev)
{
command.execute(cx);
}
KeymapResult::Cancelled(pending) => {
let mut pending = pending.into_iter();
if let Some(first) = pending.next() {
// Note that since this is the first pending key, we know
// it can't map to a command by itself.
match first.char() {
// The first key is both the start of a menu and a regular
// insert key. The user may have intended to type it as an
// insert, and then execute the remaining suffix of keys.
Some(ch) => commands::insert::insert_char(cx, ch),
// If the first key is not a character to insert, then we
// assume the user intended to enter a command menu, so we
// should just discard pending keys if they don't match.
None => continue,
}
}

// Sadly VecDeque has no extend_front method.
for event in pending.rev() {
queue.push_front(event);
}
}
_ => unreachable!(),
}
_ => unreachable!(),
}
}
}
Expand Down

0 comments on commit 957453e

Please sign in to comment.