rmux-proto 0.2.0

RMUX detached IPC protocol DTOs, framing, and wire-safe error types.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
use serde::{Deserialize, Deserializer, Serialize};
use std::path::PathBuf;

use crate::{
    PaneOutputSubscriptionId, PaneTarget, PaneTargetRef, ProcessCommand, ResizePaneAdjustment,
    SessionName, SplitDirection, WindowTarget,
};

#[path = "pane/compat.rs"]
mod compat;

/// Target forms accepted by `split-window`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SplitWindowTarget {
    /// Splits the active pane in the addressed session.
    Session(SessionName),
    /// Splits the addressed pane directly.
    Pane(PaneTarget),
}

/// Request payload for `split-window`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SplitWindowRequest {
    /// The exact split target.
    pub target: SplitWindowTarget,
    /// The requested split direction.
    pub direction: SplitDirection,
    /// Whether the new pane is inserted *before* the target on the chosen
    /// axis (tmux `-b`). Default `false` puts the new pane after the target.
    #[serde(default)]
    pub before: bool,
    /// Optional per-spawn environment overrides in `NAME=VALUE` form.
    #[serde(default)]
    pub environment: Option<Vec<String>>,
}

/// Extended request payload for `split-window`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct SplitWindowExtRequest {
    /// The exact split target.
    pub target: SplitWindowTarget,
    /// The requested split direction.
    pub direction: SplitDirection,
    /// Whether the new pane is inserted *before* the target on the chosen
    /// axis (tmux `-b`). Default `false` puts the new pane after the target.
    #[serde(default)]
    pub before: bool,
    /// Optional per-spawn environment overrides in `NAME=VALUE` form.
    #[serde(default)]
    pub environment: Option<Vec<String>>,
    /// Legacy optional command argv for the new pane. A single argument runs
    /// via `$SHELL -c`.
    #[serde(default)]
    pub command: Option<Vec<String>>,
    /// Explicit process launch mode for the new pane.
    #[serde(default)]
    pub process_command: Option<ProcessCommand>,
    /// Optional working-directory override for the new pane process.
    #[serde(default)]
    pub start_directory: Option<PathBuf>,
    /// Optional pane-local `remain-on-exit` override applied before spawn.
    #[serde(default)]
    pub keep_alive_on_exit: Option<bool>,
}

impl<'de> Deserialize<'de> for SplitWindowExtRequest {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_struct(
            "SplitWindowExtRequest",
            &[
                "target",
                "direction",
                "before",
                "environment",
                "command",
                "process_command",
                "start_directory",
                "keep_alive_on_exit",
            ],
            compat::SplitWindowExtRequestVisitor,
        )
    }
}

/// The supported relative directions for `swap-pane`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SwapPaneDirection {
    /// Swap the target pane with the next pane.
    Down,
    /// Swap the target pane with the previous pane.
    Up,
}

/// Request payload for `swap-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SwapPaneRequest {
    /// The source pane slot.
    pub source: PaneTarget,
    /// The destination pane slot.
    pub target: PaneTarget,
    /// The optional relative swap direction for `-D` or `-U`.
    #[serde(default)]
    pub direction: Option<SwapPaneDirection>,
    /// Whether pane selection should remain detached from the swap.
    pub detached: bool,
    /// Whether zoomed windows should be restored after the swap (`-Z`).
    #[serde(default)]
    pub preserve_zoom: bool,
}

/// Request payload for `last-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LastPaneRequest {
    /// The addressed window.
    pub target: WindowTarget,
}

/// Request payload for `join-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct JoinPaneRequest {
    /// The source pane being moved.
    pub source: PaneTarget,
    /// The destination pane the source is joined next to.
    pub target: PaneTarget,
    /// The layout direction requested for the join.
    pub direction: SplitDirection,
    /// Whether the destination pane should remain inactive after the join.
    pub detached: bool,
    /// Whether the source pane should be inserted before the target pane.
    #[serde(default)]
    pub before: bool,
    /// Whether the source pane should span the full window.
    #[serde(default)]
    pub full_size: bool,
    /// Optional requested size for the inserted pane.
    #[serde(default)]
    pub size: Option<PaneSplitSize>,
}

/// Request payload for `break-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BreakPaneRequest {
    /// The source pane being moved into its own window.
    pub source: PaneTarget,
    /// The optional destination window slot.
    pub target: Option<WindowTarget>,
    /// The optional explicit name for the new window.
    pub name: Option<String>,
    /// Whether the new window should remain inactive after the break.
    pub detached: bool,
    /// Whether the pane should be placed after the destination or current window.
    #[serde(default)]
    pub after: bool,
    /// Whether the pane should be placed before the destination or current window.
    #[serde(default)]
    pub before: bool,
    /// Whether the resulting pane target should be printed.
    #[serde(default)]
    pub print_target: bool,
    /// Optional format used when printing the resulting pane target.
    #[serde(default)]
    pub format: Option<String>,
}

/// Size forms accepted by pane split and join commands.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PaneSplitSize {
    /// A concrete absolute size in cells.
    Absolute(u32),
    /// A percentage of the relevant base size.
    Percentage(u8),
}

/// Request payload for `move-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MovePaneRequest {
    /// The source pane being moved.
    pub source: PaneTarget,
    /// The destination pane the source is joined next to.
    pub target: PaneTarget,
    /// The layout direction requested for the move.
    pub direction: SplitDirection,
    /// Whether the destination pane should remain inactive after the move.
    pub detached: bool,
    /// Whether the source pane should be inserted before the target pane.
    #[serde(default)]
    pub before: bool,
    /// Whether the source pane should span the full window.
    #[serde(default)]
    pub full_size: bool,
    /// Optional requested size for the inserted pane.
    #[serde(default)]
    pub size: Option<PaneSplitSize>,
}

/// Request payload for `kill-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct KillPaneRequest {
    /// The exact pane target.
    pub target: PaneTarget,
    /// Whether all panes except the target should be killed.
    #[serde(default)]
    pub kill_all_except: bool,
}

/// Request payload for `resize-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ResizePaneRequest {
    /// The exact pane target.
    pub target: PaneTarget,
    /// The semantic resize request.
    pub adjustment: ResizePaneAdjustment,
}

/// Request payload for `display-panes`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DisplayPanesRequest {
    /// The exact session whose active window should receive the overlay.
    pub target: SessionName,
    /// Optional duration override in milliseconds.
    #[serde(default)]
    pub duration_ms: Option<u64>,
    /// Whether the command should return immediately without waiting for selection.
    #[serde(default)]
    pub non_blocking: bool,
    /// Whether pane selection should not run a follow-up command.
    #[serde(default)]
    pub no_command: bool,
    /// Optional template command executed after pane selection.
    #[serde(default)]
    pub template: Option<String>,
}

/// Request payload for `pipe-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PipePaneRequest {
    /// The exact pane target.
    pub target: PaneTarget,
    /// Whether pipe output should be written into the pane (`-I`).
    #[serde(default)]
    pub stdin: bool,
    /// Whether pane output should be written into the pipe (`-O`).
    #[serde(default)]
    pub stdout: bool,
    /// Whether an existing pipe should be toggled off without reopening (`-o`).
    #[serde(default)]
    pub once: bool,
    /// The optional shell command. Omitting it closes any existing pipe.
    #[serde(default)]
    pub command: Option<String>,
}

/// Request payload for `respawn-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct RespawnPaneRequest {
    /// The exact pane target.
    pub target: PaneTarget,
    /// Whether a running pane should be killed before respawning (`-k`).
    #[serde(default)]
    pub kill: bool,
    /// Optional working-directory override.
    #[serde(default)]
    pub start_directory: Option<PathBuf>,
    /// Optional per-spawn environment overrides in `NAME=VALUE` form.
    #[serde(default)]
    pub environment: Option<Vec<String>>,
    /// Legacy optional shell command argv. A single argument is executed via
    /// `$SHELL -c`.
    #[serde(default)]
    pub command: Option<Vec<String>>,
    /// Explicit process launch mode.
    #[serde(default)]
    pub process_command: Option<ProcessCommand>,
}

impl<'de> Deserialize<'de> for RespawnPaneRequest {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_struct(
            "RespawnPaneRequest",
            &[
                "target",
                "kill",
                "start_directory",
                "environment",
                "command",
                "process_command",
            ],
            compat::RespawnPaneRequestVisitor,
        )
    }
}

/// Request payload for `select-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SelectPaneRequest {
    /// The exact pane target.
    pub target: PaneTarget,
    /// Optional pane title to set without changing the active pane (`-T`).
    #[serde(default)]
    pub title: Option<String>,
}

/// SDK pane input request that can address a stable pane id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneInputRequest {
    /// The exact pane target or stable pane id.
    pub target: PaneTargetRef,
    /// Text or key tokens to send.
    pub keys: Vec<String>,
    /// Whether tokens should be written literally instead of interpreted as
    /// tmux-compatible key names.
    #[serde(default)]
    pub literal: bool,
}

/// SDK pane input broadcast request with stable pane-id targeting.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneBroadcastInputRequest {
    /// Pane targets addressed in caller order.
    pub targets: Vec<PaneTargetRef>,
    /// Text or key tokens to send to each pane.
    pub keys: Vec<String>,
    /// Whether tokens should be written literally instead of interpreted as
    /// tmux-compatible key names.
    #[serde(default)]
    pub literal: bool,
}

/// SDK resize request that can address a stable pane id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneResizeRequest {
    /// The exact pane target or stable pane id.
    pub target: PaneTargetRef,
    /// The semantic resize request.
    pub adjustment: ResizePaneAdjustment,
}

/// SDK kill request that can address a stable pane id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneKillRequest {
    /// The exact pane target or stable pane id.
    pub target: PaneTargetRef,
    /// Whether all panes except the target should be killed.
    #[serde(default)]
    pub kill_all_except: bool,
}

/// SDK respawn request that can address a stable pane id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneRespawnRequest {
    /// The exact pane target or stable pane id.
    pub target: PaneTargetRef,
    /// Whether a running pane should be killed before respawning.
    #[serde(default)]
    pub kill: bool,
    /// Optional working-directory override.
    #[serde(default)]
    pub start_directory: Option<PathBuf>,
    /// Optional per-spawn environment overrides in `NAME=VALUE` form.
    #[serde(default)]
    pub environment: Option<Vec<String>>,
    /// Legacy optional shell command argv. A single argument is executed via
    /// `$SHELL -c`.
    #[serde(default)]
    pub command: Option<Vec<String>>,
    /// Explicit process launch mode.
    #[serde(default)]
    pub process_command: Option<ProcessCommand>,
    /// Optional pane-local `remain-on-exit` override applied before respawn.
    #[serde(default)]
    pub keep_alive_on_exit: Option<bool>,
}

/// SDK snapshot request that can address a stable pane id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneSnapshotRefRequest {
    /// The exact pane target or stable pane id.
    pub target: PaneTargetRef,
}

/// SDK select/title request that can address a stable pane id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneSelectRequest {
    /// The exact pane target or stable pane id.
    pub target: PaneTargetRef,
    /// Optional pane title to set without changing the active pane.
    #[serde(default)]
    pub title: Option<String>,
}

/// Direction used by `select-pane -U/-D/-L/-R`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SelectPaneDirection {
    /// Select the pane above the target pane.
    Up,
    /// Select the pane below the target pane.
    Down,
    /// Select the pane to the left of the target pane.
    Left,
    /// Select the pane to the right of the target pane.
    Right,
}

/// Request payload for directional `select-pane`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SelectPaneAdjacentRequest {
    /// The pane used as the directional anchor.
    pub target: PaneTarget,
    /// The requested adjacent-pane direction.
    pub direction: SelectPaneDirection,
}

/// Request payload for `select-pane -m` and `select-pane -M`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SelectPaneMarkRequest {
    /// The pane target used to resolve the current session/window context.
    pub target: PaneTarget,
    /// Whether to clear the existing marked pane instead of toggling the target.
    pub clear: bool,
    /// Optional pane title to set while applying the mark operation (`-T`).
    #[serde(default)]
    pub title: Option<String>,
}

/// Request payload for the daemon-backed pane snapshot endpoint.
///
/// Unlike [`CapturePaneRequest`](crate::CapturePaneRequest), which returns a
/// pre-rendered byte stream of the visible viewport, this request asks the
/// daemon to expose its live in-memory grid as structured cells. The daemon
/// reads the cells directly from the rmux-core screen that is fed by its
/// crate-private terminal parser, so there is no `String::from_utf8_lossy`
/// reconstruction step on either side of the wire.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneSnapshotRequest {
    /// The exact pane target whose visible viewport should be captured.
    pub target: PaneTarget,
}

/// Starting position for a pane-output subscription cursor.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum PaneOutputSubscriptionStart {
    /// Start after the newest output currently retained by the pane.
    Now,
    /// Start at the oldest retained output event.
    Oldest,
}

/// Request payload for subscribing to live pane-output events.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SubscribePaneOutputRequest {
    /// The exact pane target whose output should be subscribed.
    pub target: PaneTarget,
    /// The initial cursor position.
    pub start: PaneOutputSubscriptionStart,
}

/// Request payload for subscribing to live pane-output events by slot or id.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SubscribePaneOutputRefRequest {
    /// The exact pane target or stable pane id whose output should be
    /// subscribed.
    pub target: PaneTargetRef,
    /// The initial cursor position.
    pub start: PaneOutputSubscriptionStart,
}

/// Request payload for unsubscribing from live pane-output events.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct UnsubscribePaneOutputRequest {
    /// The subscription to remove.
    pub subscription_id: PaneOutputSubscriptionId,
}

/// Request payload for polling a pane-output subscription cursor.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct PaneOutputCursorRequest {
    /// The subscription whose cursor should be polled.
    pub subscription_id: PaneOutputSubscriptionId,
    /// Optional caller-requested event cap. The server clamps this to the
    /// recorded v1 default batch limit.
    #[serde(default)]
    pub max_events: Option<u16>,
}

/// Request payload for `send-keys`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SendKeysRequest {
    /// The exact pane target.
    pub target: PaneTarget,
    /// Key tokens in left-to-right order.
    pub keys: Vec<String>,
}

/// Extended request payload for `send-keys`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SendKeysExtRequest {
    /// The optional explicit pane target.
    pub target: Option<PaneTarget>,
    /// Key tokens in left-to-right order.
    pub keys: Vec<String>,
    /// Whether tmux format expansion should be applied to each token first.
    pub expand_formats: bool,
    /// Whether each token should be interpreted as a hexadecimal byte value.
    pub hex: bool,
    /// Whether tokens should be sent as literal bytes instead of key names.
    #[serde(default)]
    pub literal: bool,
    /// Whether keys should be dispatched through the client's key table.
    pub dispatch_key_table: bool,
    /// Whether tokens describe copy-mode commands.
    pub copy_mode_command: bool,
    /// Whether the payload should be treated as a mouse event.
    pub forward_mouse_event: bool,
    /// Whether the target terminal should be reset before sending keys.
    pub reset_terminal: bool,
    /// Optional tmux repeat count for command or key dispatch.
    pub repeat_count: Option<usize>,
}