Skip to main content

kitty_rc/commands/
action.rs

1use crate::protocol::KittyMessage;
2
3pub struct ActionCommand {
4    action: String,
5    args: Vec<String>,
6}
7
8impl ActionCommand {
9    pub fn new(action: impl Into<String>) -> Self {
10        Self {
11            action: action.into(),
12            args: Vec::new(),
13        }
14    }
15
16    pub fn arg(mut self, arg: impl Into<String>) -> Self {
17        self.args.push(arg.into());
18        self
19    }
20
21    pub fn args(mut self, args: impl IntoIterator<Item = impl Into<String>>) -> Self {
22        for arg in args {
23            self.args.push(arg.into());
24        }
25        self
26    }
27
28    pub fn build(self) -> Result<KittyMessage, crate::error::CommandError> {
29        let mut payload = serde_json::Map::new();
30        payload.insert("action".to_string(), serde_json::Value::String(self.action));
31
32        if !self.args.is_empty() {
33            payload.insert("args".to_string(), serde_json::Value::Array(
34                self.args.into_iter().map(|a| serde_json::Value::String(a)).collect()
35            ));
36        }
37
38        Ok(KittyMessage::new("send_key", vec![0, 14, 2])
39            .payload(serde_json::Value::Object(payload)))
40    }
41}
42
43// Session actions
44
45pub struct QuitAction;
46
47impl QuitAction {
48    pub fn new() -> ActionCommand {
49        ActionCommand::new("quit")
50    }
51}
52
53// Tab actions
54
55pub struct NewTabAction;
56
57impl NewTabAction {
58    pub fn new() -> ActionCommand {
59        ActionCommand::new("new_tab")
60    }
61}
62
63pub struct CloseTabAction;
64
65impl CloseTabAction {
66    pub fn new() -> ActionCommand {
67        ActionCommand::new("close_tab")
68    }
69}
70
71pub struct NextTabAction;
72
73impl NextTabAction {
74    pub fn new() -> ActionCommand {
75        ActionCommand::new("next_tab")
76    }
77}
78
79pub struct PreviousTabAction;
80
81impl PreviousTabAction {
82    pub fn new() -> ActionCommand {
83        ActionCommand::new("previous_tab")
84    }
85}
86
87pub struct GotoTabAction;
88
89impl GotoTabAction {
90    pub fn new(tab_num: i32) -> ActionCommand {
91        ActionCommand::new("goto_tab").arg(tab_num.to_string())
92    }
93}
94
95pub struct SetTabTitleAction;
96
97impl SetTabTitleAction {
98    pub fn new(title: impl Into<String>) -> ActionCommand {
99        ActionCommand::new("set_tab_title").arg(title.into())
100    }
101}
102
103pub struct DetachTabAction;
104
105impl DetachTabAction {
106    pub fn new() -> ActionCommand {
107        ActionCommand::new("detach_tab")
108    }
109}
110
111pub struct MoveTabForwardAction;
112
113impl MoveTabForwardAction {
114    pub fn new() -> ActionCommand {
115        ActionCommand::new("move_tab_forward")
116    }
117}
118
119pub struct MoveTabBackwardAction;
120
121impl MoveTabBackwardAction {
122    pub fn new() -> ActionCommand {
123        ActionCommand::new("move_tab_backward")
124    }
125}
126
127// Window actions
128
129pub struct NewWindowAction;
130
131impl NewWindowAction {
132    pub fn new() -> ActionCommand {
133        ActionCommand::new("new_window")
134    }
135}
136
137pub struct NewWindowWithCwdAction;
138
139impl NewWindowWithCwdAction {
140    pub fn new() -> ActionCommand {
141        ActionCommand::new("new_window_with_cwd")
142    }
143}
144
145pub struct CloseWindowAction;
146
147impl CloseWindowAction {
148    pub fn new() -> ActionCommand {
149        ActionCommand::new("close_window")
150    }
151}
152
153pub struct CloseWindowWithConfirmationAction;
154
155impl CloseWindowWithConfirmationAction {
156    pub fn new() -> ActionCommand {
157        ActionCommand::new("close_window_with_confirmation")
158    }
159}
160
161pub struct NextWindowAction;
162
163impl NextWindowAction {
164    pub fn new() -> ActionCommand {
165        ActionCommand::new("next_window")
166    }
167}
168
169pub struct PreviousWindowAction;
170
171impl PreviousWindowAction {
172    pub fn new() -> ActionCommand {
173        ActionCommand::new("previous_window")
174    }
175}
176
177pub struct MoveWindowForwardAction;
178
179impl MoveWindowForwardAction {
180    pub fn new() -> ActionCommand {
181        ActionCommand::new("move_window_forward")
182    }
183}
184
185pub struct MoveWindowBackwardAction;
186
187impl MoveWindowBackwardAction {
188    pub fn new() -> ActionCommand {
189        ActionCommand::new("move_window_backward")
190    }
191}
192
193pub struct NthWindowAction;
194
195impl NthWindowAction {
196    pub fn new(n: i32) -> ActionCommand {
197        ActionCommand::new("nth_window").arg(n.to_string())
198    }
199}
200
201pub struct FirstWindowAction;
202
203impl FirstWindowAction {
204    pub fn new() -> ActionCommand {
205        ActionCommand::new("first_window")
206    }
207}
208
209pub struct SetWindowTitleAction;
210
211impl SetWindowTitleAction {
212    pub fn new(title: impl Into<String>) -> ActionCommand {
213        ActionCommand::new("set_window_title").arg(title.into())
214    }
215}
216
217pub struct ResizeWindowAction;
218
219impl ResizeWindowAction {
220    pub fn new(shrink: bool) -> ActionCommand {
221        if shrink {
222            ActionCommand::new("resize_window").arg("shrink")
223        } else {
224            ActionCommand::new("resize_window").arg("taller")
225        }
226    }
227}
228
229pub struct ResetWindowSizesAction;
230
231impl ResetWindowSizesAction {
232    pub fn new() -> ActionCommand {
233        ActionCommand::new("reset_window_sizes")
234    }
235}
236
237pub struct MoveWindowAction;
238
239impl MoveWindowAction {
240    pub fn new(direction: impl Into<String>) -> ActionCommand {
241        ActionCommand::new("move_window").arg(direction.into())
242    }
243}
244
245pub struct NeighboringWindowAction;
246
247impl NeighboringWindowAction {
248    pub fn new(direction: impl Into<String>) -> ActionCommand {
249        ActionCommand::new("neighboring_window").arg(direction.into())
250    }
251}
252
253pub struct ToggleFullscreenAction;
254
255impl ToggleFullscreenAction {
256    pub fn new() -> ActionCommand {
257        ActionCommand::new("toggle_fullscreen")
258    }
259}
260
261pub struct ToggleMaximizedAction;
262
263impl ToggleMaximizedAction {
264    pub fn new() -> ActionCommand {
265        ActionCommand::new("toggle_maximized")
266    }
267}
268
269// Clipboard actions
270
271pub struct CopyToClipboardAction;
272
273impl CopyToClipboardAction {
274    pub fn new() -> ActionCommand {
275        ActionCommand::new("copy_to_clipboard")
276    }
277}
278
279pub struct PasteAction;
280
281impl PasteAction {
282    pub fn new() -> ActionCommand {
283        ActionCommand::new("paste")
284    }
285}
286
287pub struct PasteFromClipboardAction;
288
289impl PasteFromClipboardAction {
290    pub fn new() -> ActionCommand {
291        ActionCommand::new("paste_from_clipboard")
292    }
293}
294
295pub struct PasteSelectionAction;
296
297impl PasteSelectionAction {
298    pub fn new() -> ActionCommand {
299        ActionCommand::new("paste_selection")
300    }
301}
302
303pub struct ClearSelectionAction;
304
305impl ClearSelectionAction {
306    pub fn new() -> ActionCommand {
307        ActionCommand::new("clear_selection")
308    }
309}
310
311pub struct CopyOrInterruptAction;
312
313impl CopyOrInterruptAction {
314    pub fn new() -> ActionCommand {
315        ActionCommand::new("copy_or_interrupt")
316    }
317}
318
319// Layout actions
320
321pub struct GotoLayoutAction;
322
323impl GotoLayoutAction {
324    pub fn new(layout: impl Into<String>) -> ActionCommand {
325        ActionCommand::new("goto_layout").arg(layout.into())
326    }
327}
328
329pub struct NextLayoutAction;
330
331impl NextLayoutAction {
332    pub fn new() -> ActionCommand {
333        ActionCommand::new("next_layout")
334    }
335}
336
337pub struct LastUsedLayoutAction;
338
339impl LastUsedLayoutAction {
340    pub fn new() -> ActionCommand {
341        ActionCommand::new("last_used_layout")
342    }
343}
344
345pub struct ToggleLayoutAction;
346
347impl ToggleLayoutAction {
348    pub fn new(layout: impl Into<String>) -> ActionCommand {
349        ActionCommand::new("toggle_layout").arg(layout.into())
350    }
351}
352
353// Scroll actions
354
355pub struct ScrollLineUpAction;
356
357impl ScrollLineUpAction {
358    pub fn new() -> ActionCommand {
359        ActionCommand::new("scroll_line_up")
360    }
361}
362
363pub struct ScrollLineDownAction;
364
365impl ScrollLineDownAction {
366    pub fn new() -> ActionCommand {
367        ActionCommand::new("scroll_line_down")
368    }
369}
370
371pub struct ScrollPageUpAction;
372
373impl ScrollPageUpAction {
374    pub fn new() -> ActionCommand {
375        ActionCommand::new("scroll_page_up")
376    }
377}
378
379pub struct ScrollPageDownAction;
380
381impl ScrollPageDownAction {
382    pub fn new() -> ActionCommand {
383        ActionCommand::new("scroll_page_down")
384    }
385}
386
387pub struct ScrollHomeAction;
388
389impl ScrollHomeAction {
390    pub fn new() -> ActionCommand {
391        ActionCommand::new("scroll_home")
392    }
393}
394
395pub struct ScrollEndAction;
396
397impl ScrollEndAction {
398    pub fn new() -> ActionCommand {
399        ActionCommand::new("scroll_end")
400    }
401}
402
403pub struct ScrollToPromptAction;
404
405impl ScrollToPromptAction {
406    pub fn new(direction: i32) -> ActionCommand {
407        ActionCommand::new("scroll_to_prompt").arg(direction.to_string())
408    }
409}
410
411pub struct ShowScrollbackAction;
412
413impl ShowScrollbackAction {
414    pub fn new() -> ActionCommand {
415        ActionCommand::new("show_scrollback")
416    }
417}
418
419// Mark actions
420
421pub struct CreateMarkerAction;
422
423impl CreateMarkerAction {
424    pub fn new() -> ActionCommand {
425        ActionCommand::new("create_marker")
426    }
427}
428
429pub struct RemoveMarkerAction;
430
431impl RemoveMarkerAction {
432    pub fn new() -> ActionCommand {
433        ActionCommand::new("remove_marker")
434    }
435}
436
437pub struct ScrollToMarkAction;
438
439impl ScrollToMarkAction {
440    pub fn new(marker_type: impl Into<String>) -> ActionCommand {
441        ActionCommand::new("scroll_to_mark").arg(marker_type.into())
442    }
443}
444
445pub struct ToggleMarkerAction;
446
447impl ToggleMarkerAction {
448    pub fn new() -> ActionCommand {
449        ActionCommand::new("toggle_marker")
450    }
451}
452
453// Mouse actions
454
455pub struct MouseClickUrlAction;
456
457impl MouseClickUrlAction {
458    pub fn new() -> ActionCommand {
459        ActionCommand::new("mouse_click_url")
460    }
461}
462
463pub struct MouseSelectionAction;
464
465impl MouseSelectionAction {
466    pub fn new() -> ActionCommand {
467        ActionCommand::new("mouse_selection")
468    }
469}
470
471// Debug actions
472
473pub struct DebugConfigAction;
474
475impl DebugConfigAction {
476    pub fn new() -> ActionCommand {
477        ActionCommand::new("debug_config")
478    }
479}
480
481pub struct DumpLinesWithAttrsAction;
482
483impl DumpLinesWithAttrsAction {
484    pub fn new() -> ActionCommand {
485        ActionCommand::new("dump_lines_with_attrs")
486    }
487}
488
489// Misc actions
490
491pub struct SendKeyAction;
492
493impl SendKeyAction {
494    pub fn new(keys: impl Into<String>) -> ActionCommand {
495        ActionCommand::new("send_key").arg(keys.into())
496    }
497}
498
499pub struct SendTextAction;
500
501impl SendTextAction {
502    pub fn new(text: impl Into<String>) -> ActionCommand {
503        ActionCommand::new("send_text").arg(text.into())
504    }
505}
506
507pub struct KittenAction;
508
509impl KittenAction {
510    pub fn new(kitten_name: impl Into<String>) -> ActionCommand {
511        ActionCommand::new("kitten").arg(kitten_name.into())
512    }
513}
514
515pub struct LaunchAction;
516
517impl LaunchAction {
518    pub fn new(args: impl Into<String>) -> ActionCommand {
519        ActionCommand::new("launch").arg(args.into())
520    }
521}
522
523pub struct SignalChildAction;
524
525impl SignalChildAction {
526    pub fn new(signal: impl Into<String>) -> ActionCommand {
527        ActionCommand::new("signal_child").arg(signal.into())
528    }
529}
530
531pub struct ClearTerminalAction;
532
533impl ClearTerminalAction {
534    pub fn new(mode: impl Into<String>) -> ActionCommand {
535        ActionCommand::new("clear_terminal").arg(mode.into())
536    }
537}
538
539pub struct ShowKittyDocAction;
540
541impl ShowKittyDocAction {
542    pub fn new(topic: impl Into<String>) -> ActionCommand {
543        ActionCommand::new("show_kitty_doc").arg(topic.into())
544    }
545}
546
547pub struct EditConfigFileAction;
548
549impl EditConfigFileAction {
550    pub fn new() -> ActionCommand {
551        ActionCommand::new("edit_config_file")
552    }
553}
554
555pub struct SetBackgroundOpacityAction;
556
557impl SetBackgroundOpacityAction {
558    pub fn new(opacity: f32) -> ActionCommand {
559        ActionCommand::new("set_background_opacity").arg(opacity.to_string())
560    }
561}
562
563pub struct ChangeFontSizeAction;
564
565impl ChangeFontSizeAction {
566    pub fn new(delta: impl Into<String>) -> ActionCommand {
567        ActionCommand::new("change_font_size").arg(delta.into())
568    }
569}
570
571pub struct LoadConfigFileAction;
572
573impl LoadConfigFileAction {
574    pub fn new(path: impl Into<String>) -> ActionCommand {
575        ActionCommand::new("load_config_file").arg(path.into())
576    }
577}
578
579pub struct SetColorsAction;
580
581impl SetColorsAction {
582    pub fn new(path: impl Into<String>) -> ActionCommand {
583        ActionCommand::new("set_colors").arg(path.into())
584    }
585}
586
587#[cfg(test)]
588mod tests {
589    use super::*;
590
591    #[test]
592    fn test_action_command_basic() {
593        let cmd = ActionCommand::new("quit").build();
594        assert!(cmd.is_ok());
595        let msg = cmd.unwrap();
596        assert_eq!(msg.cmd, "send_key");
597    }
598
599    #[test]
600    fn test_action_command_with_args() {
601        let cmd = ActionCommand::new("goto_tab")
602            .arg("1")
603            .build();
604        assert!(cmd.is_ok());
605        let msg = cmd.unwrap();
606        assert!(msg.payload.is_some());
607    }
608
609    #[test]
610    fn test_quit_action() {
611        let cmd = QuitAction::new().build();
612        assert!(cmd.is_ok());
613        let msg = cmd.unwrap();
614        assert_eq!(msg.cmd, "send_key");
615    }
616
617    #[test]
618    fn test_new_tab_action() {
619        let cmd = NewTabAction::new().build();
620        assert!(cmd.is_ok());
621    }
622
623    #[test]
624    fn test_goto_tab_action() {
625        let cmd = GotoTabAction::new(5).build();
626        assert!(cmd.is_ok());
627        let msg = cmd.unwrap();
628        assert!(msg.payload.is_some());
629    }
630
631    #[test]
632    fn test_new_window_action() {
633        let cmd = NewWindowAction::new().build();
634        assert!(cmd.is_ok());
635    }
636
637    #[test]
638    fn test_nth_window_action() {
639        let cmd = NthWindowAction::new(3).build();
640        assert!(cmd.is_ok());
641    }
642
643    #[test]
644    fn test_copy_to_clipboard_action() {
645        let cmd = CopyToClipboardAction::new().build();
646        assert!(cmd.is_ok());
647    }
648
649    #[test]
650    fn test_paste_action() {
651        let cmd = PasteAction::new().build();
652        assert!(cmd.is_ok());
653    }
654
655    #[test]
656    fn test_goto_layout_action() {
657        let cmd = GotoLayoutAction::new("tall").build();
658        assert!(cmd.is_ok());
659    }
660
661    #[test]
662    fn test_scroll_line_up_action() {
663        let cmd = ScrollLineUpAction::new().build();
664        assert!(cmd.is_ok());
665    }
666
667    #[test]
668    fn test_create_marker_action() {
669        let cmd = CreateMarkerAction::new().build();
670        assert!(cmd.is_ok());
671    }
672
673    #[test]
674    fn test_send_key_action() {
675        let cmd = SendKeyAction::new("ctrl+c").build();
676        assert!(cmd.is_ok());
677    }
678
679    #[test]
680    fn test_send_text_action() {
681        let cmd = SendTextAction::new("hello").build();
682        assert!(cmd.is_ok());
683    }
684
685    #[test]
686    fn test_kitten_action() {
687        let cmd = KittenAction::new("hints").build();
688        assert!(cmd.is_ok());
689    }
690
691    #[test]
692    fn test_signal_child_action() {
693        let cmd = SignalChildAction::new("SIGTERM").build();
694        assert!(cmd.is_ok());
695    }
696
697    #[test]
698    fn test_clear_terminal_action() {
699        let cmd = ClearTerminalAction::new("reset").build();
700        assert!(cmd.is_ok());
701    }
702
703    #[test]
704    fn test_set_background_opacity_action() {
705        let cmd = SetBackgroundOpacityAction::new(0.8).build();
706        assert!(cmd.is_ok());
707    }
708}