1use crate::{
3 config::KeyBindings,
4 editor::Actions,
5 key::Input,
6 term::CurShape,
7 trie::{QueryResult, Trie},
8};
9use std::fmt;
10use tracing::error;
11
12mod insert;
13mod normal;
14
15pub(crate) fn modes(custom_bindings: &KeyBindings) -> Vec<Mode> {
17 let mut normal = normal::normal_mode().0;
18 if let Err(e) = normal.with_overrides(custom_bindings.normal.clone()) {
19 error!("unable to apply keymap overrides for NORMAL mode: {e}");
20 }
21
22 let mut insert = insert::insert_mode().0;
23 if let Err(e) = insert.with_overrides(custom_bindings.insert.clone()) {
24 error!("unable to apply keymap overrides for INSERT mode: {e}");
25 }
26
27 vec![normal, insert]
28}
29
30pub(crate) fn keybindings() -> Vec<(&'static str, Vec<(String, &'static str)>)> {
32 vec![
33 ("NORMAL", normal::normal_mode().1),
34 ("INSERT", insert::insert_mode().1),
35 ]
36}
37
38#[derive(Debug)]
39pub(crate) struct Mode {
40 pub(crate) name: String,
41 pub(crate) cur_shape: CurShape,
42 pub(crate) keymap: Trie<Input, Actions>,
43 handle_expired_pending: fn(&[Input]) -> Option<Actions>,
44}
45
46impl fmt::Display for Mode {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 write!(f, "{}", self.name)
49 }
50}
51
52impl Mode {
53 pub(crate) fn ephemeral_mode(name: &str) -> Self {
54 Mode {
55 name: name.to_string(),
56 cur_shape: CurShape::Block,
57 keymap: Trie::try_from_iter(Vec::new()).unwrap(),
58 handle_expired_pending: |_| None,
59 }
60 }
61
62 fn with_overrides(&mut self, overrides: Trie<Input, Actions>) -> Result<(), &'static str> {
63 self.keymap = self.keymap.clone().merge_overriding(overrides)?;
64
65 Ok(())
66 }
67
68 pub fn handle_keys(&self, keys: &mut Vec<Input>) -> Option<Actions> {
69 match self.keymap.get(keys) {
70 QueryResult::Val(actions) => {
71 keys.clear();
72 Some(actions.clone())
73 }
74 QueryResult::Partial => None,
75 QueryResult::Missing => {
76 let res = (self.handle_expired_pending)(keys);
77 keys.clear();
78 res
79 }
80 }
81 }
82}
83
84#[macro_export]
86macro_rules! keymap {
87 ($($docs:expr; [$($k:expr),+] => [ $($v:expr),+ ]),+,) => {
88 {
89 let mut pairs = Vec::new();
90 let mut docs = Vec::new();
91
92 $(
93 let key = vec![$($k),+];
94 let value = $crate::keymap!(@action $($v),+);
95 pairs.push((key, value));
96
97 let doc_key = vec![$($k.to_string()),+].join(" ");
98 docs.push((doc_key, $docs));
99 )+
100
101 ($crate::trie::Trie::try_from_iter(pairs).unwrap(), docs)
102 }
103 };
104
105 (@action $v:expr) => { $crate::editor::Actions::Single($v) };
106 (@action $($v:expr),+) => { $crate::editor::Actions::Multi(vec![$($v),+]) };
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[test]
118 fn mode_keymaps_have_no_collisions() {
119 _ = modes(&KeyBindings::default());
120 }
121}