add fallback onNextKey

adds a variant of on_next_key callbacks that are only called when no other
mapping matches a key
pull/9801/head
Pascal Kuthe 8 months ago
parent 68201ae622
commit 2dba70ddb8
No known key found for this signature in database
GPG Key ID: D715E8655AE166A6

@ -87,6 +87,11 @@ use grep_searcher::{sinks, BinaryDetection, SearcherBuilder};
use ignore::{DirEntry, WalkBuilder, WalkState}; use ignore::{DirEntry, WalkBuilder, WalkState};
pub type OnKeyCallback = Box<dyn FnOnce(&mut Context, KeyEvent)>; pub type OnKeyCallback = Box<dyn FnOnce(&mut Context, KeyEvent)>;
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum OnKeyCallbackKind {
PseudoPending,
Fallback,
}
pub struct Context<'a> { pub struct Context<'a> {
pub register: Option<char>, pub register: Option<char>,
@ -94,7 +99,7 @@ pub struct Context<'a> {
pub editor: &'a mut Editor, pub editor: &'a mut Editor,
pub callback: Vec<crate::compositor::Callback>, pub callback: Vec<crate::compositor::Callback>,
pub on_next_key_callback: Option<OnKeyCallback>, pub on_next_key_callback: Option<(OnKeyCallback, OnKeyCallbackKind)>,
pub jobs: &'a mut Jobs, pub jobs: &'a mut Jobs,
} }
@ -120,7 +125,19 @@ impl<'a> Context<'a> {
&mut self, &mut self,
on_next_key_callback: impl FnOnce(&mut Context, KeyEvent) + 'static, on_next_key_callback: impl FnOnce(&mut Context, KeyEvent) + 'static,
) { ) {
self.on_next_key_callback = Some(Box::new(on_next_key_callback)); self.on_next_key_callback = Some((
Box::new(on_next_key_callback),
OnKeyCallbackKind::PseudoPending,
));
}
#[inline]
pub fn on_next_key_fallback(
&mut self,
on_next_key_callback: impl FnOnce(&mut Context, KeyEvent) + 'static,
) {
self.on_next_key_callback =
Some((Box::new(on_next_key_callback), OnKeyCallbackKind::Fallback));
} }
#[inline] #[inline]

@ -1,5 +1,5 @@
use crate::{ use crate::{
commands::{self, OnKeyCallback}, commands::{self, OnKeyCallback, OnKeyCallbackKind},
compositor::{Component, Context, Event, EventResult}, compositor::{Component, Context, Event, EventResult},
events::{OnModeSwitch, PostCommand}, events::{OnModeSwitch, PostCommand},
key, key,
@ -36,7 +36,7 @@ use tui::{buffer::Buffer as Surface, text::Span};
pub struct EditorView { pub struct EditorView {
pub keymaps: Keymaps, pub keymaps: Keymaps,
on_next_key: Option<OnKeyCallback>, on_next_key: Option<(OnKeyCallback, OnKeyCallbackKind)>,
pseudo_pending: Vec<KeyEvent>, pseudo_pending: Vec<KeyEvent>,
pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>), pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
pub(crate) completion: Option<Completion>, pub(crate) completion: Option<Completion>,
@ -917,10 +917,12 @@ impl EditorView {
if let Some(keyresult) = self.handle_keymap_event(Mode::Insert, cx, event) { if let Some(keyresult) = self.handle_keymap_event(Mode::Insert, cx, event) {
match keyresult { match keyresult {
KeymapResult::NotFound => { KeymapResult::NotFound => {
if !self.on_next_key(OnKeyCallbackKind::Fallback, cx, event) {
if let Some(ch) = event.char() { if let Some(ch) = event.char() {
commands::insert::insert_char(cx, ch) commands::insert::insert_char(cx, ch)
} }
} }
}
KeymapResult::Cancelled(pending) => { KeymapResult::Cancelled(pending) => {
for ev in pending { for ev in pending {
match ev.char() { match ev.char() {
@ -1014,7 +1016,10 @@ impl EditorView {
// set the register // set the register
cxt.register = cxt.editor.selected_register.take(); cxt.register = cxt.editor.selected_register.take();
self.handle_keymap_event(mode, cxt, event); let res = self.handle_keymap_event(mode, cxt, event);
if matches!(&res, Some(KeymapResult::NotFound)) {
self.on_next_key(OnKeyCallbackKind::Fallback, cxt, event);
}
if self.keymaps.pending().is_empty() { if self.keymaps.pending().is_empty() {
cxt.editor.count = None cxt.editor.count = None
} else { } else {
@ -1090,7 +1095,7 @@ impl EditorView {
modifiers: KeyModifiers::empty(), modifiers: KeyModifiers::empty(),
}; };
// dismiss any pending keys // dismiss any pending keys
if let Some(on_next_key) = self.on_next_key.take() { if let Some((on_next_key, _)) = self.on_next_key.take() {
on_next_key(cxt, null_key_event); on_next_key(cxt, null_key_event);
} }
self.handle_keymap_event(cxt.editor.mode, cxt, null_key_event); self.handle_keymap_event(cxt.editor.mode, cxt, null_key_event);
@ -1313,6 +1318,24 @@ impl EditorView {
_ => EventResult::Ignored(None), _ => EventResult::Ignored(None),
} }
} }
fn on_next_key(
&mut self,
kind: OnKeyCallbackKind,
ctx: &mut commands::Context,
event: KeyEvent,
) -> bool {
if let Some((on_next_key, kind_)) = self.on_next_key.take() {
if kind == kind_ {
on_next_key(ctx, event);
true
} else {
self.on_next_key = Some((on_next_key, kind_));
false
}
} else {
false
}
}
} }
impl Component for EditorView { impl Component for EditorView {
@ -1364,10 +1387,7 @@ impl Component for EditorView {
let mode = cx.editor.mode(); let mode = cx.editor.mode();
if let Some(on_next_key) = self.on_next_key.take() { if !self.on_next_key(OnKeyCallbackKind::PseudoPending, &mut cx, key) {
// if there's a command waiting input, do that first
on_next_key(&mut cx, key);
} else {
match mode { match mode {
Mode::Insert => { Mode::Insert => {
// let completion swallow the event if necessary // let completion swallow the event if necessary
@ -1417,8 +1437,8 @@ impl Component for EditorView {
self.on_next_key = cx.on_next_key_callback.take(); self.on_next_key = cx.on_next_key_callback.take();
match self.on_next_key { match self.on_next_key {
Some(_) => self.pseudo_pending.push(key), Some((_, OnKeyCallbackKind::PseudoPending)) => self.pseudo_pending.push(key),
None => self.pseudo_pending.clear(), _ => self.pseudo_pending.clear(),
} }
// appease borrowck // appease borrowck

Loading…
Cancel
Save