1use rmux_proto::{
2 BreakPaneRequest, CancelSdkWaitRequest, ClockModeRequest, CopyModeRequest, DisplayPanesRequest,
3 JoinPaneRequest, KillPaneRequest, LastPaneRequest, MovePaneRequest, PaneBroadcastInputRequest,
4 PaneInputRequest, PaneOutputCursorRequest, PaneOutputSubscriptionId,
5 PaneOutputSubscriptionStart, PaneSnapshotRefRequest, PaneTarget, PaneTargetRef,
6 PipePaneRequest, Request, ResizePaneAdjustment, ResizePaneRequest,
7 ResizePaneTargetActionRequest, RespawnPaneRequest, Response, SdkWaitForOutputRefRequest,
8 SdkWaitId, SdkWaitOwnerId, SelectPaneAdjacentRequest, SelectPaneDirection,
9 SelectPaneMarkRequest, SelectPaneRequest, SendKeysExt2Request, SendKeysExtRequest,
10 SendKeysRequest, SendPrefixRequest, SessionName, SubscribePaneOutputRefRequest,
11 SwapPaneDirection, SwapPaneRequest, UnsubscribePaneOutputRequest, WindowTarget,
12 CAPABILITY_SDK_PANE_BROADCAST, CAPABILITY_SDK_PANE_BY_ID, CAPABILITY_SDK_WAITS,
13 CAPABILITY_TARGET_CLIENT_COMMANDS,
14};
15
16use crate::{connection::Connection, ClientError};
17
18impl Connection {
19 pub fn swap_pane(
21 &mut self,
22 source: PaneTarget,
23 target: PaneTarget,
24 detached: bool,
25 preserve_zoom: bool,
26 ) -> Result<Response, ClientError> {
27 self.roundtrip(&Request::SwapPane(SwapPaneRequest {
28 source,
29 target,
30 direction: None,
31 detached,
32 preserve_zoom,
33 }))
34 }
35
36 pub fn swap_pane_with_next(
38 &mut self,
39 target: PaneTarget,
40 detached: bool,
41 preserve_zoom: bool,
42 ) -> Result<Response, ClientError> {
43 self.roundtrip(&Request::SwapPane(SwapPaneRequest {
44 source: target.clone(),
45 target,
46 direction: Some(SwapPaneDirection::Down),
47 detached,
48 preserve_zoom,
49 }))
50 }
51
52 pub fn swap_pane_with_previous(
54 &mut self,
55 target: PaneTarget,
56 detached: bool,
57 preserve_zoom: bool,
58 ) -> Result<Response, ClientError> {
59 self.roundtrip(&Request::SwapPane(SwapPaneRequest {
60 source: target.clone(),
61 target,
62 direction: Some(SwapPaneDirection::Up),
63 detached,
64 preserve_zoom,
65 }))
66 }
67
68 pub fn last_pane(&mut self, target: WindowTarget) -> Result<Response, ClientError> {
70 self.last_pane_with_zoom(target, false)
71 }
72
73 pub fn last_pane_with_zoom(
75 &mut self,
76 target: WindowTarget,
77 preserve_zoom: bool,
78 ) -> Result<Response, ClientError> {
79 self.last_pane_with_options(target, preserve_zoom, None)
80 }
81
82 pub fn last_pane_with_options(
84 &mut self,
85 target: WindowTarget,
86 preserve_zoom: bool,
87 input_disabled: Option<bool>,
88 ) -> Result<Response, ClientError> {
89 self.roundtrip(&Request::LastPane(LastPaneRequest {
90 target,
91 preserve_zoom,
92 input_disabled,
93 }))
94 }
95
96 pub fn join_pane(&mut self, request: JoinPaneRequest) -> Result<Response, ClientError> {
98 self.roundtrip(&Request::JoinPane(request))
99 }
100
101 pub fn move_pane(&mut self, request: MovePaneRequest) -> Result<Response, ClientError> {
103 self.roundtrip(&Request::MovePane(request))
104 }
105
106 pub fn break_pane(&mut self, request: BreakPaneRequest) -> Result<Response, ClientError> {
108 self.roundtrip(&Request::BreakPane(Box::new(request)))
109 }
110
111 pub fn resize_pane(
113 &mut self,
114 target: PaneTarget,
115 adjustment: ResizePaneAdjustment,
116 ) -> Result<Response, ClientError> {
117 self.roundtrip(&Request::ResizePane(ResizePaneRequest {
118 target,
119 adjustment,
120 }))
121 }
122
123 pub fn resize_pane_target_action(
125 &mut self,
126 request: ResizePaneTargetActionRequest,
127 ) -> Result<Response, ClientError> {
128 self.roundtrip(&Request::ResizePaneTargetAction(request))
129 }
130
131 pub fn display_panes(
133 &mut self,
134 target: SessionName,
135 duration_ms: Option<u64>,
136 non_blocking: bool,
137 no_command: bool,
138 template: Option<String>,
139 ) -> Result<Response, ClientError> {
140 self.display_panes_target_client(
141 target,
142 duration_ms,
143 non_blocking,
144 no_command,
145 template,
146 None,
147 )
148 }
149
150 #[allow(clippy::too_many_arguments)]
152 pub fn display_panes_target_client(
153 &mut self,
154 target: SessionName,
155 duration_ms: Option<u64>,
156 non_blocking: bool,
157 no_command: bool,
158 template: Option<String>,
159 target_client: Option<String>,
160 ) -> Result<Response, ClientError> {
161 let request = Request::DisplayPanes(Box::new(DisplayPanesRequest {
162 target,
163 duration_ms,
164 non_blocking,
165 no_command,
166 template,
167 target_client,
168 }));
169 if non_blocking {
170 self.roundtrip(&request)
171 } else {
172 self.roundtrip_without_read_timeout(&request)
173 }
174 }
175
176 pub fn pipe_pane(
178 &mut self,
179 target: PaneTarget,
180 stdin: bool,
181 stdout: bool,
182 once: bool,
183 command: Option<String>,
184 ) -> Result<Response, ClientError> {
185 self.roundtrip(&Request::PipePane(PipePaneRequest {
186 target,
187 stdin,
188 stdout,
189 once,
190 command,
191 }))
192 }
193
194 pub fn respawn_pane(&mut self, request: RespawnPaneRequest) -> Result<Response, ClientError> {
196 self.roundtrip(&Request::RespawnPane(Box::new(request)))
197 }
198
199 pub fn select_pane(&mut self, target: PaneTarget) -> Result<Response, ClientError> {
201 self.select_pane_with_title(target, None)
202 }
203
204 pub fn select_pane_with_title(
206 &mut self,
207 target: PaneTarget,
208 title: Option<String>,
209 ) -> Result<Response, ClientError> {
210 self.select_pane_with_title_and_zoom(target, title, false)
211 }
212
213 pub fn select_pane_with_title_and_zoom(
215 &mut self,
216 target: PaneTarget,
217 title: Option<String>,
218 preserve_zoom: bool,
219 ) -> Result<Response, ClientError> {
220 self.select_pane_with_options(target, title, None, None, preserve_zoom)
221 }
222
223 pub fn select_pane_with_options(
225 &mut self,
226 target: PaneTarget,
227 title: Option<String>,
228 style: Option<String>,
229 input_disabled: Option<bool>,
230 preserve_zoom: bool,
231 ) -> Result<Response, ClientError> {
232 self.roundtrip(&Request::SelectPane(Box::new(SelectPaneRequest {
233 target,
234 title,
235 input_disabled,
236 preserve_zoom,
237 style,
238 })))
239 }
240
241 pub fn select_pane_input(
243 &mut self,
244 target: PaneTarget,
245 disabled: bool,
246 ) -> Result<Response, ClientError> {
247 self.roundtrip(&Request::SelectPane(Box::new(SelectPaneRequest {
248 target,
249 title: None,
250 style: None,
251 input_disabled: Some(disabled),
252 preserve_zoom: false,
253 })))
254 }
255
256 pub fn select_pane_adjacent(
258 &mut self,
259 target: PaneTarget,
260 direction: SelectPaneDirection,
261 ) -> Result<Response, ClientError> {
262 self.select_pane_adjacent_with_zoom(target, direction, false)
263 }
264
265 pub fn select_pane_adjacent_with_zoom(
267 &mut self,
268 target: PaneTarget,
269 direction: SelectPaneDirection,
270 preserve_zoom: bool,
271 ) -> Result<Response, ClientError> {
272 self.roundtrip(&Request::SelectPaneAdjacent(SelectPaneAdjacentRequest {
273 target,
274 direction,
275 preserve_zoom,
276 }))
277 }
278
279 pub fn select_pane_mark(
281 &mut self,
282 target: PaneTarget,
283 clear: bool,
284 ) -> Result<Response, ClientError> {
285 self.select_pane_mark_with_title(target, clear, None)
286 }
287
288 pub fn select_pane_mark_with_title(
290 &mut self,
291 target: PaneTarget,
292 clear: bool,
293 title: Option<String>,
294 ) -> Result<Response, ClientError> {
295 self.roundtrip(&Request::SelectPaneMark(SelectPaneMarkRequest {
296 target,
297 clear,
298 title,
299 }))
300 }
301
302 pub fn kill_pane(&mut self, target: PaneTarget) -> Result<Response, ClientError> {
304 self.kill_pane_with_options(target, false)
305 }
306
307 pub fn kill_pane_with_options(
309 &mut self,
310 target: PaneTarget,
311 kill_all_except: bool,
312 ) -> Result<Response, ClientError> {
313 self.roundtrip(&Request::KillPane(KillPaneRequest {
314 target,
315 kill_all_except,
316 }))
317 }
318
319 pub fn send_keys(
321 &mut self,
322 target: PaneTarget,
323 keys: Vec<String>,
324 ) -> Result<Response, ClientError> {
325 self.roundtrip(&Request::SendKeys(SendKeysRequest { target, keys }))
326 }
327
328 pub fn send_keys_extended(
330 &mut self,
331 request: SendKeysExtRequest,
332 ) -> Result<Response, ClientError> {
333 self.roundtrip(&Request::SendKeysExt(request))
334 }
335
336 pub fn send_keys_extended_target_client(
338 &mut self,
339 request: SendKeysExt2Request,
340 ) -> Result<Response, ClientError> {
341 if !self.supports_capability(CAPABILITY_TARGET_CLIENT_COMMANDS)? {
342 return Err(ClientError::Protocol(
343 rmux_proto::RmuxError::UnsupportedCapability {
344 feature: CAPABILITY_TARGET_CLIENT_COMMANDS.to_owned(),
345 supported: Vec::new(),
346 },
347 ));
348 }
349 self.roundtrip(&Request::SendKeysExt2(Box::new(request)))
350 }
351
352 pub fn pane_input(&mut self, request: PaneInputRequest) -> Result<Response, ClientError> {
354 if !self.supports_capability(CAPABILITY_SDK_PANE_BY_ID)? {
355 return Err(ClientError::Protocol(
356 rmux_proto::RmuxError::UnsupportedCapability {
357 feature: CAPABILITY_SDK_PANE_BY_ID.to_owned(),
358 supported: Vec::new(),
359 },
360 ));
361 }
362 self.roundtrip(&Request::PaneInput(request))
363 }
364
365 pub fn pane_broadcast_input(
367 &mut self,
368 request: PaneBroadcastInputRequest,
369 ) -> Result<Response, ClientError> {
370 if !self.supports_capability(CAPABILITY_SDK_PANE_BROADCAST)? {
371 return Err(ClientError::Protocol(
372 rmux_proto::RmuxError::UnsupportedCapability {
373 feature: CAPABILITY_SDK_PANE_BROADCAST.to_owned(),
374 supported: Vec::new(),
375 },
376 ));
377 }
378 self.roundtrip(&Request::PaneBroadcastInput(request))
379 }
380
381 pub fn pane_snapshot_ref(&mut self, target: PaneTargetRef) -> Result<Response, ClientError> {
383 if !self.supports_capability(CAPABILITY_SDK_PANE_BY_ID)? {
384 return Err(ClientError::Protocol(
385 rmux_proto::RmuxError::UnsupportedCapability {
386 feature: CAPABILITY_SDK_PANE_BY_ID.to_owned(),
387 supported: Vec::new(),
388 },
389 ));
390 }
391 self.roundtrip(&Request::PaneSnapshotRef(PaneSnapshotRefRequest { target }))
392 }
393
394 pub fn subscribe_pane_output_ref(
396 &mut self,
397 target: PaneTargetRef,
398 start: PaneOutputSubscriptionStart,
399 ) -> Result<Response, ClientError> {
400 if !self.supports_capability(CAPABILITY_SDK_PANE_BY_ID)? {
401 return Err(ClientError::Protocol(
402 rmux_proto::RmuxError::UnsupportedCapability {
403 feature: CAPABILITY_SDK_PANE_BY_ID.to_owned(),
404 supported: Vec::new(),
405 },
406 ));
407 }
408 self.roundtrip(&Request::SubscribePaneOutputRef(
409 SubscribePaneOutputRefRequest { target, start },
410 ))
411 }
412
413 pub fn pane_output_cursor(
415 &mut self,
416 subscription_id: PaneOutputSubscriptionId,
417 max_events: Option<u16>,
418 ) -> Result<Response, ClientError> {
419 self.roundtrip(&Request::PaneOutputCursor(PaneOutputCursorRequest {
420 subscription_id,
421 max_events,
422 }))
423 }
424
425 pub fn unsubscribe_pane_output(
427 &mut self,
428 subscription_id: PaneOutputSubscriptionId,
429 ) -> Result<Response, ClientError> {
430 self.roundtrip(&Request::UnsubscribePaneOutput(
431 UnsubscribePaneOutputRequest { subscription_id },
432 ))
433 }
434
435 pub fn sdk_wait_for_output_ref(
437 &mut self,
438 owner_id: SdkWaitOwnerId,
439 wait_id: SdkWaitId,
440 target: PaneTargetRef,
441 bytes: Vec<u8>,
442 start: PaneOutputSubscriptionStart,
443 ) -> Result<Response, ClientError> {
444 if !self.supports_capability(CAPABILITY_SDK_WAITS)? {
445 return Err(ClientError::Protocol(
446 rmux_proto::RmuxError::UnsupportedCapability {
447 feature: CAPABILITY_SDK_WAITS.to_owned(),
448 supported: Vec::new(),
449 },
450 ));
451 }
452 self.roundtrip_without_read_timeout(&Request::SdkWaitForOutputRef(
453 SdkWaitForOutputRefRequest {
454 owner_id,
455 wait_id,
456 target,
457 bytes,
458 start,
459 },
460 ))
461 }
462
463 pub fn arm_sdk_wait_for_output_ref(
468 &mut self,
469 owner_id: SdkWaitOwnerId,
470 wait_id: SdkWaitId,
471 target: PaneTargetRef,
472 bytes: Vec<u8>,
473 start: PaneOutputSubscriptionStart,
474 ) -> Result<(), ClientError> {
475 if !self.supports_capability(CAPABILITY_SDK_WAITS)? {
476 return Err(ClientError::Protocol(
477 rmux_proto::RmuxError::UnsupportedCapability {
478 feature: CAPABILITY_SDK_WAITS.to_owned(),
479 supported: Vec::new(),
480 },
481 ));
482 }
483 self.write_request(&Request::SdkWaitForOutputRef(SdkWaitForOutputRefRequest {
484 owner_id,
485 wait_id,
486 target,
487 bytes,
488 start,
489 }))
490 }
491
492 pub fn cancel_sdk_wait(
494 &mut self,
495 owner_id: SdkWaitOwnerId,
496 wait_id: SdkWaitId,
497 ) -> Result<Response, ClientError> {
498 if !self.supports_capability(CAPABILITY_SDK_WAITS)? {
499 return Err(ClientError::Protocol(
500 rmux_proto::RmuxError::UnsupportedCapability {
501 feature: CAPABILITY_SDK_WAITS.to_owned(),
502 supported: Vec::new(),
503 },
504 ));
505 }
506 self.roundtrip(&Request::CancelSdkWait(CancelSdkWaitRequest {
507 owner_id,
508 wait_id,
509 }))
510 }
511
512 pub fn send_prefix(
514 &mut self,
515 target: Option<PaneTarget>,
516 secondary: bool,
517 ) -> Result<Response, ClientError> {
518 self.roundtrip(&Request::SendPrefix(SendPrefixRequest {
519 target,
520 secondary,
521 }))
522 }
523
524 pub fn copy_mode(&mut self, request: CopyModeRequest) -> Result<Response, ClientError> {
526 self.roundtrip(&Request::CopyMode(request))
527 }
528
529 pub fn clock_mode(&mut self, target: Option<PaneTarget>) -> Result<Response, ClientError> {
531 self.roundtrip(&Request::ClockMode(ClockModeRequest { target }))
532 }
533}