Skip to main content

rmux_client/commands/
pane.rs

1use rmux_proto::{
2    BreakPaneRequest, ClockModeRequest, CopyModeRequest, DisplayPanesRequest, JoinPaneRequest,
3    KillPaneRequest, LastPaneRequest, MovePaneRequest, PaneTarget, PipePaneRequest, Request,
4    ResizePaneAdjustment, ResizePaneRequest, RespawnPaneRequest, Response,
5    SelectPaneAdjacentRequest, SelectPaneDirection, SelectPaneMarkRequest, SelectPaneRequest,
6    SendKeysExt2Request, SendKeysExtRequest, SendKeysRequest, SendPrefixRequest, SessionName,
7    SwapPaneDirection, SwapPaneRequest, WindowTarget, CAPABILITY_TARGET_CLIENT_COMMANDS,
8};
9
10use crate::{connection::Connection, ClientError};
11
12impl Connection {
13    /// Sends a `swap-pane` request over the detached RPC channel.
14    pub fn swap_pane(
15        &mut self,
16        source: PaneTarget,
17        target: PaneTarget,
18        detached: bool,
19        preserve_zoom: bool,
20    ) -> Result<Response, ClientError> {
21        self.roundtrip(&Request::SwapPane(SwapPaneRequest {
22            source,
23            target,
24            direction: None,
25            detached,
26            preserve_zoom,
27        }))
28    }
29
30    /// Sends `swap-pane -D` over the detached RPC channel.
31    pub fn swap_pane_with_next(
32        &mut self,
33        target: PaneTarget,
34        detached: bool,
35        preserve_zoom: bool,
36    ) -> Result<Response, ClientError> {
37        self.roundtrip(&Request::SwapPane(SwapPaneRequest {
38            source: target.clone(),
39            target,
40            direction: Some(SwapPaneDirection::Down),
41            detached,
42            preserve_zoom,
43        }))
44    }
45
46    /// Sends `swap-pane -U` over the detached RPC channel.
47    pub fn swap_pane_with_previous(
48        &mut self,
49        target: PaneTarget,
50        detached: bool,
51        preserve_zoom: bool,
52    ) -> Result<Response, ClientError> {
53        self.roundtrip(&Request::SwapPane(SwapPaneRequest {
54            source: target.clone(),
55            target,
56            direction: Some(SwapPaneDirection::Up),
57            detached,
58            preserve_zoom,
59        }))
60    }
61
62    /// Sends a `last-pane` request over the detached RPC channel.
63    pub fn last_pane(&mut self, target: WindowTarget) -> Result<Response, ClientError> {
64        self.last_pane_with_zoom(target, false)
65    }
66
67    /// Sends a `last-pane` request with optional zoom preservation.
68    pub fn last_pane_with_zoom(
69        &mut self,
70        target: WindowTarget,
71        preserve_zoom: bool,
72    ) -> Result<Response, ClientError> {
73        self.last_pane_with_options(target, preserve_zoom, None)
74    }
75
76    /// Sends a `last-pane` request with tmux selection options.
77    pub fn last_pane_with_options(
78        &mut self,
79        target: WindowTarget,
80        preserve_zoom: bool,
81        input_disabled: Option<bool>,
82    ) -> Result<Response, ClientError> {
83        self.roundtrip(&Request::LastPane(LastPaneRequest {
84            target,
85            preserve_zoom,
86            input_disabled,
87        }))
88    }
89
90    /// Sends a `join-pane` request over the detached RPC channel.
91    pub fn join_pane(&mut self, request: JoinPaneRequest) -> Result<Response, ClientError> {
92        self.roundtrip(&Request::JoinPane(request))
93    }
94
95    /// Sends a `move-pane` request over the detached RPC channel.
96    pub fn move_pane(&mut self, request: MovePaneRequest) -> Result<Response, ClientError> {
97        self.roundtrip(&Request::MovePane(request))
98    }
99
100    /// Sends a `break-pane` request over the detached RPC channel.
101    pub fn break_pane(&mut self, request: BreakPaneRequest) -> Result<Response, ClientError> {
102        self.roundtrip(&Request::BreakPane(request))
103    }
104
105    /// Sends a `resize-pane` request over the detached RPC channel.
106    pub fn resize_pane(
107        &mut self,
108        target: PaneTarget,
109        adjustment: ResizePaneAdjustment,
110    ) -> Result<Response, ClientError> {
111        self.roundtrip(&Request::ResizePane(ResizePaneRequest {
112            target,
113            adjustment,
114        }))
115    }
116
117    /// Sends a `display-panes` request over the detached RPC channel.
118    pub fn display_panes(
119        &mut self,
120        target: SessionName,
121        duration_ms: Option<u64>,
122        non_blocking: bool,
123        no_command: bool,
124        template: Option<String>,
125    ) -> Result<Response, ClientError> {
126        let request = Request::DisplayPanes(DisplayPanesRequest {
127            target,
128            duration_ms,
129            non_blocking,
130            no_command,
131            template,
132        });
133        if non_blocking {
134            self.roundtrip(&request)
135        } else {
136            self.roundtrip_without_read_timeout(&request)
137        }
138    }
139
140    /// Sends a `pipe-pane` request over the detached RPC channel.
141    pub fn pipe_pane(
142        &mut self,
143        target: PaneTarget,
144        stdin: bool,
145        stdout: bool,
146        once: bool,
147        command: Option<String>,
148    ) -> Result<Response, ClientError> {
149        self.roundtrip(&Request::PipePane(PipePaneRequest {
150            target,
151            stdin,
152            stdout,
153            once,
154            command,
155        }))
156    }
157
158    /// Sends a `respawn-pane` request over the detached RPC channel.
159    pub fn respawn_pane(&mut self, request: RespawnPaneRequest) -> Result<Response, ClientError> {
160        self.roundtrip(&Request::RespawnPane(request))
161    }
162
163    /// Sends a `select-pane` request over the detached RPC channel.
164    pub fn select_pane(&mut self, target: PaneTarget) -> Result<Response, ClientError> {
165        self.select_pane_with_title(target, None)
166    }
167
168    /// Sends a `select-pane` request with an optional title over the detached RPC channel.
169    pub fn select_pane_with_title(
170        &mut self,
171        target: PaneTarget,
172        title: Option<String>,
173    ) -> Result<Response, ClientError> {
174        self.select_pane_with_title_and_zoom(target, title, false)
175    }
176
177    /// Sends a `select-pane` request with optional title and zoom preservation.
178    pub fn select_pane_with_title_and_zoom(
179        &mut self,
180        target: PaneTarget,
181        title: Option<String>,
182        preserve_zoom: bool,
183    ) -> Result<Response, ClientError> {
184        self.select_pane_with_options(target, title, None, None, preserve_zoom)
185    }
186
187    /// Sends a `select-pane` request with optional title, style, input state, and zoom preservation.
188    pub fn select_pane_with_options(
189        &mut self,
190        target: PaneTarget,
191        title: Option<String>,
192        style: Option<String>,
193        input_disabled: Option<bool>,
194        preserve_zoom: bool,
195    ) -> Result<Response, ClientError> {
196        self.roundtrip(&Request::SelectPane(SelectPaneRequest {
197            target,
198            title,
199            input_disabled,
200            preserve_zoom,
201            style,
202        }))
203    }
204
205    /// Sends a `select-pane -d` / `-e` input-state request.
206    pub fn select_pane_input(
207        &mut self,
208        target: PaneTarget,
209        disabled: bool,
210    ) -> Result<Response, ClientError> {
211        self.roundtrip(&Request::SelectPane(SelectPaneRequest {
212            target,
213            title: None,
214            style: None,
215            input_disabled: Some(disabled),
216            preserve_zoom: false,
217        }))
218    }
219
220    /// Sends a directional `select-pane` request over the detached RPC channel.
221    pub fn select_pane_adjacent(
222        &mut self,
223        target: PaneTarget,
224        direction: SelectPaneDirection,
225    ) -> Result<Response, ClientError> {
226        self.select_pane_adjacent_with_zoom(target, direction, false)
227    }
228
229    /// Sends a directional `select-pane` request with optional zoom preservation.
230    pub fn select_pane_adjacent_with_zoom(
231        &mut self,
232        target: PaneTarget,
233        direction: SelectPaneDirection,
234        preserve_zoom: bool,
235    ) -> Result<Response, ClientError> {
236        self.roundtrip(&Request::SelectPaneAdjacent(SelectPaneAdjacentRequest {
237            target,
238            direction,
239            preserve_zoom,
240        }))
241    }
242
243    /// Sends `select-pane -m` or `select-pane -M` over the detached RPC channel.
244    pub fn select_pane_mark(
245        &mut self,
246        target: PaneTarget,
247        clear: bool,
248    ) -> Result<Response, ClientError> {
249        self.select_pane_mark_with_title(target, clear, None)
250    }
251
252    /// Sends `select-pane -m/-M` with an optional title over the detached RPC channel.
253    pub fn select_pane_mark_with_title(
254        &mut self,
255        target: PaneTarget,
256        clear: bool,
257        title: Option<String>,
258    ) -> Result<Response, ClientError> {
259        self.roundtrip(&Request::SelectPaneMark(SelectPaneMarkRequest {
260            target,
261            clear,
262            title,
263        }))
264    }
265
266    /// Sends a `kill-pane` request over the detached RPC channel.
267    pub fn kill_pane(&mut self, target: PaneTarget) -> Result<Response, ClientError> {
268        self.kill_pane_with_options(target, false)
269    }
270
271    /// Sends a `kill-pane` request with extended tmux flags.
272    pub fn kill_pane_with_options(
273        &mut self,
274        target: PaneTarget,
275        kill_all_except: bool,
276    ) -> Result<Response, ClientError> {
277        self.roundtrip(&Request::KillPane(KillPaneRequest {
278            target,
279            kill_all_except,
280        }))
281    }
282
283    /// Sends a `send-keys` request over the detached RPC channel.
284    pub fn send_keys(
285        &mut self,
286        target: PaneTarget,
287        keys: Vec<String>,
288    ) -> Result<Response, ClientError> {
289        self.roundtrip(&Request::SendKeys(SendKeysRequest { target, keys }))
290    }
291
292    /// Sends an extended `send-keys` request over the detached RPC channel.
293    pub fn send_keys_extended(
294        &mut self,
295        request: SendKeysExtRequest,
296    ) -> Result<Response, ClientError> {
297        self.roundtrip(&Request::SendKeysExt(request))
298    }
299
300    /// Sends a target-client aware `send-keys` request over detached RPC.
301    pub fn send_keys_extended_target_client(
302        &mut self,
303        request: SendKeysExt2Request,
304    ) -> Result<Response, ClientError> {
305        if !self.supports_capability(CAPABILITY_TARGET_CLIENT_COMMANDS)? {
306            return Err(ClientError::Protocol(
307                rmux_proto::RmuxError::UnsupportedCapability {
308                    feature: CAPABILITY_TARGET_CLIENT_COMMANDS.to_owned(),
309                    supported: Vec::new(),
310                },
311            ));
312        }
313        self.roundtrip(&Request::SendKeysExt2(request))
314    }
315
316    /// Sends a `send-prefix` request over the detached RPC channel.
317    pub fn send_prefix(
318        &mut self,
319        target: Option<PaneTarget>,
320        secondary: bool,
321    ) -> Result<Response, ClientError> {
322        self.roundtrip(&Request::SendPrefix(SendPrefixRequest {
323            target,
324            secondary,
325        }))
326    }
327
328    /// Sends a `copy-mode` request over the detached RPC channel.
329    pub fn copy_mode(&mut self, request: CopyModeRequest) -> Result<Response, ClientError> {
330        self.roundtrip(&Request::CopyMode(request))
331    }
332
333    /// Sends a `clock-mode` request over the detached RPC channel.
334    pub fn clock_mode(&mut self, target: Option<PaneTarget>) -> Result<Response, ClientError> {
335        self.roundtrip(&Request::ClockMode(ClockModeRequest { target }))
336    }
337}