1use crate::input::key_translator::{KeyEventKey, KeyTranslator};
12use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
13use rust_i18n::t;
14use std::collections::{HashMap, HashSet};
15
16#[derive(Debug, Clone)]
18pub struct ExpectedKey {
19 pub code: KeyCode,
20 pub modifiers: KeyModifiers,
21}
22
23impl ExpectedKey {
24 pub const fn new(code: KeyCode, modifiers: KeyModifiers) -> Self {
25 Self { code, modifiers }
26 }
27
28 pub fn to_key_event(&self) -> KeyEvent {
30 KeyEvent::new(self.code, self.modifiers)
31 }
32}
33
34#[derive(Debug, Clone)]
36pub struct CalibrationTarget {
37 pub name: &'static str,
39 pub expected: ExpectedKey,
41}
42
43#[derive(Debug, Clone)]
45pub struct CalibrationGroup {
46 pub name: &'static str,
48 pub targets: Vec<CalibrationTarget>,
50}
51
52pub fn calibration_groups() -> Vec<CalibrationGroup> {
54 vec![
55 CalibrationGroup {
57 name: "Basic Editing",
58 targets: vec![
59 CalibrationTarget {
60 name: "BACKSPACE",
61 expected: ExpectedKey::new(KeyCode::Backspace, KeyModifiers::NONE),
62 },
63 CalibrationTarget {
64 name: "DELETE",
65 expected: ExpectedKey::new(KeyCode::Delete, KeyModifiers::NONE),
66 },
67 CalibrationTarget {
68 name: "TAB",
69 expected: ExpectedKey::new(KeyCode::Tab, KeyModifiers::NONE),
70 },
71 CalibrationTarget {
72 name: "SHIFT+TAB",
73 expected: ExpectedKey::new(KeyCode::BackTab, KeyModifiers::SHIFT),
74 },
75 ],
76 },
77 CalibrationGroup {
79 name: "Line Navigation",
80 targets: vec![
81 CalibrationTarget {
82 name: "HOME",
83 expected: ExpectedKey::new(KeyCode::Home, KeyModifiers::NONE),
84 },
85 CalibrationTarget {
86 name: "END",
87 expected: ExpectedKey::new(KeyCode::End, KeyModifiers::NONE),
88 },
89 CalibrationTarget {
90 name: "SHIFT+HOME",
91 expected: ExpectedKey::new(KeyCode::Home, KeyModifiers::SHIFT),
92 },
93 CalibrationTarget {
94 name: "SHIFT+END",
95 expected: ExpectedKey::new(KeyCode::End, KeyModifiers::SHIFT),
96 },
97 ],
98 },
99 CalibrationGroup {
101 name: "Word Navigation",
102 targets: vec![
103 CalibrationTarget {
104 name: "ALT+LEFT",
105 expected: ExpectedKey::new(KeyCode::Left, KeyModifiers::ALT),
106 },
107 CalibrationTarget {
108 name: "ALT+RIGHT",
109 expected: ExpectedKey::new(KeyCode::Right, KeyModifiers::ALT),
110 },
111 CalibrationTarget {
112 name: "ALT+SHIFT+LEFT",
113 expected: ExpectedKey::new(
114 KeyCode::Left,
115 KeyModifiers::ALT.union(KeyModifiers::SHIFT),
116 ),
117 },
118 CalibrationTarget {
119 name: "ALT+SHIFT+RIGHT",
120 expected: ExpectedKey::new(
121 KeyCode::Right,
122 KeyModifiers::ALT.union(KeyModifiers::SHIFT),
123 ),
124 },
125 CalibrationTarget {
126 name: "CTRL+LEFT",
127 expected: ExpectedKey::new(KeyCode::Left, KeyModifiers::CONTROL),
128 },
129 CalibrationTarget {
130 name: "CTRL+RIGHT",
131 expected: ExpectedKey::new(KeyCode::Right, KeyModifiers::CONTROL),
132 },
133 CalibrationTarget {
134 name: "CTRL+SHIFT+LEFT",
135 expected: ExpectedKey::new(
136 KeyCode::Left,
137 KeyModifiers::CONTROL.union(KeyModifiers::SHIFT),
138 ),
139 },
140 CalibrationTarget {
141 name: "CTRL+SHIFT+RIGHT",
142 expected: ExpectedKey::new(
143 KeyCode::Right,
144 KeyModifiers::CONTROL.union(KeyModifiers::SHIFT),
145 ),
146 },
147 ],
148 },
149 CalibrationGroup {
151 name: "Document Navigation",
152 targets: vec![
153 CalibrationTarget {
154 name: "PAGE UP",
155 expected: ExpectedKey::new(KeyCode::PageUp, KeyModifiers::NONE),
156 },
157 CalibrationTarget {
158 name: "PAGE DOWN",
159 expected: ExpectedKey::new(KeyCode::PageDown, KeyModifiers::NONE),
160 },
161 CalibrationTarget {
162 name: "CTRL+HOME",
163 expected: ExpectedKey::new(KeyCode::Home, KeyModifiers::CONTROL),
164 },
165 CalibrationTarget {
166 name: "CTRL+END",
167 expected: ExpectedKey::new(KeyCode::End, KeyModifiers::CONTROL),
168 },
169 ],
170 },
171 CalibrationGroup {
173 name: "Emacs-Style",
174 targets: vec![
175 CalibrationTarget {
176 name: "CTRL+A",
177 expected: ExpectedKey::new(KeyCode::Char('a'), KeyModifiers::CONTROL),
178 },
179 CalibrationTarget {
180 name: "CTRL+E",
181 expected: ExpectedKey::new(KeyCode::Char('e'), KeyModifiers::CONTROL),
182 },
183 CalibrationTarget {
184 name: "CTRL+K",
185 expected: ExpectedKey::new(KeyCode::Char('k'), KeyModifiers::CONTROL),
186 },
187 CalibrationTarget {
188 name: "CTRL+Y",
189 expected: ExpectedKey::new(KeyCode::Char('y'), KeyModifiers::CONTROL),
190 },
191 ],
192 },
193 ]
194}
195
196#[derive(Debug, Clone)]
198pub enum CalibrationStep {
199 Capture {
201 group_idx: usize,
203 key_idx: usize,
205 },
206 Verify,
208}
209
210#[derive(Debug, Clone, PartialEq)]
212pub enum KeyStatus {
213 Pending,
215 Captured,
217 Skipped,
219 Verified,
221}
222
223#[derive(Debug, Clone)]
225pub enum WizardAction {
226 Continue,
228 GoBack,
230 SkipGroup,
232 Abort,
234 Save,
236 Restart,
238 ReservedKey,
240 KeyCaptured,
242 KeyVerified,
244 ShowConfirmation,
246}
247
248#[derive(Debug, Clone, PartialEq)]
250pub enum PendingConfirmation {
251 None,
253 Abort,
255 Restart,
257}
258
259#[derive(Debug)]
261pub struct CalibrationWizard {
262 pub step: CalibrationStep,
264 groups: Vec<CalibrationGroup>,
266 pending_translations: HashMap<KeyEventKey, KeyEventKey>,
268 key_statuses: Vec<KeyStatus>,
270 captured_raw_keys: HashMap<usize, KeyEventKey>,
272 skipped_groups: HashSet<usize>,
274 verified: HashSet<usize>,
276 pub status_message: Option<String>,
278 pub pending_confirmation: PendingConfirmation,
280}
281
282impl CalibrationWizard {
283 pub fn new() -> Self {
285 let groups = calibration_groups();
286 let total_keys: usize = groups.iter().map(|g| g.targets.len()).sum();
287
288 Self {
289 step: CalibrationStep::Capture {
290 group_idx: 0,
291 key_idx: 0,
292 },
293 groups,
294 pending_translations: HashMap::new(),
295 key_statuses: vec![KeyStatus::Pending; total_keys],
296 captured_raw_keys: HashMap::new(),
297 skipped_groups: HashSet::new(),
298 verified: HashSet::new(),
299 status_message: None,
300 pending_confirmation: PendingConfirmation::None,
301 }
302 }
303
304 pub fn has_pending_confirmation(&self) -> bool {
306 self.pending_confirmation != PendingConfirmation::None
307 }
308
309 pub fn handle_confirmation_key(&mut self, key: KeyEvent) -> WizardAction {
312 if key.modifiers != KeyModifiers::NONE {
313 return WizardAction::Continue;
314 }
315
316 match key.code {
317 KeyCode::Char('d') if self.pending_confirmation == PendingConfirmation::Abort => {
318 self.pending_confirmation = PendingConfirmation::None;
320 WizardAction::Abort
321 }
322 KeyCode::Char('r') if self.pending_confirmation == PendingConfirmation::Restart => {
323 self.pending_confirmation = PendingConfirmation::None;
325 self.restart();
326 WizardAction::Restart
327 }
328 KeyCode::Char('c') | KeyCode::Esc => {
329 self.pending_confirmation = PendingConfirmation::None;
331 self.status_message = Some(t!("calibration.cancelled").to_string());
332 WizardAction::Continue
333 }
334 _ => WizardAction::Continue,
335 }
336 }
337
338 pub fn groups(&self) -> &[CalibrationGroup] {
340 &self.groups
341 }
342
343 pub fn key_status(&self, flat_idx: usize) -> &KeyStatus {
345 self.key_statuses
346 .get(flat_idx)
347 .unwrap_or(&KeyStatus::Pending)
348 }
349
350 pub fn is_group_skipped(&self, group_idx: usize) -> bool {
352 self.skipped_groups.contains(&group_idx)
353 }
354
355 pub fn current_target(&self) -> Option<(&CalibrationGroup, &CalibrationTarget, usize)> {
357 match &self.step {
358 CalibrationStep::Capture { group_idx, key_idx } => {
359 let group = self.groups.get(*group_idx)?;
360 let target = group.targets.get(*key_idx)?;
361 let flat_idx = self.flat_index(*group_idx, *key_idx);
362 Some((group, target, flat_idx))
363 }
364 CalibrationStep::Verify => None,
365 }
366 }
367
368 pub fn current_step_info(&self) -> (usize, usize) {
370 let total: usize = self.groups.iter().map(|g| g.targets.len()).sum();
371 match &self.step {
372 CalibrationStep::Capture { group_idx, key_idx } => {
373 let step = self.flat_index(*group_idx, *key_idx) + 1;
374 (step, total)
375 }
376 CalibrationStep::Verify => (total, total),
377 }
378 }
379
380 fn flat_index(&self, group_idx: usize, key_idx: usize) -> usize {
382 let mut idx = 0;
383 for (i, group) in self.groups.iter().enumerate() {
384 if i == group_idx {
385 return idx + key_idx;
386 }
387 idx += group.targets.len();
388 }
389 idx
390 }
391
392 #[allow(dead_code)]
394 fn unflat_index(&self, flat_idx: usize) -> Option<(usize, usize)> {
395 let mut idx = 0;
396 for (group_idx, group) in self.groups.iter().enumerate() {
397 if flat_idx < idx + group.targets.len() {
398 return Some((group_idx, flat_idx - idx));
399 }
400 idx += group.targets.len();
401 }
402 None
403 }
404
405 pub fn handle_capture_key(&mut self, key: KeyEvent) -> WizardAction {
407 let CalibrationStep::Capture { group_idx, key_idx } = &self.step else {
408 return WizardAction::Continue;
409 };
410
411 let group_idx = *group_idx;
412 let key_idx = *key_idx;
413
414 if key.modifiers == KeyModifiers::NONE {
416 match key.code {
417 KeyCode::Char('s') => {
418 let flat_idx = self.flat_index(group_idx, key_idx);
420 self.key_statuses[flat_idx] = KeyStatus::Skipped;
421 self.status_message = Some(t!("calibration.skipped_key").to_string());
422 self.advance_to_next();
423 return WizardAction::Continue;
424 }
425 KeyCode::Char('b') => {
426 if self.go_back() {
428 return WizardAction::GoBack;
429 } else {
430 self.status_message = Some(t!("calibration.at_first_key").to_string());
431 return WizardAction::Continue;
432 }
433 }
434 KeyCode::Char('g') => {
435 self.skip_current_group();
437 return WizardAction::SkipGroup;
438 }
439 KeyCode::Char('a') => {
440 self.pending_confirmation = PendingConfirmation::Abort;
442 return WizardAction::ShowConfirmation;
443 }
444 KeyCode::Char('y') | KeyCode::Char('n') | KeyCode::Char('r') => {
445 self.status_message = Some(t!("calibration.reserved_key").to_string());
447 return WizardAction::ReservedKey;
448 }
449 _ => {}
450 }
451 }
452
453 let flat_idx = self.flat_index(group_idx, key_idx);
455 let target = &self.groups[group_idx].targets[key_idx];
456 let expected = target.expected.to_key_event();
457
458 if key.code == expected.code && key.modifiers == expected.modifiers {
460 self.key_statuses[flat_idx] = KeyStatus::Skipped;
461 self.captured_raw_keys.remove(&flat_idx);
462 self.status_message = Some(t!("calibration.key_works").to_string());
463 } else {
464 let raw_key = KeyEventKey::from_key_event(&key);
466 let expected_key = KeyEventKey::from_key_event(&expected);
467 self.pending_translations
468 .insert(raw_key.clone(), expected_key);
469 self.captured_raw_keys.insert(flat_idx, raw_key);
470 self.key_statuses[flat_idx] = KeyStatus::Captured;
471 self.status_message = Some(
472 t!(
473 "calibration.captured",
474 key = format!("{:?}", key.code),
475 target = target.name
476 )
477 .to_string(),
478 );
479 }
480
481 self.advance_to_next();
482 WizardAction::KeyCaptured
483 }
484
485 pub fn handle_verify_key(&mut self, key: KeyEvent) -> WizardAction {
487 if key.modifiers == KeyModifiers::NONE {
489 match key.code {
490 KeyCode::Char('y') => {
491 return WizardAction::Save;
492 }
493 KeyCode::Char('r') => {
494 self.pending_confirmation = PendingConfirmation::Restart;
496 return WizardAction::ShowConfirmation;
497 }
498 KeyCode::Char('a') => {
499 self.pending_confirmation = PendingConfirmation::Abort;
501 return WizardAction::ShowConfirmation;
502 }
503 KeyCode::Char('b') => {
504 if self.go_back() {
506 return WizardAction::GoBack;
507 }
508 return WizardAction::Continue;
509 }
510 _ => {}
511 }
512 }
513
514 let translated = self.translate_key(key);
517
518 for (group_idx, group) in self.groups.iter().enumerate() {
520 if self.skipped_groups.contains(&group_idx) {
521 continue;
522 }
523 for (key_idx, target) in group.targets.iter().enumerate() {
524 let expected = target.expected.to_key_event();
525 if translated.code == expected.code && translated.modifiers == expected.modifiers {
526 let flat_idx = self.flat_index(group_idx, key_idx);
527 self.verified.insert(flat_idx);
528 self.key_statuses[flat_idx] = KeyStatus::Verified;
529 self.status_message =
530 Some(t!("calibration.key_verified", key = target.name).to_string());
531 return WizardAction::KeyVerified;
532 }
533 }
534 }
535
536 self.status_message = Some(t!("calibration.key_not_recognized").to_string());
537 WizardAction::Continue
538 }
539
540 fn translate_key(&self, key: KeyEvent) -> KeyEvent {
542 let raw_key = KeyEventKey::from_key_event(&key);
543 if let Some(expected_key) = self.pending_translations.get(&raw_key) {
544 expected_key.to_key_event()
545 } else {
546 key
547 }
548 }
549
550 fn skip_current_group(&mut self) {
552 if let CalibrationStep::Capture { group_idx, key_idx } = &self.step {
553 let group_idx = *group_idx;
554 let key_idx = *key_idx;
555
556 let group = &self.groups[group_idx];
558 for i in key_idx..group.targets.len() {
559 let flat_idx = self.flat_index(group_idx, i);
560 self.key_statuses[flat_idx] = KeyStatus::Skipped;
561 }
562
563 self.skipped_groups.insert(group_idx);
564 self.status_message =
565 Some(t!("calibration.skipped_group", group = group.name).to_string());
566
567 if group_idx + 1 < self.groups.len() {
569 self.step = CalibrationStep::Capture {
570 group_idx: group_idx + 1,
571 key_idx: 0,
572 };
573 } else {
574 self.step = CalibrationStep::Verify;
575 }
576 }
577 }
578
579 fn advance_to_next(&mut self) {
581 if let CalibrationStep::Capture { group_idx, key_idx } = &self.step {
582 let group_idx = *group_idx;
583 let key_idx = *key_idx;
584
585 let group = &self.groups[group_idx];
586 if key_idx + 1 < group.targets.len() {
587 self.step = CalibrationStep::Capture {
589 group_idx,
590 key_idx: key_idx + 1,
591 };
592 } else if group_idx + 1 < self.groups.len() {
593 self.step = CalibrationStep::Capture {
595 group_idx: group_idx + 1,
596 key_idx: 0,
597 };
598 } else {
599 self.step = CalibrationStep::Verify;
601 self.status_message = Some(t!("calibration.capture_complete").to_string());
602 }
603 }
604 }
605
606 fn go_back(&mut self) -> bool {
609 let (group_idx, key_idx) = match &self.step {
610 CalibrationStep::Capture { group_idx, key_idx } => (*group_idx, *key_idx),
611 CalibrationStep::Verify => {
612 let last_group = self.groups.len() - 1;
614 let last_key = self.groups[last_group].targets.len() - 1;
615 self.step = CalibrationStep::Capture {
616 group_idx: last_group,
617 key_idx: last_key,
618 };
619 self.undo_key_at(last_group, last_key);
620 self.status_message = Some(t!("calibration.went_back").to_string());
621 return true;
622 }
623 };
624
625 if group_idx == 0 && key_idx == 0 {
627 return false;
628 }
629
630 let (prev_group, prev_key) = if key_idx > 0 {
632 (group_idx, key_idx - 1)
633 } else {
634 let prev_group = group_idx - 1;
636 let prev_key = self.groups[prev_group].targets.len() - 1;
637 self.skipped_groups.remove(&prev_group);
639 (prev_group, prev_key)
640 };
641
642 self.step = CalibrationStep::Capture {
643 group_idx: prev_group,
644 key_idx: prev_key,
645 };
646 self.undo_key_at(prev_group, prev_key);
647 self.status_message = Some(t!("calibration.went_back").to_string());
648 true
649 }
650
651 fn undo_key_at(&mut self, group_idx: usize, key_idx: usize) {
653 let flat_idx = self.flat_index(group_idx, key_idx);
654
655 if let Some(raw_key) = self.captured_raw_keys.remove(&flat_idx) {
657 self.pending_translations.remove(&raw_key);
658 }
659
660 self.key_statuses[flat_idx] = KeyStatus::Pending;
662 }
663
664 pub fn restart(&mut self) {
666 let total_keys: usize = self.groups.iter().map(|g| g.targets.len()).sum();
667 self.step = CalibrationStep::Capture {
668 group_idx: 0,
669 key_idx: 0,
670 };
671 self.pending_translations.clear();
672 self.key_statuses = vec![KeyStatus::Pending; total_keys];
673 self.captured_raw_keys.clear();
674 self.skipped_groups.clear();
675 self.verified.clear();
676 self.status_message = Some(t!("calibration.restarted").to_string());
677 }
678
679 pub fn is_verify_phase(&self) -> bool {
681 matches!(self.step, CalibrationStep::Verify)
682 }
683
684 pub fn translation_count(&self) -> usize {
686 self.pending_translations.len()
687 }
688
689 pub fn build_translator(&self) -> KeyTranslator {
691 let mut translator = KeyTranslator::new();
692 for (raw, expected) in &self.pending_translations {
693 translator.add_translation(raw.to_key_event(), expected.to_key_event());
694 }
695 translator
696 }
697
698 pub fn verification_progress(&self) -> (usize, usize) {
700 let total: usize = self
701 .key_statuses
702 .iter()
703 .filter(|s| matches!(s, KeyStatus::Captured))
704 .count();
705 let verified = self.verified.len();
706 (verified, total)
707 }
708
709 pub fn all_key_info(&self) -> Vec<(usize, usize, &CalibrationTarget, &KeyStatus)> {
711 let mut result = Vec::new();
712 let mut flat_idx = 0;
713 for (group_idx, group) in self.groups.iter().enumerate() {
714 for (key_idx, target) in group.targets.iter().enumerate() {
715 let status = &self.key_statuses[flat_idx];
716 result.push((group_idx, key_idx, target, status));
717 flat_idx += 1;
718 }
719 }
720 result
721 }
722}
723
724impl Default for CalibrationWizard {
725 fn default() -> Self {
726 Self::new()
727 }
728}
729
730#[cfg(test)]
731mod tests {
732 use super::*;
733
734 #[test]
735 fn test_wizard_creation() {
736 let wizard = CalibrationWizard::new();
737 assert!(matches!(
738 wizard.step,
739 CalibrationStep::Capture {
740 group_idx: 0,
741 key_idx: 0
742 }
743 ));
744 assert_eq!(wizard.translation_count(), 0);
745 }
746
747 #[test]
748 fn test_step_info() {
749 let wizard = CalibrationWizard::new();
750 let (step, total) = wizard.current_step_info();
751 assert_eq!(step, 1);
752 assert_eq!(total, 24); }
754
755 #[test]
756 fn test_skip_key() {
757 let mut wizard = CalibrationWizard::new();
758
759 let key = KeyEvent::new(KeyCode::Char('s'), KeyModifiers::NONE);
761 let action = wizard.handle_capture_key(key);
762
763 assert!(matches!(action, WizardAction::Continue));
764 assert_eq!(*wizard.key_status(0), KeyStatus::Skipped);
765
766 assert!(matches!(
768 wizard.step,
769 CalibrationStep::Capture {
770 group_idx: 0,
771 key_idx: 1
772 }
773 ));
774 }
775
776 #[test]
777 fn test_skip_group() {
778 let mut wizard = CalibrationWizard::new();
779
780 let key = KeyEvent::new(KeyCode::Char('g'), KeyModifiers::NONE);
782 let action = wizard.handle_capture_key(key);
783
784 assert!(matches!(action, WizardAction::SkipGroup));
785 assert!(wizard.is_group_skipped(0));
786
787 assert!(matches!(
789 wizard.step,
790 CalibrationStep::Capture {
791 group_idx: 1,
792 key_idx: 0
793 }
794 ));
795 }
796
797 #[test]
798 fn test_abort_with_confirmation() {
799 let mut wizard = CalibrationWizard::new();
800
801 let key = KeyEvent::new(KeyCode::Char('a'), KeyModifiers::NONE);
803 let action = wizard.handle_capture_key(key);
804
805 assert!(matches!(action, WizardAction::ShowConfirmation));
807 assert!(wizard.has_pending_confirmation());
808 assert!(matches!(
809 wizard.pending_confirmation,
810 PendingConfirmation::Abort
811 ));
812
813 let confirm_key = KeyEvent::new(KeyCode::Char('d'), KeyModifiers::NONE);
815 let action = wizard.handle_confirmation_key(confirm_key);
816
817 assert!(matches!(action, WizardAction::Abort));
818 }
819
820 #[test]
821 fn test_abort_cancelled() {
822 let mut wizard = CalibrationWizard::new();
823
824 let key = KeyEvent::new(KeyCode::Char('a'), KeyModifiers::NONE);
826 wizard.handle_capture_key(key);
827
828 let cancel_key = KeyEvent::new(KeyCode::Char('c'), KeyModifiers::NONE);
830 let action = wizard.handle_confirmation_key(cancel_key);
831
832 assert!(matches!(action, WizardAction::Continue));
833 assert!(!wizard.has_pending_confirmation());
834 }
835
836 #[test]
837 fn test_go_back() {
838 let mut wizard = CalibrationWizard::new();
839
840 let backspace = KeyEvent::new(KeyCode::Char('\x7f'), KeyModifiers::NONE);
842 wizard.handle_capture_key(backspace);
843
844 assert!(matches!(
846 wizard.step,
847 CalibrationStep::Capture {
848 group_idx: 0,
849 key_idx: 1
850 }
851 ));
852 assert_eq!(wizard.translation_count(), 1);
853
854 let go_back = KeyEvent::new(KeyCode::Char('b'), KeyModifiers::NONE);
856 let action = wizard.handle_capture_key(go_back);
857
858 assert!(matches!(action, WizardAction::GoBack));
859
860 assert!(matches!(
862 wizard.step,
863 CalibrationStep::Capture {
864 group_idx: 0,
865 key_idx: 0
866 }
867 ));
868
869 assert_eq!(wizard.translation_count(), 0);
871 assert_eq!(*wizard.key_status(0), KeyStatus::Pending);
872 }
873
874 #[test]
875 fn test_go_back_at_first_key() {
876 let mut wizard = CalibrationWizard::new();
877
878 let go_back = KeyEvent::new(KeyCode::Char('b'), KeyModifiers::NONE);
880 let action = wizard.handle_capture_key(go_back);
881
882 assert!(matches!(action, WizardAction::Continue));
884 assert!(matches!(
885 wizard.step,
886 CalibrationStep::Capture {
887 group_idx: 0,
888 key_idx: 0
889 }
890 ));
891 }
892
893 #[test]
894 fn test_reserved_key() {
895 let mut wizard = CalibrationWizard::new();
896
897 let key = KeyEvent::new(KeyCode::Char('y'), KeyModifiers::NONE);
899 let action = wizard.handle_capture_key(key);
900
901 assert!(matches!(action, WizardAction::ReservedKey));
902 }
903
904 #[test]
905 fn test_capture_key() {
906 let mut wizard = CalibrationWizard::new();
907
908 let key = KeyEvent::new(KeyCode::Char('\x7f'), KeyModifiers::NONE);
910 let action = wizard.handle_capture_key(key);
911
912 assert!(matches!(action, WizardAction::KeyCaptured));
913 assert_eq!(*wizard.key_status(0), KeyStatus::Captured);
914 assert_eq!(wizard.translation_count(), 1);
915 }
916
917 #[test]
918 fn test_capture_correct_key() {
919 let mut wizard = CalibrationWizard::new();
920
921 let key = KeyEvent::new(KeyCode::Backspace, KeyModifiers::NONE);
923 let action = wizard.handle_capture_key(key);
924
925 assert!(matches!(action, WizardAction::KeyCaptured));
926 assert_eq!(*wizard.key_status(0), KeyStatus::Skipped);
928 assert_eq!(wizard.translation_count(), 0);
929 }
930
931 #[test]
932 fn test_restart() {
933 let mut wizard = CalibrationWizard::new();
934
935 let key = KeyEvent::new(KeyCode::Char('\x7f'), KeyModifiers::NONE);
937 wizard.handle_capture_key(key);
938
939 assert_eq!(wizard.translation_count(), 1);
940
941 wizard.restart();
943
944 assert_eq!(wizard.translation_count(), 0);
945 assert!(matches!(
946 wizard.step,
947 CalibrationStep::Capture {
948 group_idx: 0,
949 key_idx: 0
950 }
951 ));
952 }
953
954 #[test]
955 fn test_verify_phase() {
956 let mut wizard = CalibrationWizard::new();
957
958 for _ in 0..24 {
960 let key = KeyEvent::new(KeyCode::Char('s'), KeyModifiers::NONE);
961 wizard.handle_capture_key(key);
962 }
963
964 assert!(wizard.is_verify_phase());
965 }
966
967 #[test]
968 fn test_verify_save() {
969 let mut wizard = CalibrationWizard::new();
970 wizard.step = CalibrationStep::Verify;
971
972 let key = KeyEvent::new(KeyCode::Char('y'), KeyModifiers::NONE);
973 let action = wizard.handle_verify_key(key);
974
975 assert!(matches!(action, WizardAction::Save));
976 }
977
978 #[test]
979 fn test_build_translator() {
980 let mut wizard = CalibrationWizard::new();
981
982 let raw = KeyEvent::new(KeyCode::Char('\x7f'), KeyModifiers::NONE);
984 wizard.handle_capture_key(raw);
985
986 let translator = wizard.build_translator();
987 assert_eq!(translator.len(), 1);
988
989 let translated = translator.translate(raw);
991 assert_eq!(translated.code, KeyCode::Backspace);
992 }
993}