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