1use core::fmt::Debug;
2
3use serde::Deserialize;
4
5use crate::input;
6use crate::key;
7use crate::keymap;
8
9pub use crate::init::MAX_TAP_DANCE_DEFINITIONS;
10
11#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
13pub struct Config {
14 #[serde(default = "default_timeout")]
16 pub timeout: u16,
17}
18
19fn default_timeout() -> u16 {
20 DEFAULT_CONFIG.timeout
21}
22
23pub const DEFAULT_CONFIG: Config = Config { timeout: 200 };
25
26impl Default for Config {
27 fn default() -> Self {
29 DEFAULT_CONFIG
30 }
31}
32
33#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
35pub struct Key<K: key::Key> {
36 definitions: [Option<K>; MAX_TAP_DANCE_DEFINITIONS],
38}
39
40impl<K: key::Key + Copy> Key<K> {
41 pub const fn new(definitions: [Option<K>; MAX_TAP_DANCE_DEFINITIONS]) -> Key<K> {
43 Key { definitions }
44 }
45
46 pub const fn from_definitions(defs: &[K]) -> Self {
48 let mut definitions: [Option<K>; MAX_TAP_DANCE_DEFINITIONS] =
49 [None; MAX_TAP_DANCE_DEFINITIONS];
50 let mut idx = 0;
51 while idx < definitions.len() && idx < defs.len() {
52 definitions[idx] = Some(defs[idx]);
53 idx += 1;
54 }
55 Self::new(definitions)
56 }
57}
58
59impl<K: key::Key> Key<K> {
60 fn new_pressed_key(
61 &self,
62 context: &K::Context,
63 key_path: key::KeyPath,
64 ) -> (
65 key::PressedKeyResult<K::PendingKeyState, K::KeyState>,
66 key::KeyEvents<K::Event>,
67 )
68 where
69 for<'ctx> &'ctx K::Context: Into<&'ctx Context>,
70 for<'ctx> &'ctx K::Context: Into<&'ctx keymap::KeymapContext>,
71 Event: Into<K::Event>,
72 PendingKeyState: Into<K::PendingKeyState>,
73 {
74 let keymap_index: u16 = key_path.keymap_index();
75
76 let td_pks = PendingKeyState::new();
77 let pk = key::PressedKeyResult::Pending(key_path, td_pks.into());
78
79 let &Context { config, .. } = context.into();
80 let timeout_ev = Event::NextPressTimeout(0);
81 let key_ev = key::Event::Key {
82 keymap_index,
83 key_event: timeout_ev,
84 };
85 let pke =
86 key::KeyEvents::scheduled_event(key::ScheduledEvent::after(config.timeout, key_ev));
87
88 (pk, pke.into_events())
89 }
90}
91
92impl<
93 K: key::Key<
94 Context = crate::init::Context,
95 Event = crate::init::Event,
96 PendingKeyState = crate::init::PendingKeyState,
97 KeyState = crate::init::KeyState,
98 >,
99 > key::Key for Key<K>
100{
101 type Context = crate::init::Context;
102 type Event = crate::init::Event;
103 type PendingKeyState = crate::init::PendingKeyState;
104 type KeyState = crate::init::KeyState;
105
106 fn new_pressed_key(
107 &self,
108 context: &Self::Context,
109 key_path: key::KeyPath,
110 ) -> (
111 key::PressedKeyResult<Self::PendingKeyState, Self::KeyState>,
112 key::KeyEvents<Self::Event>,
113 ) {
114 self.new_pressed_key(context, key_path.clone())
115 }
116
117 fn handle_event(
118 &self,
119 pending_state: &mut Self::PendingKeyState,
120 context: &Self::Context,
121 key_path: key::KeyPath,
122 event: key::Event<Self::Event>,
123 ) -> (Option<key::NewPressedKey>, key::KeyEvents<Self::Event>) {
124 let keymap_index = key_path.keymap_index();
125 let td_pks_res: Result<&mut PendingKeyState, _> = pending_state.try_into();
126 if let Ok(td_pks) = td_pks_res {
127 if let Ok(td_ev) = event.try_into_key_event(|e| e.try_into()) {
128 let (maybe_resolution, pke) =
129 td_pks.handle_event(context.into(), keymap_index, td_ev);
130
131 if let Some(TapDanceResolution(idx)) = maybe_resolution {
132 let new_key_path = key_path.append_path_item(idx as u16);
134
135 (
136 Some(key::NewPressedKey::key_path(new_key_path)),
137 pke.into_events(),
138 )
139 } else {
140 let definition_count = self.definitions.iter().filter(|o| o.is_some()).count();
142 if td_pks.press_count as usize >= definition_count - 1 {
143 let idx = definition_count - 1;
144 let new_key_path = key_path.append_path_item(idx as u16);
146
147 (
148 Some(key::NewPressedKey::key_path(new_key_path)),
149 pke.into_events(),
150 )
151 } else {
152 (None, pke.into_events())
153 }
154 }
155 } else {
156 (None, key::KeyEvents::no_events())
157 }
158 } else {
159 (None, key::KeyEvents::no_events())
160 }
161 }
162
163 fn lookup(
164 &self,
165 path: &[u16],
166 ) -> &dyn key::Key<
167 Context = Self::Context,
168 Event = Self::Event,
169 PendingKeyState = Self::PendingKeyState,
170 KeyState = Self::KeyState,
171 > {
172 match path {
173 [] => self,
174 [idx, path @ ..] => match &self.definitions[*idx as usize] {
176 Some(key) => key.lookup(path),
177 None => panic!(),
178 },
179 }
180 }
181}
182
183#[derive(Debug, Clone, Copy, PartialEq)]
185pub struct Context {
186 config: Config,
187}
188
189pub const DEFAULT_CONTEXT: Context = Context::from_config(DEFAULT_CONFIG);
191
192impl Context {
193 pub const fn from_config(config: Config) -> Context {
195 Context { config }
196 }
197}
198
199#[derive(Debug, Clone, Copy, PartialEq)]
201pub struct TapDanceResolution(u8);
202
203#[derive(Debug, Clone, Copy, PartialEq)]
205pub enum Event {
206 NextPressTimeout(u8),
208}
209
210#[derive(Debug, Clone, PartialEq)]
212pub struct PendingKeyState {
213 press_count: u8,
214}
215
216impl PendingKeyState {
217 fn new() -> PendingKeyState {
219 PendingKeyState { press_count: 0 }
220 }
221
222 fn handle_event(
223 &mut self,
224 context: &Context,
225 keymap_index: u16,
226 event: key::Event<Event>,
227 ) -> (Option<TapDanceResolution>, key::KeyEvents<Event>) {
228 match event {
229 key::Event::Key {
230 key_event: Event::NextPressTimeout(press_timed_out),
231 keymap_index: ev_kmi,
232 } if ev_kmi == keymap_index && press_timed_out == self.press_count => (
233 Some(TapDanceResolution(self.press_count)),
234 key::KeyEvents::no_events(),
235 ),
236
237 key::Event::Input(input::Event::Press {
238 keymap_index: ev_kmi,
239 }) if ev_kmi == keymap_index => {
240 self.press_count += 1;
241
242 let Context { config } = context;
243 let timeout_ev = Event::NextPressTimeout(self.press_count);
244
245 let key_ev = key::Event::Key {
246 keymap_index,
247 key_event: timeout_ev,
248 };
249 let pke = key::KeyEvents::scheduled_event(key::ScheduledEvent::after(
250 config.timeout,
251 key_ev,
252 ));
253
254 (None, pke)
255 }
256
257 _ => (None, key::KeyEvents::no_events()),
258 }
259 }
260}