mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 09:26:19 +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};
|
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 @@ pub fn on_next_key(
|
|||||||
&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 @@
|
|||||||
|
|
||||||
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,8 +917,10 @@ fn insert_mode(&mut self, cx: &mut commands::Context, event: KeyEvent) {
|
|||||||
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 let Some(ch) = event.char() {
|
if !self.on_next_key(OnKeyCallbackKind::Fallback, cx, event) {
|
||||||
commands::insert::insert_char(cx, ch)
|
if let Some(ch) = event.char() {
|
||||||
|
commands::insert::insert_char(cx, ch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeymapResult::Cancelled(pending) => {
|
KeymapResult::Cancelled(pending) => {
|
||||||
@ -1014,7 +1016,10 @@ fn command_mode(&mut self, mode: Mode, cxt: &mut commands::Context, event: KeyEv
|
|||||||
// 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 @@ fn handle_non_key_input(&mut self, cxt: &mut commands::Context) {
|
|||||||
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 @@ fn handle_mouse_event(
|
|||||||
_ => 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 @@ fn handle_event(
|
|||||||
|
|
||||||
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 @@ fn handle_event(
|
|||||||
|
|
||||||
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…
Reference in New Issue
Block a user