mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-25 02:46:17 +04:00
add fallback onNextKey
adds a variant of on_next_key callbacks that are only called when no other mapping matches a key
This commit is contained in:
parent
68201ae622
commit
2dba70ddb8
@ -87,6 +87,11 @@
|
||||
use ignore::{DirEntry, WalkBuilder, WalkState};
|
||||
|
||||
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 register: Option<char>,
|
||||
@ -94,7 +99,7 @@ pub struct Context<'a> {
|
||||
pub editor: &'a mut Editor,
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
@ -120,7 +125,19 @@ pub fn on_next_key(
|
||||
&mut self,
|
||||
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]
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
commands::{self, OnKeyCallback},
|
||||
commands::{self, OnKeyCallback, OnKeyCallbackKind},
|
||||
compositor::{Component, Context, Event, EventResult},
|
||||
events::{OnModeSwitch, PostCommand},
|
||||
key,
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
pub struct EditorView {
|
||||
pub keymaps: Keymaps,
|
||||
on_next_key: Option<OnKeyCallback>,
|
||||
on_next_key: Option<(OnKeyCallback, OnKeyCallbackKind)>,
|
||||
pseudo_pending: Vec<KeyEvent>,
|
||||
pub(crate) last_insert: (commands::MappableCommand, Vec<InsertEvent>),
|
||||
pub(crate) completion: Option<Completion>,
|
||||
@ -917,10 +917,12 @@ 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 !self.on_next_key(OnKeyCallbackKind::Fallback, cx, event) {
|
||||
if let Some(ch) = event.char() {
|
||||
commands::insert::insert_char(cx, ch)
|
||||
}
|
||||
}
|
||||
}
|
||||
KeymapResult::Cancelled(pending) => {
|
||||
for ev in pending {
|
||||
match ev.char() {
|
||||
@ -1014,7 +1016,10 @@ fn command_mode(&mut self, mode: Mode, cxt: &mut commands::Context, event: KeyEv
|
||||
// set the register
|
||||
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() {
|
||||
cxt.editor.count = None
|
||||
} else {
|
||||
@ -1090,7 +1095,7 @@ fn handle_non_key_input(&mut self, cxt: &mut commands::Context) {
|
||||
modifiers: KeyModifiers::empty(),
|
||||
};
|
||||
// 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);
|
||||
}
|
||||
self.handle_keymap_event(cxt.editor.mode, cxt, null_key_event);
|
||||
@ -1313,6 +1318,24 @@ fn handle_mouse_event(
|
||||
_ => 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 {
|
||||
@ -1364,10 +1387,7 @@ fn handle_event(
|
||||
|
||||
let mode = cx.editor.mode();
|
||||
|
||||
if let Some(on_next_key) = self.on_next_key.take() {
|
||||
// if there's a command waiting input, do that first
|
||||
on_next_key(&mut cx, key);
|
||||
} else {
|
||||
if !self.on_next_key(OnKeyCallbackKind::PseudoPending, &mut cx, key) {
|
||||
match mode {
|
||||
Mode::Insert => {
|
||||
// let completion swallow the event if necessary
|
||||
@ -1417,8 +1437,8 @@ fn handle_event(
|
||||
|
||||
self.on_next_key = cx.on_next_key_callback.take();
|
||||
match self.on_next_key {
|
||||
Some(_) => self.pseudo_pending.push(key),
|
||||
None => self.pseudo_pending.clear(),
|
||||
Some((_, OnKeyCallbackKind::PseudoPending)) => self.pseudo_pending.push(key),
|
||||
_ => self.pseudo_pending.clear(),
|
||||
}
|
||||
|
||||
// appease borrowck
|
||||
|
Loading…
Reference in New Issue
Block a user