1use crate::{
3 editor::Actions,
4 key::Input,
5 term::CurShape,
6 trie::{QueryResult, Trie},
7};
8use std::fmt;
9
10mod insert;
11mod normal;
12
13pub(crate) use normal::normal_mode;
14
15pub(crate) fn modes() -> Vec<Mode> {
17 vec![normal::normal_mode(), insert::insert_mode()]
18}
19
20#[derive(Debug)]
21pub(crate) struct Mode {
22 pub(crate) name: String,
23 pub(crate) cur_shape: CurShape,
24 pub(crate) keymap: Trie<Input, Actions>,
25 handle_expired_pending: fn(&[Input]) -> QueryResult<Actions>,
26}
27
28impl fmt::Display for Mode {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 write!(f, "{}", self.name)
31 }
32}
33
34impl Mode {
35 pub(crate) fn ephemeral_mode(name: &str) -> Self {
36 Mode {
37 name: name.to_string(),
38 cur_shape: CurShape::Block,
39 keymap: Trie::from_pairs(Vec::new()).unwrap(),
40 handle_expired_pending: |_| QueryResult::Missing,
41 }
42 }
43
44 pub fn handle_keys(&self, keys: &mut Vec<Input>) -> Option<Actions> {
45 match self.keymap.get(keys) {
46 QueryResult::Val(outcome) => {
47 keys.clear();
48 Some(outcome)
49 }
50 QueryResult::Partial => None,
51 QueryResult::Missing => {
52 let res = (self.handle_expired_pending)(keys);
53 match res {
54 QueryResult::Val(outcome) => {
55 keys.clear();
56 Some(outcome)
57 }
58 QueryResult::Missing => {
59 keys.clear();
60 None
61 }
62 QueryResult::Partial => None,
63 }
64 }
65 }
66 }
67}
68
69#[macro_export]
71macro_rules! keymap {
72 ($([$($k:expr),+] => [ $($v:expr),+ ]),+,) => {
73 {
74 let mut pairs = Vec::new();
75
76 $(
77 let key = vec![$($k),+];
78 let value = $crate::keymap!(@action $($v),+);
79 pairs.push((key, value));
80 )+
81
82 $crate::trie::Trie::from_pairs(pairs).unwrap()
83 }
84 };
85
86 (@action $v:expr) => { $crate::editor::Actions::Single($v) };
87 (@action $($v:expr),+) => { $crate::editor::Actions::Multi(vec![$($v),+]) };
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
99 fn mode_keymaps_have_no_collisions() {
100 _ = modes();
101 }
102}