1pub const HELP: &str = "F1";
4pub const THEME: &str = "F2";
5pub const FILTER_AGENT: &str = "F3";
6pub const FILTER_WORKSPACE: &str = "F4";
7pub const FILTER_DATE_FROM: &str = "F5";
8pub const FILTER_DATE_TO: &str = "F6";
9pub const CONTEXT_WINDOW: &str = "F7";
10pub const EDITOR: &str = "F8";
11pub const MATCH_MODE: &str = "F9";
12pub const SEARCH_MODE: &str = "Alt+S";
13pub const QUIT: &str = "Esc/F10";
14pub const CLEAR_FILTERS: &str = "Ctrl+Del";
15pub const RESET_STATE: &str = "Ctrl+Shift+Del";
16pub const RANKING: &str = "F12";
17pub const REFRESH: &str = "Ctrl+Shift+R";
18pub const DETAIL_OPEN: &str = "Enter";
19pub const DETAIL_CLOSE: &str = "Esc";
20pub const FOCUS_QUERY: &str = "Tab/Shift+Tab";
21pub const HISTORY_NEXT: &str = "Ctrl+n";
22pub const HISTORY_PREV: &str = "Ctrl+p";
23pub const HISTORY_CYCLE: &str = "Ctrl+R";
24
25pub const SCOPE_AGENT: &str = "Shift+F3";
27pub const SCOPE_WORKSPACE: &str = "Shift+F4";
28pub const CYCLE_TIME_PRESETS: &str = "Shift+F5";
29
30pub const PALETTE: &str = "Ctrl+P";
32pub const DENSITY: &str = "Ctrl+D";
33pub const BORDERS: &str = "Ctrl+B";
34pub const STATS_BAR: &str = "Ctrl+S";
35
36pub const COPY: &str = "Alt+Y";
38pub const COPY_PATH: &str = "Ctrl+Y";
39pub const COPY_CONTENT: &str = "Ctrl+Shift+C";
40pub const BULK_MENU: &str = "Alt+B";
41pub const JSON_VIEW: &str = "Alt+Shift+J";
42pub const TOGGLE_SELECT: &str = "Ctrl+X";
43pub const PANE_FILTER: &str = "Alt+/";
44pub const EXPORT_HTML: &str = "Ctrl+E";
45pub const EXPORT_MARKDOWN: &str = "Ctrl+Shift+E";
46
47pub const DETAIL_FIND: &str = "/";
49pub const DETAIL_FIND_NEXT: &str = "n";
50pub const DETAIL_FIND_PREV: &str = "N";
51
52pub const THEME_PREV: &str = "Shift+F2";
54
55pub const SOURCES: &str = "Ctrl+Shift+S";
57
58pub const INSPECTOR: &str = "Ctrl+Shift+I";
60
61pub const MACRO_TOGGLE: &str = "Alt+M";
63
64pub const SURFACE_ANALYTICS: &str = "Alt+A";
66pub const SURFACE_SWARM: &str = "Alt+W";
67
68pub const TAB_FOCUS: &str = "Tab";
70pub const VIM_NAV: &str = "Alt+h/j/k/l";
71pub const JUMP_TOP: &str = "Home";
72pub const JUMP_BOTTOM: &str = "End";
73
74#[cfg(test)]
79mod tests {
80 use super::*;
81 use std::collections::HashSet;
82
83 #[test]
88 fn function_key_shortcuts_are_not_empty() {
89 assert!(!HELP.is_empty());
90 assert!(!THEME.is_empty());
91 assert!(!FILTER_AGENT.is_empty());
92 assert!(!FILTER_WORKSPACE.is_empty());
93 assert!(!FILTER_DATE_FROM.is_empty());
94 assert!(!FILTER_DATE_TO.is_empty());
95 assert!(!CONTEXT_WINDOW.is_empty());
96 assert!(!EDITOR.is_empty());
97 assert!(!MATCH_MODE.is_empty());
98 assert!(!RANKING.is_empty());
99 }
100
101 #[test]
102 fn function_key_shortcuts_have_expected_values() {
103 assert_eq!(HELP, "F1");
104 assert_eq!(THEME, "F2");
105 assert_eq!(FILTER_AGENT, "F3");
106 assert_eq!(FILTER_WORKSPACE, "F4");
107 assert_eq!(FILTER_DATE_FROM, "F5");
108 assert_eq!(FILTER_DATE_TO, "F6");
109 assert_eq!(CONTEXT_WINDOW, "F7");
110 assert_eq!(EDITOR, "F8");
111 assert_eq!(MATCH_MODE, "F9");
112 assert_eq!(RANKING, "F12");
113 }
114
115 #[test]
120 fn modifier_shortcuts_are_not_empty() {
121 assert!(!SEARCH_MODE.is_empty());
122 assert!(!SURFACE_ANALYTICS.is_empty());
123 assert!(!CLEAR_FILTERS.is_empty());
124 assert!(!RESET_STATE.is_empty());
125 assert!(!REFRESH.is_empty());
126 assert!(!HISTORY_NEXT.is_empty());
127 assert!(!HISTORY_PREV.is_empty());
128 assert!(!HISTORY_CYCLE.is_empty());
129 assert!(!STATS_BAR.is_empty());
130 assert!(!TOGGLE_SELECT.is_empty());
131 }
132
133 #[test]
134 fn modifier_shortcuts_have_expected_values() {
135 assert_eq!(SEARCH_MODE, "Alt+S");
136 assert_eq!(SURFACE_ANALYTICS, "Alt+A");
137 assert_eq!(CLEAR_FILTERS, "Ctrl+Del");
138 assert_eq!(RESET_STATE, "Ctrl+Shift+Del");
139 assert_eq!(REFRESH, "Ctrl+Shift+R");
140 assert_eq!(HISTORY_NEXT, "Ctrl+n");
141 assert_eq!(HISTORY_PREV, "Ctrl+p");
142 assert_eq!(HISTORY_CYCLE, "Ctrl+R");
143 assert_eq!(STATS_BAR, "Ctrl+S");
144 assert_eq!(TOGGLE_SELECT, "Ctrl+X");
145 }
146
147 #[test]
152 fn scope_shortcuts_are_not_empty() {
153 assert!(!SCOPE_AGENT.is_empty());
154 assert!(!SCOPE_WORKSPACE.is_empty());
155 assert!(!CYCLE_TIME_PRESETS.is_empty());
156 }
157
158 #[test]
159 fn scope_shortcuts_have_expected_values() {
160 assert_eq!(SCOPE_AGENT, "Shift+F3");
161 assert_eq!(SCOPE_WORKSPACE, "Shift+F4");
162 assert_eq!(CYCLE_TIME_PRESETS, "Shift+F5");
163 }
164
165 #[test]
170 fn action_shortcuts_are_not_empty() {
171 assert!(!COPY.is_empty());
172 assert!(!BULK_MENU.is_empty());
173 assert!(!PANE_FILTER.is_empty());
174 assert!(!EXPORT_HTML.is_empty());
175 assert!(!EXPORT_MARKDOWN.is_empty());
176 }
177
178 #[test]
179 fn action_shortcuts_have_expected_values() {
180 assert_eq!(COPY, "Alt+Y");
181 assert_eq!(BULK_MENU, "Alt+B");
182 assert_eq!(PANE_FILTER, "Alt+/");
183 assert_eq!(EXPORT_HTML, "Ctrl+E");
184 assert_eq!(EXPORT_MARKDOWN, "Ctrl+Shift+E");
185 }
186
187 #[test]
192 fn navigation_shortcuts_are_not_empty() {
193 assert!(!TAB_FOCUS.is_empty());
194 assert!(!VIM_NAV.is_empty());
195 assert!(!JUMP_TOP.is_empty());
196 assert!(!JUMP_BOTTOM.is_empty());
197 }
198
199 #[test]
200 fn navigation_shortcuts_have_expected_values() {
201 assert_eq!(TAB_FOCUS, "Tab");
202 assert_eq!(VIM_NAV, "Alt+h/j/k/l");
203 assert_eq!(JUMP_TOP, "Home");
204 assert_eq!(JUMP_BOTTOM, "End");
205 }
206
207 #[test]
212 fn detail_shortcuts_are_not_empty() {
213 assert!(!DETAIL_OPEN.is_empty());
214 assert!(!DETAIL_CLOSE.is_empty());
215 assert!(!FOCUS_QUERY.is_empty());
216 }
217
218 #[test]
219 fn detail_shortcuts_have_expected_values() {
220 assert_eq!(DETAIL_OPEN, "Enter");
221 assert_eq!(DETAIL_CLOSE, "Esc");
222 assert_eq!(FOCUS_QUERY, "Tab/Shift+Tab");
223 }
224
225 #[test]
230 fn quit_shortcut_is_not_empty() {
231 assert!(!QUIT.is_empty());
232 }
233
234 #[test]
235 fn quit_shortcut_has_expected_value() {
236 assert_eq!(QUIT, "Esc/F10");
237 }
238
239 #[test]
244 fn primary_function_keys_are_unique() {
245 let mut seen = HashSet::new();
246 let function_keys = [
247 HELP,
248 THEME,
249 FILTER_AGENT,
250 FILTER_WORKSPACE,
251 FILTER_DATE_FROM,
252 FILTER_DATE_TO,
253 CONTEXT_WINDOW,
254 EDITOR,
255 MATCH_MODE,
256 RANKING,
257 ];
258
259 for key in &function_keys {
260 assert!(seen.insert(*key), "Duplicate function key found: {}", key);
261 }
262 }
263
264 #[test]
265 fn shift_function_keys_are_unique() {
266 let mut seen = HashSet::new();
267 let shift_keys = [THEME_PREV, SCOPE_AGENT, SCOPE_WORKSPACE, CYCLE_TIME_PRESETS];
268
269 for key in &shift_keys {
270 assert!(
271 seen.insert(*key),
272 "Duplicate shift+function key found: {}",
273 key
274 );
275 }
276 }
277
278 #[test]
279 fn ctrl_shortcuts_are_unique() {
280 let mut seen = HashSet::new();
281 let ctrl_keys = [
282 CLEAR_FILTERS,
283 RESET_STATE,
284 REFRESH,
285 HISTORY_NEXT,
286 HISTORY_PREV,
287 HISTORY_CYCLE,
288 STATS_BAR,
289 TOGGLE_SELECT,
290 ];
291
292 for key in &ctrl_keys {
293 assert!(seen.insert(*key), "Duplicate ctrl shortcut found: {}", key);
294 }
295 }
296
297 #[test]
302 fn function_key_format_is_valid() {
303 let function_keys = [
305 HELP,
306 THEME,
307 FILTER_AGENT,
308 FILTER_WORKSPACE,
309 FILTER_DATE_FROM,
310 FILTER_DATE_TO,
311 CONTEXT_WINDOW,
312 EDITOR,
313 MATCH_MODE,
314 RANKING,
315 ];
316
317 for key in &function_keys {
318 assert!(
319 key.starts_with('F') && key[1..].chars().all(|c| c.is_ascii_digit()),
320 "Invalid function key format: {}",
321 key
322 );
323 }
324 }
325
326 #[test]
327 fn shift_function_key_format_is_valid() {
328 let shift_keys = [THEME_PREV, SCOPE_AGENT, SCOPE_WORKSPACE, CYCLE_TIME_PRESETS];
329
330 for key in &shift_keys {
331 assert!(
332 key.starts_with("Shift+F"),
333 "Shift key should start with 'Shift+F': {}",
334 key
335 );
336 }
337 }
338
339 #[test]
340 fn modifier_shortcuts_contain_plus_separator() {
341 let modifier_keys = [
342 SEARCH_MODE,
343 SURFACE_ANALYTICS,
344 CLEAR_FILTERS,
345 RESET_STATE,
346 REFRESH,
347 HISTORY_NEXT,
348 HISTORY_PREV,
349 HISTORY_CYCLE,
350 STATS_BAR,
351 TOGGLE_SELECT,
352 ];
353
354 for key in &modifier_keys {
355 assert!(
356 key.contains('+'),
357 "Modifier shortcut should contain '+': {}",
358 key
359 );
360 }
361 }
362}