rmux_proto/request/pane.rs
1use serde::{Deserialize, Deserializer, Serialize};
2use std::path::PathBuf;
3
4use crate::{
5 PaneOutputSubscriptionId, PaneStateSubscriptionId, PaneTarget, PaneTargetRef, ProcessCommand,
6 ResizePaneAdjustment, SessionName, SetOptionMode, SplitDirection, WindowTarget,
7};
8
9#[path = "pane/compat.rs"]
10mod compat;
11
12/// Target forms accepted by `split-window`.
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub enum SplitWindowTarget {
15 /// Splits the active pane in the addressed session.
16 Session(SessionName),
17 /// Splits the addressed pane directly.
18 Pane(PaneTarget),
19}
20
21/// Request payload for `split-window`.
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
23pub struct SplitWindowRequest {
24 /// The exact split target.
25 pub target: SplitWindowTarget,
26 /// The requested split direction.
27 pub direction: SplitDirection,
28 /// Whether the new pane is inserted *before* the target on the chosen
29 /// axis (tmux `-b`). Default `false` puts the new pane after the target.
30 #[serde(default)]
31 pub before: bool,
32 /// Optional per-spawn environment overrides in `NAME=VALUE` form.
33 #[serde(default)]
34 pub environment: Option<Vec<String>>,
35}
36
37/// Extended request payload for `split-window`.
38#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
39pub struct SplitWindowExtRequest {
40 /// The exact split target.
41 pub target: SplitWindowTarget,
42 /// The requested split direction.
43 pub direction: SplitDirection,
44 /// Whether the new pane is inserted *before* the target on the chosen
45 /// axis (tmux `-b`). Default `false` puts the new pane after the target.
46 #[serde(default)]
47 pub before: bool,
48 /// Optional per-spawn environment overrides in `NAME=VALUE` form.
49 #[serde(default)]
50 pub environment: Option<Vec<String>>,
51 /// Legacy optional command argv for the new pane. A single argument runs
52 /// via `$SHELL -c`.
53 #[serde(default)]
54 pub command: Option<Vec<String>>,
55 /// Explicit process launch mode for the new pane.
56 #[serde(default)]
57 pub process_command: Option<ProcessCommand>,
58 /// Optional working-directory override for the new pane process.
59 #[serde(default)]
60 pub start_directory: Option<PathBuf>,
61 /// Optional pane-local `remain-on-exit` override applied before spawn.
62 #[serde(default)]
63 pub keep_alive_on_exit: Option<bool>,
64 /// Whether pane selection should stay on the original pane after split.
65 #[serde(default)]
66 pub detached: bool,
67 /// Optional tmux `-l` split size expression.
68 #[serde(default)]
69 pub size: Option<String>,
70 /// Whether an existing zoomed window should remain zoomed after split.
71 #[serde(default)]
72 pub preserve_zoom: bool,
73 /// Whether the new pane should split the full window root (`split-window -f`).
74 #[serde(default)]
75 pub full_size: bool,
76 /// Raw bytes read from client stdin for `split-window -I`.
77 #[serde(default)]
78 pub stdin_payload: Option<Vec<u8>>,
79}
80
81/// Request payload for `split-window` carrying raw tmux target text.
82#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
83pub struct SplitWindowTargetActionRequest {
84 /// Optional raw `-t` target. `None` uses the requester's current pane.
85 #[serde(default)]
86 pub target: Option<String>,
87 /// The requested split direction.
88 pub direction: SplitDirection,
89 /// Whether the new pane is inserted before the target.
90 #[serde(default)]
91 pub before: bool,
92 /// Optional per-spawn environment overrides in `NAME=VALUE` form.
93 #[serde(default)]
94 pub environment: Option<Vec<String>>,
95 /// Legacy optional command argv for the new pane.
96 #[serde(default)]
97 pub command: Option<Vec<String>>,
98 /// Explicit process launch mode for the new pane.
99 #[serde(default)]
100 pub process_command: Option<ProcessCommand>,
101 /// Optional working-directory override for the new pane process.
102 #[serde(default)]
103 pub start_directory: Option<PathBuf>,
104 /// Optional pane-local `remain-on-exit` override applied before spawn.
105 #[serde(default)]
106 pub keep_alive_on_exit: Option<bool>,
107 /// Whether pane selection should stay on the original pane after split.
108 #[serde(default)]
109 pub detached: bool,
110 /// Optional tmux `-l` split size expression.
111 #[serde(default)]
112 pub size: Option<String>,
113 /// Whether an existing zoomed window should remain zoomed after split.
114 #[serde(default)]
115 pub preserve_zoom: bool,
116 /// Whether the new pane should split the full window root.
117 #[serde(default)]
118 pub full_size: bool,
119 /// Raw bytes read from client stdin for `split-window -I`.
120 #[serde(default)]
121 pub stdin_payload: Option<Vec<u8>>,
122}
123
124/// SDK split request that returns the new pane's visible slot and stable id
125/// atomically with the mutation.
126///
127/// This is a capability-gated append-only wire extension. The existing
128/// [`SplitWindowTargetActionRequest`] remains unchanged for CLI callers.
129#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
130pub struct SplitWindowIdentityRequest {
131 /// Complete split action resolved server-side before the mutation.
132 pub action: SplitWindowTargetActionRequest,
133}
134
135impl<'de> Deserialize<'de> for SplitWindowExtRequest {
136 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
137 where
138 D: Deserializer<'de>,
139 {
140 deserializer.deserialize_struct(
141 "SplitWindowExtRequest",
142 &[
143 "target",
144 "direction",
145 "before",
146 "environment",
147 "command",
148 "process_command",
149 "start_directory",
150 "keep_alive_on_exit",
151 "detached",
152 "size",
153 "preserve_zoom",
154 "full_size",
155 "stdin_payload",
156 ],
157 compat::SplitWindowExtRequestVisitor,
158 )
159 }
160}
161
162/// The supported relative directions for `swap-pane`.
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
164pub enum SwapPaneDirection {
165 /// Swap the target pane with the next pane.
166 Down,
167 /// Swap the target pane with the previous pane.
168 Up,
169}
170
171/// Request payload for `swap-pane`.
172#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
173pub struct SwapPaneRequest {
174 /// The source pane slot.
175 pub source: PaneTarget,
176 /// The destination pane slot.
177 pub target: PaneTarget,
178 /// The optional relative swap direction for `-D` or `-U`.
179 #[serde(default)]
180 pub direction: Option<SwapPaneDirection>,
181 /// Whether pane selection should remain detached from the swap.
182 pub detached: bool,
183 /// Whether zoomed windows should be restored after the swap (`-Z`).
184 #[serde(default)]
185 pub preserve_zoom: bool,
186}
187
188/// Request payload for `last-pane`.
189#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
190pub struct LastPaneRequest {
191 /// The addressed window.
192 pub target: WindowTarget,
193 /// Whether an existing zoomed window should remain zoomed after selecting.
194 #[serde(default)]
195 pub preserve_zoom: bool,
196 /// Optional input gating to apply to the newly selected pane.
197 #[serde(default)]
198 pub input_disabled: Option<bool>,
199}
200
201impl<'de> Deserialize<'de> for LastPaneRequest {
202 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
203 where
204 D: Deserializer<'de>,
205 {
206 deserializer.deserialize_struct(
207 "LastPaneRequest",
208 &["target", "preserve_zoom", "input_disabled"],
209 compat::LastPaneRequestVisitor,
210 )
211 }
212}
213
214/// Request payload for `join-pane`.
215#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
216pub struct JoinPaneRequest {
217 /// The source pane being moved.
218 pub source: PaneTarget,
219 /// The destination pane the source is joined next to.
220 pub target: PaneTarget,
221 /// The layout direction requested for the join.
222 pub direction: SplitDirection,
223 /// Whether the destination pane should remain inactive after the join.
224 pub detached: bool,
225 /// Whether the source pane should be inserted before the target pane.
226 #[serde(default)]
227 pub before: bool,
228 /// Whether the source pane should span the full window.
229 #[serde(default)]
230 pub full_size: bool,
231 /// Optional requested size for the inserted pane.
232 #[serde(default)]
233 pub size: Option<PaneSplitSize>,
234}
235
236/// Request payload for `break-pane`.
237#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
238pub struct BreakPaneRequest {
239 /// The source pane being moved into its own window.
240 pub source: PaneTarget,
241 /// The optional destination window slot.
242 pub target: Option<WindowTarget>,
243 /// The optional explicit name for the new window.
244 pub name: Option<String>,
245 /// Whether the new window should remain inactive after the break.
246 pub detached: bool,
247 /// Whether the pane should be placed after the destination or current window.
248 #[serde(default)]
249 pub after: bool,
250 /// Whether the pane should be placed before the destination or current window.
251 #[serde(default)]
252 pub before: bool,
253 /// Whether the resulting pane target should be printed.
254 #[serde(default)]
255 pub print_target: bool,
256 /// Optional format used when printing the resulting pane target.
257 #[serde(default)]
258 pub format: Option<String>,
259}
260
261/// Size forms accepted by pane split and join commands.
262#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
263pub enum PaneSplitSize {
264 /// A concrete absolute size in cells.
265 Absolute(u32),
266 /// A percentage of the relevant base size.
267 Percentage(u8),
268}
269
270/// Request payload for `move-pane`.
271#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
272pub struct MovePaneRequest {
273 /// The source pane being moved.
274 pub source: PaneTarget,
275 /// The destination pane the source is joined next to.
276 pub target: PaneTarget,
277 /// The layout direction requested for the move.
278 pub direction: SplitDirection,
279 /// Whether the destination pane should remain inactive after the move.
280 pub detached: bool,
281 /// Whether the source pane should be inserted before the target pane.
282 #[serde(default)]
283 pub before: bool,
284 /// Whether the source pane should span the full window.
285 #[serde(default)]
286 pub full_size: bool,
287 /// Optional requested size for the inserted pane.
288 #[serde(default)]
289 pub size: Option<PaneSplitSize>,
290}
291
292/// Request payload for `kill-pane`.
293#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
294pub struct KillPaneRequest {
295 /// The exact pane target.
296 pub target: PaneTarget,
297 /// Whether all panes except the target should be killed.
298 #[serde(default)]
299 pub kill_all_except: bool,
300}
301
302/// Request payload for `resize-pane`.
303#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
304pub struct ResizePaneRequest {
305 /// The exact pane target.
306 pub target: PaneTarget,
307 /// The semantic resize request.
308 pub adjustment: ResizePaneAdjustment,
309}
310
311/// Request payload for `resize-pane` carrying raw tmux target text.
312#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
313pub struct ResizePaneTargetActionRequest {
314 /// Optional raw `-t` target. `None` uses the requester's current pane.
315 #[serde(default)]
316 pub target: Option<String>,
317 /// The semantic resize request.
318 pub adjustment: ResizePaneAdjustment,
319}
320
321/// Request payload for `display-panes`.
322#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
323pub struct DisplayPanesRequest {
324 /// The exact session whose active window should receive the overlay.
325 pub target: SessionName,
326 /// Optional duration override in milliseconds.
327 #[serde(default)]
328 pub duration_ms: Option<u64>,
329 /// Whether the command should return immediately without waiting for selection.
330 #[serde(default)]
331 pub non_blocking: bool,
332 /// Whether pane selection should not run a follow-up command.
333 #[serde(default)]
334 pub no_command: bool,
335 /// Optional template command executed after pane selection.
336 #[serde(default)]
337 pub template: Option<String>,
338 /// Optional attached client that should receive the pane overlay.
339 #[serde(default)]
340 pub target_client: Option<String>,
341}
342
343/// Request payload for `pipe-pane`.
344#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
345pub struct PipePaneRequest {
346 /// The exact pane target.
347 pub target: PaneTarget,
348 /// Whether pipe output should be written into the pane (`-I`).
349 #[serde(default)]
350 pub stdin: bool,
351 /// Whether pane output should be written into the pipe (`-O`).
352 #[serde(default)]
353 pub stdout: bool,
354 /// Whether an existing pipe should be toggled off without reopening (`-o`).
355 #[serde(default)]
356 pub once: bool,
357 /// The optional shell command. Omitting it closes any existing pipe.
358 #[serde(default)]
359 pub command: Option<String>,
360}
361
362/// Request payload for `respawn-pane`.
363#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
364pub struct RespawnPaneRequest {
365 /// The exact pane target.
366 pub target: PaneTarget,
367 /// Whether a running pane should be killed before respawning (`-k`).
368 #[serde(default)]
369 pub kill: bool,
370 /// Optional working-directory override.
371 #[serde(default)]
372 pub start_directory: Option<PathBuf>,
373 /// Optional per-spawn environment overrides in `NAME=VALUE` form.
374 #[serde(default)]
375 pub environment: Option<Vec<String>>,
376 /// Legacy optional shell command argv. A single argument is executed via
377 /// `$SHELL -c`.
378 #[serde(default)]
379 pub command: Option<Vec<String>>,
380 /// Explicit process launch mode.
381 #[serde(default)]
382 pub process_command: Option<ProcessCommand>,
383}
384
385impl<'de> Deserialize<'de> for RespawnPaneRequest {
386 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
387 where
388 D: Deserializer<'de>,
389 {
390 deserializer.deserialize_struct(
391 "RespawnPaneRequest",
392 &[
393 "target",
394 "kill",
395 "start_directory",
396 "environment",
397 "command",
398 "process_command",
399 ],
400 compat::RespawnPaneRequestVisitor,
401 )
402 }
403}
404
405/// Request payload for `select-pane`.
406#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
407pub struct SelectPaneRequest {
408 /// The exact pane target.
409 pub target: PaneTarget,
410 /// Optional pane title to set without changing the active pane (`-T`).
411 #[serde(default)]
412 pub title: Option<String>,
413 /// Optional pane input state mutation (`select-pane -d` / `-e`).
414 #[serde(default)]
415 pub input_disabled: Option<bool>,
416 /// Whether an existing zoomed window should remain zoomed after selecting.
417 #[serde(default)]
418 pub preserve_zoom: bool,
419 /// Optional pane style to set on the pane-local `window-style` option (`-P`).
420 #[serde(default)]
421 pub style: Option<String>,
422}
423
424impl<'de> Deserialize<'de> for SelectPaneRequest {
425 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
426 where
427 D: Deserializer<'de>,
428 {
429 deserializer.deserialize_struct(
430 "SelectPaneRequest",
431 &[
432 "target",
433 "title",
434 "input_disabled",
435 "preserve_zoom",
436 "style",
437 ],
438 compat::SelectPaneRequestVisitor,
439 )
440 }
441}
442
443/// SDK pane input request that can address a stable pane id.
444#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
445pub struct PaneInputRequest {
446 /// The exact pane target or stable pane id.
447 pub target: PaneTargetRef,
448 /// Text or key tokens to send.
449 pub keys: Vec<String>,
450 /// Whether tokens should be written literally instead of interpreted as
451 /// tmux-compatible key names.
452 #[serde(default)]
453 pub literal: bool,
454}
455
456/// SDK pane input broadcast request with stable pane-id targeting.
457#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
458pub struct PaneBroadcastInputRequest {
459 /// Pane targets addressed in caller order.
460 pub targets: Vec<PaneTargetRef>,
461 /// Text or key tokens to send to each pane.
462 pub keys: Vec<String>,
463 /// Whether tokens should be written literally instead of interpreted as
464 /// tmux-compatible key names.
465 #[serde(default)]
466 pub literal: bool,
467}
468
469/// SDK resize request that can address a stable pane id.
470#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
471pub struct PaneResizeRequest {
472 /// The exact pane target or stable pane id.
473 pub target: PaneTargetRef,
474 /// The semantic resize request.
475 pub adjustment: ResizePaneAdjustment,
476}
477
478/// SDK kill request that can address a stable pane id.
479#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
480pub struct PaneKillRequest {
481 /// The exact pane target or stable pane id.
482 pub target: PaneTargetRef,
483 /// Whether all panes except the target should be killed.
484 #[serde(default)]
485 pub kill_all_except: bool,
486}
487
488/// SDK respawn request that can address a stable pane id.
489#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
490pub struct PaneRespawnRequest {
491 /// The exact pane target or stable pane id.
492 pub target: PaneTargetRef,
493 /// Whether a running pane should be killed before respawning.
494 #[serde(default)]
495 pub kill: bool,
496 /// Optional working-directory override.
497 #[serde(default)]
498 pub start_directory: Option<PathBuf>,
499 /// Optional per-spawn environment overrides in `NAME=VALUE` form.
500 #[serde(default)]
501 pub environment: Option<Vec<String>>,
502 /// Legacy optional shell command argv. A single argument is executed via
503 /// `$SHELL -c`.
504 #[serde(default)]
505 pub command: Option<Vec<String>>,
506 /// Explicit process launch mode.
507 #[serde(default)]
508 pub process_command: Option<ProcessCommand>,
509 /// Optional pane-local `remain-on-exit` override applied before respawn.
510 #[serde(default)]
511 pub keep_alive_on_exit: Option<bool>,
512}
513
514/// SDK snapshot request that can address a stable pane id.
515#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
516pub struct PaneSnapshotRefRequest {
517 /// The exact pane target or stable pane id.
518 pub target: PaneTargetRef,
519}
520
521/// SDK select/title request that can address a stable pane id.
522#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
523pub struct PaneSelectRequest {
524 /// The exact pane target or stable pane id.
525 pub target: PaneTargetRef,
526 /// Optional pane title to set without changing the active pane.
527 #[serde(default)]
528 pub title: Option<String>,
529}
530
531/// SDK pane option mutation request that can address a stable pane id.
532#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
533pub struct PaneOptionSetRequest {
534 /// The exact pane target or stable pane id.
535 pub target: PaneTargetRef,
536 /// The tmux-style option name.
537 pub name: String,
538 /// The value to set. `None` is valid only when `unset` is true or when the
539 /// option type supports value-less toggles.
540 #[serde(default)]
541 pub value: Option<String>,
542 /// The scalar/array mutation mode.
543 pub mode: SetOptionMode,
544 /// Whether to remove the pane-local explicit value instead of setting it.
545 #[serde(default)]
546 pub unset: bool,
547}
548
549/// SDK pane option lookup request that can address a stable pane id.
550#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
551pub struct PaneOptionGetRequest {
552 /// The exact pane target or stable pane id.
553 pub target: PaneTargetRef,
554 /// The tmux-style option name.
555 pub name: String,
556}
557
558/// SDK pane-state subscription request that can address a stable pane id.
559#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
560pub struct SubscribePaneStateRequest {
561 /// The exact pane target or stable pane id.
562 pub target: PaneTargetRef,
563 /// Whether the initial snapshot and stream should include title changes.
564 #[serde(default = "default_include_pane_state_title")]
565 pub include_title: bool,
566 /// Whether the initial snapshot and stream should include pane options.
567 #[serde(default = "default_include_pane_state_options")]
568 pub include_options: bool,
569 /// Whether the initial snapshot and stream should include foreground state.
570 #[serde(default)]
571 pub include_foreground: bool,
572}
573
574/// SDK pane-state cursor request.
575#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
576pub struct PaneStateCursorRequest {
577 /// The subscription to poll.
578 pub subscription_id: PaneStateSubscriptionId,
579 /// Return records whose revision is strictly greater than this value.
580 pub after_revision: u64,
581 /// Whether the server may hold the request until a new record appears.
582 #[serde(default)]
583 pub wait: bool,
584 /// Optional per-response event cap.
585 #[serde(default)]
586 pub max_events: Option<u16>,
587}
588
589/// SDK pane-state unsubscription request.
590#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
591pub struct UnsubscribePaneStateRequest {
592 /// The subscription to remove.
593 pub subscription_id: PaneStateSubscriptionId,
594}
595
596/// SDK foreground-state request that can address a stable pane id.
597#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
598pub struct PaneForegroundStateRequest {
599 /// The exact pane target or stable pane id.
600 pub target: PaneTargetRef,
601}
602
603const fn default_include_pane_state_title() -> bool {
604 true
605}
606
607const fn default_include_pane_state_options() -> bool {
608 true
609}
610
611/// Direction used by `select-pane -U/-D/-L/-R`.
612#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
613pub enum SelectPaneDirection {
614 /// Select the pane above the target pane.
615 Up,
616 /// Select the pane below the target pane.
617 Down,
618 /// Select the pane to the left of the target pane.
619 Left,
620 /// Select the pane to the right of the target pane.
621 Right,
622}
623
624/// Request payload for directional `select-pane`.
625#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
626pub struct SelectPaneAdjacentRequest {
627 /// The pane used as the directional anchor.
628 pub target: PaneTarget,
629 /// The requested adjacent-pane direction.
630 pub direction: SelectPaneDirection,
631 /// Whether an existing zoomed window should remain zoomed after selecting.
632 #[serde(default)]
633 pub preserve_zoom: bool,
634}
635
636impl<'de> Deserialize<'de> for SelectPaneAdjacentRequest {
637 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
638 where
639 D: Deserializer<'de>,
640 {
641 deserializer.deserialize_struct(
642 "SelectPaneAdjacentRequest",
643 &["target", "direction", "preserve_zoom"],
644 compat::SelectPaneAdjacentRequestVisitor,
645 )
646 }
647}
648
649/// Request payload for `select-pane -m` and `select-pane -M`.
650#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
651pub struct SelectPaneMarkRequest {
652 /// The pane target used to resolve the current session/window context.
653 pub target: PaneTarget,
654 /// Whether to clear the existing marked pane instead of toggling the target.
655 pub clear: bool,
656 /// Optional pane title to set while applying the mark operation (`-T`).
657 #[serde(default)]
658 pub title: Option<String>,
659}
660
661/// Request payload for the daemon-backed pane snapshot endpoint.
662///
663/// Unlike [`CapturePaneRequest`](crate::CapturePaneRequest), which returns a
664/// pre-rendered byte stream of the visible viewport, this request asks the
665/// daemon to expose its live in-memory grid as structured cells. The daemon
666/// reads the cells directly from the rmux-core screen that is fed by its
667/// crate-private terminal parser, so there is no `String::from_utf8_lossy`
668/// reconstruction step on either side of the wire.
669#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
670pub struct PaneSnapshotRequest {
671 /// The exact pane target whose visible viewport should be captured.
672 pub target: PaneTarget,
673}
674
675/// Starting position for a pane-output subscription cursor.
676#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
677pub enum PaneOutputSubscriptionStart {
678 /// Start after the newest output currently retained by the pane.
679 Now,
680 /// Start at the oldest retained output event.
681 Oldest,
682}
683
684/// Request payload for subscribing to live pane-output events.
685#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
686pub struct SubscribePaneOutputRequest {
687 /// The exact pane target whose output should be subscribed.
688 pub target: PaneTarget,
689 /// The initial cursor position.
690 pub start: PaneOutputSubscriptionStart,
691}
692
693/// Request payload for subscribing to live pane-output events by slot or id.
694#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
695pub struct SubscribePaneOutputRefRequest {
696 /// The exact pane target or stable pane id whose output should be
697 /// subscribed.
698 pub target: PaneTargetRef,
699 /// The initial cursor position.
700 pub start: PaneOutputSubscriptionStart,
701}
702
703/// Request payload for unsubscribing from live pane-output events.
704#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
705pub struct UnsubscribePaneOutputRequest {
706 /// The subscription to remove.
707 pub subscription_id: PaneOutputSubscriptionId,
708}
709
710/// Request payload for polling a pane-output subscription cursor.
711#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
712pub struct PaneOutputCursorRequest {
713 /// The subscription whose cursor should be polled.
714 pub subscription_id: PaneOutputSubscriptionId,
715 /// Optional caller-requested event cap. The server clamps this to the
716 /// recorded v1 default batch limit.
717 #[serde(default)]
718 pub max_events: Option<u16>,
719}
720
721/// Projection selected for a recoverable pane stream.
722#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
723#[non_exhaustive]
724pub enum PaneStreamMode {
725 /// Raw terminal bytes with automatic in-band renderer rebases.
726 Raw,
727 /// Authoritative structured viewport frames.
728 Surface,
729}
730
731/// Request payload for opening a recoverable pane stream.
732#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
733pub struct SubscribePaneStreamRequest {
734 /// Stable pane identity or pane slot resolved atomically by the daemon.
735 pub target: PaneTargetRef,
736 /// Requested projection.
737 pub mode: PaneStreamMode,
738 /// Include a typed snapshot with raw rebases.
739 ///
740 /// Raw emulator consumers normally leave this false; inspection tools can
741 /// request it without forcing every rebase to carry duplicate state.
742 pub include_snapshot: bool,
743}
744
745/// Request payload for polling a recoverable pane stream.
746#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
747pub struct PaneStreamCursorRequest {
748 /// Opaque stream subscription allocated by the daemon.
749 pub subscription_id: PaneOutputSubscriptionId,
750 /// Optional caller cap, clamped to the daemon subscription limit.
751 #[serde(default)]
752 pub max_events: Option<u16>,
753}
754
755/// Request payload for closing a recoverable pane stream.
756#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
757pub struct UnsubscribePaneStreamRequest {
758 /// Opaque stream subscription allocated by the daemon.
759 pub subscription_id: PaneOutputSubscriptionId,
760}
761
762/// Request payload for `send-keys`.
763#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
764pub struct SendKeysRequest {
765 /// The exact pane target.
766 pub target: PaneTarget,
767 /// Key tokens in left-to-right order.
768 pub keys: Vec<String>,
769}
770
771/// Extended request payload for `send-keys`.
772#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
773pub struct SendKeysExtRequest {
774 /// The optional explicit pane target.
775 pub target: Option<PaneTarget>,
776 /// Key tokens in left-to-right order.
777 pub keys: Vec<String>,
778 /// Whether tmux format expansion should be applied to each token first.
779 pub expand_formats: bool,
780 /// Whether each token should be interpreted as a hexadecimal byte value.
781 pub hex: bool,
782 /// Whether tokens should be sent as literal bytes instead of key names.
783 #[serde(default)]
784 pub literal: bool,
785 /// Whether keys should be dispatched through the client's key table.
786 pub dispatch_key_table: bool,
787 /// Whether tokens describe copy-mode commands.
788 pub copy_mode_command: bool,
789 /// Whether the payload should be treated as a mouse event.
790 pub forward_mouse_event: bool,
791 /// Whether the target terminal should be reset before sending keys.
792 pub reset_terminal: bool,
793 /// Optional tmux repeat count for command or key dispatch.
794 pub repeat_count: Option<usize>,
795}
796
797/// Further-extended request payload for `send-keys -c`.
798///
799/// This is intentionally separate from [`SendKeysExtRequest`] so the original
800/// bincode field order remains wire-compatible with older clients and daemons.
801#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
802pub struct SendKeysExt2Request {
803 /// The optional explicit pane target.
804 pub target: Option<PaneTarget>,
805 /// Key tokens in left-to-right order.
806 pub keys: Vec<String>,
807 /// Whether tmux format expansion should be applied to each token first.
808 pub expand_formats: bool,
809 /// Whether each token should be interpreted as a hexadecimal byte value.
810 pub hex: bool,
811 /// Whether tokens should be sent as literal bytes instead of key names.
812 #[serde(default)]
813 pub literal: bool,
814 /// Whether keys should be dispatched through the client's key table.
815 pub dispatch_key_table: bool,
816 /// Whether tokens describe copy-mode commands.
817 pub copy_mode_command: bool,
818 /// Whether the payload should be treated as a mouse event.
819 pub forward_mouse_event: bool,
820 /// Whether the target terminal should be reset before sending keys.
821 pub reset_terminal: bool,
822 /// Optional tmux repeat count for command or key dispatch.
823 pub repeat_count: Option<usize>,
824 /// Optional target client used for current-pane resolution and client key dispatch.
825 pub target_client: Option<String>,
826}