inquire/prompts/
action.rs1use std::fmt::Debug;
5
6use crate::ui::{Key, KeyModifiers};
7
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
15pub enum Action<I>
16where
17 I: Copy + Clone + PartialEq + Eq,
18{
19 Submit,
21 Cancel,
23 Interrupt,
25 Inner(I),
27}
28
29impl<I> Action<I>
30where
31 I: Copy + Clone + PartialEq + Eq,
32{
33 pub fn from_key<C>(key: Key, config: &C) -> Option<Action<I>>
35 where
36 I: InnerAction<Config = C>,
37 {
38 match key {
39 Key::Enter
40 | Key::Char('\n', KeyModifiers::NONE)
41 | Key::Char('j', KeyModifiers::CONTROL) => Some(Action::Submit),
42 Key::Escape | Key::Char('g' | 'd', KeyModifiers::CONTROL) => Some(Action::Cancel),
43 Key::Char('c', KeyModifiers::CONTROL) => Some(Action::Interrupt),
44 key => I::from_key(key, config).map(Action::Inner),
45 }
46 }
47}
48
49pub trait InnerAction
54where
55 Self: Sized + Copy + Clone + PartialEq + Eq,
56{
57 type Config;
61
62 fn from_key(key: Key, config: &Self::Config) -> Option<Self>
64 where
65 Self: Sized;
66}
67
68#[cfg(test)]
69mod test {
70 use crate::{
71 ui::{Key, KeyModifiers},
72 Action, InnerAction,
73 };
74
75 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
76 pub enum MockInnerAction {
77 Action(Key),
78 }
79
80 impl InnerAction for MockInnerAction {
81 type Config = ();
82
83 fn from_key(key: Key, _config: &()) -> Option<Self>
84 where
85 Self: Sized,
86 {
87 Some(Self::Action(key))
88 }
89 }
90
91 #[test]
92 fn standard_keybindings_for_submit() {
93 let key = Key::Enter;
94 assert_eq!(
95 Some(Action::<MockInnerAction>::Submit),
96 Action::from_key(key, &())
97 );
98 }
99
100 #[test]
101 fn standard_keybindings_for_cancel() {
102 let key = Key::Escape;
103 assert_eq!(
104 Some(Action::<MockInnerAction>::Cancel),
105 Action::from_key(key, &())
106 );
107 }
108
109 #[test]
110 fn ctrl_c_results_in_interrupt_action() {
111 let key = Key::Char('c', KeyModifiers::CONTROL);
112 assert_eq!(
113 Some(Action::<MockInnerAction>::Interrupt),
114 Action::from_key(key, &())
115 );
116 }
117
118 #[test]
119 fn generic_keys_are_passed_down_to_inner_action() {
120 assert_eq!(
121 Some(Action::<MockInnerAction>::Inner(MockInnerAction::Action(
122 Key::Char('a', KeyModifiers::NONE)
123 ))),
124 Action::from_key(Key::Char('a', KeyModifiers::NONE), &())
125 );
126 assert_eq!(
127 Some(Action::<MockInnerAction>::Inner(MockInnerAction::Action(
128 Key::Home
129 ))),
130 Action::from_key(Key::Home, &())
131 );
132 assert_eq!(
133 Some(Action::<MockInnerAction>::Inner(MockInnerAction::Action(
134 Key::PageDown(KeyModifiers::NONE)
135 ))),
136 Action::from_key(Key::PageDown(KeyModifiers::NONE), &())
137 );
138 }
139
140 #[test]
141 fn emacs_control_keybindings() {
142 assert_eq!(
143 Some(Action::<MockInnerAction>::Submit),
144 Action::from_key(Key::Char('j', KeyModifiers::CONTROL), &())
145 );
146 assert_eq!(
147 Some(Action::<MockInnerAction>::Cancel),
148 Action::from_key(Key::Char('g', KeyModifiers::CONTROL), &())
149 );
150 }
151}