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