1use crate::demo_components::get_component;
2use crossterm::event::{KeyCode, KeyModifiers};
3use std::time::Duration;
4
5#[derive(Clone, Debug)]
6#[allow(dead_code)]
7pub enum DemoAction {
8 Wait(Duration),
10 Key(KeyCode),
12 KeyWithModifiers(KeyCode, KeyModifiers),
14 TypeString(String, Duration), ShowHint(String, Duration), Checkpoint(String),
20 VimMotion(String),
22}
23
24#[allow(dead_code)]
25pub struct DemoScript {
26 pub actions: Vec<DemoAction>,
27}
28
29impl DemoScript {
30 pub fn from_components(component_ids: &[&str]) -> Self {
32 let mut actions = vec![];
33
34 for id in component_ids {
35 if let Some(component) = get_component(id) {
36 actions.extend(component.actions);
37 } else {
38 eprintln!("Warning: Unknown demo component ID: {id}");
39 }
40 }
41
42 Self { actions }
43 }
44
45 pub fn marketing_demo() -> Self {
46 Self::from_components(&[
47 "intro_message",
48 "select_paragraph",
49 "highlight_selection",
50 "execute_ls",
51 "search_cargo",
52 "yank_line",
53 "execute_cat_with_paste",
54 ])
56 }
57
58 pub fn speed_demo() -> Self {
59 Self::from_components(&[
60 "intro_message",
61 "basic_navigation",
62 "word_navigation",
63 "select_paragraph",
64 "highlight_selection",
65 "final_message_short",
66 ])
67 }
68
69 pub fn power_user_demo() -> Self {
70 Self::from_components(&[
71 "intro_message",
72 "paragraph_navigation",
73 "search_navigation",
74 "visual_char_mode",
75 "yank_selection",
76 "execute_ls",
77 "yank_and_execute",
78 "execute_grep",
79 "final_message",
80 ])
81 }
82
83 pub fn minimal_demo() -> Self {
84 Self::from_components(&[
85 "intro_message",
86 "basic_navigation",
87 "select_word",
88 "highlight_selection",
89 "clear_highlights",
90 "final_message_short",
91 ])
92 }
93
94 pub fn workflow_demo() -> Self {
95 Self::from_components(&[
96 "intro_message",
97 "basic_navigation",
98 "visual_char_mode",
99 "yank_selection",
100 "execute_cat",
101 "select_line",
102 "highlight_selection",
103 "final_message",
104 ])
105 }
106
107 #[allow(dead_code)]
108 pub fn beginner_tutorial() -> Self {
109 use DemoAction::*;
110
111 let actions = vec![
112 ShowHint(
114 "Welcome to hygg! Let's learn the basics.".to_string(),
115 Duration::from_millis(3000),
116 ),
117 Wait(Duration::from_millis(1000)),
118 ShowHint(
120 "Use j/k to move down/up (try it now!)".to_string(),
121 Duration::from_millis(5000),
122 ),
123 Checkpoint("Waiting for user to practice j/k".to_string()),
124 ];
126
127 Self { actions }
128 }
129
130 #[allow(dead_code)]
132 pub fn tutorial_test() -> Self {
133 use DemoAction::*;
134
135 let actions = vec![
136 Wait(Duration::from_millis(500)),
138 Wait(Duration::from_millis(500)),
140 Key(KeyCode::Char('j')),
141 Wait(Duration::from_millis(500)),
142 Key(KeyCode::Char(':')),
144 Wait(Duration::from_millis(100)),
145 Key(KeyCode::Char('n')),
146 Key(KeyCode::Char('e')),
147 Key(KeyCode::Char('x')),
148 Key(KeyCode::Char('t')),
149 Key(KeyCode::Enter),
150 Wait(Duration::from_millis(500)),
151 Key(KeyCode::Char('v')),
154 Wait(Duration::from_millis(200)),
155 Key(KeyCode::Char('w')),
156 Wait(Duration::from_millis(200)),
157 Key(KeyCode::Char('y')),
158 Wait(Duration::from_millis(500)),
159 Key(KeyCode::Char(':')),
161 Wait(Duration::from_millis(100)),
162 Key(KeyCode::Char('n')),
163 Key(KeyCode::Char('e')),
164 Key(KeyCode::Char('x')),
165 Key(KeyCode::Char('t')),
166 Key(KeyCode::Enter),
167 Wait(Duration::from_millis(500)),
168 VimMotion("vip".to_string()),
170 Wait(Duration::from_millis(500)),
171 Key(KeyCode::Char(':')),
172 Wait(Duration::from_millis(100)),
173 Key(KeyCode::Char('h')),
174 Key(KeyCode::Enter),
175 Wait(Duration::from_millis(500)),
176 Key(KeyCode::Char(':')),
178 Wait(Duration::from_millis(100)),
179 Key(KeyCode::Char('n')),
180 Key(KeyCode::Char('e')),
181 Key(KeyCode::Char('x')),
182 Key(KeyCode::Char('t')),
183 Key(KeyCode::Enter),
184 Wait(Duration::from_millis(500)),
185 Key(KeyCode::Char('/')),
187 Wait(Duration::from_millis(200)),
188 Key(KeyCode::Char('s')),
189 Key(KeyCode::Char('p')),
190 Key(KeyCode::Char('e')),
191 Key(KeyCode::Char('c')),
192 Key(KeyCode::Char('i')),
193 Key(KeyCode::Char('a')),
194 Key(KeyCode::Char('l')),
195 Key(KeyCode::Enter),
196 Wait(Duration::from_millis(500)),
197 Key(KeyCode::Char(':')),
199 Wait(Duration::from_millis(100)),
200 Key(KeyCode::Char('n')),
201 Key(KeyCode::Char('e')),
202 Key(KeyCode::Char('x')),
203 Key(KeyCode::Char('t')),
204 Key(KeyCode::Enter),
205 Wait(Duration::from_millis(500)),
206 Key(KeyCode::Char('m')),
208 Wait(Duration::from_millis(200)),
209 Key(KeyCode::Char('a')),
210 Wait(Duration::from_millis(500)),
211 Key(KeyCode::Char(':')),
213 Wait(Duration::from_millis(100)),
214 Key(KeyCode::Char('n')),
215 Key(KeyCode::Char('e')),
216 Key(KeyCode::Char('x')),
217 Key(KeyCode::Char('t')),
218 Key(KeyCode::Enter),
219 Wait(Duration::from_millis(500)),
220 Key(KeyCode::Char(':')),
222 Wait(Duration::from_millis(100)),
223 Key(KeyCode::Char('!')),
224 Key(KeyCode::Char('e')),
225 Key(KeyCode::Char('c')),
226 Key(KeyCode::Char('h')),
227 Key(KeyCode::Char('o')),
228 Key(KeyCode::Char(' ')),
229 Key(KeyCode::Char('h')),
230 Key(KeyCode::Char('e')),
231 Key(KeyCode::Char('l')),
232 Key(KeyCode::Char('l')),
233 Key(KeyCode::Char('o')),
234 Key(KeyCode::Char(' ')),
235 Key(KeyCode::Char('w')),
236 Key(KeyCode::Char('o')),
237 Key(KeyCode::Char('r')),
238 Key(KeyCode::Char('l')),
239 Key(KeyCode::Char('d')),
240 Key(KeyCode::Enter),
241 Wait(Duration::from_millis(1000)), Key(KeyCode::Char(':')),
244 Wait(Duration::from_millis(100)),
245 Key(KeyCode::Char('n')),
246 Key(KeyCode::Char('e')),
247 Key(KeyCode::Char('x')),
248 Key(KeyCode::Char('t')),
249 Key(KeyCode::Enter),
250 Wait(Duration::from_millis(500)),
251 Key(KeyCode::Enter),
253 Wait(Duration::from_millis(1000)),
254 ];
255
256 Self { actions }
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use super::*;
263
264 #[test]
265 fn test_from_components() {
266 let demo = DemoScript::from_components(&["intro_message", "final_message"]);
267 assert!(!demo.actions.is_empty());
268 }
269
270 #[test]
271 fn test_marketing_demo_has_correct_components() {
272 let demo = DemoScript::marketing_demo();
273 assert!(!demo.actions.is_empty());
274 }
275
276 #[test]
277 fn test_from_components_with_invalid_id() {
278 let demo = DemoScript::from_components(&[
280 "intro_message",
281 "invalid_component",
282 "final_message",
283 ]);
284 assert!(!demo.actions.is_empty());
286 }
287}