1use std::{
10 any::TypeId,
11 collections::HashMap,
12 slice,
13 sync::{LazyLock, Mutex},
14};
15
16use crossterm::event::KeyEvent;
17
18pub use self::global::*;
19use super::Mode;
20use crate::{
21 Ns, context,
22 data::{BulkDataWriter, Pass, RwData},
23 mode::{self, Binding, Bindings},
24 text::{Inlay, Text, txt},
25 ui::Widget,
26};
27
28static CUR_SEQ: LazyLock<RwData<(Vec<KeyEvent>, bool)>> = LazyLock::new(RwData::default);
29
30mod global {
31 use std::{
32 any::TypeId,
33 str::Chars,
34 sync::{LazyLock, Mutex},
35 };
36
37 use crossterm::event::{KeyCode, KeyEvent, KeyModifiers as KeyMod};
38
39 use super::{MapsTo, Remapper};
40 use crate::{
41 data::{BulkDataWriter, DataMap, Pass, RwData},
42 mode::{Description, MappedBindings, Mode},
43 text::{Text, txt},
44 };
45
46 static REMAPPER: BulkDataWriter<Remapper> = BulkDataWriter::new();
47 pub(in crate::mode) static MODE_TYPE_ID: Mutex<TypeId> = Mutex::new(TypeId::of::<()>());
48 static SEND_KEY: LazyLock<RwData<fn(&mut Pass, KeyEvent)>> =
49 LazyLock::new(|| RwData::new(|_, _| {}));
50
51 pub struct RemapBuilder {
64 pub(super) takes: Vec<KeyEvent>,
65 pub(super) gives: MapsTo,
66 pub(super) is_alias: bool,
67 pub(super) doc: Option<Text>,
68 pub(super) remap: fn(&mut Remapper, Vec<KeyEvent>, MapsTo, bool, Option<Text>),
69 }
70
71 impl RemapBuilder {
72 pub fn doc<T: Into<Text>>(self, doc: T) {
80 let mut builder = self;
81 builder.doc = Some(doc.into());
82 }
83 }
84
85 impl Drop for RemapBuilder {
86 fn drop(&mut self) {
87 let remap = self.remap;
88 let takes = std::mem::take(&mut self.takes);
89 let gives = std::mem::replace(&mut self.gives, MapsTo::Keys(Vec::new()));
90 let is_alias = self.is_alias;
91 let doc = self.doc.take();
92 REMAPPER.mutate(move |remapper| remap(remapper, takes, gives, is_alias, doc));
93 }
94 }
95
96 pub fn map<M: Mode>(takes: &str, gives: impl IntoMapsTo) -> RemapBuilder {
133 let takes = str_to_keys(takes);
134 RemapBuilder {
135 takes,
136 gives: gives.into_maps_to(),
137 is_alias: false,
138 doc: None,
139 remap: |remapper, takes, gives, is_alias, doc| {
140 remapper.remap::<M>(takes, gives, is_alias, doc)
141 },
142 }
143 }
144
145 pub fn alias<M: Mode>(takes: &str, gives: impl IntoMapsTo) -> RemapBuilder {
169 let takes = str_to_keys(takes);
170 RemapBuilder {
171 takes,
172 gives: gives.into_maps_to(),
173 is_alias: true,
174 doc: None,
175 remap: |remapper, takes, gives, is_alias, doc| {
176 remapper.remap::<M>(takes, gives, is_alias, doc)
177 },
178 }
179 }
180
181 pub fn current_sequence() -> DataMap<(Vec<KeyEvent>, bool), (Vec<KeyEvent>, bool)> {
183 super::CUR_SEQ.map(Clone::clone)
184 }
185
186 pub fn reset_current_sequence(pa: &mut Pass) {
188 *super::CUR_SEQ.write(pa) = (Vec::new(), false)
189 }
190
191 pub fn current_mode_bindings(pa: &mut Pass) -> &MappedBindings {
204 &REMAPPER.write(pa).mapped_bindings[&MODE_TYPE_ID.lock().unwrap()]
205 }
206
207 pub fn change_binding_description<M: Mode>(seq: &[KeyEvent], new: Text) {
212 let seq = seq.to_vec();
213 REMAPPER.mutate(move |remapper| {
214 let bindings = remapper
215 .mapped_bindings
216 .entry(TypeId::of::<M>())
217 .or_insert_with(MappedBindings::for_mode::<M>);
218
219 bindings.replace_seq_description(&seq, new);
220 });
221 }
222
223 pub fn change_bindings<M: Mode>(bindings: super::Bindings) {
237 use std::collections::hash_map::Entry;
238
239 let bindings = MappedBindings::new(bindings);
240
241 REMAPPER.mutate(
242 move |remapper| match remapper.mapped_bindings.entry(TypeId::of::<M>()) {
243 Entry::Occupied(mut occupied_entry) => *occupied_entry.get_mut() = bindings,
244 Entry::Vacant(vacant_entry) => _ = vacant_entry.insert(bindings),
245 },
246 );
247 }
248
249 pub fn current_seq_descriptions(
270 pa: &mut Pass,
271 ) -> (Option<&Text>, impl Iterator<Item = Description<'_>>) {
272 let ((cur_seq, _), remapper) = pa.write_many((&*super::CUR_SEQ, &REMAPPER));
273 remapper.mapped_bindings[&*MODE_TYPE_ID.lock().unwrap()].descriptions_for(cur_seq)
274 }
275
276 pub fn keys_to_text(keys: &[KeyEvent]) -> Text {
278 use crossterm::event::KeyCode::*;
279 let mut builder = Text::builder();
280
281 for key in keys {
282 if key.modifiers != KeyMod::NONE
283 || !matches!(key.code, KeyCode::Char(char) if char != ' ')
284 {
285 builder.push(txt!("[key.angle]<"));
286 }
287
288 builder.push(modifier_text(key.modifiers));
289
290 match key.code {
291 Backspace => builder.push(txt!("[key.special]BS")),
292 Enter | Char('\n') => builder.push(txt!("[key.special]Enter")),
293 Left => builder.push(txt!("[key.special]Left")),
294 Right => builder.push(txt!("[key.special]Right")),
295 Up => builder.push(txt!("[key.special]Up")),
296 Down => builder.push(txt!("[key.special]Down")),
297 Home => builder.push(txt!("[key.special]Home")),
298 End => builder.push(txt!("[key.special]End")),
299 PageUp => builder.push(txt!("[key.special]PageU")),
300 PageDown => builder.push(txt!("[key.special]PageD")),
301 Tab => builder.push(txt!("[key.special]Tab")),
302 BackTab => builder.push(txt!("[key.special]BTab")),
303 Delete => builder.push(txt!("[key.special]Del")),
304 Insert => builder.push(txt!("[key.special]Ins")),
305 F(num) => builder.push(txt!("[key.special]F{num}")),
306 Char(' ') => builder.push(txt!("[key.char]Space")),
307 Char(char) => builder.push(txt!("[key.char]{char}")),
308 Null => builder.push(txt!("[key.special]Null")),
309 Esc => builder.push(txt!("[key.special]Esc")),
310 CapsLock => builder.push(txt!("[key.special]CapsL")),
311 ScrollLock => builder.push(txt!("[key.special]ScrollL")),
312 NumLock => builder.push(txt!("[key.special]NumL")),
313 PrintScreen => builder.push(txt!("[key.special]PrSc")),
314 Pause => builder.push(txt!("[key.special]Pause")),
315 Menu => builder.push(txt!("[key.special]Menu")),
316 KeypadBegin => builder.push(txt!("[key.special]KeypadBeg")),
317 Media(m_code) => builder.push(txt!("[key.special]Media{m_code}")),
318 Modifier(m_code) => builder.push(txt!("[key.special]Mod{m_code}")),
319 }
320
321 if key.modifiers != KeyMod::NONE
322 || !matches!(key.code, KeyCode::Char(char) if char != ' ')
323 {
324 builder.push(txt!("[key.angle]>"));
325 }
326 }
327
328 builder.build()
329 }
330
331 pub fn modifier_text(modif: KeyMod) -> Text {
334 if modif == KeyMod::NONE {
335 return Text::new();
336 }
337
338 let mut builder = Text::builder();
339
340 builder.push(crate::form::id_of!("key.mod"));
341
342 for modif in modif.iter() {
343 builder.push(match modif {
344 KeyMod::ALT => "a",
345 KeyMod::CONTROL => "c",
346 KeyMod::SHIFT => "s",
347 KeyMod::META => "m",
348 KeyMod::SUPER => "Super",
349 KeyMod::HYPER => "Hyper",
350 _ => "",
351 });
352 }
353
354 builder.push(txt!("[key.mod.separator]-"));
355
356 builder.build()
357 }
358
359 pub fn keys_to_string(keys: &[KeyEvent]) -> String {
361 use std::fmt::Write;
362
363 use crossterm::event::{KeyCode::*, KeyModifiers as Mod};
364 let mut seq = String::new();
365
366 for key in keys {
367 if !key.modifiers.is_empty() {
368 seq.push('<');
369 for modif in key.modifiers.iter() {
370 seq.push_str(match modif {
371 Mod::ALT => "a",
372 Mod::CONTROL => "c",
373 Mod::SHIFT => "s",
374 Mod::META => "m",
375 Mod::SUPER => "Super",
376 Mod::HYPER => "Hyper",
377 _ => "",
378 });
379 }
380 seq.push('-');
381 } else if !matches!(key.code, Char(_)) {
382 seq.push('<');
383 }
384
385 match key.code {
386 Backspace => seq.push_str("BS>"),
387 Enter => seq.push_str("Enter>"),
388 Left => seq.push_str("Left>"),
389 Right => seq.push_str("Right>"),
390 Up => seq.push_str("Up>"),
391 Down => seq.push_str("Down>"),
392 Home => seq.push_str("Home>"),
393 End => seq.push_str("End>"),
394 PageUp => seq.push_str("PageU>"),
395 PageDown => seq.push_str("PageD>"),
396 Tab => seq.push_str("Tab>"),
397 BackTab => seq.push_str("BTab>"),
398 Delete => seq.push_str("Del>"),
399 Insert => seq.push_str("Ins>"),
400 F(num) => write!(seq, "F{num}>").unwrap(),
401 Char(char) => {
402 write!(seq, "{char}").unwrap();
403 if !key.modifiers.is_empty() {
404 seq.push('>');
405 }
406 }
407 Null => seq.push_str("Null>"),
408 Esc => seq.push_str("Esc>"),
409 CapsLock => seq.push_str("CapsL>"),
410 ScrollLock => seq.push_str("ScrollL>"),
411 NumLock => seq.push_str("NumL>"),
412 PrintScreen => seq.push_str("PrSc>"),
413 Pause => seq.push_str("Pause>"),
414 Menu => seq.push_str("Menu>"),
415 KeypadBegin => seq.push_str("KeypadBeg>"),
416 Media(m_code) => write!(seq, "Media{m_code}>").unwrap(),
417 Modifier(m_code) => write!(seq, "Mod{m_code}>").unwrap(),
418 }
419 }
420
421 seq
422 }
423
424 pub fn str_to_keys(str: &str) -> Vec<KeyEvent> {
429 const SPECIAL: &[(&str, KeyCode)] = &[
430 ("Enter", KeyCode::Enter),
431 ("Tab", KeyCode::Tab),
432 ("Bspc", KeyCode::Backspace),
433 ("Del", KeyCode::Delete),
434 ("Esc", KeyCode::Esc),
435 ("Up", KeyCode::Up),
436 ("Down", KeyCode::Down),
437 ("Left", KeyCode::Left),
438 ("Right", KeyCode::Right),
439 ("PageU", KeyCode::PageUp),
440 ("PageD", KeyCode::PageDown),
441 ("Home", KeyCode::Home),
442 ("End", KeyCode::End),
443 ("Ins", KeyCode::Insert),
444 ("F1", KeyCode::F(1)),
445 ("F2", KeyCode::F(2)),
446 ("F3", KeyCode::F(3)),
447 ("F4", KeyCode::F(4)),
448 ("F5", KeyCode::F(5)),
449 ("F6", KeyCode::F(6)),
450 ("F7", KeyCode::F(7)),
451 ("F8", KeyCode::F(8)),
452 ("F9", KeyCode::F(9)),
453 ("F10", KeyCode::F(10)),
454 ("F11", KeyCode::F(11)),
455 ("F12", KeyCode::F(12)),
456 ];
457 const MODS: &[(&str, KeyMod)] = &[
458 ("c", KeyMod::CONTROL),
459 ("a", KeyMod::ALT),
460 ("s", KeyMod::SHIFT),
461 ("m", KeyMod::META),
462 ("super", KeyMod::SUPER),
463 ("hyper", KeyMod::HYPER),
464 ];
465 fn match_key(chars: Chars) -> Option<(KeyEvent, Chars)> {
466 let matched_mods = {
467 let mut chars = chars.clone();
468 let mut mods = KeyMod::empty();
469 let mut seq = String::new();
470
471 loop {
472 let char = chars.next()?;
473 if char == '-' {
474 if mods.is_empty() {
475 break None;
476 } else {
477 break Some((mods, chars));
478 }
479 }
480
481 seq.push(char);
482
483 if let Some((_, m)) = MODS.iter().find(|(str, _)| str == &seq)
484 && !mods.contains(*m)
485 {
486 mods = mods.union(*m);
487 seq.clear();
488 } else if !MODS[4..6].iter().any(|(str, _)| str.starts_with(&seq)) {
489 break None;
490 }
491 }
492 };
493
494 let (mut mods, mut chars) = match matched_mods {
495 Some((mods, chars)) => (mods, chars),
496 None => (KeyMod::empty(), chars),
497 };
498
499 let mut code = Some(chars.next().map(KeyCode::Char)?);
500 let mut seq = code.unwrap().to_string();
501
502 loop {
503 if let Some(c) = code.take() {
504 match chars.next()? {
505 '>' if seq.len() > 1 || !mods.is_empty() => {
506 if let KeyCode::Char(_) = c {
508 mods.remove(KeyMod::SHIFT);
509 }
510 break Some((KeyEvent::new(c, mods), chars));
511 }
512 _ if seq.len() > 1 => break None,
513 char => seq.push(char),
514 }
515 }
516
517 if let Some((str, c)) = SPECIAL.iter().find(|(str, _)| str.starts_with(&seq)) {
518 if str == &seq {
519 code = Some(*c);
520 } else {
521 seq.push(chars.next()?);
522 }
523 } else {
524 break None;
525 }
526 }
527 }
528
529 let mut keys = Vec::new();
530 let mut chars = str.chars();
531 let mut next = chars.next();
532
533 while let Some(char) = next {
534 if char == '<'
535 && let Some((key, ahead)) = match_key(chars.clone())
536 {
537 keys.push(key);
538 chars = ahead;
539 } else {
540 keys.push(KeyEvent::from(KeyCode::Char(char)));
541 }
542
543 next = chars.next();
544 }
545
546 keys
547 }
548
549 #[doc(hidden)]
551 pub trait IntoMapsTo: Send + 'static {
552 fn into_maps_to(self) -> MapsTo;
553 }
554
555 impl IntoMapsTo for &'static str {
556 fn into_maps_to(self) -> MapsTo {
557 MapsTo::Keys(str_to_keys(self))
558 }
559 }
560
561 impl<F: for<'p> FnMut(&'p mut Pass) + Send + 'static> IntoMapsTo for F {
562 fn into_maps_to(self) -> MapsTo {
563 MapsTo::Function(Box::new(Mutex::new(self)))
564 }
565 }
566
567 pub(crate) fn send_key_event(pa: &mut Pass, mut key: KeyEvent) {
569 if let KeyCode::Char(_) = key.code {
571 key.modifiers.remove(KeyMod::SHIFT);
572 }
573
574 SEND_KEY.read(pa)(pa, key);
575
576 crate::hook::trigger(pa, crate::hook::KeyTyped(key));
577 }
578
579 pub(in crate::mode) fn set_mode_for_remapper<M: Mode>(pa: &mut Pass) {
581 REMAPPER
582 .write(pa)
583 .mapped_bindings
584 .entry(TypeId::of::<M>())
585 .or_insert_with(MappedBindings::for_mode::<M>);
586 *SEND_KEY.write(pa) = |pa, key| super::send_key::<M>(&REMAPPER, pa, key);
587 *MODE_TYPE_ID.lock().unwrap() = TypeId::of::<M>();
588 }
589}
590
591#[derive(Default)]
593struct Remapper {
594 mapped_bindings: HashMap<TypeId, MappedBindings>,
595 mapped_seq: Vec<KeyEvent>,
596}
597
598impl Remapper {
599 fn remap<M: Mode>(
601 &mut self,
602 takes: Vec<KeyEvent>,
603 gives: MapsTo,
604 is_alias: bool,
605 doc: Option<Text>,
606 ) {
607 fn remap_inner(
608 inner: &mut Remapper,
609 ty: TypeId,
610 takes: Vec<KeyEvent>,
611 gives: MapsTo,
612 is_alias: bool,
613 doc: Option<Text>,
614 ) {
615 let mapped_bindings = inner.mapped_bindings.get_mut(&ty).unwrap();
616
617 let remap = Remap::new(takes, gives, is_alias, doc);
618
619 if let Some(i) = mapped_bindings.remaps.iter().position(|r| {
620 r.takes.starts_with(&remap.takes) || remap.takes.starts_with(&r.takes)
621 }) {
622 mapped_bindings.remaps[i] = remap;
623 } else {
624 mapped_bindings.remaps.push(remap);
625 }
626 }
627
628 self.mapped_bindings
629 .entry(TypeId::of::<M>())
630 .or_insert_with(MappedBindings::for_mode::<M>);
631
632 remap_inner(self, TypeId::of::<M>(), takes, gives, is_alias, doc);
633 }
634}
635
636fn send_key<M: Mode>(bdw: &BulkDataWriter<Remapper>, pa: &mut Pass, key: KeyEvent) {
638 fn send_key_inner(
639 bdw: &BulkDataWriter<Remapper>,
640 key_event: KeyEvent,
641 pa: &mut Pass,
642 ty: TypeId,
643 ) {
644 let ((cur_seq, is_alias), remapper) = pa.write_many((&*CUR_SEQ, bdw));
645 let mapped_bindings = &remapper.mapped_bindings[&ty];
646
647 cur_seq.push(key_event);
648 if !mapped_bindings.sequence_has_followup(cur_seq) {
649 cur_seq.clear();
650 }
651 remapper.mapped_seq.push(key_event);
652
653 let clear_mapped_sequence = |pa: &mut Pass| {
654 bdw.write(pa).mapped_seq.clear();
655 CUR_SEQ.write(pa).1 = false;
656 };
657
658 let (mapped_seq, is_alias) = (remapper.mapped_seq.clone(), *is_alias);
659
660 let keys_to_send = if let Some(i) = mapped_bindings
661 .remaps
662 .iter()
663 .position(|r| r.takes.starts_with(&mapped_seq))
664 {
665 let remap = &mapped_bindings.remaps[i];
666 if remap.takes.len() == mapped_seq.len() {
667 if remap.is_alias {
668 remove_alias_and(pa, |_, _| {});
669 }
670
671 clear_mapped_sequence(pa);
672
673 let mapped_bindings = &mut bdw.write(pa).mapped_bindings;
674 let remap = mapped_bindings.get_mut(&ty).unwrap().remaps.remove(i);
675
676 match &remap.gives {
677 MapsTo::Keys(keys) => {
678 let keys = keys.clone();
679 let mapped_bindings = &mut bdw.write(pa).mapped_bindings;
680 mapped_bindings
681 .get_mut(&ty)
682 .unwrap()
683 .remaps
684 .insert(i, remap);
685 keys
686 }
687 MapsTo::Function(function) => {
688 function.lock().unwrap()(pa);
689 let mapped_bindings = &mut bdw.write(pa).mapped_bindings;
690 mapped_bindings
691 .get_mut(&ty)
692 .unwrap()
693 .remaps
694 .insert(i, remap);
695 return;
696 }
697 }
698 } else {
699 if remap.is_alias {
700 CUR_SEQ.write(pa).1 = true;
701
702 remove_alias_and(pa, |widget, main| {
703 widget.text_mut().insert_tag(
704 Ns::for_alias(),
705 main,
706 Inlay::new(txt!("[alias]{}", keys_to_string(&mapped_seq))),
707 );
708 });
709 }
710 return;
711 }
712 } else {
713 if is_alias {
714 remove_alias_and(pa, |_, _| {});
715 }
716
717 clear_mapped_sequence(pa);
718
719 mapped_seq
720 };
721
722 mode::send_keys_to(pa, keys_to_send);
723 }
724
725 send_key_inner(bdw, key, pa, TypeId::of::<M>());
726}
727
728#[derive(Debug)]
731struct Remap {
732 takes: Vec<KeyEvent>,
733 gives: MapsTo,
734 is_alias: bool,
735 desc: Option<Text>,
736}
737
738impl Remap {
739 pub fn new(takes: Vec<KeyEvent>, gives: MapsTo, is_alias: bool, desc: Option<Text>) -> Self {
741 Self { takes, gives, is_alias, desc }
742 }
743}
744
745pub enum MapsTo {
748 Keys(Vec<KeyEvent>),
750 Function(Box<Mutex<dyn FnMut(&mut Pass) + Send>>),
752}
753
754impl std::fmt::Debug for MapsTo {
755 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
756 match self {
757 Self::Keys(arg0) => f.debug_tuple("Keys").field(arg0).finish(),
758 Self::Function(_) => f.debug_tuple("Function").finish_non_exhaustive(),
759 }
760 }
761}
762
763#[derive(Debug)]
766pub struct MappedBindings {
767 bindings: Bindings,
768 remaps: Vec<Remap>,
769}
770
771impl MappedBindings {
772 fn for_mode<M: Mode>() -> Self {
774 Self {
775 bindings: M::bindings(),
776 remaps: Vec::new(),
777 }
778 }
779
780 fn new(bindings: Bindings) -> Self {
782 Self { bindings, remaps: Vec::new() }
783 }
784}
785
786impl MappedBindings {
787 pub fn matches_sequence(&self, seq: &[KeyEvent]) -> bool {
793 self.remaps.iter().any(|remap| {
794 seq.starts_with(&remap.takes) && self.matches_sequence(&seq[remap.takes.len()..])
795 }) || self.bindings.matches_sequence(seq)
796 }
797
798 pub fn sequence_has_followup(&self, seq: &[KeyEvent]) -> bool {
804 self.remaps
805 .iter()
806 .any(|remap| remap.takes.starts_with(seq) && remap.takes.len() > seq.len())
807 || self.bindings.sequence_has_followup(seq)
808 }
809
810 pub fn descriptions_for<'a>(
813 &'a self,
814 seq: &'a [KeyEvent],
815 ) -> (Option<&'a Text>, impl Iterator<Item = Description<'a>>) {
816 let bindings = self.bindings.bindings_for(seq);
817
818 let iter = bindings
819 .into_iter()
820 .flat_map(|bindings| bindings.list.iter())
821 .map(|(pats, desc, _)| Description {
822 text: Some(desc),
823 keys: KeyDescriptions {
824 seq,
825 ty: DescriptionType::Binding(pats, pats.iter(), StripPrefix {
826 seq,
827 remaps: self.remaps.iter(),
828 }),
829 },
830 })
831 .chain(
832 self.remaps
833 .iter()
834 .filter(move |remap| {
835 if !remap.takes.starts_with(seq) {
836 return false;
837 }
838 if remap.desc.is_some() {
839 return true;
840 }
841
842 if let (MapsTo::Keys(gives), Some(bindings)) = (&remap.gives, bindings)
843 && gives.len() == 1
844 && bindings
845 .list
846 .iter()
847 .any(|(pats, ..)| pats.iter().any(|pat| pat.matches(gives[0])))
848 {
849 false
850 } else {
851 true
852 }
853 })
854 .map(|remap| Description {
855 text: remap.desc.as_ref().or_else(|| {
856 if let MapsTo::Keys(keys) = &remap.gives {
857 self.bindings.description_for(keys)
858 } else {
859 None
860 }
861 }),
862 keys: KeyDescriptions {
863 seq,
864 ty: DescriptionType::Remap(Some(remap)),
865 },
866 }),
867 );
868
869 (bindings.and_then(|b| b.title.as_ref()), iter)
870 }
871
872 fn replace_seq_description(&mut self, seq: &[KeyEvent], new: Text) {
874 if let Some(remap) = self.remaps.iter_mut().find(|remap| remap.takes == seq) {
875 remap.desc = (!new.is_empty_empty()).then_some(new);
876 } else if let Some(desc) = self.bindings.description_for_mut(seq) {
877 *desc = new;
878 }
879 }
880}
881
882pub struct Description<'a> {
902 pub text: Option<&'a Text>,
904 pub keys: KeyDescriptions<'a>,
910}
911
912#[derive(Debug)]
915pub enum KeyDescription<'a> {
916 Binding(Binding),
919 Remap(&'a [KeyEvent], &'a MapsTo),
921}
922
923pub struct KeyDescriptions<'a> {
935 seq: &'a [KeyEvent],
936 ty: DescriptionType<'a>,
937}
938
939impl KeyDescriptions<'_> {
940 pub fn into_text(self) -> Text {
948 let mut builder = Text::builder();
949
950 for (i, key_desc) in self.enumerate() {
951 if i > 0 {
952 builder.push(txt!("[separator],"));
953 }
954 match key_desc {
955 KeyDescription::Binding(binding) => builder.push(binding.as_text()),
956 KeyDescription::Remap(key_events, _) => {
957 builder.push(txt!("[remap:100]{}", super::keys_to_text(key_events)))
958 }
959 }
960 }
961
962 builder.build()
963 }
964}
965
966impl<'a> Iterator for KeyDescriptions<'a> {
967 type Item = KeyDescription<'a>;
968
969 fn next(&mut self) -> Option<Self::Item> {
970 let (pats, pats_iter, deprefixed) = match &mut self.ty {
971 DescriptionType::Binding(pats, pats_iter, deprefixed) => (pats, pats_iter, deprefixed),
972 DescriptionType::Remap(remap) => {
973 return remap.take().and_then(|remap| {
974 remap
975 .takes
976 .strip_prefix(self.seq)
977 .map(|takes| KeyDescription::Remap(takes, &remap.gives))
978 });
979 }
980 };
981
982 pats_iter
983 .find_map(|pat| {
984 pat.as_key_event()
985 .is_none_or(|key_event| {
986 !deprefixed
987 .clone()
988 .any(|(_, takes)| takes.starts_with(&[key_event]))
989 })
990 .then_some(KeyDescription::Binding(*pat))
991 })
992 .or_else(|| {
993 deprefixed.find_map(|(remap, takes)| {
994 if remap.takes.starts_with(self.seq)
995 && remap.desc.is_none()
996 && let MapsTo::Keys(given_keys) = &remap.gives
997 && given_keys.len() == 1
998 && pats.iter().any(|pat| pat.matches(given_keys[0]))
999 {
1000 Some(KeyDescription::Remap(takes, &remap.gives))
1001 } else {
1002 None
1003 }
1004 })
1005 })
1006 }
1007}
1008
1009enum DescriptionType<'a> {
1011 Binding(&'a [Binding], slice::Iter<'a, Binding>, StripPrefix<'a>),
1012 Remap(Option<&'a Remap>),
1013}
1014
1015fn remove_alias_and(pa: &mut Pass, f: impl FnOnce(&mut dyn Widget, usize)) {
1016 let widget = context::current_widget_node(pa);
1017 widget.mutate_data(pa, |handle| {
1020 let pa = unsafe { &mut Pass::new() };
1021 let widget = handle.write(pa);
1022 if let Some(main) = widget.text().get_main_sel() {
1023 let byte = main.caret().byte();
1024 widget.text_mut().remove_tags(Ns::for_alias(), ..);
1025 f(&mut *widget, byte)
1026 }
1027 })
1028}
1029
1030#[derive(Clone)]
1031struct StripPrefix<'a> {
1032 seq: &'a [KeyEvent],
1033 remaps: slice::Iter<'a, Remap>,
1034}
1035
1036impl<'a> Iterator for StripPrefix<'a> {
1037 type Item = (&'a Remap, &'a [KeyEvent]);
1038
1039 fn next(&mut self) -> Option<Self::Item> {
1040 let remap = self.remaps.next()?;
1041 Some((remap, remap.takes.strip_prefix(self.seq)?))
1042 }
1043}