Skip to main content

duat_core/mode/
remap.rs

1//! Remapping functionality for Duat
2//!
3//! This module's purpose is to support the [`map`] and [`alias`]
4//! commands, not only by giving having these two functions, but also
5//! in limiting what can be mapped, and making use of [`bindings`] in
6//! order to properly document everything.
7//!
8//! [`bindings`]: super::bindings
9use 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    /// A mapping constructor, used by the [`map`] and [`alias`]
52    /// commands
53    ///
54    /// This builder's purpose is pretty much just to let you document
55    /// your mappings. This can be useful especially for [`Plugin`]
56    /// writers.
57    ///
58    /// The mapping is done once the `RemapBuilder` is [dropped], so
59    /// assigning it to a variable is not recommended
60    ///
61    /// [`Plugin`]: crate::Plugin
62    /// [dropped]: Drop::drop
63    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        /// Adds documentation for the mapped sequence
73        ///
74        /// This documentation will be shown alongside the rest of the
75        /// [`Bindings`] for the [`Mode`]. If this function is not
76        /// called, then the sequence will be shown by itself.
77        ///
78        /// [`Bindings`]: crate::mode::Bindings
79        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    /// Maps a sequence of keys to another
97    ///
98    /// The keys follow the same rules as Vim, so regular, standalone
99    /// characters are mapped verbatim, while "`<{mod}-{key}>`" and
100    /// "`<{special}>`" sequences are mapped like in Vim.
101    ///
102    /// Here are the available special keys:
103    ///
104    /// - `<Enter> => Enter`,
105    /// - `<Tab> => Tab`,
106    /// - `<Bspc> => Backspace`,
107    /// - `<Del> => Delete`,
108    /// - `<Esc> => Esc`,
109    /// - `<Up> => Up`,
110    /// - `<Down> => Down`,
111    /// - `<Left> => Left`,
112    /// - `<Right> => Right`,
113    /// - `<PageU> => PageUp`,
114    /// - `<PageD> => PageDown`,
115    /// - `<Home> => Home`,
116    /// - `<End> => End`,
117    /// - `<Ins> => Insert`,
118    /// - `<F{1-12}> => F({1-12})`,
119    ///
120    /// And the following modifiers are available:
121    ///
122    /// - `C => Control`,
123    /// - `A => Alt`,
124    /// - `S => Shift`,
125    /// - `M => Meta`,
126    /// - `super => Super`,
127    /// - `hyper => Hyper`,
128    ///
129    /// If another sequence already exists on the same mode which
130    /// would intersect with this one, the new sequence will not be
131    /// added.
132    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    /// Aliases a sequence of keys to another
146    ///
147    /// The difference between aliasing and mapping is that an alias
148    /// will be displayed on the text as a [ghost text], making it
149    /// seem like you are typing normally. This text will be printed
150    /// with the `Alias` [form].
151    ///
152    /// If another sequence already exists on the same mode, which
153    /// would intersect with this one, the new sequence will not be
154    /// added.
155    ///
156    /// # Note
157    ///
158    /// This sequence is not like Vim's `alias`, in that if you make a
159    /// mistake while typing the sequence, the alias is undone, and
160    /// you will be just typing normally.
161    ///
162    /// The alias command also works on any [`Mode`], not just
163    /// "insert like" modes. You can also use any key in the input or
164    /// output of this `alias`
165    ///
166    /// [ghost text]: crate::text::Inlay
167    /// [form]: crate::form::Form
168    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    /// The current sequence of [`KeyEvent`]s being mapped
182    pub fn current_sequence() -> DataMap<(Vec<KeyEvent>, bool), (Vec<KeyEvent>, bool)> {
183        super::CUR_SEQ.map(Clone::clone)
184    }
185
186    /// Resets the current sequence of sent keys
187    pub fn reset_current_sequence(pa: &mut Pass) {
188        *super::CUR_SEQ.write(pa) = (Vec::new(), false)
189    }
190
191    /// The base [`MappedBindings`] for the current [`Mode`]
192    ///
193    /// This does not take into account the [current_sequence]. For
194    /// the [`Description`]s of the bindings and remaps given the
195    /// current sequence, you can see [`current_seq_descriptions`]
196    ///
197    /// The reason why this function takes a [`&mut Pass`] rather than
198    /// a `&Pass` is because there might have been [`map`]s and
199    /// [`alias`]es that happened asynchronously before this call, so
200    /// those need to be added in before returning the [`Iterator`]
201    ///
202    /// [`&mut Pass`]: Pass
203    pub fn current_mode_bindings(pa: &mut Pass) -> &MappedBindings {
204        &REMAPPER.write(pa).mapped_bindings[&MODE_TYPE_ID.lock().unwrap()]
205    }
206
207    /// Changes the description for a given [`KeyEvent`] sequence
208    ///
209    /// This will also change the description for every other sequence
210    /// that is associated with the same description.
211    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    /// Replaces the [`Bindings`] for a [`Mode`]
224    ///
225    /// Do note that if you change the `Bindings`, you will replace
226    /// _which_ keys get sent to the `Mode`. You can use this for your
227    /// own gain, since you might want to block certain keybindings.
228    ///
229    /// The main purpose for this function, however, is to create
230    /// "dynamic `Bindings`". In Duat, the [`Bindings`] struct kind of
231    /// assumes that your mappings are static sequences of keys,
232    /// however, sometimes that is not the case. This function serves
233    /// the purpose of covering other possibilities.
234    ///
235    /// [`Bindings`]: super::Bindings
236    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    /// The [`Description`]s of all [`Binding`]s and remaps of the
250    /// current [`Mode`], given the current sequence
251    ///
252    /// For example, in Vim, you can type `ciw` to `c`hange `i`nside a
253    /// `w`ord. If the current sequence of keys was `ci`, then this
254    /// function would return a list of bindings and remappings that
255    /// could follow. Which in this case would include `w` and many
256    /// other keys.
257    ///
258    /// The reason why this function takes a [`&mut Pass`] rather than
259    /// a `&Pass` is because there might have been [`map`]s and
260    /// [`alias`]es that happened asynchronously before this call, so
261    /// those need to be added in before returning the [`Iterator`]
262    ///
263    /// This function also returns a title in the form of
264    /// [`Option<Text>`] in case the bindings has a custom title that
265    /// better describes what the keys do.
266    ///
267    /// [`&mut Pass`]: Pass
268    /// [`Binding`]: super::Binding
269    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    /// Turns a sequence of [`KeyEvent`]s into a [`Text`]
277    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    /// The [`Text`] for a [`KeyMod`], like `AS-`, is empty if `modif
332    /// == KeyMod::NONE`
333    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    /// Turns a string of [`KeyEvent`]s into a [`String`]
360    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    /// Converts an `&str` to a sequence of [`KeyEvent`]s
425    ///
426    /// The conversion follows the same rules as remaps in Vim, that
427    /// is:
428    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                            // Characters are sent as-is, no shifting required.
507                            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    /// Trait to distinguish [`Mode`]s from [`KeyEvent`]s
550    #[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    /// Sends a key to be remapped
568    pub(crate) fn send_key_event(pa: &mut Pass, mut key: KeyEvent) {
569        // No need to send shift to, for example, Char('L').
570        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    /// Sets the key sending function
580    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/// The structure responsible for remapping sequences of characters
592#[derive(Default)]
593struct Remapper {
594    mapped_bindings: HashMap<TypeId, MappedBindings>,
595    mapped_seq: Vec<KeyEvent>,
596}
597
598impl Remapper {
599    /// Maps a sequence of characters to another
600    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
636/// Sends a key to be remapped or not
637fn 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/// A sequence of characters that should be turned into another
729/// sequence of characters or a [`Mode`]
730#[derive(Debug)]
731struct Remap {
732    takes: Vec<KeyEvent>,
733    gives: MapsTo,
734    is_alias: bool,
735    desc: Option<Text>,
736}
737
738impl Remap {
739    /// Returns a new `Remap`
740    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
745/// What a [`map`] or [`alias`] gives, can be a sequence of
746/// [`KeyEvent`]s or a [`Mode`]
747pub enum MapsTo {
748    /// A sequence of [`KeyEvent`]s that a remap maps to
749    Keys(Vec<KeyEvent>),
750    /// A [`Mode`] that a remap switches to
751    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/// The set of regular [`Mode`] [`Bindings`], as well as all
764/// `Remap`s
765#[derive(Debug)]
766pub struct MappedBindings {
767    bindings: Bindings,
768    remaps: Vec<Remap>,
769}
770
771impl MappedBindings {
772    /// Returns `Self` for the available [`Bindings`] for a [`Mode`]
773    fn for_mode<M: Mode>() -> Self {
774        Self {
775            bindings: M::bindings(),
776            remaps: Vec::new(),
777        }
778    }
779
780    /// Returns `Self` from custom [`Bindings`]
781    fn new(bindings: Bindings) -> Self {
782        Self { bindings, remaps: Vec::new() }
783    }
784}
785
786impl MappedBindings {
787    /// Wether these `MappedBindings` accepts the sequence of
788    /// [`KeyEvent`]s
789    ///
790    /// This will be true if either the normal [`Mode`] provided
791    /// [`Bindings`] match the sequence, or if a remap binds it.
792    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    /// Wether the given sequence of [`KeyEvent`]s has a followup
799    /// in these `MappedBindings`
800    ///
801    /// This will be true if either the normal [`Mode`] provided
802    /// [`Bindings`] match the sequence, or if a remap binds it.
803    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    /// The [`Description`]s for the bindings available, given the
811    /// keys sent so far
812    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    /// Replace the description for a sequence of [`KeyEvent`]s
873    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
882/// The description for [`KeyEvent`]s that are mapped or bound in a
883/// [`Mode`]
884///
885/// This description will include an explaining [`Text`] as well as
886/// an [`Iterator`], which returns one of the following:
887///
888/// - A sequence of `KeyEvent`s that are mapped to the action
889/// - A list of [`Binding`]s that are bound to the action
890///
891/// The first one happens when you call [`map`] or [`alias`], since
892/// they let you map a sequence of [`KeyEvent`]s.
893///
894/// The second one comes from a [`Mode`]s own [`Bindings`] from
895/// [`Mode::bindings`]. This is a list of _patterns_ for [`KeyEvent`]s
896/// that are bound to actions. This list is immutable, and each item
897/// is an alternation of _patterns_ (e.g. `'a'..='z'`, "any media
898/// key", concrete [`KeyEvent`]s, etc).
899///
900/// One other thing to note is that
901pub struct Description<'a> {
902    /// The [`Text`] describing what the [`KeyEvent`] will do
903    pub text: Option<&'a Text>,
904    /// The [`Mode`]'s native bindings and all [maps] and [aliases] to
905    /// those bindings
906    ///
907    /// [maps]: map
908    /// [aliases]: alias
909    pub keys: KeyDescriptions<'a>,
910}
911
912/// A [`Mode`]'s bound [`Binding`] or a mapped [`KeyEvent`]
913/// sequence
914#[derive(Debug)]
915pub enum KeyDescription<'a> {
916    /// A [`Mode`]'s regular binding, comes from the [`Bindings`]
917    /// struct
918    Binding(Binding),
919    /// A remapped sequence, comes from [`map`] or [`alias`]
920    Remap(&'a [KeyEvent], &'a MapsTo),
921}
922
923/// An [`Iterator`] over the possible patterns that match a
924/// [`Description`]
925///
926/// This returns a [`KeyDescription`], where
927/// [`KeyDescription::Binding`] represents a pattern that is naturally
928/// bound to a [`Mode`], via [`Mode::bindings`], while a
929/// [`KeyDescription::Remap`] represents a [`KeyEvent`] sequence that
930/// was [mapped] or [aliased] to it.
931///
932/// [mapped]: map
933/// [aliased]: alias
934pub struct KeyDescriptions<'a> {
935    seq: &'a [KeyEvent],
936    ty: DescriptionType<'a>,
937}
938
939impl KeyDescriptions<'_> {
940    /// Gets a [`Text`] to describe the [`Binding`]s and remaps
941    ///
942    /// This function makes use of the `key.char`, `key.mod`,
943    /// `key.special`, `key.range` and `key.any`, `separator` and
944    /// `remap` [`Form`]s.
945    ///
946    /// [`Form`]: crate::form::Form
947    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
1009/// Two types of description
1010enum 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    // SAFETY: Given that the Pass is immediately mutably borrowed, it
1018    // can't be used to act on CurWidget.current.
1019    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}