Skip to main content

rmux_proto/request/
pane.rs

1use serde::{Deserialize, Deserializer, Serialize};
2use std::path::PathBuf;
3
4use crate::{
5    PaneOutputSubscriptionId, PaneTarget, PaneTargetRef, ProcessCommand, ResizePaneAdjustment,
6    SessionName, 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}
65
66impl<'de> Deserialize<'de> for SplitWindowExtRequest {
67    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68    where
69        D: Deserializer<'de>,
70    {
71        deserializer.deserialize_struct(
72            "SplitWindowExtRequest",
73            &[
74                "target",
75                "direction",
76                "before",
77                "environment",
78                "command",
79                "process_command",
80                "start_directory",
81                "keep_alive_on_exit",
82            ],
83            compat::SplitWindowExtRequestVisitor,
84        )
85    }
86}
87
88/// The supported relative directions for `swap-pane`.
89#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
90pub enum SwapPaneDirection {
91    /// Swap the target pane with the next pane.
92    Down,
93    /// Swap the target pane with the previous pane.
94    Up,
95}
96
97/// Request payload for `swap-pane`.
98#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
99pub struct SwapPaneRequest {
100    /// The source pane slot.
101    pub source: PaneTarget,
102    /// The destination pane slot.
103    pub target: PaneTarget,
104    /// The optional relative swap direction for `-D` or `-U`.
105    #[serde(default)]
106    pub direction: Option<SwapPaneDirection>,
107    /// Whether pane selection should remain detached from the swap.
108    pub detached: bool,
109    /// Whether zoomed windows should be restored after the swap (`-Z`).
110    #[serde(default)]
111    pub preserve_zoom: bool,
112}
113
114/// Request payload for `last-pane`.
115#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
116pub struct LastPaneRequest {
117    /// The addressed window.
118    pub target: WindowTarget,
119}
120
121/// Request payload for `join-pane`.
122#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
123pub struct JoinPaneRequest {
124    /// The source pane being moved.
125    pub source: PaneTarget,
126    /// The destination pane the source is joined next to.
127    pub target: PaneTarget,
128    /// The layout direction requested for the join.
129    pub direction: SplitDirection,
130    /// Whether the destination pane should remain inactive after the join.
131    pub detached: bool,
132    /// Whether the source pane should be inserted before the target pane.
133    #[serde(default)]
134    pub before: bool,
135    /// Whether the source pane should span the full window.
136    #[serde(default)]
137    pub full_size: bool,
138    /// Optional requested size for the inserted pane.
139    #[serde(default)]
140    pub size: Option<PaneSplitSize>,
141}
142
143/// Request payload for `break-pane`.
144#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
145pub struct BreakPaneRequest {
146    /// The source pane being moved into its own window.
147    pub source: PaneTarget,
148    /// The optional destination window slot.
149    pub target: Option<WindowTarget>,
150    /// The optional explicit name for the new window.
151    pub name: Option<String>,
152    /// Whether the new window should remain inactive after the break.
153    pub detached: bool,
154    /// Whether the pane should be placed after the destination or current window.
155    #[serde(default)]
156    pub after: bool,
157    /// Whether the pane should be placed before the destination or current window.
158    #[serde(default)]
159    pub before: bool,
160    /// Whether the resulting pane target should be printed.
161    #[serde(default)]
162    pub print_target: bool,
163    /// Optional format used when printing the resulting pane target.
164    #[serde(default)]
165    pub format: Option<String>,
166}
167
168/// Size forms accepted by pane split and join commands.
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
170pub enum PaneSplitSize {
171    /// A concrete absolute size in cells.
172    Absolute(u32),
173    /// A percentage of the relevant base size.
174    Percentage(u8),
175}
176
177/// Request payload for `move-pane`.
178#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
179pub struct MovePaneRequest {
180    /// The source pane being moved.
181    pub source: PaneTarget,
182    /// The destination pane the source is joined next to.
183    pub target: PaneTarget,
184    /// The layout direction requested for the move.
185    pub direction: SplitDirection,
186    /// Whether the destination pane should remain inactive after the move.
187    pub detached: bool,
188    /// Whether the source pane should be inserted before the target pane.
189    #[serde(default)]
190    pub before: bool,
191    /// Whether the source pane should span the full window.
192    #[serde(default)]
193    pub full_size: bool,
194    /// Optional requested size for the inserted pane.
195    #[serde(default)]
196    pub size: Option<PaneSplitSize>,
197}
198
199/// Request payload for `kill-pane`.
200#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
201pub struct KillPaneRequest {
202    /// The exact pane target.
203    pub target: PaneTarget,
204    /// Whether all panes except the target should be killed.
205    #[serde(default)]
206    pub kill_all_except: bool,
207}
208
209/// Request payload for `resize-pane`.
210#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
211pub struct ResizePaneRequest {
212    /// The exact pane target.
213    pub target: PaneTarget,
214    /// The semantic resize request.
215    pub adjustment: ResizePaneAdjustment,
216}
217
218/// Request payload for `display-panes`.
219#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
220pub struct DisplayPanesRequest {
221    /// The exact session whose active window should receive the overlay.
222    pub target: SessionName,
223    /// Optional duration override in milliseconds.
224    #[serde(default)]
225    pub duration_ms: Option<u64>,
226    /// Whether the command should return immediately without waiting for selection.
227    #[serde(default)]
228    pub non_blocking: bool,
229    /// Whether pane selection should not run a follow-up command.
230    #[serde(default)]
231    pub no_command: bool,
232    /// Optional template command executed after pane selection.
233    #[serde(default)]
234    pub template: Option<String>,
235}
236
237/// Request payload for `pipe-pane`.
238#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
239pub struct PipePaneRequest {
240    /// The exact pane target.
241    pub target: PaneTarget,
242    /// Whether pipe output should be written into the pane (`-I`).
243    #[serde(default)]
244    pub stdin: bool,
245    /// Whether pane output should be written into the pipe (`-O`).
246    #[serde(default)]
247    pub stdout: bool,
248    /// Whether an existing pipe should be toggled off without reopening (`-o`).
249    #[serde(default)]
250    pub once: bool,
251    /// The optional shell command. Omitting it closes any existing pipe.
252    #[serde(default)]
253    pub command: Option<String>,
254}
255
256/// Request payload for `respawn-pane`.
257#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
258pub struct RespawnPaneRequest {
259    /// The exact pane target.
260    pub target: PaneTarget,
261    /// Whether a running pane should be killed before respawning (`-k`).
262    #[serde(default)]
263    pub kill: bool,
264    /// Optional working-directory override.
265    #[serde(default)]
266    pub start_directory: Option<PathBuf>,
267    /// Optional per-spawn environment overrides in `NAME=VALUE` form.
268    #[serde(default)]
269    pub environment: Option<Vec<String>>,
270    /// Legacy optional shell command argv. A single argument is executed via
271    /// `$SHELL -c`.
272    #[serde(default)]
273    pub command: Option<Vec<String>>,
274    /// Explicit process launch mode.
275    #[serde(default)]
276    pub process_command: Option<ProcessCommand>,
277}
278
279impl<'de> Deserialize<'de> for RespawnPaneRequest {
280    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
281    where
282        D: Deserializer<'de>,
283    {
284        deserializer.deserialize_struct(
285            "RespawnPaneRequest",
286            &[
287                "target",
288                "kill",
289                "start_directory",
290                "environment",
291                "command",
292                "process_command",
293            ],
294            compat::RespawnPaneRequestVisitor,
295        )
296    }
297}
298
299/// Request payload for `select-pane`.
300#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
301pub struct SelectPaneRequest {
302    /// The exact pane target.
303    pub target: PaneTarget,
304    /// Optional pane title to set without changing the active pane (`-T`).
305    #[serde(default)]
306    pub title: Option<String>,
307}
308
309/// SDK pane input request that can address a stable pane id.
310#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
311pub struct PaneInputRequest {
312    /// The exact pane target or stable pane id.
313    pub target: PaneTargetRef,
314    /// Text or key tokens to send.
315    pub keys: Vec<String>,
316    /// Whether tokens should be written literally instead of interpreted as
317    /// tmux-compatible key names.
318    #[serde(default)]
319    pub literal: bool,
320}
321
322/// SDK pane input broadcast request with stable pane-id targeting.
323#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
324pub struct PaneBroadcastInputRequest {
325    /// Pane targets addressed in caller order.
326    pub targets: Vec<PaneTargetRef>,
327    /// Text or key tokens to send to each pane.
328    pub keys: Vec<String>,
329    /// Whether tokens should be written literally instead of interpreted as
330    /// tmux-compatible key names.
331    #[serde(default)]
332    pub literal: bool,
333}
334
335/// SDK resize request that can address a stable pane id.
336#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
337pub struct PaneResizeRequest {
338    /// The exact pane target or stable pane id.
339    pub target: PaneTargetRef,
340    /// The semantic resize request.
341    pub adjustment: ResizePaneAdjustment,
342}
343
344/// SDK kill request that can address a stable pane id.
345#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
346pub struct PaneKillRequest {
347    /// The exact pane target or stable pane id.
348    pub target: PaneTargetRef,
349    /// Whether all panes except the target should be killed.
350    #[serde(default)]
351    pub kill_all_except: bool,
352}
353
354/// SDK respawn request that can address a stable pane id.
355#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
356pub struct PaneRespawnRequest {
357    /// The exact pane target or stable pane id.
358    pub target: PaneTargetRef,
359    /// Whether a running pane should be killed before respawning.
360    #[serde(default)]
361    pub kill: bool,
362    /// Optional working-directory override.
363    #[serde(default)]
364    pub start_directory: Option<PathBuf>,
365    /// Optional per-spawn environment overrides in `NAME=VALUE` form.
366    #[serde(default)]
367    pub environment: Option<Vec<String>>,
368    /// Legacy optional shell command argv. A single argument is executed via
369    /// `$SHELL -c`.
370    #[serde(default)]
371    pub command: Option<Vec<String>>,
372    /// Explicit process launch mode.
373    #[serde(default)]
374    pub process_command: Option<ProcessCommand>,
375    /// Optional pane-local `remain-on-exit` override applied before respawn.
376    #[serde(default)]
377    pub keep_alive_on_exit: Option<bool>,
378}
379
380/// SDK snapshot request that can address a stable pane id.
381#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
382pub struct PaneSnapshotRefRequest {
383    /// The exact pane target or stable pane id.
384    pub target: PaneTargetRef,
385}
386
387/// SDK select/title request that can address a stable pane id.
388#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
389pub struct PaneSelectRequest {
390    /// The exact pane target or stable pane id.
391    pub target: PaneTargetRef,
392    /// Optional pane title to set without changing the active pane.
393    #[serde(default)]
394    pub title: Option<String>,
395}
396
397/// Direction used by `select-pane -U/-D/-L/-R`.
398#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
399pub enum SelectPaneDirection {
400    /// Select the pane above the target pane.
401    Up,
402    /// Select the pane below the target pane.
403    Down,
404    /// Select the pane to the left of the target pane.
405    Left,
406    /// Select the pane to the right of the target pane.
407    Right,
408}
409
410/// Request payload for directional `select-pane`.
411#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
412pub struct SelectPaneAdjacentRequest {
413    /// The pane used as the directional anchor.
414    pub target: PaneTarget,
415    /// The requested adjacent-pane direction.
416    pub direction: SelectPaneDirection,
417}
418
419/// Request payload for `select-pane -m` and `select-pane -M`.
420#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
421pub struct SelectPaneMarkRequest {
422    /// The pane target used to resolve the current session/window context.
423    pub target: PaneTarget,
424    /// Whether to clear the existing marked pane instead of toggling the target.
425    pub clear: bool,
426    /// Optional pane title to set while applying the mark operation (`-T`).
427    #[serde(default)]
428    pub title: Option<String>,
429}
430
431/// Request payload for the daemon-backed pane snapshot endpoint.
432///
433/// Unlike [`CapturePaneRequest`](crate::CapturePaneRequest), which returns a
434/// pre-rendered byte stream of the visible viewport, this request asks the
435/// daemon to expose its live in-memory grid as structured cells. The daemon
436/// reads the cells directly from the rmux-core screen that is fed by its
437/// crate-private terminal parser, so there is no `String::from_utf8_lossy`
438/// reconstruction step on either side of the wire.
439#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
440pub struct PaneSnapshotRequest {
441    /// The exact pane target whose visible viewport should be captured.
442    pub target: PaneTarget,
443}
444
445/// Starting position for a pane-output subscription cursor.
446#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
447pub enum PaneOutputSubscriptionStart {
448    /// Start after the newest output currently retained by the pane.
449    Now,
450    /// Start at the oldest retained output event.
451    Oldest,
452}
453
454/// Request payload for subscribing to live pane-output events.
455#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
456pub struct SubscribePaneOutputRequest {
457    /// The exact pane target whose output should be subscribed.
458    pub target: PaneTarget,
459    /// The initial cursor position.
460    pub start: PaneOutputSubscriptionStart,
461}
462
463/// Request payload for subscribing to live pane-output events by slot or id.
464#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
465pub struct SubscribePaneOutputRefRequest {
466    /// The exact pane target or stable pane id whose output should be
467    /// subscribed.
468    pub target: PaneTargetRef,
469    /// The initial cursor position.
470    pub start: PaneOutputSubscriptionStart,
471}
472
473/// Request payload for unsubscribing from live pane-output events.
474#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
475pub struct UnsubscribePaneOutputRequest {
476    /// The subscription to remove.
477    pub subscription_id: PaneOutputSubscriptionId,
478}
479
480/// Request payload for polling a pane-output subscription cursor.
481#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
482pub struct PaneOutputCursorRequest {
483    /// The subscription whose cursor should be polled.
484    pub subscription_id: PaneOutputSubscriptionId,
485    /// Optional caller-requested event cap. The server clamps this to the
486    /// recorded v1 default batch limit.
487    #[serde(default)]
488    pub max_events: Option<u16>,
489}
490
491/// Request payload for `send-keys`.
492#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
493pub struct SendKeysRequest {
494    /// The exact pane target.
495    pub target: PaneTarget,
496    /// Key tokens in left-to-right order.
497    pub keys: Vec<String>,
498}
499
500/// Extended request payload for `send-keys`.
501#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
502pub struct SendKeysExtRequest {
503    /// The optional explicit pane target.
504    pub target: Option<PaneTarget>,
505    /// Key tokens in left-to-right order.
506    pub keys: Vec<String>,
507    /// Whether tmux format expansion should be applied to each token first.
508    pub expand_formats: bool,
509    /// Whether each token should be interpreted as a hexadecimal byte value.
510    pub hex: bool,
511    /// Whether tokens should be sent as literal bytes instead of key names.
512    #[serde(default)]
513    pub literal: bool,
514    /// Whether keys should be dispatched through the client's key table.
515    pub dispatch_key_table: bool,
516    /// Whether tokens describe copy-mode commands.
517    pub copy_mode_command: bool,
518    /// Whether the payload should be treated as a mouse event.
519    pub forward_mouse_event: bool,
520    /// Whether the target terminal should be reset before sending keys.
521    pub reset_terminal: bool,
522    /// Optional tmux repeat count for command or key dispatch.
523    pub repeat_count: Option<usize>,
524}