1use crate::{
2 client_server_contract::client_server_contract::{
3 client_to_server_msg, server_to_client_msg, ActionMsg, AttachClientMsg,
4 AttachWatcherClientMsg, BackgroundColorMsg, CliPipeOutputMsg, ClientExitedMsg,
5 ClientToServerMsg as ProtoClientToServerMsg, ColorRegistersMsg, ConfigFileUpdatedMsg,
6 ConnStatusMsg, ConnectedMsg, DesktopNotificationResponseMsg, DetachSessionMsg, ExitMsg,
7 ExitReason as ProtoExitReason, FailedToStartWebServerMsg, FirstClientConnectedMsg,
8 ForegroundColorMsg, InputMode as ProtoInputMode, KeyMsg, KillSessionMsg,
9 LayoutMetadata as ProtoLayoutMetadata, LogErrorMsg, LogMsg,
10 PaneMetadata as ProtoPaneMetadata, PaneRenderUpdateMsg, QueryTerminalSizeMsg,
11 RenamedSessionMsg, RenderMsg, ServerToClientMsg as ProtoServerToClientMsg,
12 StartWebServerMsg, SubscribeToPaneRendersMsg, SubscribedPaneClosedMsg, SwitchSessionMsg,
13 TabMetadata as ProtoTabMetadata, TerminalPixelDimensionsMsg, TerminalResizeMsg,
14 UnblockCliPipeInputMsg, UnblockInputThreadMsg, WebServerStartedMsg,
15 },
16 data::{InputMode, PaneId},
17 errors::prelude::*,
18 ipc::{
19 ClientToServerMsg, ColorRegister, ExitReason, PaneReference, PixelDimensions,
20 ServerToClientMsg,
21 },
22};
23use std::collections::BTreeMap;
24use std::path::PathBuf;
25
26impl From<ClientToServerMsg> for ProtoClientToServerMsg {
28 fn from(msg: ClientToServerMsg) -> Self {
29 let message = match msg {
30 ClientToServerMsg::DetachSession { client_ids } => {
31 client_to_server_msg::Message::DetachSession(DetachSessionMsg {
32 client_ids: client_ids.into_iter().map(|id| id as u32).collect(),
33 })
34 },
35 ClientToServerMsg::TerminalPixelDimensions { pixel_dimensions } => {
36 client_to_server_msg::Message::TerminalPixelDimensions(TerminalPixelDimensionsMsg {
37 pixel_dimensions: Some(pixel_dimensions.into()),
38 })
39 },
40 ClientToServerMsg::BackgroundColor { color } => {
41 client_to_server_msg::Message::BackgroundColor(BackgroundColorMsg { color })
42 },
43 ClientToServerMsg::ForegroundColor { color } => {
44 client_to_server_msg::Message::ForegroundColor(ForegroundColorMsg { color })
45 },
46 ClientToServerMsg::ColorRegisters { color_registers } => {
47 client_to_server_msg::Message::ColorRegisters(ColorRegistersMsg {
48 color_registers: color_registers.into_iter().map(|cr| cr.into()).collect(),
49 })
50 },
51 ClientToServerMsg::TerminalResize { new_size } => {
52 client_to_server_msg::Message::TerminalResize(TerminalResizeMsg {
53 new_size: Some(new_size.into()),
54 })
55 },
56 ClientToServerMsg::FirstClientConnected {
57 cli_assets,
58 is_web_client,
59 } => client_to_server_msg::Message::FirstClientConnected(FirstClientConnectedMsg {
60 cli_assets: Some(cli_assets.into()),
61 is_web_client,
62 }),
63 ClientToServerMsg::AttachClient {
64 cli_assets,
65 tab_position_to_focus,
66 pane_to_focus,
67 is_web_client,
68 } => client_to_server_msg::Message::AttachClient(AttachClientMsg {
69 cli_assets: Some(cli_assets.into()),
70 tab_position_to_focus: tab_position_to_focus.map(|pos| pos as u32),
71 pane_to_focus: pane_to_focus.map(|p| p.into()),
72 is_web_client,
73 }),
74 ClientToServerMsg::AttachWatcherClient {
75 terminal_size,
76 is_web_client,
77 } => client_to_server_msg::Message::AttachWatcherClient(AttachWatcherClientMsg {
78 terminal_size: Some(terminal_size.into()),
79 is_web_client,
80 }),
81 ClientToServerMsg::Action {
82 action,
83 terminal_id,
84 client_id,
85 is_cli_client,
86 } => client_to_server_msg::Message::Action(ActionMsg {
87 action: Some(action.into()),
88 terminal_id,
89 client_id: client_id.map(|id| id as u32),
90 is_cli_client,
91 }),
92 ClientToServerMsg::Key {
93 key,
94 raw_bytes,
95 is_kitty_keyboard_protocol,
96 } => client_to_server_msg::Message::Key(KeyMsg {
97 key: Some(key.into()),
98 raw_bytes: raw_bytes.into_iter().map(|b| b as u32).collect(),
99 is_kitty_keyboard_protocol,
100 }),
101 ClientToServerMsg::ClientExited => {
102 client_to_server_msg::Message::ClientExited(ClientExitedMsg {})
103 },
104 ClientToServerMsg::KillSession => {
105 client_to_server_msg::Message::KillSession(KillSessionMsg {})
106 },
107 ClientToServerMsg::ConnStatus => {
108 client_to_server_msg::Message::ConnStatus(ConnStatusMsg {})
109 },
110 ClientToServerMsg::WebServerStarted { base_url } => {
111 client_to_server_msg::Message::WebServerStarted(WebServerStartedMsg { base_url })
112 },
113 ClientToServerMsg::FailedToStartWebServer { error } => {
114 client_to_server_msg::Message::FailedToStartWebServer(FailedToStartWebServerMsg {
115 error,
116 })
117 },
118 ClientToServerMsg::SubscribeToPaneRenders {
119 pane_ids,
120 scrollback,
121 ansi,
122 } => client_to_server_msg::Message::SubscribeToPaneRenders(SubscribeToPaneRendersMsg {
123 pane_ids: pane_ids.into_iter().map(|id| id.into()).collect(),
124 scrollback: scrollback.map(|s| s as u32),
125 ansi,
126 }),
127 ClientToServerMsg::DesktopNotificationResponse { raw_bytes } => {
128 client_to_server_msg::Message::DesktopNotificationResponse(
129 DesktopNotificationResponseMsg { raw_bytes },
130 )
131 },
132 };
133
134 ProtoClientToServerMsg {
135 message: Some(message),
136 }
137 }
138}
139
140impl TryFrom<ProtoClientToServerMsg> for ClientToServerMsg {
142 type Error = anyhow::Error;
143
144 fn try_from(msg: ProtoClientToServerMsg) -> Result<Self> {
145 match msg.message {
146 Some(client_to_server_msg::Message::DetachSession(detach)) => {
147 Ok(ClientToServerMsg::DetachSession {
148 client_ids: detach.client_ids.into_iter().map(|id| id as u16).collect(),
149 })
150 },
151 Some(client_to_server_msg::Message::TerminalPixelDimensions(pixel_dims)) => {
152 Ok(ClientToServerMsg::TerminalPixelDimensions {
153 pixel_dimensions: pixel_dims
154 .pixel_dimensions
155 .ok_or_else(|| anyhow!("Missing pixel_dimensions"))?
156 .try_into()?,
157 })
158 },
159 Some(client_to_server_msg::Message::BackgroundColor(bg_color)) => {
160 Ok(ClientToServerMsg::BackgroundColor {
161 color: bg_color.color,
162 })
163 },
164 Some(client_to_server_msg::Message::ForegroundColor(fg_color)) => {
165 Ok(ClientToServerMsg::ForegroundColor {
166 color: fg_color.color,
167 })
168 },
169 Some(client_to_server_msg::Message::ColorRegisters(color_regs)) => {
170 Ok(ClientToServerMsg::ColorRegisters {
171 color_registers: color_regs
172 .color_registers
173 .into_iter()
174 .map(|cr| cr.try_into())
175 .collect::<Result<Vec<_>>>()?,
176 })
177 },
178 Some(client_to_server_msg::Message::TerminalResize(resize)) => {
179 Ok(ClientToServerMsg::TerminalResize {
180 new_size: resize
181 .new_size
182 .ok_or_else(|| anyhow!("Missing new_size"))?
183 .try_into()?,
184 })
185 },
186 Some(client_to_server_msg::Message::FirstClientConnected(first_client)) => {
187 Ok(ClientToServerMsg::FirstClientConnected {
188 cli_assets: first_client
189 .cli_assets
190 .ok_or_else(|| anyhow!("Missing cli_assets"))?
191 .try_into()?,
192 is_web_client: first_client.is_web_client,
193 })
194 },
195 Some(client_to_server_msg::Message::AttachClient(attach)) => {
196 Ok(ClientToServerMsg::AttachClient {
197 cli_assets: attach
198 .cli_assets
199 .ok_or_else(|| anyhow!("Missing cli_assets"))?
200 .try_into()?,
201 tab_position_to_focus: attach.tab_position_to_focus.map(|pos| pos as usize),
202 pane_to_focus: attach.pane_to_focus.map(|p| p.try_into()).transpose()?,
203 is_web_client: attach.is_web_client,
204 })
205 },
206 Some(client_to_server_msg::Message::AttachWatcherClient(attach_watcher)) => {
207 Ok(ClientToServerMsg::AttachWatcherClient {
208 terminal_size: attach_watcher
209 .terminal_size
210 .ok_or_else(|| anyhow::anyhow!("Missing terminal_size"))?
211 .try_into()?,
212 is_web_client: attach_watcher.is_web_client,
213 })
214 },
215 Some(client_to_server_msg::Message::Action(action)) => Ok(ClientToServerMsg::Action {
216 action: action
217 .action
218 .ok_or_else(|| anyhow!("Missing action"))?
219 .try_into()?,
220 terminal_id: action.terminal_id,
221 client_id: action.client_id.map(|id| id as u16),
222 is_cli_client: action.is_cli_client,
223 }),
224 Some(client_to_server_msg::Message::Key(key)) => Ok(ClientToServerMsg::Key {
225 key: key.key.ok_or_else(|| anyhow!("Missing key"))?.try_into()?,
226 raw_bytes: key.raw_bytes.into_iter().map(|b| b as u8).collect(),
227 is_kitty_keyboard_protocol: key.is_kitty_keyboard_protocol,
228 }),
229 Some(client_to_server_msg::Message::ClientExited(_)) => {
230 Ok(ClientToServerMsg::ClientExited)
231 },
232 Some(client_to_server_msg::Message::KillSession(_)) => {
233 Ok(ClientToServerMsg::KillSession)
234 },
235 Some(client_to_server_msg::Message::ConnStatus(_)) => Ok(ClientToServerMsg::ConnStatus),
236 Some(client_to_server_msg::Message::WebServerStarted(web_server)) => {
237 Ok(ClientToServerMsg::WebServerStarted {
238 base_url: web_server.base_url,
239 })
240 },
241 Some(client_to_server_msg::Message::FailedToStartWebServer(failed)) => {
242 Ok(ClientToServerMsg::FailedToStartWebServer {
243 error: failed.error,
244 })
245 },
246 Some(client_to_server_msg::Message::SubscribeToPaneRenders(msg)) => {
247 let pane_ids: Result<Vec<PaneId>> =
248 msg.pane_ids.into_iter().map(|p| p.try_into()).collect();
249 Ok(ClientToServerMsg::SubscribeToPaneRenders {
250 pane_ids: pane_ids?,
251 scrollback: msg.scrollback.map(|s| s as usize),
252 ansi: msg.ansi,
253 })
254 },
255 Some(client_to_server_msg::Message::DesktopNotificationResponse(msg)) => {
256 Ok(ClientToServerMsg::DesktopNotificationResponse {
257 raw_bytes: msg.raw_bytes,
258 })
259 },
260 None => Err(anyhow!("Empty ClientToServerMsg message")),
261 }
262 }
263}
264
265impl From<ServerToClientMsg> for ProtoServerToClientMsg {
267 fn from(msg: ServerToClientMsg) -> Self {
268 let message = match msg {
269 ServerToClientMsg::Render { content } => {
270 server_to_client_msg::Message::Render(RenderMsg { content })
271 },
272 ServerToClientMsg::UnblockInputThread => {
273 server_to_client_msg::Message::UnblockInputThread(UnblockInputThreadMsg {})
274 },
275 ServerToClientMsg::Exit { exit_reason } => {
276 let (proto_exit_reason, payload) = match exit_reason {
277 ExitReason::Error(ref msg) => (ProtoExitReason::Error, Some(msg.clone())),
278 ExitReason::CustomExitStatus(status) => {
279 (ProtoExitReason::CustomExitStatus, Some(status.to_string()))
280 },
281 other => (ProtoExitReason::from(other), None),
282 };
283 server_to_client_msg::Message::Exit(ExitMsg {
284 exit_reason: proto_exit_reason as i32,
285 payload,
286 })
287 },
288 ServerToClientMsg::Connected => {
289 server_to_client_msg::Message::Connected(ConnectedMsg {})
290 },
291 ServerToClientMsg::Log { lines } => {
292 server_to_client_msg::Message::Log(LogMsg { lines })
293 },
294 ServerToClientMsg::LogError { lines } => {
295 server_to_client_msg::Message::LogError(LogErrorMsg { lines })
296 },
297 ServerToClientMsg::SwitchSession { connect_to_session } => {
298 server_to_client_msg::Message::SwitchSession(SwitchSessionMsg {
299 connect_to_session: Some(connect_to_session.into()),
300 })
301 },
302 ServerToClientMsg::UnblockCliPipeInput { pipe_name } => {
303 server_to_client_msg::Message::UnblockCliPipeInput(UnblockCliPipeInputMsg {
304 pipe_name,
305 })
306 },
307 ServerToClientMsg::CliPipeOutput { pipe_name, output } => {
308 server_to_client_msg::Message::CliPipeOutput(CliPipeOutputMsg { pipe_name, output })
309 },
310 ServerToClientMsg::QueryTerminalSize => {
311 server_to_client_msg::Message::QueryTerminalSize(QueryTerminalSizeMsg {})
312 },
313 ServerToClientMsg::StartWebServer => {
314 server_to_client_msg::Message::StartWebServer(StartWebServerMsg {})
315 },
316 ServerToClientMsg::RenamedSession { name } => {
317 server_to_client_msg::Message::RenamedSession(RenamedSessionMsg { name })
318 },
319 ServerToClientMsg::ConfigFileUpdated => {
320 server_to_client_msg::Message::ConfigFileUpdated(ConfigFileUpdatedMsg {})
321 },
322 ServerToClientMsg::PaneRenderUpdate {
323 pane_id,
324 viewport,
325 scrollback,
326 is_initial,
327 } => server_to_client_msg::Message::PaneRenderUpdate(PaneRenderUpdateMsg {
328 pane_id: Some(pane_id.into()),
329 viewport,
330 scrollback: scrollback.clone().unwrap_or_default(),
331 has_scrollback: scrollback.is_some(),
332 is_initial,
333 }),
334 ServerToClientMsg::SubscribedPaneClosed { pane_id } => {
335 server_to_client_msg::Message::SubscribedPaneClosed(SubscribedPaneClosedMsg {
336 pane_id: Some(pane_id.into()),
337 })
338 },
339 };
340
341 ProtoServerToClientMsg {
342 message: Some(message),
343 }
344 }
345}
346
347impl TryFrom<ProtoServerToClientMsg> for ServerToClientMsg {
349 type Error = anyhow::Error;
350
351 fn try_from(msg: ProtoServerToClientMsg) -> Result<Self> {
352 match msg.message {
353 Some(server_to_client_msg::Message::Render(render)) => Ok(ServerToClientMsg::Render {
354 content: render.content,
355 }),
356 Some(server_to_client_msg::Message::UnblockInputThread(_)) => {
357 Ok(ServerToClientMsg::UnblockInputThread)
358 },
359 Some(server_to_client_msg::Message::Exit(exit)) => {
360 let proto_exit_reason = ProtoExitReason::from_i32(exit.exit_reason)
361 .ok_or_else(|| anyhow!("Invalid exit_reason"))?;
362
363 let exit_reason = match proto_exit_reason {
364 ProtoExitReason::Error => {
365 let error_msg =
366 exit.payload.unwrap_or_else(|| "Protobuf error".to_string());
367 ExitReason::Error(error_msg)
368 },
369 ProtoExitReason::CustomExitStatus => {
370 let status_str = exit.payload.unwrap_or_else(|| "0".to_string());
371 let status = status_str
372 .parse::<i32>()
373 .map_err(|_| anyhow!("Invalid custom exit status: {}", status_str))?;
374 ExitReason::CustomExitStatus(status)
375 },
376 other => other.try_into()?,
377 };
378
379 Ok(ServerToClientMsg::Exit { exit_reason })
380 },
381 Some(server_to_client_msg::Message::Connected(_)) => Ok(ServerToClientMsg::Connected),
382 Some(server_to_client_msg::Message::Log(log)) => {
383 Ok(ServerToClientMsg::Log { lines: log.lines })
384 },
385 Some(server_to_client_msg::Message::LogError(log_error)) => {
386 Ok(ServerToClientMsg::LogError {
387 lines: log_error.lines,
388 })
389 },
390 Some(server_to_client_msg::Message::SwitchSession(switch)) => {
391 Ok(ServerToClientMsg::SwitchSession {
392 connect_to_session: switch
393 .connect_to_session
394 .ok_or_else(|| anyhow!("Missing connect_to_session"))?
395 .try_into()?,
396 })
397 },
398 Some(server_to_client_msg::Message::UnblockCliPipeInput(unblock)) => {
399 Ok(ServerToClientMsg::UnblockCliPipeInput {
400 pipe_name: unblock.pipe_name,
401 })
402 },
403 Some(server_to_client_msg::Message::CliPipeOutput(pipe_output)) => {
404 Ok(ServerToClientMsg::CliPipeOutput {
405 pipe_name: pipe_output.pipe_name,
406 output: pipe_output.output,
407 })
408 },
409 Some(server_to_client_msg::Message::QueryTerminalSize(_)) => {
410 Ok(ServerToClientMsg::QueryTerminalSize)
411 },
412 Some(server_to_client_msg::Message::StartWebServer(_)) => {
413 Ok(ServerToClientMsg::StartWebServer)
414 },
415 Some(server_to_client_msg::Message::RenamedSession(renamed)) => {
416 Ok(ServerToClientMsg::RenamedSession { name: renamed.name })
417 },
418 Some(server_to_client_msg::Message::ConfigFileUpdated(_)) => {
419 Ok(ServerToClientMsg::ConfigFileUpdated)
420 },
421 Some(server_to_client_msg::Message::PaneRenderUpdate(msg)) => {
422 let pane_id: PaneId = msg
423 .pane_id
424 .ok_or_else(|| anyhow!("Missing pane_id"))?
425 .try_into()?;
426 let scrollback = if msg.has_scrollback {
427 Some(msg.scrollback)
428 } else {
429 None
430 };
431 Ok(ServerToClientMsg::PaneRenderUpdate {
432 pane_id,
433 viewport: msg.viewport,
434 scrollback,
435 is_initial: msg.is_initial,
436 })
437 },
438 Some(server_to_client_msg::Message::SubscribedPaneClosed(msg)) => {
439 let pane_id: PaneId = msg
440 .pane_id
441 .ok_or_else(|| anyhow!("Missing pane_id"))?
442 .try_into()?;
443 Ok(ServerToClientMsg::SubscribedPaneClosed { pane_id })
444 },
445 None => Err(anyhow!("Empty ServerToClientMsg message")),
446 }
447 }
448}
449
450impl From<crate::pane_size::Size> for crate::client_server_contract::client_server_contract::Size {
452 fn from(size: crate::pane_size::Size) -> Self {
453 Self {
454 cols: size.cols as u32,
455 rows: size.rows as u32,
456 }
457 }
458}
459
460impl TryFrom<crate::client_server_contract::client_server_contract::Size>
461 for crate::pane_size::Size
462{
463 type Error = anyhow::Error;
464 fn try_from(size: crate::client_server_contract::client_server_contract::Size) -> Result<Self> {
465 Ok(Self {
466 rows: size.rows as usize,
467 cols: size.cols as usize,
468 })
469 }
470}
471
472impl From<PixelDimensions>
473 for crate::client_server_contract::client_server_contract::PixelDimensions
474{
475 fn from(pixel_dims: PixelDimensions) -> Self {
476 Self {
477 text_area_size: pixel_dims.text_area_size.map(|size| {
478 crate::client_server_contract::client_server_contract::SizeInPixels {
479 width: size.width as u32,
480 height: size.height as u32,
481 }
482 }),
483 character_cell_size: pixel_dims.character_cell_size.map(|size| {
484 crate::client_server_contract::client_server_contract::SizeInPixels {
485 width: size.width as u32,
486 height: size.height as u32,
487 }
488 }),
489 }
490 }
491}
492
493impl TryFrom<crate::client_server_contract::client_server_contract::PixelDimensions>
494 for PixelDimensions
495{
496 type Error = anyhow::Error;
497 fn try_from(
498 pixel_dims: crate::client_server_contract::client_server_contract::PixelDimensions,
499 ) -> Result<Self> {
500 Ok(Self {
501 text_area_size: pixel_dims
502 .text_area_size
503 .map(|size| crate::pane_size::SizeInPixels {
504 width: size.width as usize,
505 height: size.height as usize,
506 }),
507 character_cell_size: pixel_dims.character_cell_size.map(|size| {
508 crate::pane_size::SizeInPixels {
509 width: size.width as usize,
510 height: size.height as usize,
511 }
512 }),
513 })
514 }
515}
516
517impl From<PaneReference> for crate::client_server_contract::client_server_contract::PaneReference {
518 fn from(pane_ref: PaneReference) -> Self {
519 Self {
520 pane_id: pane_ref.pane_id,
521 is_plugin: pane_ref.is_plugin,
522 }
523 }
524}
525
526impl TryFrom<crate::client_server_contract::client_server_contract::PaneReference>
527 for PaneReference
528{
529 type Error = anyhow::Error;
530 fn try_from(
531 pane_ref: crate::client_server_contract::client_server_contract::PaneReference,
532 ) -> Result<Self> {
533 Ok(Self {
534 pane_id: pane_ref.pane_id,
535 is_plugin: pane_ref.is_plugin,
536 })
537 }
538}
539
540impl From<ColorRegister> for crate::client_server_contract::client_server_contract::ColorRegister {
541 fn from(color_reg: ColorRegister) -> Self {
542 Self {
543 index: color_reg.index as u32,
544 color: color_reg.color,
545 }
546 }
547}
548
549impl TryFrom<crate::client_server_contract::client_server_contract::ColorRegister>
550 for ColorRegister
551{
552 type Error = anyhow::Error;
553 fn try_from(
554 color_reg: crate::client_server_contract::client_server_contract::ColorRegister,
555 ) -> Result<Self> {
556 Ok(Self {
557 index: color_reg.index as usize,
558 color: color_reg.color,
559 })
560 }
561}
562
563impl From<crate::input::cli_assets::CliAssets>
564 for crate::client_server_contract::client_server_contract::CliAssets
565{
566 fn from(cli_assets: crate::input::cli_assets::CliAssets) -> Self {
567 Self {
568 config_file_path: cli_assets
569 .config_file_path
570 .map(|p| p.to_string_lossy().to_string()),
571 config_dir: cli_assets
572 .config_dir
573 .map(|p| p.to_string_lossy().to_string()),
574 should_ignore_config: cli_assets.should_ignore_config,
575 configuration_options: cli_assets.configuration_options.map(|o| o.into()),
576 layout: cli_assets.layout.map(|l| l.into()),
577 terminal_window_size: Some(cli_assets.terminal_window_size.into()),
578 data_dir: cli_assets.data_dir.map(|p| p.to_string_lossy().to_string()),
579 is_debug: cli_assets.is_debug,
580 max_panes: cli_assets.max_panes.map(|m| m as u32),
581 force_run_layout_commands: cli_assets.force_run_layout_commands,
582 cwd: cli_assets.cwd.map(|p| p.to_string_lossy().to_string()),
583 }
584 }
585}
586
587impl TryFrom<crate::client_server_contract::client_server_contract::CliAssets>
588 for crate::input::cli_assets::CliAssets
589{
590 type Error = anyhow::Error;
591 fn try_from(
592 cli_assets: crate::client_server_contract::client_server_contract::CliAssets,
593 ) -> Result<Self> {
594 Ok(Self {
595 config_file_path: cli_assets.config_file_path.map(PathBuf::from),
596 config_dir: cli_assets.config_dir.map(PathBuf::from),
597 should_ignore_config: cli_assets.should_ignore_config,
598 configuration_options: cli_assets
599 .configuration_options
600 .map(|o| o.try_into())
601 .transpose()?,
602 layout: cli_assets.layout.map(|l| l.try_into()).transpose()?,
603 terminal_window_size: cli_assets
604 .terminal_window_size
605 .ok_or_else(|| anyhow!("CliAssets missing terminal_window_size"))?
606 .try_into()?,
607 data_dir: cli_assets.data_dir.map(PathBuf::from),
608 is_debug: cli_assets.is_debug,
609 max_panes: cli_assets.max_panes.map(|m| m as usize),
610 force_run_layout_commands: cli_assets.force_run_layout_commands,
611 cwd: cli_assets.cwd.map(PathBuf::from),
612 })
613 }
614}
615
616impl From<crate::input::options::Options>
617 for crate::client_server_contract::client_server_contract::Options
618{
619 fn from(options: crate::input::options::Options) -> Self {
620 use crate::client_server_contract::client_server_contract::{
621 Clipboard as ProtoClipboard, OnForceClose as ProtoOnForceClose,
622 WebSharing as ProtoWebSharing,
623 };
624
625 Self {
626 simplified_ui: options.simplified_ui,
627 theme: options.theme,
628 default_mode: options.default_mode.map(|m| input_mode_to_proto_i32(m)),
629 default_shell: options
630 .default_shell
631 .map(|p| p.to_string_lossy().to_string()),
632 default_cwd: options.default_cwd.map(|p| p.to_string_lossy().to_string()),
633 default_layout: options
634 .default_layout
635 .map(|p| p.to_string_lossy().to_string()),
636 layout_dir: options.layout_dir.map(|p| p.to_string_lossy().to_string()),
637 theme_dir: options.theme_dir.map(|p| p.to_string_lossy().to_string()),
638 mouse_mode: options.mouse_mode,
639 pane_frames: options.pane_frames,
640 mirror_session: options.mirror_session,
641 on_force_close: options.on_force_close.map(|o| match o {
642 crate::input::options::OnForceClose::Quit => ProtoOnForceClose::Quit as i32,
643 crate::input::options::OnForceClose::Detach => ProtoOnForceClose::Detach as i32,
644 }),
645 scroll_buffer_size: options.scroll_buffer_size.map(|s| s as u32),
646 copy_command: options.copy_command,
647 copy_clipboard: options.copy_clipboard.map(|c| match c {
648 crate::input::options::Clipboard::System => ProtoClipboard::System as i32,
649 crate::input::options::Clipboard::Primary => ProtoClipboard::Primary as i32,
650 }),
651 copy_on_select: options.copy_on_select,
652 osc8_hyperlinks: options.osc8_hyperlinks,
653 scrollback_editor: options
654 .scrollback_editor
655 .map(|p| p.to_string_lossy().to_string()),
656 session_name: options.session_name,
657 attach_to_session: options.attach_to_session,
658 auto_layout: options.auto_layout,
659 session_serialization: options.session_serialization,
660 serialize_pane_viewport: options.serialize_pane_viewport,
661 scrollback_lines_to_serialize: options.scrollback_lines_to_serialize.map(|s| s as u32),
662 styled_underlines: options.styled_underlines,
663 serialization_interval: options.serialization_interval,
664 disable_session_metadata: options.disable_session_metadata,
665 support_kitty_keyboard_protocol: options.support_kitty_keyboard_protocol,
666 web_server: options.web_server,
667 web_sharing: options.web_sharing.map(|w| match w {
668 crate::data::WebSharing::On => ProtoWebSharing::On as i32,
669 crate::data::WebSharing::Off => ProtoWebSharing::Off as i32,
670 crate::data::WebSharing::Disabled => ProtoWebSharing::Disabled as i32,
671 }),
672 stacked_resize: options.stacked_resize,
673 show_startup_tips: options.show_startup_tips,
674 show_release_notes: options.show_release_notes,
675 advanced_mouse_actions: options.advanced_mouse_actions,
676 mouse_hover_effects: options.mouse_hover_effects,
677 web_server_ip: options.web_server_ip.map(|ip| ip.to_string()),
678 web_server_port: options.web_server_port.map(|p| p as u32),
679 web_server_cert: options
680 .web_server_cert
681 .map(|p| p.to_string_lossy().to_string()),
682 web_server_key: options
683 .web_server_key
684 .map(|p| p.to_string_lossy().to_string()),
685 enforce_https_for_localhost: options.enforce_https_for_localhost,
686 post_command_discovery_hook: options.post_command_discovery_hook,
687 client_async_worker_tasks: options.client_async_worker_tasks.map(|v| v as u64),
688 visual_bell: options.visual_bell,
689 focus_follows_mouse: options.focus_follows_mouse,
690 mouse_click_through: options.mouse_click_through,
691 }
692 }
693}
694
695impl TryFrom<crate::client_server_contract::client_server_contract::Options>
696 for crate::input::options::Options
697{
698 type Error = anyhow::Error;
699 fn try_from(
700 options: crate::client_server_contract::client_server_contract::Options,
701 ) -> Result<Self> {
702 use crate::client_server_contract::client_server_contract::{
703 Clipboard as ProtoClipboard, OnForceClose as ProtoOnForceClose,
704 WebSharing as ProtoWebSharing,
705 };
706
707 Ok(Self {
708 simplified_ui: options.simplified_ui,
709 theme: options.theme,
710 default_mode: options
711 .default_mode
712 .map(|m| proto_i32_to_input_mode(m))
713 .transpose()?,
714 default_shell: options.default_shell.map(std::path::PathBuf::from),
715 default_cwd: options.default_cwd.map(std::path::PathBuf::from),
716 default_layout: options.default_layout.map(std::path::PathBuf::from),
717 layout_dir: options.layout_dir.map(std::path::PathBuf::from),
718 theme_dir: options.theme_dir.map(std::path::PathBuf::from),
719 mouse_mode: options.mouse_mode,
720 pane_frames: options.pane_frames,
721 mirror_session: options.mirror_session,
722 on_force_close: options
723 .on_force_close
724 .map(|o| match ProtoOnForceClose::from_i32(o) {
725 Some(ProtoOnForceClose::Quit) => Ok(crate::input::options::OnForceClose::Quit),
726 Some(ProtoOnForceClose::Detach) => {
727 Ok(crate::input::options::OnForceClose::Detach)
728 },
729 _ => Err(anyhow!("Invalid OnForceClose value: {}", o)),
730 })
731 .transpose()?,
732 scroll_buffer_size: options.scroll_buffer_size.map(|s| s as usize),
733 copy_command: options.copy_command,
734 copy_clipboard: options
735 .copy_clipboard
736 .map(|c| match ProtoClipboard::from_i32(c) {
737 Some(ProtoClipboard::System) => Ok(crate::input::options::Clipboard::System),
738 Some(ProtoClipboard::Primary) => Ok(crate::input::options::Clipboard::Primary),
739 _ => Err(anyhow!("Invalid Clipboard value: {}", c)),
740 })
741 .transpose()?,
742 copy_on_select: options.copy_on_select,
743 osc8_hyperlinks: options.osc8_hyperlinks,
744 scrollback_editor: options.scrollback_editor.map(std::path::PathBuf::from),
745 session_name: options.session_name,
746 attach_to_session: options.attach_to_session,
747 auto_layout: options.auto_layout,
748 session_serialization: options.session_serialization,
749 serialize_pane_viewport: options.serialize_pane_viewport,
750 scrollback_lines_to_serialize: options
751 .scrollback_lines_to_serialize
752 .map(|s| s as usize),
753 styled_underlines: options.styled_underlines,
754 serialization_interval: options.serialization_interval,
755 disable_session_metadata: options.disable_session_metadata,
756 support_kitty_keyboard_protocol: options.support_kitty_keyboard_protocol,
757 web_server: options.web_server,
758 web_sharing: options
759 .web_sharing
760 .map(|w| match ProtoWebSharing::from_i32(w) {
761 Some(ProtoWebSharing::On) => Ok(crate::data::WebSharing::On),
762 Some(ProtoWebSharing::Off) => Ok(crate::data::WebSharing::Off),
763 Some(ProtoWebSharing::Disabled) => Ok(crate::data::WebSharing::Disabled),
764 _ => Err(anyhow!("Invalid WebSharing value: {}", w)),
765 })
766 .transpose()?,
767 stacked_resize: options.stacked_resize,
768 show_startup_tips: options.show_startup_tips,
769 show_release_notes: options.show_release_notes,
770 advanced_mouse_actions: options.advanced_mouse_actions,
771 mouse_hover_effects: options.mouse_hover_effects,
772 web_server_ip: options
773 .web_server_ip
774 .map(|ip| ip.parse())
775 .transpose()
776 .map_err(|e| anyhow!("Invalid IP address: {}", e))?,
777 web_server_port: options.web_server_port.map(|p| p as u16),
778 web_server_cert: options.web_server_cert.map(std::path::PathBuf::from),
779 web_server_key: options.web_server_key.map(std::path::PathBuf::from),
780 enforce_https_for_localhost: options.enforce_https_for_localhost,
781 post_command_discovery_hook: options.post_command_discovery_hook,
782 client_async_worker_tasks: options.client_async_worker_tasks.map(|v| v as usize),
783 visual_bell: options.visual_bell,
784 focus_follows_mouse: options.focus_follows_mouse,
785 mouse_click_through: options.mouse_click_through,
786 })
787 }
788}
789
790impl From<crate::input::actions::Action>
792 for crate::client_server_contract::client_server_contract::Action
793{
794 fn from(action: crate::input::actions::Action) -> Self {
795 use crate::client_server_contract::client_server_contract::{
796 action::ActionType,
797 AreFloatingPanesVisibleAction,
798 BreakPaneAction,
799 BreakPaneLeftAction,
800 BreakPaneRightAction,
801 ChangeFloatingPaneCoordinatesAction,
802 ClearScreenAction,
803 ClearScreenByPaneIdAction,
804 CliPipeAction,
805 CloseFocusAction,
806 CloseFocusByPaneIdAction,
807 ClosePluginPaneAction,
808 CloseTabAction,
809 CloseTabByIdAction,
810 CloseTerminalPaneAction,
811 ConfirmAction,
812 CopyAction,
813 CurrentTabInfoAction,
814 DenyAction,
815 DetachAction,
816 DumpLayoutAction,
817 DumpScreenAction,
818 EditFileAction,
819 EditScrollbackAction,
820 EditScrollbackByPaneIdAction,
821 FocusNextPaneAction,
822 FocusPaneByPaneIdAction,
823 FocusPluginPaneWithIdAction,
824 FocusPreviousPaneAction,
825 FocusTerminalPaneWithIdAction,
826 GoToNextTabAction,
827 GoToPreviousTabAction,
828 GoToTabAction,
829 GoToTabByIdAction,
830 GoToTabNameAction,
831 HalfPageScrollDownAction,
832 HalfPageScrollDownByPaneIdAction,
833 HalfPageScrollUpAction,
834 HalfPageScrollUpByPaneIdAction,
835 HideFloatingPanesAction,
836 KeybindPipeAction,
837 LaunchOrFocusPluginAction,
838 LaunchPluginAction,
839 ListClientsAction,
840 ListPanesAction,
841 ListTabsAction,
842 MouseEventAction,
843 MoveFocusAction,
844 MoveFocusOrTabAction,
845 MovePaneAction,
846 MovePaneBackwardsAction,
847 MovePaneBackwardsByPaneIdAction,
848 MovePaneByPaneIdAction,
849 MoveTabAction,
850 MoveTabByTabIdAction,
851 NewBlockingPaneAction,
852 NewFloatingPaneAction,
853 NewFloatingPluginPaneAction,
854 NewInPlacePaneAction,
855 NewInPlacePluginPaneAction,
856 NewPaneAction,
857 NewStackedPaneAction,
858 NewTabAction,
859 NewTiledPaneAction,
860 NewTiledPluginPaneAction,
861 NextSwapLayoutAction,
862 NextSwapLayoutByTabIdAction,
863 NoOpAction,
864 OverrideLayoutAction,
865 PageScrollDownAction,
866 PageScrollDownByPaneIdAction,
867 PageScrollUpAction,
868 PageScrollUpByPaneIdAction,
869 PaneIdWithPlugin,
870 PaneNameInputAction,
871 PasteAction,
872 PreviousSwapLayoutAction,
873 PreviousSwapLayoutByTabIdAction,
874 QueryTabNamesAction,
875 QuitAction,
876 RenamePaneByPaneIdAction,
877 RenamePluginPaneAction,
878 RenameSessionAction,
879 RenameTabAction,
880 RenameTabByIdAction,
881 RenameTerminalPaneAction,
882 ResizeAction,
883 ResizeByPaneIdAction,
884 RunAction,
885 SaveSessionAction,
886 ScrollDownAction,
887 ScrollDownAtAction,
888 ScrollDownByPaneIdAction,
889 ScrollToBottomAction,
890 ScrollToBottomByPaneIdAction,
891 ScrollToTopAction,
892 ScrollToTopByPaneIdAction,
893 ScrollUpAction,
894 ScrollUpAtAction,
895 ScrollUpByPaneIdAction,
897 SearchAction,
898 SearchInputAction,
899 SearchToggleOptionAction,
900 SetPaneBorderlessAction,
901 SetPaneColorAction,
902 ShowFloatingPanesAction,
903 SkipConfirmAction,
904 StackPanesAction,
905 StartOrReloadPluginAction,
906 SwitchFocusAction,
907 SwitchModeForAllClientsAction,
908 SwitchSessionAction,
909 SwitchToModeAction,
910 TabNameInputAction,
911 ToggleActiveSyncTabAction,
912 ToggleActiveSyncTabByTabIdAction,
913 ToggleFloatingPanesAction,
914 ToggleFloatingPanesByTabIdAction,
915 ToggleFocusFullscreenAction,
916 ToggleFullscreenByPaneIdAction,
917 ToggleGroupMarkingAction,
918 ToggleMouseModeAction,
919 TogglePaneBorderlessAction,
920 TogglePaneEmbedOrFloatingAction,
921 TogglePaneEmbedOrFloatingByPaneIdAction,
922 TogglePaneFramesAction,
923 TogglePaneInGroupAction,
924 TogglePanePinnedAction,
925 TogglePanePinnedByPaneIdAction,
926 ToggleTabAction,
927 UndoRenamePaneAction,
928 UndoRenamePaneByPaneIdAction,
929 UndoRenameTabAction,
930 UndoRenameTabByTabIdAction,
932 WriteAction,
933 WriteCharsAction,
934 WriteCharsToPaneIdAction,
935 WriteToPaneIdAction,
936 };
937 use std::collections::HashMap;
938
939 let action_type = match action {
940 crate::input::actions::Action::Quit => ActionType::Quit(QuitAction {}),
941 crate::input::actions::Action::Write {
942 key_with_modifier,
943 bytes,
944 is_kitty_keyboard_protocol,
945 } => ActionType::Write(WriteAction {
946 key_with_modifier: key_with_modifier.map(|k| k.into()),
947 bytes: bytes.into_iter().map(|b| b as u32).collect(),
948 is_kitty_keyboard_protocol,
949 }),
950 crate::input::actions::Action::WriteChars { chars } => {
951 ActionType::WriteChars(WriteCharsAction { chars })
952 },
953 crate::input::actions::Action::WriteToPaneId { bytes, pane_id } => {
954 ActionType::WriteToPaneId(WriteToPaneIdAction {
955 pane_id: Some(pane_id.into()),
956 bytes: bytes.into_iter().map(|b| b as u32).collect(),
957 })
958 },
959 crate::input::actions::Action::WriteCharsToPaneId { chars, pane_id } => {
960 ActionType::WriteCharsToPaneId(WriteCharsToPaneIdAction {
961 pane_id: Some(pane_id.into()),
962 chars,
963 })
964 },
965 crate::input::actions::Action::Paste { chars, pane_id } => {
966 ActionType::Paste(PasteAction {
967 chars,
968 pane_id: pane_id.map(|p| p.into()),
969 })
970 },
971 crate::input::actions::Action::SwitchToMode { input_mode } => {
972 ActionType::SwitchToMode(SwitchToModeAction {
973 input_mode: input_mode_to_proto_i32(input_mode),
974 })
975 },
976 crate::input::actions::Action::SwitchModeForAllClients { input_mode } => {
977 ActionType::SwitchModeForAllClients(SwitchModeForAllClientsAction {
978 input_mode: input_mode_to_proto_i32(input_mode),
979 })
980 },
981 crate::input::actions::Action::Resize { resize, direction } => {
982 ActionType::Resize(ResizeAction {
983 resize: resize_to_proto_i32(resize),
984 direction: direction.map(|d| direction_to_proto_i32(d)),
985 })
986 },
987 crate::input::actions::Action::FocusNextPane => {
988 ActionType::FocusNextPane(FocusNextPaneAction {})
989 },
990 crate::input::actions::Action::FocusPreviousPane => {
991 ActionType::FocusPreviousPane(FocusPreviousPaneAction {})
992 },
993 crate::input::actions::Action::SwitchFocus => {
994 ActionType::SwitchFocus(SwitchFocusAction {})
995 },
996 crate::input::actions::Action::MoveFocus { direction } => {
997 ActionType::MoveFocus(MoveFocusAction {
998 direction: direction_to_proto_i32(direction),
999 })
1000 },
1001 crate::input::actions::Action::MoveFocusOrTab { direction } => {
1002 ActionType::MoveFocusOrTab(MoveFocusOrTabAction {
1003 direction: direction_to_proto_i32(direction),
1004 })
1005 },
1006 crate::input::actions::Action::MovePane { direction } => {
1007 ActionType::MovePane(MovePaneAction {
1008 direction: direction.map(|d| direction_to_proto_i32(d)),
1009 })
1010 },
1011 crate::input::actions::Action::MovePaneBackwards => {
1012 ActionType::MovePaneBackwards(MovePaneBackwardsAction {})
1013 },
1014 crate::input::actions::Action::ClearScreen => {
1015 ActionType::ClearScreen(ClearScreenAction {})
1016 },
1017 crate::input::actions::Action::DumpScreen {
1018 file_path,
1019 include_scrollback,
1020 pane_id,
1021 ansi,
1022 } => {
1023 let dump_to_stdout = file_path.is_none();
1024 ActionType::DumpScreen(DumpScreenAction {
1025 file_path: file_path.unwrap_or_default(),
1026 include_scrollback,
1027 pane_id: pane_id.map(|p| p.into()),
1028 dump_to_stdout,
1029 ansi,
1030 })
1031 },
1032 crate::input::actions::Action::DumpLayout => {
1033 ActionType::DumpLayout(DumpLayoutAction {})
1034 },
1035 crate::input::actions::Action::EditScrollback { ansi } => {
1036 ActionType::EditScrollback(EditScrollbackAction { ansi })
1037 },
1038 crate::input::actions::Action::ScrollUp => ActionType::ScrollUp(ScrollUpAction {}),
1039 crate::input::actions::Action::ScrollUpAt { position } => {
1040 ActionType::ScrollUpAt(ScrollUpAtAction {
1041 position: Some(position.into()),
1042 })
1043 },
1044 crate::input::actions::Action::ScrollDown => {
1045 ActionType::ScrollDown(ScrollDownAction {})
1046 },
1047 crate::input::actions::Action::ScrollDownAt { position } => {
1048 ActionType::ScrollDownAt(ScrollDownAtAction {
1049 position: Some(position.into()),
1050 })
1051 },
1052 crate::input::actions::Action::ScrollToBottom => {
1053 ActionType::ScrollToBottom(ScrollToBottomAction {})
1054 },
1055 crate::input::actions::Action::ScrollToTop => {
1056 ActionType::ScrollToTop(ScrollToTopAction {})
1057 },
1058 crate::input::actions::Action::PageScrollUp => {
1059 ActionType::PageScrollUp(PageScrollUpAction {})
1060 },
1061 crate::input::actions::Action::PageScrollDown => {
1062 ActionType::PageScrollDown(PageScrollDownAction {})
1063 },
1064 crate::input::actions::Action::HalfPageScrollUp => {
1065 ActionType::HalfPageScrollUp(HalfPageScrollUpAction {})
1066 },
1067 crate::input::actions::Action::HalfPageScrollDown => {
1068 ActionType::HalfPageScrollDown(HalfPageScrollDownAction {})
1069 },
1070 crate::input::actions::Action::ToggleFocusFullscreen => {
1071 ActionType::ToggleFocusFullscreen(ToggleFocusFullscreenAction {})
1072 },
1073 crate::input::actions::Action::TogglePaneFrames => {
1074 ActionType::TogglePaneFrames(TogglePaneFramesAction {})
1075 },
1076 crate::input::actions::Action::ToggleActiveSyncTab => {
1077 ActionType::ToggleActiveSyncTab(ToggleActiveSyncTabAction {})
1078 },
1079 crate::input::actions::Action::NewPane {
1080 direction,
1081 pane_name,
1082 start_suppressed,
1083 } => ActionType::NewPane(NewPaneAction {
1084 direction: direction.map(|d| direction_to_proto_i32(d)),
1085 pane_name,
1086 start_suppressed,
1087 near_current_pane: false,
1088 }),
1089 crate::input::actions::Action::EditFile {
1090 payload,
1091 direction,
1092 floating,
1093 in_place,
1094 close_replaced_pane,
1095 start_suppressed,
1096 coordinates,
1097 near_current_pane,
1098 tab_id,
1099 ..
1100 } => ActionType::EditFile(EditFileAction {
1101 payload: Some(payload.into()),
1102 direction: direction.map(|d| direction_to_proto_i32(d)),
1103 floating,
1104 in_place,
1105 close_replaced_pane,
1106 start_suppressed,
1107 coordinates: coordinates.map(|c| c.into()),
1108 near_current_pane,
1109 tab_id: tab_id.map(|t| t as u32),
1110 }),
1111 crate::input::actions::Action::NewFloatingPane {
1112 command,
1113 pane_name,
1114 coordinates,
1115 near_current_pane,
1116 tab_id,
1117 ..
1118 } => ActionType::NewFloatingPane(NewFloatingPaneAction {
1119 command: command.map(|c| c.into()),
1120 pane_name,
1121 coordinates: coordinates.map(|c| c.into()),
1122 near_current_pane,
1123 tab_id: tab_id.map(|t| t as u32),
1124 }),
1125 crate::input::actions::Action::NewTiledPane {
1126 direction,
1127 command,
1128 pane_name,
1129 near_current_pane,
1130 borderless,
1131 tab_id,
1132 ..
1133 } => ActionType::NewTiledPane(NewTiledPaneAction {
1134 direction: direction.map(|d| direction_to_proto_i32(d)),
1135 command: command.map(|c| c.into()),
1136 pane_name,
1137 near_current_pane,
1138 borderless,
1139 tab_id: tab_id.map(|t| t as u32),
1140 }),
1141 crate::input::actions::Action::NewInPlacePane {
1142 command,
1143 pane_name,
1144 near_current_pane,
1145 pane_id_to_replace,
1146 close_replaced_pane,
1147 tab_id,
1148 ..
1149 } => ActionType::NewInPlacePane(NewInPlacePaneAction {
1150 command: command.map(|c| c.into()),
1151 pane_name,
1152 near_current_pane,
1153 pane_id_to_replace: pane_id_to_replace.and_then(|p| p.try_into().ok()),
1154 close_replaced_pane,
1155 tab_id: tab_id.map(|t| t as u32),
1156 }),
1157 crate::input::actions::Action::NewStackedPane {
1158 command,
1159 pane_name,
1160 near_current_pane,
1161 tab_id,
1162 ..
1163 } => ActionType::NewStackedPane(NewStackedPaneAction {
1164 command: command.map(|c| c.into()),
1165 pane_name,
1166 near_current_pane,
1167 tab_id: tab_id.map(|t| t as u32),
1168 }),
1169 crate::input::actions::Action::NewBlockingPane {
1170 placement,
1171 pane_name,
1172 command,
1173 unblock_condition,
1174 near_current_pane,
1175 tab_id,
1176 ..
1177 } => ActionType::NewBlockingPane(NewBlockingPaneAction {
1178 placement: Some(placement.into()),
1179 pane_name,
1180 command: command.map(|c| c.into()),
1181 unblock_condition: unblock_condition.map(|c| unblock_condition_to_proto_i32(c)),
1182 near_current_pane,
1183 tab_id: tab_id.map(|t| t as u32),
1184 }),
1185 crate::input::actions::Action::TogglePaneEmbedOrFloating => {
1186 ActionType::TogglePaneEmbedOrFloating(TogglePaneEmbedOrFloatingAction {})
1187 },
1188 crate::input::actions::Action::ToggleFloatingPanes => {
1189 ActionType::ToggleFloatingPanes(ToggleFloatingPanesAction {})
1190 },
1191 crate::input::actions::Action::ShowFloatingPanes { tab_id } => {
1192 ActionType::ShowFloatingPanes(ShowFloatingPanesAction {
1193 tab_id: tab_id.map(|id| id as u32),
1194 })
1195 },
1196 crate::input::actions::Action::HideFloatingPanes { tab_id } => {
1197 ActionType::HideFloatingPanes(HideFloatingPanesAction {
1198 tab_id: tab_id.map(|id| id as u32),
1199 })
1200 },
1201 crate::input::actions::Action::AreFloatingPanesVisible { tab_id } => {
1202 ActionType::AreFloatingPanesVisible(AreFloatingPanesVisibleAction {
1203 tab_id: tab_id.map(|id| id as u32),
1204 })
1205 },
1206 crate::input::actions::Action::CloseFocus => {
1207 ActionType::CloseFocus(CloseFocusAction {})
1208 },
1209 crate::input::actions::Action::PaneNameInput { input } => {
1210 ActionType::PaneNameInput(PaneNameInputAction {
1211 input: input.into_iter().map(|b| b as u32).collect(),
1212 })
1213 },
1214 crate::input::actions::Action::UndoRenamePane => {
1215 ActionType::UndoRenamePane(UndoRenamePaneAction {})
1216 },
1217 crate::input::actions::Action::NewTab {
1218 tiled_layout,
1219 floating_layouts,
1220 swap_tiled_layouts,
1221 swap_floating_layouts,
1222 tab_name,
1223 should_change_focus_to_new_tab,
1224 cwd,
1225 initial_panes,
1226 first_pane_unblock_condition,
1227 } => ActionType::NewTab(NewTabAction {
1228 tiled_layout: tiled_layout.map(|l| l.into()),
1229 floating_layouts: floating_layouts.into_iter().map(|l| l.into()).collect(),
1230 swap_tiled_layouts: swap_tiled_layouts
1231 .map(|layouts| layouts.into_iter().map(|l| l.into()).collect())
1232 .unwrap_or_default(),
1233 swap_floating_layouts: swap_floating_layouts
1234 .map(|layouts| layouts.into_iter().map(|l| l.into()).collect())
1235 .unwrap_or_default(),
1236 tab_name,
1237 should_change_focus_to_new_tab,
1238 cwd: cwd.map(|p| p.to_string_lossy().to_string()),
1239 initial_panes: initial_panes
1240 .map(|panes| panes.into_iter().map(|p| p.into()).collect())
1241 .unwrap_or_default(),
1242 first_pane_unblock_condition: first_pane_unblock_condition
1243 .map(|c| unblock_condition_to_proto_i32(c)),
1244 }),
1245 crate::input::actions::Action::NoOp => ActionType::NoOp(NoOpAction {}),
1246 crate::input::actions::Action::GoToNextTab => {
1247 ActionType::GoToNextTab(GoToNextTabAction {})
1248 },
1249 crate::input::actions::Action::GoToPreviousTab => {
1250 ActionType::GoToPreviousTab(GoToPreviousTabAction {})
1251 },
1252 crate::input::actions::Action::CloseTab => ActionType::CloseTab(CloseTabAction {}),
1253 crate::input::actions::Action::GoToTab { index } => {
1254 ActionType::GoToTab(GoToTabAction { index })
1255 },
1256 crate::input::actions::Action::GoToTabName { name, create } => {
1257 ActionType::GoToTabName(GoToTabNameAction { name, create })
1258 },
1259 crate::input::actions::Action::ToggleTab => ActionType::ToggleTab(ToggleTabAction {}),
1260 crate::input::actions::Action::TabNameInput { input } => {
1261 ActionType::TabNameInput(TabNameInputAction {
1262 input: input.into_iter().map(|b| b as u32).collect(),
1263 })
1264 },
1265 crate::input::actions::Action::UndoRenameTab => {
1266 ActionType::UndoRenameTab(UndoRenameTabAction {})
1267 },
1268 crate::input::actions::Action::MoveTab { direction } => {
1269 ActionType::MoveTab(MoveTabAction {
1270 direction: direction_to_proto_i32(direction),
1271 })
1272 },
1273 crate::input::actions::Action::Run {
1274 command,
1275 near_current_pane,
1276 } => ActionType::Run(RunAction {
1277 command: Some(command.into()),
1278 near_current_pane,
1279 }),
1280 crate::input::actions::Action::Detach => ActionType::Detach(DetachAction {}),
1281 crate::input::actions::Action::SwitchSession {
1282 name,
1283 tab_position,
1284 pane_id,
1285 layout,
1286 cwd,
1287 } => ActionType::SwitchSession(SwitchSessionAction {
1288 name: name.clone(),
1289 tab_position: tab_position.map(|p| p as u32),
1290 pane_id: pane_id.map(|(id, is_plugin)| PaneIdWithPlugin {
1291 pane_id: id,
1292 is_plugin: is_plugin,
1293 }),
1294 layout: layout.as_ref().map(|l| l.clone().into()),
1295 cwd: cwd.as_ref().map(|p| p.to_string_lossy().to_string()),
1296 }),
1297 crate::input::actions::Action::LaunchOrFocusPlugin {
1298 plugin,
1299 should_float,
1300 move_to_focused_tab,
1301 should_open_in_place,
1302 close_replaced_pane,
1303 skip_cache,
1304 tab_id,
1305 ..
1306 } => ActionType::LaunchOrFocusPlugin(LaunchOrFocusPluginAction {
1307 plugin: Some(plugin.into()),
1308 should_float,
1309 move_to_focused_tab,
1310 should_open_in_place,
1311 close_replaced_pane,
1312 skip_cache,
1313 tab_id: tab_id.map(|t| t as u32),
1314 }),
1315 crate::input::actions::Action::LaunchPlugin {
1316 plugin,
1317 should_float,
1318 should_open_in_place,
1319 close_replaced_pane,
1320 skip_cache,
1321 cwd,
1322 tab_id,
1323 ..
1324 } => ActionType::LaunchPlugin(LaunchPluginAction {
1325 plugin: Some(plugin.into()),
1326 should_float,
1327 should_open_in_place,
1328 close_replaced_pane,
1329 skip_cache,
1330 cwd: cwd.map(|p| p.to_string_lossy().to_string()),
1331 tab_id: tab_id.map(|t| t as u32),
1332 }),
1333 crate::input::actions::Action::MouseEvent { event } => {
1334 ActionType::MouseEvent(MouseEventAction {
1335 event: Some(event.into()),
1336 })
1337 },
1338 crate::input::actions::Action::Copy => ActionType::Copy(CopyAction {}),
1339 crate::input::actions::Action::Confirm => ActionType::Confirm(ConfirmAction {}),
1340 crate::input::actions::Action::Deny => ActionType::Deny(DenyAction {}),
1341 crate::input::actions::Action::SkipConfirm { action } => {
1342 ActionType::SkipConfirm(Box::new(SkipConfirmAction {
1343 action: Some(Box::new((*action).into())),
1344 }))
1345 },
1346 crate::input::actions::Action::SearchInput { input } => {
1347 ActionType::SearchInput(SearchInputAction {
1348 input: input.into_iter().map(|b| b as u32).collect(),
1349 })
1350 },
1351 crate::input::actions::Action::Search { direction } => {
1352 ActionType::Search(SearchAction {
1353 direction: search_direction_to_proto_i32(direction),
1354 })
1355 },
1356 crate::input::actions::Action::SearchToggleOption { option } => {
1357 ActionType::SearchToggleOption(SearchToggleOptionAction {
1358 option: search_option_to_proto_i32(option),
1359 })
1360 },
1361 crate::input::actions::Action::ToggleMouseMode => {
1362 ActionType::ToggleMouseMode(ToggleMouseModeAction {})
1363 },
1364 crate::input::actions::Action::PreviousSwapLayout => {
1365 ActionType::PreviousSwapLayout(PreviousSwapLayoutAction {})
1366 },
1367 crate::input::actions::Action::NextSwapLayout => {
1368 ActionType::NextSwapLayout(NextSwapLayoutAction {})
1369 },
1370 crate::input::actions::Action::OverrideLayout {
1371 tabs,
1372 retain_existing_terminal_panes,
1373 retain_existing_plugin_panes,
1374 apply_only_to_active_tab,
1375 } => ActionType::OverrideLayout(OverrideLayoutAction {
1376 tabs: tabs.into_iter().map(|t| t.into()).collect(),
1377 retain_existing_terminal_panes,
1378 retain_existing_plugin_panes,
1379 apply_only_to_active_tab,
1380 }),
1381 crate::input::actions::Action::QueryTabNames => {
1382 ActionType::QueryTabNames(QueryTabNamesAction {})
1383 },
1384 crate::input::actions::Action::NewTiledPluginPane {
1385 plugin,
1386 pane_name,
1387 skip_cache,
1388 cwd,
1389 tab_id,
1390 ..
1391 } => ActionType::NewTiledPluginPane(NewTiledPluginPaneAction {
1392 plugin: Some(plugin.into()),
1393 pane_name,
1394 skip_cache,
1395 cwd: cwd.map(|p| p.to_string_lossy().to_string()),
1396 tab_id: tab_id.map(|t| t as u32),
1397 }),
1398 crate::input::actions::Action::NewFloatingPluginPane {
1399 plugin,
1400 pane_name,
1401 skip_cache,
1402 cwd,
1403 coordinates,
1404 tab_id,
1405 ..
1406 } => ActionType::NewFloatingPluginPane(NewFloatingPluginPaneAction {
1407 plugin: Some(plugin.into()),
1408 pane_name,
1409 skip_cache,
1410 cwd: cwd.map(|p| p.to_string_lossy().to_string()),
1411 coordinates: coordinates.map(|c| c.into()),
1412 tab_id: tab_id.map(|t| t as u32),
1413 }),
1414 crate::input::actions::Action::NewInPlacePluginPane {
1415 plugin,
1416 pane_name,
1417 skip_cache,
1418 close_replaced_pane,
1419 tab_id,
1420 ..
1421 } => ActionType::NewInPlacePluginPane(NewInPlacePluginPaneAction {
1422 plugin: Some(plugin.into()),
1423 pane_name,
1424 skip_cache,
1425 close_replaced_pane,
1426 tab_id: tab_id.map(|t| t as u32),
1427 }),
1428 crate::input::actions::Action::StartOrReloadPlugin { plugin } => {
1429 ActionType::StartOrReloadPlugin(StartOrReloadPluginAction {
1430 plugin: Some(plugin.into()),
1431 })
1432 },
1433 crate::input::actions::Action::CloseTerminalPane { pane_id } => {
1434 ActionType::CloseTerminalPane(CloseTerminalPaneAction { pane_id })
1435 },
1436 crate::input::actions::Action::ClosePluginPane { pane_id } => {
1437 ActionType::ClosePluginPane(ClosePluginPaneAction { pane_id })
1438 },
1439 crate::input::actions::Action::FocusTerminalPaneWithId {
1440 pane_id,
1441 should_float_if_hidden,
1442 should_be_in_place_if_hidden,
1443 } => ActionType::FocusTerminalPaneWithId(FocusTerminalPaneWithIdAction {
1444 pane_id,
1445 should_float_if_hidden,
1446 should_be_in_place_if_hidden,
1447 }),
1448 crate::input::actions::Action::FocusPluginPaneWithId {
1449 pane_id,
1450 should_float_if_hidden,
1451 should_be_in_place_if_hidden,
1452 } => ActionType::FocusPluginPaneWithId(FocusPluginPaneWithIdAction {
1453 pane_id,
1454 should_float_if_hidden,
1455 should_be_in_place_if_hidden,
1456 }),
1457 crate::input::actions::Action::RenameTerminalPane { pane_id, name } => {
1458 ActionType::RenameTerminalPane(RenameTerminalPaneAction {
1459 pane_id,
1460 name: name.into_iter().map(|b| b as u32).collect(),
1461 })
1462 },
1463 crate::input::actions::Action::RenamePluginPane { pane_id, name } => {
1464 ActionType::RenamePluginPane(RenamePluginPaneAction {
1465 pane_id,
1466 name: name.into_iter().map(|b| b as u32).collect(),
1467 })
1468 },
1469 crate::input::actions::Action::RenameTab { tab_index, name } => {
1470 ActionType::RenameTab(RenameTabAction {
1471 tab_index,
1472 name: name.into_iter().map(|b| b as u32).collect(),
1473 })
1474 },
1475 crate::input::actions::Action::GoToTabById { id } => {
1476 ActionType::GoToTabById(GoToTabByIdAction { id })
1477 },
1478 crate::input::actions::Action::CloseTabById { id } => {
1479 ActionType::CloseTabById(CloseTabByIdAction { id })
1480 },
1481 crate::input::actions::Action::RenameTabById { id, name } => {
1482 ActionType::RenameTabById(RenameTabByIdAction { id, name })
1483 },
1484 crate::input::actions::Action::BreakPane => ActionType::BreakPane(BreakPaneAction {}),
1485 crate::input::actions::Action::BreakPaneRight => {
1486 ActionType::BreakPaneRight(BreakPaneRightAction {})
1487 },
1488 crate::input::actions::Action::BreakPaneLeft => {
1489 ActionType::BreakPaneLeft(BreakPaneLeftAction {})
1490 },
1491 crate::input::actions::Action::RenameSession { name } => {
1492 ActionType::RenameSession(RenameSessionAction { name })
1493 },
1494 crate::input::actions::Action::CliPipe {
1495 pipe_id,
1496 name,
1497 payload,
1498 args,
1499 plugin,
1500 configuration,
1501 launch_new,
1502 skip_cache,
1503 floating,
1504 in_place,
1505 cwd,
1506 pane_title,
1507 } => ActionType::CliPipe(CliPipeAction {
1508 pipe_id,
1509 name,
1510 payload,
1511 args: args
1512 .map(|a| a.into_iter().collect::<HashMap<_, _>>())
1513 .unwrap_or_default(),
1514 plugin,
1515 configuration: configuration
1516 .map(|c| c.into_iter().collect::<HashMap<_, _>>())
1517 .unwrap_or_default(),
1518 launch_new,
1519 skip_cache,
1520 floating,
1521 in_place,
1522 cwd: cwd.map(|p| p.to_string_lossy().to_string()),
1523 pane_title,
1524 }),
1525 crate::input::actions::Action::KeybindPipe {
1526 name,
1527 payload,
1528 args,
1529 plugin,
1530 plugin_id,
1531 configuration,
1532 launch_new,
1533 skip_cache,
1534 floating,
1535 in_place,
1536 cwd,
1537 pane_title,
1538 } => ActionType::KeybindPipe(KeybindPipeAction {
1539 name,
1540 payload,
1541 args: args
1542 .map(|a| a.into_iter().collect::<HashMap<_, _>>())
1543 .unwrap_or_default(),
1544 plugin,
1545 plugin_id,
1546 configuration: configuration
1547 .map(|c| c.into_iter().collect::<HashMap<_, _>>())
1548 .unwrap_or_default(),
1549 launch_new,
1550 skip_cache,
1551 floating,
1552 in_place,
1553 cwd: cwd.map(|p| p.to_string_lossy().to_string()),
1554 pane_title,
1555 }),
1556 crate::input::actions::Action::ListClients => {
1557 ActionType::ListClients(ListClientsAction {})
1558 },
1559 crate::input::actions::Action::ListPanes {
1560 show_tab,
1561 show_command,
1562 show_state,
1563 show_geometry,
1564 show_all,
1565 output_json,
1566 } => ActionType::ListPanes(ListPanesAction {
1567 show_tab,
1568 show_command,
1569 show_state,
1570 show_geometry,
1571 show_all,
1572 output_json,
1573 }),
1574 crate::input::actions::Action::TogglePanePinned => {
1575 ActionType::TogglePanePinned(TogglePanePinnedAction {})
1576 },
1577 crate::input::actions::Action::StackPanes { pane_ids } => {
1578 ActionType::StackPanes(StackPanesAction {
1579 pane_ids: pane_ids.into_iter().map(|id| id.into()).collect(),
1580 })
1581 },
1582 crate::input::actions::Action::ChangeFloatingPaneCoordinates {
1583 pane_id,
1584 coordinates,
1585 } => ActionType::ChangeFloatingPaneCoordinates(ChangeFloatingPaneCoordinatesAction {
1586 pane_id: Some(pane_id.into()),
1587 coordinates: Some(coordinates.into()),
1588 }),
1589 crate::input::actions::Action::TogglePaneBorderless { pane_id } => {
1590 ActionType::TogglePaneBorderless(TogglePaneBorderlessAction {
1591 pane_id: Some(pane_id.into()),
1592 })
1593 },
1594 crate::input::actions::Action::SetPaneBorderless {
1595 pane_id,
1596 borderless,
1597 } => ActionType::SetPaneBorderless(SetPaneBorderlessAction {
1598 pane_id: Some(pane_id.into()),
1599 borderless,
1600 }),
1601 crate::input::actions::Action::TogglePaneInGroup => {
1602 ActionType::TogglePaneInGroup(TogglePaneInGroupAction {})
1603 },
1604 crate::input::actions::Action::ToggleGroupMarking => {
1605 ActionType::ToggleGroupMarking(ToggleGroupMarkingAction {})
1606 },
1607 crate::input::actions::Action::SaveSession => {
1608 ActionType::SaveSession(SaveSessionAction {})
1609 },
1610 crate::input::actions::Action::ListTabs {
1611 show_state,
1612 show_dimensions,
1613 show_panes,
1614 show_layout,
1615 show_all,
1616 output_json,
1617 } => ActionType::ListTabs(ListTabsAction {
1618 show_state,
1619 show_dimensions,
1620 show_panes,
1621 show_layout,
1622 show_all,
1623 output_json,
1624 }),
1625 crate::input::actions::Action::CurrentTabInfo { output_json } => {
1626 ActionType::CurrentTabInfo(CurrentTabInfoAction { output_json })
1627 },
1628 crate::input::actions::Action::SetPaneColor { pane_id, fg, bg } => {
1629 ActionType::SetPaneColor(SetPaneColorAction {
1630 pane_id: Some(pane_id.into()),
1631 fg,
1632 bg,
1633 })
1634 },
1635 crate::input::actions::Action::ScrollUpByPaneId { pane_id } => {
1637 ActionType::ScrollUpByPaneId(ScrollUpByPaneIdAction {
1638 pane_id: Some(pane_id.into()),
1639 })
1640 },
1641 crate::input::actions::Action::ScrollDownByPaneId { pane_id } => {
1642 ActionType::ScrollDownByPaneId(ScrollDownByPaneIdAction {
1643 pane_id: Some(pane_id.into()),
1644 })
1645 },
1646 crate::input::actions::Action::ScrollToTopByPaneId { pane_id } => {
1647 ActionType::ScrollToTopByPaneId(ScrollToTopByPaneIdAction {
1648 pane_id: Some(pane_id.into()),
1649 })
1650 },
1651 crate::input::actions::Action::ScrollToBottomByPaneId { pane_id } => {
1652 ActionType::ScrollToBottomByPaneId(ScrollToBottomByPaneIdAction {
1653 pane_id: Some(pane_id.into()),
1654 })
1655 },
1656 crate::input::actions::Action::PageScrollUpByPaneId { pane_id } => {
1657 ActionType::PageScrollUpByPaneId(PageScrollUpByPaneIdAction {
1658 pane_id: Some(pane_id.into()),
1659 })
1660 },
1661 crate::input::actions::Action::PageScrollDownByPaneId { pane_id } => {
1662 ActionType::PageScrollDownByPaneId(PageScrollDownByPaneIdAction {
1663 pane_id: Some(pane_id.into()),
1664 })
1665 },
1666 crate::input::actions::Action::HalfPageScrollUpByPaneId { pane_id } => {
1667 ActionType::HalfPageScrollUpByPaneId(HalfPageScrollUpByPaneIdAction {
1668 pane_id: Some(pane_id.into()),
1669 })
1670 },
1671 crate::input::actions::Action::HalfPageScrollDownByPaneId { pane_id } => {
1672 ActionType::HalfPageScrollDownByPaneId(HalfPageScrollDownByPaneIdAction {
1673 pane_id: Some(pane_id.into()),
1674 })
1675 },
1676 crate::input::actions::Action::ResizeByPaneId {
1677 pane_id,
1678 resize,
1679 direction,
1680 } => ActionType::ResizeByPaneId(ResizeByPaneIdAction {
1681 pane_id: Some(pane_id.into()),
1682 resize_action: Some(ResizeAction {
1683 resize: resize_to_proto_i32(resize),
1684 direction: direction.map(|d| direction_to_proto_i32(d)),
1685 }),
1686 }),
1687 crate::input::actions::Action::MovePaneByPaneId { pane_id, direction } => {
1688 ActionType::MovePaneByPaneId(MovePaneByPaneIdAction {
1689 pane_id: Some(pane_id.into()),
1690 direction: direction.map(|d| direction_to_proto_i32(d)),
1691 })
1692 },
1693 crate::input::actions::Action::MovePaneBackwardsByPaneId { pane_id } => {
1694 ActionType::MovePaneBackwardsByPaneId(MovePaneBackwardsByPaneIdAction {
1695 pane_id: Some(pane_id.into()),
1696 })
1697 },
1698 crate::input::actions::Action::ClearScreenByPaneId { pane_id } => {
1699 ActionType::ClearScreenByPaneId(ClearScreenByPaneIdAction {
1700 pane_id: Some(pane_id.into()),
1701 })
1702 },
1703 crate::input::actions::Action::EditScrollbackByPaneId { pane_id, ansi } => {
1704 ActionType::EditScrollbackByPaneId(EditScrollbackByPaneIdAction {
1705 pane_id: Some(pane_id.into()),
1706 ansi,
1707 })
1708 },
1709 crate::input::actions::Action::ToggleFocusFullscreenByPaneId { pane_id } => {
1710 ActionType::ToggleFullscreenByPaneId(ToggleFullscreenByPaneIdAction {
1711 pane_id: Some(pane_id.into()),
1712 })
1713 },
1714 crate::input::actions::Action::TogglePaneEmbedOrFloatingByPaneId { pane_id } => {
1715 ActionType::TogglePaneEmbedOrFloatingByPaneId(
1716 TogglePaneEmbedOrFloatingByPaneIdAction {
1717 pane_id: Some(pane_id.into()),
1718 },
1719 )
1720 },
1721 crate::input::actions::Action::CloseFocusByPaneId { pane_id } => {
1722 ActionType::CloseFocusByPaneId(CloseFocusByPaneIdAction {
1723 pane_id: Some(pane_id.into()),
1724 })
1725 },
1726 crate::input::actions::Action::RenamePaneByPaneId { pane_id, name } => {
1727 ActionType::RenamePaneByPaneId(RenamePaneByPaneIdAction {
1728 pane_id: pane_id.map(|id| id.into()),
1729 name,
1730 })
1731 },
1732 crate::input::actions::Action::UndoRenamePaneByPaneId { pane_id } => {
1733 ActionType::UndoRenamePaneByPaneId(UndoRenamePaneByPaneIdAction {
1734 pane_id: Some(pane_id.into()),
1735 })
1736 },
1737 crate::input::actions::Action::TogglePanePinnedByPaneId { pane_id } => {
1738 ActionType::TogglePanePinnedByPaneId(TogglePanePinnedByPaneIdAction {
1739 pane_id: Some(pane_id.into()),
1740 })
1741 },
1742 crate::input::actions::Action::FocusPaneByPaneId { pane_id } => {
1743 ActionType::FocusPaneByPaneId(FocusPaneByPaneIdAction {
1744 pane_id: Some(pane_id.into()),
1745 })
1746 },
1747 crate::input::actions::Action::UndoRenameTabByTabId { id } => {
1749 ActionType::UndoRenameTabByTabId(UndoRenameTabByTabIdAction { id })
1750 },
1751 crate::input::actions::Action::ToggleActiveSyncTabByTabId { id } => {
1752 ActionType::ToggleActiveSyncTabByTabId(ToggleActiveSyncTabByTabIdAction { id })
1753 },
1754 crate::input::actions::Action::ToggleFloatingPanesByTabId { id } => {
1755 ActionType::ToggleFloatingPanesByTabId(ToggleFloatingPanesByTabIdAction { id })
1756 },
1757 crate::input::actions::Action::PreviousSwapLayoutByTabId { id } => {
1758 ActionType::PreviousSwapLayoutByTabId(PreviousSwapLayoutByTabIdAction { id })
1759 },
1760 crate::input::actions::Action::NextSwapLayoutByTabId { id } => {
1761 ActionType::NextSwapLayoutByTabId(NextSwapLayoutByTabIdAction { id })
1762 },
1763 crate::input::actions::Action::MoveTabByTabId { id, direction } => {
1764 ActionType::MoveTabByTabId(MoveTabByTabIdAction {
1765 id,
1766 direction: direction_to_proto_i32(direction),
1767 })
1768 },
1769 };
1770
1771 Self {
1772 action_type: Some(action_type),
1773 }
1774 }
1775}
1776
1777impl TryFrom<crate::client_server_contract::client_server_contract::Action>
1778 for crate::input::actions::Action
1779{
1780 type Error = anyhow::Error;
1781 fn try_from(
1782 action: crate::client_server_contract::client_server_contract::Action,
1783 ) -> Result<Self> {
1784 use crate::client_server_contract::client_server_contract::action::ActionType;
1785
1786 let action_type = action
1787 .action_type
1788 .ok_or_else(|| anyhow!("Action missing action_type"))?;
1789
1790 match action_type {
1791 ActionType::Quit(_) => Ok(crate::input::actions::Action::Quit),
1792 ActionType::Write(write_action) => Ok(crate::input::actions::Action::Write {
1793 key_with_modifier: write_action
1794 .key_with_modifier
1795 .map(|k| k.try_into())
1796 .transpose()?,
1797 bytes: write_action.bytes.into_iter().map(|b| b as u8).collect(),
1798 is_kitty_keyboard_protocol: write_action.is_kitty_keyboard_protocol,
1799 }),
1800 ActionType::WriteChars(write_chars_action) => {
1801 Ok(crate::input::actions::Action::WriteChars {
1802 chars: write_chars_action.chars,
1803 })
1804 },
1805 ActionType::WriteToPaneId(write_to_pane_id_action) => {
1806 Ok(crate::input::actions::Action::WriteToPaneId {
1807 bytes: write_to_pane_id_action
1808 .bytes
1809 .into_iter()
1810 .map(|b| b as u8)
1811 .collect(),
1812 pane_id: write_to_pane_id_action
1813 .pane_id
1814 .ok_or_else(|| anyhow!("WriteToPaneId missing pane_id"))?
1815 .try_into()?,
1816 })
1817 },
1818 ActionType::WriteCharsToPaneId(write_chars_to_pane_id_action) => {
1819 Ok(crate::input::actions::Action::WriteCharsToPaneId {
1820 chars: write_chars_to_pane_id_action.chars,
1821 pane_id: write_chars_to_pane_id_action
1822 .pane_id
1823 .ok_or_else(|| anyhow!("WriteCharsToPaneId missing pane_id"))?
1824 .try_into()?,
1825 })
1826 },
1827 ActionType::Paste(paste_action) => Ok(crate::input::actions::Action::Paste {
1828 chars: paste_action.chars,
1829 pane_id: paste_action.pane_id.map(|p| p.try_into()).transpose()?,
1830 }),
1831 ActionType::SwitchToMode(switch_mode_action) => {
1832 Ok(crate::input::actions::Action::SwitchToMode {
1833 input_mode: proto_i32_to_input_mode(switch_mode_action.input_mode)?,
1834 })
1835 },
1836 ActionType::SwitchModeForAllClients(switch_mode_action) => {
1837 Ok(crate::input::actions::Action::SwitchModeForAllClients {
1838 input_mode: proto_i32_to_input_mode(switch_mode_action.input_mode)?,
1839 })
1840 },
1841 ActionType::Resize(resize_action) => Ok(crate::input::actions::Action::Resize {
1842 resize: proto_i32_to_resize(resize_action.resize)?,
1843 direction: resize_action
1844 .direction
1845 .map(|d| proto_i32_to_direction(d))
1846 .transpose()?,
1847 }),
1848 ActionType::FocusNextPane(_) => Ok(crate::input::actions::Action::FocusNextPane),
1849 ActionType::FocusPreviousPane(_) => {
1850 Ok(crate::input::actions::Action::FocusPreviousPane)
1851 },
1852 ActionType::SwitchFocus(_) => Ok(crate::input::actions::Action::SwitchFocus),
1853 ActionType::MoveFocus(move_focus_action) => {
1854 Ok(crate::input::actions::Action::MoveFocus {
1855 direction: proto_i32_to_direction(move_focus_action.direction)?,
1856 })
1857 },
1858 ActionType::MoveFocusOrTab(move_focus_action) => {
1859 Ok(crate::input::actions::Action::MoveFocusOrTab {
1860 direction: proto_i32_to_direction(move_focus_action.direction)?,
1861 })
1862 },
1863 ActionType::MovePane(move_pane_action) => Ok(crate::input::actions::Action::MovePane {
1864 direction: move_pane_action
1865 .direction
1866 .map(|d| proto_i32_to_direction(d))
1867 .transpose()?,
1868 }),
1869 ActionType::MovePaneBackwards(_) => {
1870 Ok(crate::input::actions::Action::MovePaneBackwards)
1871 },
1872 ActionType::ClearScreen(_) => Ok(crate::input::actions::Action::ClearScreen),
1873 ActionType::DumpScreen(dump_screen_action) => {
1874 let file_path = if dump_screen_action.dump_to_stdout {
1875 None
1876 } else {
1877 Some(dump_screen_action.file_path)
1878 };
1879 Ok(crate::input::actions::Action::DumpScreen {
1880 file_path,
1881 include_scrollback: dump_screen_action.include_scrollback,
1882 pane_id: dump_screen_action.pane_id.and_then(|p| p.try_into().ok()),
1883 ansi: dump_screen_action.ansi,
1884 })
1885 },
1886 ActionType::DumpLayout(_) => Ok(crate::input::actions::Action::DumpLayout),
1887 ActionType::SaveSession(_) => Ok(crate::input::actions::Action::SaveSession),
1888 ActionType::EditScrollback(edit_scrollback_action) => {
1889 Ok(crate::input::actions::Action::EditScrollback {
1890 ansi: edit_scrollback_action.ansi,
1891 })
1892 },
1893 ActionType::ScrollUp(_) => Ok(crate::input::actions::Action::ScrollUp),
1894 ActionType::ScrollUpAt(scroll_action) => {
1895 Ok(crate::input::actions::Action::ScrollUpAt {
1896 position: scroll_action
1897 .position
1898 .ok_or_else(|| anyhow!("ScrollUpAt missing position"))?
1899 .try_into()?,
1900 })
1901 },
1902 ActionType::ScrollDown(_) => Ok(crate::input::actions::Action::ScrollDown),
1903 ActionType::ScrollDownAt(scroll_action) => {
1904 Ok(crate::input::actions::Action::ScrollDownAt {
1905 position: scroll_action
1906 .position
1907 .ok_or_else(|| anyhow!("ScrollDownAt missing position"))?
1908 .try_into()?,
1909 })
1910 },
1911 ActionType::ScrollToBottom(_) => Ok(crate::input::actions::Action::ScrollToBottom),
1912 ActionType::ScrollToTop(_) => Ok(crate::input::actions::Action::ScrollToTop),
1913 ActionType::PageScrollUp(_) => Ok(crate::input::actions::Action::PageScrollUp),
1914 ActionType::PageScrollDown(_) => Ok(crate::input::actions::Action::PageScrollDown),
1915 ActionType::HalfPageScrollUp(_) => Ok(crate::input::actions::Action::HalfPageScrollUp),
1916 ActionType::HalfPageScrollDown(_) => {
1917 Ok(crate::input::actions::Action::HalfPageScrollDown)
1918 },
1919 ActionType::ToggleFocusFullscreen(_) => {
1920 Ok(crate::input::actions::Action::ToggleFocusFullscreen)
1921 },
1922 ActionType::TogglePaneFrames(_) => Ok(crate::input::actions::Action::TogglePaneFrames),
1923 ActionType::ToggleActiveSyncTab(_) => {
1924 Ok(crate::input::actions::Action::ToggleActiveSyncTab)
1925 },
1926 ActionType::NewPane(new_pane_action) => Ok(crate::input::actions::Action::NewPane {
1927 direction: new_pane_action
1928 .direction
1929 .map(|d| proto_i32_to_direction(d))
1930 .transpose()?,
1931 pane_name: new_pane_action.pane_name,
1932 start_suppressed: new_pane_action.start_suppressed,
1933 }),
1934 ActionType::EditFile(edit_file_action) => Ok(crate::input::actions::Action::EditFile {
1935 payload: edit_file_action
1936 .payload
1937 .ok_or_else(|| anyhow!("EditFile missing payload"))?
1938 .try_into()?,
1939 direction: edit_file_action
1940 .direction
1941 .map(|d| proto_i32_to_direction(d))
1942 .transpose()?,
1943 floating: edit_file_action.floating,
1944 in_place: edit_file_action.in_place,
1945 close_replaced_pane: edit_file_action.close_replaced_pane,
1946 start_suppressed: edit_file_action.start_suppressed,
1947 coordinates: edit_file_action
1948 .coordinates
1949 .map(|c| c.try_into())
1950 .transpose()?,
1951 near_current_pane: edit_file_action.near_current_pane,
1952 tab_id: edit_file_action.tab_id.map(|t| t as usize),
1953 }),
1954 ActionType::NewFloatingPane(new_floating_action) => {
1955 Ok(crate::input::actions::Action::NewFloatingPane {
1956 command: new_floating_action
1957 .command
1958 .map(|c| c.try_into())
1959 .transpose()?,
1960 pane_name: new_floating_action.pane_name,
1961 coordinates: new_floating_action
1962 .coordinates
1963 .map(|c| c.try_into())
1964 .transpose()?,
1965 near_current_pane: new_floating_action.near_current_pane,
1966 tab_id: new_floating_action.tab_id.map(|t| t as usize),
1967 })
1968 },
1969 ActionType::NewTiledPane(new_tiled_action) => {
1970 Ok(crate::input::actions::Action::NewTiledPane {
1971 direction: new_tiled_action
1972 .direction
1973 .map(|d| proto_i32_to_direction(d))
1974 .transpose()?,
1975 command: new_tiled_action.command.map(|c| c.try_into()).transpose()?,
1976 pane_name: new_tiled_action.pane_name,
1977 near_current_pane: new_tiled_action.near_current_pane,
1978 borderless: new_tiled_action.borderless,
1979 tab_id: new_tiled_action.tab_id.map(|t| t as usize),
1980 })
1981 },
1982 ActionType::NewInPlacePane(new_in_place_action) => {
1983 Ok(crate::input::actions::Action::NewInPlacePane {
1984 command: new_in_place_action
1985 .command
1986 .map(|c| c.try_into())
1987 .transpose()?,
1988 pane_name: new_in_place_action.pane_name,
1989 near_current_pane: new_in_place_action.near_current_pane,
1990 pane_id_to_replace: new_in_place_action
1991 .pane_id_to_replace
1992 .and_then(|p| p.try_into().ok()),
1993 close_replaced_pane: new_in_place_action.close_replaced_pane,
1994 tab_id: new_in_place_action.tab_id.map(|t| t as usize),
1995 })
1996 },
1997 ActionType::NewStackedPane(new_stacked_action) => {
1998 Ok(crate::input::actions::Action::NewStackedPane {
1999 command: new_stacked_action
2000 .command
2001 .map(|c| c.try_into())
2002 .transpose()?,
2003 pane_name: new_stacked_action.pane_name,
2004 near_current_pane: new_stacked_action.near_current_pane,
2005 tab_id: new_stacked_action.tab_id.map(|t| t as usize),
2006 })
2007 },
2008 ActionType::NewBlockingPane(new_blocking_action) => {
2009 Ok(crate::input::actions::Action::NewBlockingPane {
2010 placement: new_blocking_action
2011 .placement
2012 .ok_or_else(|| anyhow!("NewBlockingPane missing placement"))?
2013 .try_into()?,
2014 pane_name: new_blocking_action.pane_name,
2015 command: new_blocking_action
2016 .command
2017 .map(|c| c.try_into())
2018 .transpose()?,
2019 unblock_condition: new_blocking_action
2020 .unblock_condition
2021 .map(|c| proto_i32_to_unblock_condition(c))
2022 .transpose()?,
2023 near_current_pane: new_blocking_action.near_current_pane,
2024 tab_id: new_blocking_action.tab_id.map(|t| t as usize),
2025 })
2026 },
2027 ActionType::TogglePaneEmbedOrFloating(_) => {
2028 Ok(crate::input::actions::Action::TogglePaneEmbedOrFloating)
2029 },
2030 ActionType::ToggleFloatingPanes(_) => {
2031 Ok(crate::input::actions::Action::ToggleFloatingPanes)
2032 },
2033 ActionType::ShowFloatingPanes(a) => {
2034 Ok(crate::input::actions::Action::ShowFloatingPanes {
2035 tab_id: a.tab_id.map(|id| id as usize),
2036 })
2037 },
2038 ActionType::HideFloatingPanes(a) => {
2039 Ok(crate::input::actions::Action::HideFloatingPanes {
2040 tab_id: a.tab_id.map(|id| id as usize),
2041 })
2042 },
2043 ActionType::AreFloatingPanesVisible(a) => {
2044 Ok(crate::input::actions::Action::AreFloatingPanesVisible {
2045 tab_id: a.tab_id.map(|id| id as usize),
2046 })
2047 },
2048 ActionType::CloseFocus(_) => Ok(crate::input::actions::Action::CloseFocus),
2049 ActionType::PaneNameInput(pane_name_action) => {
2050 Ok(crate::input::actions::Action::PaneNameInput {
2051 input: pane_name_action
2052 .input
2053 .into_iter()
2054 .map(|b| b as u8)
2055 .collect(),
2056 })
2057 },
2058 ActionType::UndoRenamePane(_) => Ok(crate::input::actions::Action::UndoRenamePane),
2059 ActionType::NewTab(new_tab_action) => Ok(crate::input::actions::Action::NewTab {
2060 tiled_layout: new_tab_action
2061 .tiled_layout
2062 .map(|l| l.try_into())
2063 .transpose()?,
2064 floating_layouts: new_tab_action
2065 .floating_layouts
2066 .into_iter()
2067 .map(|l| l.try_into())
2068 .collect::<Result<Vec<_>>>()?,
2069 swap_tiled_layouts: if new_tab_action.swap_tiled_layouts.is_empty() {
2070 None
2071 } else {
2072 Some(
2073 new_tab_action
2074 .swap_tiled_layouts
2075 .into_iter()
2076 .map(|l| l.try_into())
2077 .collect::<Result<Vec<_>>>()?,
2078 )
2079 },
2080 swap_floating_layouts: if new_tab_action.swap_floating_layouts.is_empty() {
2081 None
2082 } else {
2083 Some(
2084 new_tab_action
2085 .swap_floating_layouts
2086 .into_iter()
2087 .map(|l| l.try_into())
2088 .collect::<Result<Vec<_>>>()?,
2089 )
2090 },
2091 tab_name: new_tab_action.tab_name,
2092 should_change_focus_to_new_tab: new_tab_action.should_change_focus_to_new_tab,
2093 cwd: new_tab_action.cwd.map(PathBuf::from),
2094 initial_panes: if new_tab_action.initial_panes.is_empty() {
2095 None
2096 } else {
2097 Some(
2098 new_tab_action
2099 .initial_panes
2100 .into_iter()
2101 .map(|p| p.try_into())
2102 .collect::<Result<Vec<_>>>()?,
2103 )
2104 },
2105
2106 first_pane_unblock_condition: new_tab_action
2107 .first_pane_unblock_condition
2108 .map(|c| proto_i32_to_unblock_condition(c))
2109 .transpose()?,
2110 }),
2111 ActionType::NoOp(_) => Ok(crate::input::actions::Action::NoOp),
2112 ActionType::GoToNextTab(_) => Ok(crate::input::actions::Action::GoToNextTab),
2113 ActionType::GoToPreviousTab(_) => Ok(crate::input::actions::Action::GoToPreviousTab),
2114 ActionType::CloseTab(_) => Ok(crate::input::actions::Action::CloseTab),
2115 ActionType::GoToTab(go_to_tab_action) => Ok(crate::input::actions::Action::GoToTab {
2116 index: go_to_tab_action.index,
2117 }),
2118 ActionType::GoToTabName(go_to_tab_name_action) => {
2119 Ok(crate::input::actions::Action::GoToTabName {
2120 name: go_to_tab_name_action.name,
2121 create: go_to_tab_name_action.create,
2122 })
2123 },
2124 ActionType::ToggleTab(_) => Ok(crate::input::actions::Action::ToggleTab),
2125 ActionType::TabNameInput(tab_name_action) => {
2126 Ok(crate::input::actions::Action::TabNameInput {
2127 input: tab_name_action.input.into_iter().map(|b| b as u8).collect(),
2128 })
2129 },
2130 ActionType::UndoRenameTab(_) => Ok(crate::input::actions::Action::UndoRenameTab),
2131 ActionType::MoveTab(move_tab_action) => Ok(crate::input::actions::Action::MoveTab {
2132 direction: proto_i32_to_direction(move_tab_action.direction)?,
2133 }),
2134 ActionType::Run(run_action) => Ok(crate::input::actions::Action::Run {
2135 command: run_action
2136 .command
2137 .ok_or_else(|| anyhow!("Run missing command"))?
2138 .try_into()?,
2139 near_current_pane: run_action.near_current_pane,
2140 }),
2141 ActionType::Detach(_) => Ok(crate::input::actions::Action::Detach),
2142 ActionType::SwitchSession(switch_session_action) => {
2143 Ok(crate::input::actions::Action::SwitchSession {
2144 name: switch_session_action.name.clone(),
2145 tab_position: switch_session_action.tab_position.map(|p| p as usize),
2146 pane_id: switch_session_action
2147 .pane_id
2148 .as_ref()
2149 .map(|p| (p.pane_id, p.is_plugin)),
2150 layout: switch_session_action
2151 .layout
2152 .map(|l| l.try_into())
2153 .transpose()?,
2154 cwd: switch_session_action.cwd.map(PathBuf::from),
2155 })
2156 },
2157 ActionType::LaunchOrFocusPlugin(launch_plugin_action) => {
2158 Ok(crate::input::actions::Action::LaunchOrFocusPlugin {
2159 plugin: launch_plugin_action
2160 .plugin
2161 .ok_or_else(|| anyhow!("LaunchOrFocusPlugin missing plugin"))?
2162 .try_into()?,
2163 should_float: launch_plugin_action.should_float,
2164 move_to_focused_tab: launch_plugin_action.move_to_focused_tab,
2165 should_open_in_place: launch_plugin_action.should_open_in_place,
2166 close_replaced_pane: launch_plugin_action.close_replaced_pane,
2167 skip_cache: launch_plugin_action.skip_cache,
2168 tab_id: launch_plugin_action.tab_id.map(|t| t as usize),
2169 })
2170 },
2171 ActionType::LaunchPlugin(launch_plugin_action) => {
2172 Ok(crate::input::actions::Action::LaunchPlugin {
2173 plugin: launch_plugin_action
2174 .plugin
2175 .ok_or_else(|| anyhow!("LaunchPlugin missing plugin"))?
2176 .try_into()?,
2177 should_float: launch_plugin_action.should_float,
2178 should_open_in_place: launch_plugin_action.should_open_in_place,
2179 close_replaced_pane: launch_plugin_action.close_replaced_pane,
2180 skip_cache: launch_plugin_action.skip_cache,
2181 cwd: launch_plugin_action.cwd.map(PathBuf::from),
2182 tab_id: launch_plugin_action.tab_id.map(|t| t as usize),
2183 })
2184 },
2185 ActionType::MouseEvent(mouse_event_action) => {
2186 Ok(crate::input::actions::Action::MouseEvent {
2187 event: mouse_event_action
2188 .event
2189 .ok_or_else(|| anyhow!("MouseEvent missing event"))?
2190 .try_into()?,
2191 })
2192 },
2193 ActionType::Copy(_) => Ok(crate::input::actions::Action::Copy),
2194 ActionType::Confirm(_) => Ok(crate::input::actions::Action::Confirm),
2195 ActionType::Deny(_) => Ok(crate::input::actions::Action::Deny),
2196 ActionType::SkipConfirm(skip_confirm_action) => {
2197 Ok(crate::input::actions::Action::SkipConfirm {
2198 action: Box::new(
2199 skip_confirm_action
2200 .action
2201 .ok_or_else(|| anyhow!("SkipConfirm missing action"))?
2202 .as_ref()
2203 .clone()
2204 .try_into()?,
2205 ),
2206 })
2207 },
2208 ActionType::SearchInput(search_input_action) => {
2209 Ok(crate::input::actions::Action::SearchInput {
2210 input: search_input_action
2211 .input
2212 .into_iter()
2213 .map(|b| b as u8)
2214 .collect(),
2215 })
2216 },
2217 ActionType::Search(search_action) => Ok(crate::input::actions::Action::Search {
2218 direction: proto_i32_to_search_direction(search_action.direction)?,
2219 }),
2220 ActionType::SearchToggleOption(search_toggle_action) => {
2221 Ok(crate::input::actions::Action::SearchToggleOption {
2222 option: proto_i32_to_search_option(search_toggle_action.option)?,
2223 })
2224 },
2225 ActionType::ToggleMouseMode(_) => Ok(crate::input::actions::Action::ToggleMouseMode),
2226 ActionType::PreviousSwapLayout(_) => {
2227 Ok(crate::input::actions::Action::PreviousSwapLayout)
2228 },
2229 ActionType::NextSwapLayout(_) => Ok(crate::input::actions::Action::NextSwapLayout),
2230 ActionType::OverrideLayout(override_layout_action) => {
2231 Ok(crate::input::actions::Action::OverrideLayout {
2232 tabs: override_layout_action
2233 .tabs
2234 .into_iter()
2235 .map(|t| t.try_into())
2236 .collect::<Result<Vec<_>>>()?,
2237 retain_existing_terminal_panes: override_layout_action
2238 .retain_existing_terminal_panes,
2239 retain_existing_plugin_panes: override_layout_action
2240 .retain_existing_plugin_panes,
2241 apply_only_to_active_tab: override_layout_action.apply_only_to_active_tab,
2242 })
2243 },
2244 ActionType::QueryTabNames(_) => Ok(crate::input::actions::Action::QueryTabNames),
2245 ActionType::NewTiledPluginPane(new_tiled_plugin_action) => {
2246 Ok(crate::input::actions::Action::NewTiledPluginPane {
2247 plugin: new_tiled_plugin_action
2248 .plugin
2249 .ok_or_else(|| anyhow!("NewTiledPluginPane missing plugin"))?
2250 .try_into()?,
2251 pane_name: new_tiled_plugin_action.pane_name,
2252 skip_cache: new_tiled_plugin_action.skip_cache,
2253 cwd: new_tiled_plugin_action.cwd.map(PathBuf::from),
2254 tab_id: new_tiled_plugin_action.tab_id.map(|t| t as usize),
2255 })
2256 },
2257 ActionType::NewFloatingPluginPane(new_floating_plugin_action) => {
2258 Ok(crate::input::actions::Action::NewFloatingPluginPane {
2259 plugin: new_floating_plugin_action
2260 .plugin
2261 .ok_or_else(|| anyhow!("NewFloatingPluginPane missing plugin"))?
2262 .try_into()?,
2263 pane_name: new_floating_plugin_action.pane_name,
2264 skip_cache: new_floating_plugin_action.skip_cache,
2265 cwd: new_floating_plugin_action.cwd.map(PathBuf::from),
2266 coordinates: new_floating_plugin_action
2267 .coordinates
2268 .map(|c| c.try_into())
2269 .transpose()?,
2270 tab_id: new_floating_plugin_action.tab_id.map(|t| t as usize),
2271 })
2272 },
2273 ActionType::NewInPlacePluginPane(new_in_place_plugin_action) => {
2274 Ok(crate::input::actions::Action::NewInPlacePluginPane {
2275 plugin: new_in_place_plugin_action
2276 .plugin
2277 .ok_or_else(|| anyhow!("NewInPlacePluginPane missing plugin"))?
2278 .try_into()?,
2279 pane_name: new_in_place_plugin_action.pane_name,
2280 skip_cache: new_in_place_plugin_action.skip_cache,
2281 close_replaced_pane: new_in_place_plugin_action.close_replaced_pane,
2282 tab_id: new_in_place_plugin_action.tab_id.map(|t| t as usize),
2283 })
2284 },
2285 ActionType::StartOrReloadPlugin(start_plugin_action) => {
2286 Ok(crate::input::actions::Action::StartOrReloadPlugin {
2287 plugin: start_plugin_action
2288 .plugin
2289 .ok_or_else(|| anyhow!("StartOrReloadPlugin missing plugin"))?
2290 .try_into()?,
2291 })
2292 },
2293 ActionType::CloseTerminalPane(close_pane_action) => {
2294 Ok(crate::input::actions::Action::CloseTerminalPane {
2295 pane_id: close_pane_action.pane_id,
2296 })
2297 },
2298 ActionType::ClosePluginPane(close_pane_action) => {
2299 Ok(crate::input::actions::Action::ClosePluginPane {
2300 pane_id: close_pane_action.pane_id,
2301 })
2302 },
2303 ActionType::FocusTerminalPaneWithId(focus_pane_action) => {
2304 Ok(crate::input::actions::Action::FocusTerminalPaneWithId {
2305 pane_id: focus_pane_action.pane_id,
2306 should_float_if_hidden: focus_pane_action.should_float_if_hidden,
2307 should_be_in_place_if_hidden: focus_pane_action.should_be_in_place_if_hidden,
2308 })
2309 },
2310 ActionType::FocusPluginPaneWithId(focus_pane_action) => {
2311 Ok(crate::input::actions::Action::FocusPluginPaneWithId {
2312 pane_id: focus_pane_action.pane_id,
2313 should_float_if_hidden: focus_pane_action.should_float_if_hidden,
2314 should_be_in_place_if_hidden: focus_pane_action.should_be_in_place_if_hidden,
2315 })
2316 },
2317 ActionType::RenameTerminalPane(rename_pane_action) => {
2318 Ok(crate::input::actions::Action::RenameTerminalPane {
2319 pane_id: rename_pane_action.pane_id,
2320 name: rename_pane_action
2321 .name
2322 .into_iter()
2323 .map(|b| b as u8)
2324 .collect(),
2325 })
2326 },
2327 ActionType::RenamePluginPane(rename_pane_action) => {
2328 Ok(crate::input::actions::Action::RenamePluginPane {
2329 pane_id: rename_pane_action.pane_id,
2330 name: rename_pane_action
2331 .name
2332 .into_iter()
2333 .map(|b| b as u8)
2334 .collect(),
2335 })
2336 },
2337 ActionType::RenameTab(rename_tab_action) => {
2338 Ok(crate::input::actions::Action::RenameTab {
2339 tab_index: rename_tab_action.tab_index,
2340 name: rename_tab_action
2341 .name
2342 .into_iter()
2343 .map(|b| b as u8)
2344 .collect(),
2345 })
2346 },
2347 ActionType::GoToTabById(go_to_tab_by_id_action) => {
2348 Ok(crate::input::actions::Action::GoToTabById {
2349 id: go_to_tab_by_id_action.id,
2350 })
2351 },
2352 ActionType::CloseTabById(close_tab_by_id_action) => {
2353 Ok(crate::input::actions::Action::CloseTabById {
2354 id: close_tab_by_id_action.id,
2355 })
2356 },
2357 ActionType::RenameTabById(rename_tab_by_id_action) => {
2358 Ok(crate::input::actions::Action::RenameTabById {
2359 id: rename_tab_by_id_action.id,
2360 name: rename_tab_by_id_action.name,
2361 })
2362 },
2363 ActionType::BreakPane(_) => Ok(crate::input::actions::Action::BreakPane),
2364 ActionType::BreakPaneRight(_) => Ok(crate::input::actions::Action::BreakPaneRight),
2365 ActionType::BreakPaneLeft(_) => Ok(crate::input::actions::Action::BreakPaneLeft),
2366 ActionType::RenameSession(rename_session_action) => {
2367 Ok(crate::input::actions::Action::RenameSession {
2368 name: rename_session_action.name,
2369 })
2370 },
2371 ActionType::CliPipe(cli_pipe_action) => Ok(crate::input::actions::Action::CliPipe {
2372 pipe_id: cli_pipe_action.pipe_id,
2373 name: cli_pipe_action.name,
2374 payload: cli_pipe_action.payload,
2375 args: if cli_pipe_action.args.is_empty() {
2376 None
2377 } else {
2378 Some(cli_pipe_action.args.into_iter().collect())
2379 },
2380 plugin: cli_pipe_action.plugin,
2381 configuration: if cli_pipe_action.configuration.is_empty() {
2382 None
2383 } else {
2384 Some(cli_pipe_action.configuration.into_iter().collect())
2385 },
2386 launch_new: cli_pipe_action.launch_new,
2387 skip_cache: cli_pipe_action.skip_cache,
2388 floating: cli_pipe_action.floating,
2389 in_place: cli_pipe_action.in_place,
2390 cwd: cli_pipe_action.cwd.map(PathBuf::from),
2391 pane_title: cli_pipe_action.pane_title,
2392 }),
2393 ActionType::KeybindPipe(keybind_pipe_action) => {
2394 Ok(crate::input::actions::Action::KeybindPipe {
2395 name: keybind_pipe_action.name,
2396 payload: keybind_pipe_action.payload,
2397 args: if keybind_pipe_action.args.is_empty() {
2398 None
2399 } else {
2400 Some(keybind_pipe_action.args.into_iter().collect())
2401 },
2402 plugin: keybind_pipe_action.plugin,
2403 plugin_id: keybind_pipe_action.plugin_id,
2404 configuration: if keybind_pipe_action.configuration.is_empty() {
2405 None
2406 } else {
2407 Some(keybind_pipe_action.configuration.into_iter().collect())
2408 },
2409 launch_new: keybind_pipe_action.launch_new,
2410 skip_cache: keybind_pipe_action.skip_cache,
2411 floating: keybind_pipe_action.floating,
2412 in_place: keybind_pipe_action.in_place,
2413 cwd: keybind_pipe_action.cwd.map(PathBuf::from),
2414 pane_title: keybind_pipe_action.pane_title,
2415 })
2416 },
2417 ActionType::ListClients(_) => Ok(crate::input::actions::Action::ListClients),
2418 ActionType::ListPanes(list_panes_action) => {
2419 Ok(crate::input::actions::Action::ListPanes {
2420 show_tab: list_panes_action.show_tab,
2421 show_command: list_panes_action.show_command,
2422 show_state: list_panes_action.show_state,
2423 show_geometry: list_panes_action.show_geometry,
2424 show_all: list_panes_action.show_all,
2425 output_json: list_panes_action.output_json,
2426 })
2427 },
2428 ActionType::ListTabs(list_tabs_action) => Ok(crate::input::actions::Action::ListTabs {
2429 show_state: list_tabs_action.show_state,
2430 show_dimensions: list_tabs_action.show_dimensions,
2431 show_panes: list_tabs_action.show_panes,
2432 show_layout: list_tabs_action.show_layout,
2433 show_all: list_tabs_action.show_all,
2434 output_json: list_tabs_action.output_json,
2435 }),
2436 ActionType::CurrentTabInfo(current_tab_info_action) => {
2437 Ok(crate::input::actions::Action::CurrentTabInfo {
2438 output_json: current_tab_info_action.output_json,
2439 })
2440 },
2441 ActionType::TogglePanePinned(_) => Ok(crate::input::actions::Action::TogglePanePinned),
2442 ActionType::StackPanes(stack_panes_action) => {
2443 Ok(crate::input::actions::Action::StackPanes {
2444 pane_ids: stack_panes_action
2445 .pane_ids
2446 .into_iter()
2447 .map(|id| id.try_into())
2448 .collect::<Result<Vec<_>>>()?,
2449 })
2450 },
2451 ActionType::ChangeFloatingPaneCoordinates(change_coords_action) => Ok(
2452 crate::input::actions::Action::ChangeFloatingPaneCoordinates {
2453 pane_id: change_coords_action
2454 .pane_id
2455 .ok_or_else(|| anyhow!("ChangeFloatingPaneCoordinates missing pane_id"))?
2456 .try_into()?,
2457 coordinates: change_coords_action
2458 .coordinates
2459 .ok_or_else(|| {
2460 anyhow!("ChangeFloatingPaneCoordinates missing coordinates")
2461 })?
2462 .try_into()?,
2463 },
2464 ),
2465 ActionType::TogglePaneBorderless(toggle_borderless_action) => {
2466 Ok(crate::input::actions::Action::TogglePaneBorderless {
2467 pane_id: toggle_borderless_action
2468 .pane_id
2469 .ok_or_else(|| anyhow!("TogglePaneBorderless missing pane_id"))?
2470 .try_into()?,
2471 })
2472 },
2473 ActionType::SetPaneBorderless(set_borderless_action) => {
2474 Ok(crate::input::actions::Action::SetPaneBorderless {
2475 pane_id: set_borderless_action
2476 .pane_id
2477 .ok_or_else(|| anyhow!("SetPaneBorderless missing pane_id"))?
2478 .try_into()?,
2479 borderless: set_borderless_action.borderless,
2480 })
2481 },
2482 ActionType::TogglePaneInGroup(_) => {
2483 Ok(crate::input::actions::Action::TogglePaneInGroup)
2484 },
2485 ActionType::ToggleGroupMarking(_) => {
2486 Ok(crate::input::actions::Action::ToggleGroupMarking)
2487 },
2488 ActionType::SetPaneColor(set_pane_color_action) => {
2489 Ok(crate::input::actions::Action::SetPaneColor {
2490 pane_id: set_pane_color_action
2491 .pane_id
2492 .ok_or_else(|| anyhow!("SetPaneColor missing pane_id"))?
2493 .try_into()?,
2494 fg: set_pane_color_action.fg,
2495 bg: set_pane_color_action.bg,
2496 })
2497 },
2498 ActionType::ScrollUpByPaneId(a) => {
2500 Ok(crate::input::actions::Action::ScrollUpByPaneId {
2501 pane_id: a
2502 .pane_id
2503 .ok_or_else(|| anyhow!("ScrollUpByPaneId missing pane_id"))?
2504 .try_into()?,
2505 })
2506 },
2507 ActionType::ScrollDownByPaneId(a) => {
2508 Ok(crate::input::actions::Action::ScrollDownByPaneId {
2509 pane_id: a
2510 .pane_id
2511 .ok_or_else(|| anyhow!("ScrollDownByPaneId missing pane_id"))?
2512 .try_into()?,
2513 })
2514 },
2515 ActionType::ScrollToTopByPaneId(a) => {
2516 Ok(crate::input::actions::Action::ScrollToTopByPaneId {
2517 pane_id: a
2518 .pane_id
2519 .ok_or_else(|| anyhow!("ScrollToTopByPaneId missing pane_id"))?
2520 .try_into()?,
2521 })
2522 },
2523 ActionType::ScrollToBottomByPaneId(a) => {
2524 Ok(crate::input::actions::Action::ScrollToBottomByPaneId {
2525 pane_id: a
2526 .pane_id
2527 .ok_or_else(|| anyhow!("ScrollToBottomByPaneId missing pane_id"))?
2528 .try_into()?,
2529 })
2530 },
2531 ActionType::PageScrollUpByPaneId(a) => {
2532 Ok(crate::input::actions::Action::PageScrollUpByPaneId {
2533 pane_id: a
2534 .pane_id
2535 .ok_or_else(|| anyhow!("PageScrollUpByPaneId missing pane_id"))?
2536 .try_into()?,
2537 })
2538 },
2539 ActionType::PageScrollDownByPaneId(a) => {
2540 Ok(crate::input::actions::Action::PageScrollDownByPaneId {
2541 pane_id: a
2542 .pane_id
2543 .ok_or_else(|| anyhow!("PageScrollDownByPaneId missing pane_id"))?
2544 .try_into()?,
2545 })
2546 },
2547 ActionType::HalfPageScrollUpByPaneId(a) => {
2548 Ok(crate::input::actions::Action::HalfPageScrollUpByPaneId {
2549 pane_id: a
2550 .pane_id
2551 .ok_or_else(|| anyhow!("HalfPageScrollUpByPaneId missing pane_id"))?
2552 .try_into()?,
2553 })
2554 },
2555 ActionType::HalfPageScrollDownByPaneId(a) => {
2556 Ok(crate::input::actions::Action::HalfPageScrollDownByPaneId {
2557 pane_id: a
2558 .pane_id
2559 .ok_or_else(|| anyhow!("HalfPageScrollDownByPaneId missing pane_id"))?
2560 .try_into()?,
2561 })
2562 },
2563 ActionType::ResizeByPaneId(a) => {
2564 let resize_action = a
2565 .resize_action
2566 .ok_or_else(|| anyhow!("ResizeByPaneId missing resize_action"))?;
2567 let resize = proto_i32_to_resize(resize_action.resize)?;
2568 let direction = resize_action
2569 .direction
2570 .map(|d| proto_i32_to_direction(d))
2571 .transpose()?;
2572 Ok(crate::input::actions::Action::ResizeByPaneId {
2573 pane_id: a
2574 .pane_id
2575 .ok_or_else(|| anyhow!("ResizeByPaneId missing pane_id"))?
2576 .try_into()?,
2577 resize,
2578 direction,
2579 })
2580 },
2581 ActionType::MovePaneByPaneId(a) => {
2582 let direction = a.direction.map(|d| proto_i32_to_direction(d)).transpose()?;
2583 Ok(crate::input::actions::Action::MovePaneByPaneId {
2584 pane_id: a
2585 .pane_id
2586 .ok_or_else(|| anyhow!("MovePaneByPaneId missing pane_id"))?
2587 .try_into()?,
2588 direction,
2589 })
2590 },
2591 ActionType::MovePaneBackwardsByPaneId(a) => {
2592 Ok(crate::input::actions::Action::MovePaneBackwardsByPaneId {
2593 pane_id: a
2594 .pane_id
2595 .ok_or_else(|| anyhow!("MovePaneBackwardsByPaneId missing pane_id"))?
2596 .try_into()?,
2597 })
2598 },
2599 ActionType::ClearScreenByPaneId(a) => {
2600 Ok(crate::input::actions::Action::ClearScreenByPaneId {
2601 pane_id: a
2602 .pane_id
2603 .ok_or_else(|| anyhow!("ClearScreenByPaneId missing pane_id"))?
2604 .try_into()?,
2605 })
2606 },
2607 ActionType::EditScrollbackByPaneId(a) => {
2608 Ok(crate::input::actions::Action::EditScrollbackByPaneId {
2609 pane_id: a
2610 .pane_id
2611 .ok_or_else(|| anyhow!("EditScrollbackByPaneId missing pane_id"))?
2612 .try_into()?,
2613 ansi: a.ansi,
2614 })
2615 },
2616 ActionType::ToggleFullscreenByPaneId(a) => Ok(
2617 crate::input::actions::Action::ToggleFocusFullscreenByPaneId {
2618 pane_id: a
2619 .pane_id
2620 .ok_or_else(|| anyhow!("ToggleFullscreenByPaneId missing pane_id"))?
2621 .try_into()?,
2622 },
2623 ),
2624 ActionType::TogglePaneEmbedOrFloatingByPaneId(a) => Ok(
2625 crate::input::actions::Action::TogglePaneEmbedOrFloatingByPaneId {
2626 pane_id: a
2627 .pane_id
2628 .ok_or_else(|| {
2629 anyhow!("TogglePaneEmbedOrFloatingByPaneId missing pane_id")
2630 })?
2631 .try_into()?,
2632 },
2633 ),
2634 ActionType::CloseFocusByPaneId(a) => {
2635 Ok(crate::input::actions::Action::CloseFocusByPaneId {
2636 pane_id: a
2637 .pane_id
2638 .ok_or_else(|| anyhow!("CloseFocusByPaneId missing pane_id"))?
2639 .try_into()?,
2640 })
2641 },
2642 ActionType::RenamePaneByPaneId(a) => {
2643 Ok(crate::input::actions::Action::RenamePaneByPaneId {
2644 pane_id: a.pane_id.map(|p| p.try_into()).transpose()?,
2645 name: a.name,
2646 })
2647 },
2648 ActionType::UndoRenamePaneByPaneId(a) => {
2649 Ok(crate::input::actions::Action::UndoRenamePaneByPaneId {
2650 pane_id: a
2651 .pane_id
2652 .ok_or_else(|| anyhow!("UndoRenamePaneByPaneId missing pane_id"))?
2653 .try_into()?,
2654 })
2655 },
2656 ActionType::TogglePanePinnedByPaneId(a) => {
2657 Ok(crate::input::actions::Action::TogglePanePinnedByPaneId {
2658 pane_id: a
2659 .pane_id
2660 .ok_or_else(|| anyhow!("TogglePanePinnedByPaneId missing pane_id"))?
2661 .try_into()?,
2662 })
2663 },
2664 ActionType::FocusPaneByPaneId(a) => {
2665 Ok(crate::input::actions::Action::FocusPaneByPaneId {
2666 pane_id: a
2667 .pane_id
2668 .ok_or_else(|| anyhow!("FocusPaneByPaneId missing pane_id"))?
2669 .try_into()?,
2670 })
2671 },
2672 ActionType::UndoRenameTabByTabId(a) => {
2674 Ok(crate::input::actions::Action::UndoRenameTabByTabId { id: a.id })
2675 },
2676 ActionType::ToggleActiveSyncTabByTabId(a) => {
2677 Ok(crate::input::actions::Action::ToggleActiveSyncTabByTabId { id: a.id })
2678 },
2679 ActionType::ToggleFloatingPanesByTabId(a) => {
2680 Ok(crate::input::actions::Action::ToggleFloatingPanesByTabId { id: a.id })
2681 },
2682 ActionType::PreviousSwapLayoutByTabId(a) => {
2683 Ok(crate::input::actions::Action::PreviousSwapLayoutByTabId { id: a.id })
2684 },
2685 ActionType::NextSwapLayoutByTabId(a) => {
2686 Ok(crate::input::actions::Action::NextSwapLayoutByTabId { id: a.id })
2687 },
2688 ActionType::MoveTabByTabId(a) => {
2689 let direction = proto_i32_to_direction(a.direction)?;
2690 Ok(crate::input::actions::Action::MoveTabByTabId {
2691 id: a.id,
2692 direction,
2693 })
2694 },
2695 }
2696 }
2697}
2698
2699impl From<crate::data::KeyWithModifier>
2700 for crate::client_server_contract::client_server_contract::KeyWithModifier
2701{
2702 fn from(key: crate::data::KeyWithModifier) -> Self {
2703 use crate::ipc::enum_conversions::{bare_key_to_proto_i32, key_modifier_to_proto_i32};
2704
2705 let (bare_key_enum, char_data) = match &key.bare_key {
2707 crate::data::BareKey::Char(c) => (
2708 crate::client_server_contract::client_server_contract::BareKey::Char as i32,
2709 Some(c.to_string()),
2710 ),
2711 other => (bare_key_to_proto_i32(*other), None),
2712 };
2713
2714 Self {
2715 bare_key: bare_key_enum,
2716 key_modifiers: key
2717 .key_modifiers
2718 .into_iter()
2719 .map(|modifier| key_modifier_to_proto_i32(modifier))
2720 .collect(),
2721 character: char_data,
2722 }
2723 }
2724}
2725
2726impl TryFrom<crate::client_server_contract::client_server_contract::KeyWithModifier>
2727 for crate::data::KeyWithModifier
2728{
2729 type Error = anyhow::Error;
2730 fn try_from(
2731 key: crate::client_server_contract::client_server_contract::KeyWithModifier,
2732 ) -> Result<Self> {
2733 use crate::ipc::enum_conversions::{bare_key_from_proto_i32, key_modifier_from_proto_i32};
2734 use std::collections::BTreeSet;
2735
2736 let bare_key = if key.bare_key
2738 == crate::client_server_contract::client_server_contract::BareKey::Char as i32
2739 {
2740 let character_str = key
2741 .character
2742 .ok_or_else(|| anyhow!("Character key missing character data"))?;
2743 let character = character_str
2744 .chars()
2745 .next()
2746 .ok_or_else(|| anyhow!("Empty character string"))?;
2747 crate::data::BareKey::Char(character)
2748 } else {
2749 bare_key_from_proto_i32(key.bare_key)?
2750 };
2751
2752 let key_modifiers: Result<BTreeSet<_>> = key
2753 .key_modifiers
2754 .into_iter()
2755 .map(|modifier| key_modifier_from_proto_i32(modifier))
2756 .collect();
2757
2758 Ok(Self {
2759 bare_key,
2760 key_modifiers: key_modifiers?,
2761 })
2762 }
2763}
2764
2765impl From<crate::data::ConnectToSession>
2766 for crate::client_server_contract::client_server_contract::ConnectToSession
2767{
2768 fn from(connect: crate::data::ConnectToSession) -> Self {
2769 Self {
2770 name: connect.name,
2771 tab_position: connect.tab_position.map(|p| p as u32),
2772 pane_id: connect.pane_id.map(|(id, is_plugin)| {
2773 crate::client_server_contract::client_server_contract::PaneIdWithPlugin {
2774 pane_id: id,
2775 is_plugin,
2776 }
2777 }),
2778 layout: connect.layout.map(|l| l.into()),
2779 cwd: connect.cwd.map(|p| p.to_string_lossy().to_string()),
2780 }
2781 }
2782}
2783
2784impl TryFrom<crate::client_server_contract::client_server_contract::ConnectToSession>
2785 for crate::data::ConnectToSession
2786{
2787 type Error = anyhow::Error;
2788 fn try_from(
2789 connect: crate::client_server_contract::client_server_contract::ConnectToSession,
2790 ) -> Result<Self> {
2791 Ok(Self {
2792 name: connect.name,
2793 tab_position: connect.tab_position.map(|p| p as usize),
2794 pane_id: connect.pane_id.map(|p| (p.pane_id, p.is_plugin)),
2795 layout: connect.layout.map(|l| l.try_into()).transpose()?,
2796 cwd: connect.cwd.map(PathBuf::from),
2797 })
2798 }
2799}
2800
2801impl From<crate::data::LayoutInfo>
2802 for crate::client_server_contract::client_server_contract::LayoutInfo
2803{
2804 fn from(layout: crate::data::LayoutInfo) -> Self {
2805 use crate::client_server_contract::client_server_contract::layout_info::LayoutType;
2806 let (layout_type, layout_metadata) = match layout {
2807 crate::data::LayoutInfo::BuiltIn(name) => (LayoutType::BuiltinName(name), None),
2808 crate::data::LayoutInfo::File(path, metadata) => {
2809 (LayoutType::FilePath(path), Some(metadata.into()))
2810 },
2811 crate::data::LayoutInfo::Url(url) => (LayoutType::Url(url), None),
2812 crate::data::LayoutInfo::Stringified(content) => {
2813 (LayoutType::Stringified(content), None)
2814 },
2815 };
2816 Self {
2817 layout_type: Some(layout_type),
2818 layout_metadata,
2819 }
2820 }
2821}
2822
2823impl TryFrom<crate::client_server_contract::client_server_contract::LayoutInfo>
2824 for crate::data::LayoutInfo
2825{
2826 type Error = anyhow::Error;
2827 fn try_from(
2828 layout: crate::client_server_contract::client_server_contract::LayoutInfo,
2829 ) -> Result<Self> {
2830 use crate::client_server_contract::client_server_contract::layout_info::LayoutType;
2831 match layout.layout_type {
2832 Some(LayoutType::BuiltinName(name)) => Ok(crate::data::LayoutInfo::BuiltIn(name)),
2833 Some(LayoutType::FilePath(path)) => {
2834 let layout_metadata = layout
2835 .layout_metadata
2836 .map(|m| m.try_into())
2837 .transpose()?
2838 .unwrap_or_default();
2839 Ok(crate::data::LayoutInfo::File(path, layout_metadata))
2840 },
2841 Some(LayoutType::Url(url)) => Ok(crate::data::LayoutInfo::Url(url)),
2842 Some(LayoutType::Stringified(content)) => {
2843 Ok(crate::data::LayoutInfo::Stringified(content))
2844 },
2845 None => Err(anyhow!("LayoutInfo missing layout_type")),
2846 }
2847 }
2848}
2849
2850impl From<crate::data::LayoutMetadata> for ProtoLayoutMetadata {
2851 fn from(metadata: crate::data::LayoutMetadata) -> Self {
2852 ProtoLayoutMetadata {
2853 tabs: metadata.tabs.into_iter().map(|t| t.into()).collect(),
2854 creation_time: metadata.creation_time,
2855 update_time: metadata.update_time,
2856 }
2857 }
2858}
2859
2860impl TryFrom<ProtoLayoutMetadata> for crate::data::LayoutMetadata {
2861 type Error = anyhow::Error;
2862 fn try_from(proto_metadata: ProtoLayoutMetadata) -> Result<Self> {
2863 let tabs = proto_metadata
2864 .tabs
2865 .into_iter()
2866 .map(|t| t.try_into())
2867 .collect::<Result<Vec<_>>>()?;
2868 Ok(crate::data::LayoutMetadata {
2869 tabs,
2870 creation_time: proto_metadata.creation_time,
2871 update_time: proto_metadata.update_time,
2872 })
2873 }
2874}
2875
2876impl From<crate::data::TabMetadata> for ProtoTabMetadata {
2877 fn from(metadata: crate::data::TabMetadata) -> Self {
2878 ProtoTabMetadata {
2879 pane_metadata: metadata.panes.into_iter().map(|p| p.into()).collect(),
2880 name: metadata.name,
2881 }
2882 }
2883}
2884
2885impl TryFrom<ProtoTabMetadata> for crate::data::TabMetadata {
2886 type Error = anyhow::Error;
2887 fn try_from(proto_metadata: ProtoTabMetadata) -> Result<Self> {
2888 let panes = proto_metadata
2889 .pane_metadata
2890 .into_iter()
2891 .map(|p| p.try_into())
2892 .collect::<Result<Vec<_>>>()?;
2893 Ok(crate::data::TabMetadata {
2894 panes,
2895 name: proto_metadata.name,
2896 })
2897 }
2898}
2899
2900impl From<crate::data::PaneMetadata> for ProtoPaneMetadata {
2901 fn from(metadata: crate::data::PaneMetadata) -> Self {
2902 ProtoPaneMetadata {
2903 name: metadata.name,
2904 is_plugin: metadata.is_plugin,
2905 is_builtin_plugin: metadata.is_builtin_plugin,
2906 }
2907 }
2908}
2909
2910impl TryFrom<ProtoPaneMetadata> for crate::data::PaneMetadata {
2911 type Error = anyhow::Error;
2912 fn try_from(proto_metadata: ProtoPaneMetadata) -> Result<Self> {
2913 Ok(crate::data::PaneMetadata {
2914 name: proto_metadata.name,
2915 is_plugin: proto_metadata.is_plugin,
2916 is_builtin_plugin: proto_metadata.is_builtin_plugin,
2917 })
2918 }
2919}
2920
2921impl From<ExitReason> for ProtoExitReason {
2922 fn from(reason: ExitReason) -> Self {
2923 match reason {
2924 ExitReason::Normal => ProtoExitReason::Normal,
2925 ExitReason::NormalDetached => ProtoExitReason::NormalDetached,
2926 ExitReason::ForceDetached => ProtoExitReason::ForceDetached,
2927 ExitReason::CannotAttach => ProtoExitReason::CannotAttach,
2928 ExitReason::Disconnect => ProtoExitReason::Disconnect,
2929 ExitReason::WebClientsForbidden => ProtoExitReason::WebClientsForbidden,
2930 ExitReason::KickedByHost => ProtoExitReason::KickedByHost,
2931 ExitReason::Error(_msg) => ProtoExitReason::Error,
2932 ExitReason::CustomExitStatus(_status) => ProtoExitReason::CustomExitStatus,
2933 }
2934 }
2935}
2936
2937impl TryFrom<ProtoExitReason> for ExitReason {
2938 type Error = anyhow::Error;
2939 fn try_from(reason: ProtoExitReason) -> Result<Self> {
2940 match reason {
2941 ProtoExitReason::Normal => Ok(ExitReason::Normal),
2942 ProtoExitReason::NormalDetached => Ok(ExitReason::NormalDetached),
2943 ProtoExitReason::ForceDetached => Ok(ExitReason::ForceDetached),
2944 ProtoExitReason::CannotAttach => Ok(ExitReason::CannotAttach),
2945 ProtoExitReason::Disconnect => Ok(ExitReason::Disconnect),
2946 ProtoExitReason::WebClientsForbidden => Ok(ExitReason::WebClientsForbidden),
2947 ProtoExitReason::KickedByHost => Ok(ExitReason::KickedByHost),
2948 ProtoExitReason::Error => Ok(ExitReason::Error("Protobuf error".to_string())),
2949 ProtoExitReason::CustomExitStatus => Ok(ExitReason::CustomExitStatus(0)),
2950 ProtoExitReason::Unspecified => Err(anyhow!("Unspecified exit reason")),
2951 }
2952 }
2953}
2954
2955fn input_mode_to_proto_i32(mode: InputMode) -> i32 {
2957 match mode {
2958 InputMode::Normal => ProtoInputMode::Normal as i32,
2959 InputMode::Locked => ProtoInputMode::Locked as i32,
2960 InputMode::Resize => ProtoInputMode::Resize as i32,
2961 InputMode::Pane => ProtoInputMode::Pane as i32,
2962 InputMode::Tab => ProtoInputMode::Tab as i32,
2963 InputMode::Scroll => ProtoInputMode::Scroll as i32,
2964 InputMode::EnterSearch => ProtoInputMode::EnterSearch as i32,
2965 InputMode::Search => ProtoInputMode::Search as i32,
2966 InputMode::RenameTab => ProtoInputMode::RenameTab as i32,
2967 InputMode::RenamePane => ProtoInputMode::RenamePane as i32,
2968 InputMode::Session => ProtoInputMode::Session as i32,
2969 InputMode::Move => ProtoInputMode::Move as i32,
2970 InputMode::Prompt => ProtoInputMode::Prompt as i32,
2971 InputMode::Tmux => ProtoInputMode::Tmux as i32,
2972 }
2973}
2974
2975fn proto_i32_to_input_mode(i: i32) -> Result<InputMode> {
2976 match ProtoInputMode::from_i32(i) {
2977 Some(ProtoInputMode::Normal) => Ok(InputMode::Normal),
2978 Some(ProtoInputMode::Locked) => Ok(InputMode::Locked),
2979 Some(ProtoInputMode::Resize) => Ok(InputMode::Resize),
2980 Some(ProtoInputMode::Pane) => Ok(InputMode::Pane),
2981 Some(ProtoInputMode::Tab) => Ok(InputMode::Tab),
2982 Some(ProtoInputMode::Scroll) => Ok(InputMode::Scroll),
2983 Some(ProtoInputMode::EnterSearch) => Ok(InputMode::EnterSearch),
2984 Some(ProtoInputMode::Search) => Ok(InputMode::Search),
2985 Some(ProtoInputMode::RenameTab) => Ok(InputMode::RenameTab),
2986 Some(ProtoInputMode::RenamePane) => Ok(InputMode::RenamePane),
2987 Some(ProtoInputMode::Session) => Ok(InputMode::Session),
2988 Some(ProtoInputMode::Move) => Ok(InputMode::Move),
2989 Some(ProtoInputMode::Prompt) => Ok(InputMode::Prompt),
2990 Some(ProtoInputMode::Tmux) => Ok(InputMode::Tmux),
2991 _ => Err(anyhow!("Invalid InputMode value: {}", i)),
2992 }
2993}
2994
2995fn resize_to_proto_i32(resize: crate::data::Resize) -> i32 {
2997 use crate::client_server_contract::client_server_contract::ResizeType;
2998 match resize {
2999 crate::data::Resize::Increase => ResizeType::Increase as i32,
3000 crate::data::Resize::Decrease => ResizeType::Decrease as i32,
3001 }
3002}
3003
3004fn direction_to_proto_i32(direction: crate::data::Direction) -> i32 {
3005 use crate::client_server_contract::client_server_contract::Direction as ProtoDirection;
3006 match direction {
3007 crate::data::Direction::Left => ProtoDirection::Left as i32,
3008 crate::data::Direction::Right => ProtoDirection::Right as i32,
3009 crate::data::Direction::Up => ProtoDirection::Up as i32,
3010 crate::data::Direction::Down => ProtoDirection::Down as i32,
3011 }
3012}
3013
3014fn search_direction_to_proto_i32(direction: crate::input::actions::SearchDirection) -> i32 {
3015 use crate::client_server_contract::client_server_contract::SearchDirection as ProtoSearchDirection;
3016 match direction {
3017 crate::input::actions::SearchDirection::Up => ProtoSearchDirection::Up as i32,
3018 crate::input::actions::SearchDirection::Down => ProtoSearchDirection::Down as i32,
3019 }
3020}
3021
3022fn search_option_to_proto_i32(option: crate::input::actions::SearchOption) -> i32 {
3023 use crate::client_server_contract::client_server_contract::SearchOption as ProtoSearchOption;
3024 match option {
3025 crate::input::actions::SearchOption::CaseSensitivity => {
3026 ProtoSearchOption::CaseSensitivity as i32
3027 },
3028 crate::input::actions::SearchOption::Wrap => ProtoSearchOption::Wrap as i32,
3029 crate::input::actions::SearchOption::WholeWord => ProtoSearchOption::WholeWord as i32,
3030 }
3031}
3032
3033fn unblock_condition_to_proto_i32(condition: crate::data::UnblockCondition) -> i32 {
3034 use crate::client_server_contract::client_server_contract::UnblockCondition as ProtoUnblockCondition;
3035 match condition {
3036 crate::data::UnblockCondition::OnExitSuccess => ProtoUnblockCondition::OnExitSuccess as i32,
3037 crate::data::UnblockCondition::OnExitFailure => ProtoUnblockCondition::OnExitFailure as i32,
3038 crate::data::UnblockCondition::OnAnyExit => ProtoUnblockCondition::OnAnyExit as i32,
3039 }
3040}
3041
3042fn proto_i32_to_resize(resize: i32) -> Result<crate::data::Resize> {
3045 use crate::client_server_contract::client_server_contract::ResizeType as ProtoResize;
3046 let proto_resize = match resize {
3047 x if x == ProtoResize::Increase as i32 => ProtoResize::Increase,
3048 x if x == ProtoResize::Decrease as i32 => ProtoResize::Decrease,
3049 _ => return Err(anyhow!("Invalid ResizeType: {}", resize)),
3050 };
3051 match proto_resize {
3052 ProtoResize::Increase => Ok(crate::data::Resize::Increase),
3053 ProtoResize::Decrease => Ok(crate::data::Resize::Decrease),
3054 ProtoResize::Unspecified => Err(anyhow!("Unspecified ResizeType")),
3055 }
3056}
3057
3058fn proto_i32_to_direction(direction: i32) -> Result<crate::data::Direction> {
3059 use crate::client_server_contract::client_server_contract::Direction as ProtoDirection;
3060 let proto_direction = match direction {
3061 x if x == ProtoDirection::Left as i32 => ProtoDirection::Left,
3062 x if x == ProtoDirection::Right as i32 => ProtoDirection::Right,
3063 x if x == ProtoDirection::Up as i32 => ProtoDirection::Up,
3064 x if x == ProtoDirection::Down as i32 => ProtoDirection::Down,
3065 _ => return Err(anyhow!("Invalid Direction: {}", direction)),
3066 };
3067 match proto_direction {
3068 ProtoDirection::Left => Ok(crate::data::Direction::Left),
3069 ProtoDirection::Right => Ok(crate::data::Direction::Right),
3070 ProtoDirection::Up => Ok(crate::data::Direction::Up),
3071 ProtoDirection::Down => Ok(crate::data::Direction::Down),
3072 ProtoDirection::Unspecified => Err(anyhow!("Unspecified direction")),
3073 }
3074}
3075
3076fn proto_i32_to_search_direction(direction: i32) -> Result<crate::input::actions::SearchDirection> {
3077 use crate::client_server_contract::client_server_contract::SearchDirection as ProtoSearchDirection;
3078 let proto_direction = match direction {
3079 x if x == ProtoSearchDirection::Up as i32 => ProtoSearchDirection::Up,
3080 x if x == ProtoSearchDirection::Down as i32 => ProtoSearchDirection::Down,
3081 _ => return Err(anyhow!("Invalid SearchDirection: {}", direction)),
3082 };
3083 match proto_direction {
3084 ProtoSearchDirection::Up => Ok(crate::input::actions::SearchDirection::Up),
3085 ProtoSearchDirection::Down => Ok(crate::input::actions::SearchDirection::Down),
3086 ProtoSearchDirection::Unspecified => Err(anyhow!("Unspecified search direction")),
3087 }
3088}
3089
3090fn proto_i32_to_search_option(option: i32) -> Result<crate::input::actions::SearchOption> {
3091 use crate::client_server_contract::client_server_contract::SearchOption as ProtoSearchOption;
3092 let proto_option = match option {
3093 x if x == ProtoSearchOption::CaseSensitivity as i32 => ProtoSearchOption::CaseSensitivity,
3094 x if x == ProtoSearchOption::WholeWord as i32 => ProtoSearchOption::WholeWord,
3095 x if x == ProtoSearchOption::Wrap as i32 => ProtoSearchOption::Wrap,
3096 _ => return Err(anyhow!("Invalid SearchOption: {}", option)),
3097 };
3098 match proto_option {
3099 ProtoSearchOption::CaseSensitivity => {
3100 Ok(crate::input::actions::SearchOption::CaseSensitivity)
3101 },
3102 ProtoSearchOption::Wrap => Ok(crate::input::actions::SearchOption::Wrap),
3103 ProtoSearchOption::WholeWord => Ok(crate::input::actions::SearchOption::WholeWord),
3104 ProtoSearchOption::Unspecified => Err(anyhow!("Unspecified search option")),
3105 }
3106}
3107
3108fn proto_i32_to_unblock_condition(condition: i32) -> Result<crate::data::UnblockCondition> {
3109 use crate::client_server_contract::client_server_contract::UnblockCondition as ProtoUnblockCondition;
3110 let proto_condition = match condition {
3111 x if x == ProtoUnblockCondition::OnExitSuccess as i32 => {
3112 ProtoUnblockCondition::OnExitSuccess
3113 },
3114 x if x == ProtoUnblockCondition::OnExitFailure as i32 => {
3115 ProtoUnblockCondition::OnExitFailure
3116 },
3117 x if x == ProtoUnblockCondition::OnAnyExit as i32 => ProtoUnblockCondition::OnAnyExit,
3118 _ => return Err(anyhow!("Invalid UnblockCondition: {}", condition)),
3119 };
3120 match proto_condition {
3121 ProtoUnblockCondition::OnExitSuccess => Ok(crate::data::UnblockCondition::OnExitSuccess),
3122 ProtoUnblockCondition::OnExitFailure => Ok(crate::data::UnblockCondition::OnExitFailure),
3123 ProtoUnblockCondition::OnAnyExit => Ok(crate::data::UnblockCondition::OnAnyExit),
3124 ProtoUnblockCondition::Unspecified => Err(anyhow!("Unspecified unblock condition")),
3125 }
3126}
3127
3128impl From<crate::position::Position>
3130 for crate::client_server_contract::client_server_contract::Position
3131{
3132 fn from(pos: crate::position::Position) -> Self {
3133 Self {
3134 line: pos.line.0 as i32,
3135 column: pos.column.0 as u64,
3136 }
3137 }
3138}
3139
3140impl TryFrom<crate::client_server_contract::client_server_contract::Position>
3142 for crate::position::Position
3143{
3144 type Error = anyhow::Error;
3145 fn try_from(
3146 pos: crate::client_server_contract::client_server_contract::Position,
3147 ) -> Result<Self> {
3148 Ok(Self {
3149 line: crate::position::Line(pos.line as isize),
3150 column: crate::position::Column(pos.column as usize),
3151 })
3152 }
3153}
3154
3155impl From<crate::input::command::OpenFilePayload>
3157 for crate::client_server_contract::client_server_contract::OpenFilePayload
3158{
3159 fn from(payload: crate::input::command::OpenFilePayload) -> Self {
3160 Self {
3161 file_to_open: payload.path.to_string_lossy().to_string(),
3162 line_number: payload.line_number.map(|n| n as u32),
3163 cwd: payload.cwd.map(|p| p.to_string_lossy().to_string()),
3164 originating_plugin: payload.originating_plugin.map(|op| op.into()),
3165 }
3166 }
3167}
3168
3169impl TryFrom<crate::client_server_contract::client_server_contract::OpenFilePayload>
3171 for crate::input::command::OpenFilePayload
3172{
3173 type Error = anyhow::Error;
3174 fn try_from(
3175 payload: crate::client_server_contract::client_server_contract::OpenFilePayload,
3176 ) -> Result<Self> {
3177 Ok(Self {
3178 path: PathBuf::from(payload.file_to_open),
3179 line_number: payload.line_number.map(|n| n as usize),
3180 cwd: payload.cwd.map(PathBuf::from),
3181 originating_plugin: payload
3182 .originating_plugin
3183 .map(|op| op.try_into())
3184 .transpose()?,
3185 })
3186 }
3187}
3188
3189impl From<crate::data::PaneId> for crate::client_server_contract::client_server_contract::PaneId {
3191 fn from(pane_id: crate::data::PaneId) -> Self {
3192 use crate::client_server_contract::client_server_contract::pane_id::PaneType;
3193 match pane_id {
3194 crate::data::PaneId::Terminal(id) => Self {
3195 pane_type: Some(PaneType::Terminal(id)),
3196 },
3197 crate::data::PaneId::Plugin(id) => Self {
3198 pane_type: Some(PaneType::Plugin(id)),
3199 },
3200 }
3201 }
3202}
3203
3204impl TryFrom<crate::client_server_contract::client_server_contract::PaneId>
3206 for crate::data::PaneId
3207{
3208 type Error = anyhow::Error;
3209 fn try_from(
3210 pane_id: crate::client_server_contract::client_server_contract::PaneId,
3211 ) -> Result<Self> {
3212 use crate::client_server_contract::client_server_contract::pane_id::PaneType;
3213 match pane_id
3214 .pane_type
3215 .ok_or_else(|| anyhow!("PaneId missing pane_type"))?
3216 {
3217 PaneType::Terminal(id) => Ok(crate::data::PaneId::Terminal(id)),
3218 PaneType::Plugin(id) => Ok(crate::data::PaneId::Plugin(id)),
3219 }
3220 }
3221}
3222
3223impl From<crate::input::layout::SplitSize>
3225 for crate::client_server_contract::client_server_contract::FloatingCoordinate
3226{
3227 fn from(size: crate::input::layout::SplitSize) -> Self {
3228 match size {
3229 crate::input::layout::SplitSize::Percent(p) => Self {
3230 coordinate_type: Some(crate::client_server_contract::client_server_contract::floating_coordinate::CoordinateType::Percent(p as f32)),
3231 },
3232 crate::input::layout::SplitSize::Fixed(f) => Self {
3233 coordinate_type: Some(crate::client_server_contract::client_server_contract::floating_coordinate::CoordinateType::Fixed(f as u32)),
3234 },
3235 }
3236 }
3237}
3238
3239impl TryFrom<crate::client_server_contract::client_server_contract::FloatingCoordinate>
3241 for crate::input::layout::SplitSize
3242{
3243 type Error = anyhow::Error;
3244 fn try_from(
3245 coord: crate::client_server_contract::client_server_contract::FloatingCoordinate,
3246 ) -> Result<Self> {
3247 use crate::client_server_contract::client_server_contract::floating_coordinate::CoordinateType;
3248 match coord
3249 .coordinate_type
3250 .ok_or_else(|| anyhow!("FloatingCoordinate missing coordinate_type"))?
3251 {
3252 CoordinateType::Percent(p) => Ok(crate::input::layout::SplitSize::Percent(p as usize)),
3253 CoordinateType::Fixed(f) => Ok(crate::input::layout::SplitSize::Fixed(f as usize)),
3254 }
3255 }
3256}
3257
3258impl From<crate::input::layout::PercentOrFixed>
3260 for crate::client_server_contract::client_server_contract::FloatingCoordinate
3261{
3262 fn from(size: crate::input::layout::PercentOrFixed) -> Self {
3263 match size {
3264 crate::input::layout::PercentOrFixed::Percent(p) => Self {
3265 coordinate_type: Some(crate::client_server_contract::client_server_contract::floating_coordinate::CoordinateType::Percent(p as f32)),
3266 },
3267 crate::input::layout::PercentOrFixed::Fixed(f) => Self {
3268 coordinate_type: Some(crate::client_server_contract::client_server_contract::floating_coordinate::CoordinateType::Fixed(f as u32)),
3269 },
3270 }
3271 }
3272}
3273
3274impl TryFrom<crate::client_server_contract::client_server_contract::FloatingCoordinate>
3276 for crate::input::layout::PercentOrFixed
3277{
3278 type Error = anyhow::Error;
3279 fn try_from(
3280 coord: crate::client_server_contract::client_server_contract::FloatingCoordinate,
3281 ) -> Result<Self> {
3282 use crate::client_server_contract::client_server_contract::floating_coordinate::CoordinateType;
3283 match coord
3284 .coordinate_type
3285 .ok_or_else(|| anyhow!("FloatingCoordinate missing coordinate_type"))?
3286 {
3287 CoordinateType::Percent(p) => {
3288 Ok(crate::input::layout::PercentOrFixed::Percent(p as usize))
3289 },
3290 CoordinateType::Fixed(f) => Ok(crate::input::layout::PercentOrFixed::Fixed(f as usize)),
3291 }
3292 }
3293}
3294
3295impl From<crate::data::FloatingPaneCoordinates>
3297 for crate::client_server_contract::client_server_contract::FloatingPaneCoordinates
3298{
3299 fn from(coords: crate::data::FloatingPaneCoordinates) -> Self {
3300 Self {
3301 x: coords.x.map(|x| x.into()),
3302 y: coords.y.map(|y| y.into()),
3303 width: coords.width.map(|w| w.into()),
3304 height: coords.height.map(|h| h.into()),
3305 pinned: coords.pinned,
3306 borderless: coords.borderless,
3307 }
3308 }
3309}
3310
3311impl TryFrom<crate::client_server_contract::client_server_contract::FloatingPaneCoordinates>
3313 for crate::data::FloatingPaneCoordinates
3314{
3315 type Error = anyhow::Error;
3316 fn try_from(
3317 coords: crate::client_server_contract::client_server_contract::FloatingPaneCoordinates,
3318 ) -> Result<Self> {
3319 Ok(Self {
3320 x: coords.x.map(|x| x.try_into()).transpose()?,
3321 y: coords.y.map(|y| y.try_into()).transpose()?,
3322 width: coords.width.map(|w| w.try_into()).transpose()?,
3323 height: coords.height.map(|h| h.try_into()).transpose()?,
3324 pinned: coords.pinned,
3325 borderless: coords.borderless,
3326 })
3327 }
3328}
3329
3330impl From<crate::data::NewPanePlacement>
3332 for crate::client_server_contract::client_server_contract::NewPanePlacement
3333{
3334 fn from(placement: crate::data::NewPanePlacement) -> Self {
3335 use crate::client_server_contract::client_server_contract::new_pane_placement::PlacementType;
3336 use crate::client_server_contract::client_server_contract::{
3337 NoPreferencePlacement, StackedPlacement, TiledPlacement,
3338 };
3339 let placement_type = match placement {
3340 crate::data::NewPanePlacement::NoPreference {
3341 borderless: Some(b),
3342 } => PlacementType::NoPreferenceWithOptions(NoPreferencePlacement {
3343 borderless: Some(b),
3344 }),
3345 crate::data::NewPanePlacement::NoPreference { borderless: None } => {
3346 PlacementType::NoPreference(true)
3347 },
3348 crate::data::NewPanePlacement::Tiled {
3349 direction,
3350 borderless: Some(b),
3351 } => PlacementType::TiledWithOptions(TiledPlacement {
3352 direction: direction.map(direction_to_proto_i32),
3353 borderless: Some(b),
3354 }),
3355 crate::data::NewPanePlacement::Tiled {
3356 direction,
3357 borderless: None,
3358 } => PlacementType::Tiled(direction.map(direction_to_proto_i32).unwrap_or(0)),
3359 crate::data::NewPanePlacement::Floating(coords) => {
3360 PlacementType::Floating(coords.map(|c| c.into()).unwrap_or_default())
3361 },
3362 crate::data::NewPanePlacement::InPlace {
3363 pane_id_to_replace,
3364 close_replaced_pane,
3365 borderless,
3366 } => PlacementType::InPlace(
3367 crate::client_server_contract::client_server_contract::NewPanePlacementInPlace {
3368 pane_id_to_replace: pane_id_to_replace.map(|id| id.into()),
3369 close_replaced_pane,
3370 borderless,
3371 },
3372 ),
3373 crate::data::NewPanePlacement::Stacked {
3374 pane_id_to_stack_under,
3375 borderless: Some(b),
3376 } => PlacementType::StackedWithOptions(StackedPlacement {
3377 pane_id_to_stack_under: pane_id_to_stack_under.map(|id| id.into()),
3378 borderless: Some(b),
3379 }),
3380 crate::data::NewPanePlacement::Stacked {
3381 pane_id_to_stack_under,
3382 borderless: None,
3383 } => PlacementType::Stacked(
3384 pane_id_to_stack_under
3385 .map(|id| id.into())
3386 .unwrap_or_default(),
3387 ),
3388 };
3389 Self {
3390 placement_type: Some(placement_type),
3391 }
3392 }
3393}
3394
3395impl TryFrom<crate::client_server_contract::client_server_contract::NewPanePlacement>
3397 for crate::data::NewPanePlacement
3398{
3399 type Error = anyhow::Error;
3400 fn try_from(
3401 placement: crate::client_server_contract::client_server_contract::NewPanePlacement,
3402 ) -> Result<Self> {
3403 use crate::client_server_contract::client_server_contract::new_pane_placement::PlacementType;
3404 match placement
3405 .placement_type
3406 .ok_or_else(|| anyhow!("NewPanePlacement missing placement_type"))?
3407 {
3408 PlacementType::NoPreferenceWithOptions(opts) => {
3410 Ok(crate::data::NewPanePlacement::NoPreference {
3411 borderless: opts.borderless,
3412 })
3413 },
3414 PlacementType::TiledWithOptions(opts) => {
3415 let direction = opts.direction.map(proto_i32_to_direction).transpose()?;
3416 Ok(crate::data::NewPanePlacement::Tiled {
3417 direction,
3418 borderless: opts.borderless,
3419 })
3420 },
3421 PlacementType::StackedWithOptions(opts) => {
3422 let pane_id = opts
3423 .pane_id_to_stack_under
3424 .map(|id| id.try_into())
3425 .transpose()?;
3426 Ok(crate::data::NewPanePlacement::Stacked {
3427 pane_id_to_stack_under: pane_id,
3428 borderless: opts.borderless,
3429 })
3430 },
3431 PlacementType::NoPreference(_) => {
3433 Ok(crate::data::NewPanePlacement::NoPreference { borderless: None })
3434 },
3435 PlacementType::Tiled(direction) => {
3436 let direction = if direction == 0 {
3437 None
3438 } else {
3439 Some(proto_i32_to_direction(direction)?)
3440 };
3441 Ok(crate::data::NewPanePlacement::Tiled {
3442 direction,
3443 borderless: None,
3444 })
3445 },
3446 PlacementType::Floating(coords) => {
3447 let coords = if coords == Default::default() {
3448 None
3449 } else {
3450 Some(coords.try_into()?)
3451 };
3452 Ok(crate::data::NewPanePlacement::Floating(coords))
3453 },
3454 PlacementType::InPlace(in_place) => Ok(crate::data::NewPanePlacement::InPlace {
3455 pane_id_to_replace: in_place
3456 .pane_id_to_replace
3457 .map(|id| id.try_into())
3458 .transpose()?,
3459 close_replaced_pane: in_place.close_replaced_pane,
3460 borderless: in_place.borderless,
3461 }),
3462 PlacementType::Stacked(pane_id) => {
3463 let pane_id = if pane_id == Default::default() {
3464 None
3465 } else {
3466 Some(pane_id.try_into()?)
3467 };
3468 Ok(crate::data::NewPanePlacement::Stacked {
3469 pane_id_to_stack_under: pane_id,
3470 borderless: None,
3471 })
3472 },
3473 }
3474 }
3475}
3476
3477impl From<crate::input::mouse::MouseEvent>
3479 for crate::client_server_contract::client_server_contract::MouseEvent
3480{
3481 fn from(event: crate::input::mouse::MouseEvent) -> Self {
3482 use crate::client_server_contract::client_server_contract::{
3483 MouseEventType as ProtoMouseEventType, Position,
3484 };
3485
3486 let position = Position {
3487 line: event.position.line.0 as i32,
3488 column: event.position.column.0 as u64,
3489 };
3490
3491 let event_type = match event.event_type {
3492 crate::input::mouse::MouseEventType::Press => ProtoMouseEventType::Press as i32,
3493 crate::input::mouse::MouseEventType::Release => ProtoMouseEventType::Release as i32,
3494 crate::input::mouse::MouseEventType::Motion => ProtoMouseEventType::Motion as i32,
3495 };
3496
3497 Self {
3498 event_type,
3499 left: event.left,
3500 right: event.right,
3501 middle: event.middle,
3502 wheel_up: event.wheel_up,
3503 wheel_down: event.wheel_down,
3504 shift: event.shift,
3505 alt: event.alt,
3506 ctrl: event.ctrl,
3507 position: Some(position),
3508 }
3509 }
3510}
3511
3512impl From<crate::input::command::RunCommandAction>
3514 for crate::client_server_contract::client_server_contract::RunCommandAction
3515{
3516 fn from(action: crate::input::command::RunCommandAction) -> Self {
3517 Self {
3518 command: action.command.to_string_lossy().to_string(),
3519 args: action.args,
3520 cwd: action.cwd.map(|p| p.to_string_lossy().to_string()),
3521 direction: action.direction.map(|d| direction_to_proto_i32(d)),
3522 hold_on_close: action.hold_on_close,
3523 hold_on_start: action.hold_on_start,
3524 originating_plugin: action.originating_plugin.map(|op| op.into()),
3525 use_terminal_title: action.use_terminal_title,
3526 }
3527 }
3528}
3529
3530impl From<crate::data::OriginatingPlugin>
3532 for crate::client_server_contract::client_server_contract::OriginatingPlugin
3533{
3534 fn from(orig: crate::data::OriginatingPlugin) -> Self {
3535 use std::collections::HashMap;
3536 let context: HashMap<String, String> =
3537 orig.context.into_iter().map(|(k, v)| (k, v)).collect();
3538
3539 Self {
3540 plugin_id: orig.plugin_id,
3541 client_id: orig.client_id as u32,
3542 context,
3543 }
3544 }
3545}
3546
3547impl TryFrom<crate::client_server_contract::client_server_contract::OriginatingPlugin>
3549 for crate::data::OriginatingPlugin
3550{
3551 type Error = anyhow::Error;
3552
3553 fn try_from(
3554 orig: crate::client_server_contract::client_server_contract::OriginatingPlugin,
3555 ) -> Result<Self> {
3556 use std::collections::BTreeMap;
3557 let context: BTreeMap<String, String> = orig.context.into_iter().collect();
3558
3559 Ok(Self {
3560 plugin_id: orig.plugin_id,
3561 client_id: orig.client_id as u16,
3562 context,
3563 })
3564 }
3565}
3566
3567fn split_direction_to_proto_i32(direction: crate::input::layout::SplitDirection) -> i32 {
3569 use crate::client_server_contract::client_server_contract::SplitDirection as ProtoSplitDirection;
3570 match direction {
3571 crate::input::layout::SplitDirection::Horizontal => ProtoSplitDirection::Horizontal as i32,
3572 crate::input::layout::SplitDirection::Vertical => ProtoSplitDirection::Vertical as i32,
3573 }
3574}
3575
3576impl From<crate::input::layout::SplitSize>
3578 for crate::client_server_contract::client_server_contract::SplitSize
3579{
3580 fn from(size: crate::input::layout::SplitSize) -> Self {
3581 use crate::client_server_contract::client_server_contract::split_size::SizeType;
3582 match size {
3583 crate::input::layout::SplitSize::Percent(p) => Self {
3584 size_type: Some(SizeType::Percent(p as u32)),
3585 },
3586 crate::input::layout::SplitSize::Fixed(f) => Self {
3587 size_type: Some(SizeType::Fixed(f as u32)),
3588 },
3589 }
3590 }
3591}
3592
3593impl From<crate::input::layout::PercentOrFixed>
3595 for crate::client_server_contract::client_server_contract::PercentOrFixed
3596{
3597 fn from(size: crate::input::layout::PercentOrFixed) -> Self {
3598 use crate::client_server_contract::client_server_contract::percent_or_fixed::SizeType;
3599 match size {
3600 crate::input::layout::PercentOrFixed::Percent(p) => Self {
3601 size_type: Some(SizeType::Percent(p as u32)),
3602 },
3603 crate::input::layout::PercentOrFixed::Fixed(f) => Self {
3604 size_type: Some(SizeType::Fixed(f as u32)),
3605 },
3606 }
3607 }
3608}
3609
3610impl From<crate::input::layout::Run>
3612 for crate::client_server_contract::client_server_contract::Run
3613{
3614 fn from(run: crate::input::layout::Run) -> Self {
3615 use crate::client_server_contract::client_server_contract::run::RunType;
3616 match run {
3617 crate::input::layout::Run::Command(cmd) => Self {
3618 run_type: Some(RunType::Command(
3619 crate::client_server_contract::client_server_contract::RunCommandAction {
3620 command: cmd.command.to_string_lossy().to_string(),
3621 args: cmd.args,
3622 cwd: cmd.cwd.map(|p| p.to_string_lossy().to_string()),
3623 direction: None, hold_on_close: cmd.hold_on_close,
3625 hold_on_start: cmd.hold_on_start,
3626 originating_plugin: cmd.originating_plugin.map(|op| op.into()),
3627 use_terminal_title: cmd.use_terminal_title,
3628 },
3629 )),
3630 },
3631 crate::input::layout::Run::Plugin(plugin) => Self {
3632 run_type: Some(RunType::Plugin(plugin.into())),
3633 },
3634 crate::input::layout::Run::EditFile(path, line_number, cwd) => Self {
3635 run_type: Some(RunType::EditFile(
3636 crate::client_server_contract::client_server_contract::RunEditFileAction {
3637 file_path: path.to_string_lossy().to_string(),
3638 line_number: line_number.map(|n| n as u32),
3639 cwd: cwd.map(|p| p.to_string_lossy().to_string()),
3640 },
3641 )),
3642 },
3643 crate::input::layout::Run::Cwd(path) => Self {
3644 run_type: Some(RunType::Cwd(path.to_string_lossy().to_string())),
3645 },
3646 }
3647 }
3648}
3649
3650impl From<crate::input::layout::TabLayoutInfo>
3652 for crate::client_server_contract::client_server_contract::TabLayoutInfo
3653{
3654 fn from(tab_info: crate::input::layout::TabLayoutInfo) -> Self {
3655 Self {
3656 tab_index: tab_info.tab_index as u32,
3657 tab_name: tab_info.tab_name,
3658 tiled_layout: Some(tab_info.tiled_layout.into()),
3659 floating_layouts: tab_info
3660 .floating_layouts
3661 .into_iter()
3662 .map(|l| l.into())
3663 .collect(),
3664 swap_tiled_layouts: tab_info
3665 .swap_tiled_layouts
3666 .unwrap_or_default()
3667 .into_iter()
3668 .map(|l| l.into())
3669 .collect(),
3670 swap_floating_layouts: tab_info
3671 .swap_floating_layouts
3672 .unwrap_or_default()
3673 .into_iter()
3674 .map(|l| l.into())
3675 .collect(),
3676 }
3677 }
3678}
3679
3680impl TryFrom<crate::client_server_contract::client_server_contract::TabLayoutInfo>
3681 for crate::input::layout::TabLayoutInfo
3682{
3683 type Error = anyhow::Error;
3684
3685 fn try_from(
3686 protobuf_tab: crate::client_server_contract::client_server_contract::TabLayoutInfo,
3687 ) -> Result<Self> {
3688 Ok(crate::input::layout::TabLayoutInfo {
3689 tab_index: protobuf_tab.tab_index as usize,
3690 tab_name: protobuf_tab.tab_name.filter(|s| !s.is_empty()),
3691 tiled_layout: protobuf_tab
3692 .tiled_layout
3693 .ok_or_else(|| anyhow!("missing tiled_layout"))?
3694 .try_into()?,
3695 floating_layouts: protobuf_tab
3696 .floating_layouts
3697 .into_iter()
3698 .map(|l| l.try_into())
3699 .collect::<Result<Vec<_>>>()?,
3700 swap_tiled_layouts: if protobuf_tab.swap_tiled_layouts.is_empty() {
3701 None
3702 } else {
3703 Some(
3704 protobuf_tab
3705 .swap_tiled_layouts
3706 .into_iter()
3707 .map(|l| l.try_into())
3708 .collect::<Result<Vec<_>>>()?,
3709 )
3710 },
3711 swap_floating_layouts: if protobuf_tab.swap_floating_layouts.is_empty() {
3712 None
3713 } else {
3714 Some(
3715 protobuf_tab
3716 .swap_floating_layouts
3717 .into_iter()
3718 .map(|l| l.try_into())
3719 .collect::<Result<Vec<_>>>()?,
3720 )
3721 },
3722 })
3723 }
3724}
3725
3726impl From<crate::input::layout::TiledPaneLayout>
3728 for crate::client_server_contract::client_server_contract::TiledPaneLayout
3729{
3730 fn from(layout: crate::input::layout::TiledPaneLayout) -> Self {
3731 Self {
3732 children_split_direction: split_direction_to_proto_i32(layout.children_split_direction),
3733 name: layout.name,
3734 children: layout.children.into_iter().map(|c| c.into()).collect(),
3735 split_size: layout.split_size.map(|s| s.into()),
3736 run: layout.run.map(|r| r.into()),
3737 borderless: layout.borderless,
3738 focus: layout.focus.map(|f| f.to_string()),
3739 exclude_from_sync: layout.exclude_from_sync,
3740 children_are_stacked: layout.children_are_stacked,
3741 external_children_index: layout.external_children_index.map(|l| l as u32),
3742 is_expanded_in_stack: layout.is_expanded_in_stack,
3743 hide_floating_panes: layout.hide_floating_panes,
3744 pane_initial_contents: layout.pane_initial_contents,
3745 default_fg: layout.default_fg,
3746 default_bg: layout.default_bg,
3747 }
3748 }
3749}
3750
3751impl From<crate::input::layout::FloatingPaneLayout>
3752 for crate::client_server_contract::client_server_contract::FloatingPaneLayout
3753{
3754 fn from(layout: crate::input::layout::FloatingPaneLayout) -> Self {
3755 Self {
3756 name: layout.name,
3757 height: layout.height.map(|h| h.into()),
3758 width: layout.width.map(|w| w.into()),
3759 x: layout.x.map(|x| x.into()),
3760 y: layout.y.map(|y| y.into()),
3761 pinned: layout.pinned,
3762 run: layout.run.map(|r| r.into()),
3763 focus: layout.focus,
3764 already_running: layout.already_running,
3765 pane_initial_contents: layout.pane_initial_contents,
3766 logical_position: layout.logical_position.map(|l| l as u32),
3767 borderless: layout.borderless,
3768 default_fg: layout.default_fg,
3769 default_bg: layout.default_bg,
3770 }
3771 }
3772}
3773
3774impl From<crate::input::layout::SwapTiledLayout>
3775 for crate::client_server_contract::client_server_contract::SwapTiledLayout
3776{
3777 fn from(layout: crate::input::layout::SwapTiledLayout) -> Self {
3778 use crate::client_server_contract::client_server_contract::LayoutConstraintTiledPair;
3779
3780 let constraint_map = layout
3781 .0
3782 .into_iter()
3783 .map(|(constraint, tiled_layout)| LayoutConstraintTiledPair {
3784 constraint: Some(constraint.into()),
3785 layout: Some(tiled_layout.into()),
3786 })
3787 .collect();
3788
3789 Self {
3790 constraint_map,
3791 name: layout.1,
3792 }
3793 }
3794}
3795
3796impl From<crate::input::layout::SwapFloatingLayout>
3797 for crate::client_server_contract::client_server_contract::SwapFloatingLayout
3798{
3799 fn from(layout: crate::input::layout::SwapFloatingLayout) -> Self {
3800 use crate::client_server_contract::client_server_contract::LayoutConstraintFloatingPair;
3801
3802 let constraint_map = layout
3803 .0
3804 .into_iter()
3805 .map(
3806 |(constraint, floating_layouts)| LayoutConstraintFloatingPair {
3807 constraint: Some(constraint.into()),
3808 layouts: floating_layouts.into_iter().map(|l| l.into()).collect(),
3809 },
3810 )
3811 .collect();
3812
3813 Self {
3814 constraint_map,
3815 name: layout.1,
3816 }
3817 }
3818}
3819
3820impl From<crate::input::layout::PluginUserConfiguration>
3822 for crate::client_server_contract::client_server_contract::PluginUserConfiguration
3823{
3824 fn from(config: crate::input::layout::PluginUserConfiguration) -> Self {
3825 Self {
3826 configuration: config.inner().clone().into_iter().collect(), }
3828 }
3829}
3830
3831impl From<crate::input::layout::LayoutConstraint>
3833 for crate::client_server_contract::client_server_contract::LayoutConstraintWithValue
3834{
3835 fn from(constraint: crate::input::layout::LayoutConstraint) -> Self {
3836 use crate::client_server_contract::client_server_contract::LayoutConstraint as ProtoLayoutConstraint;
3837 match constraint {
3838 crate::input::layout::LayoutConstraint::MaxPanes(n) => Self {
3839 constraint_type: ProtoLayoutConstraint::MaxPanes as i32,
3840 value: Some(n as u32),
3841 },
3842 crate::input::layout::LayoutConstraint::MinPanes(n) => Self {
3843 constraint_type: ProtoLayoutConstraint::MinPanes as i32,
3844 value: Some(n as u32),
3845 },
3846 crate::input::layout::LayoutConstraint::ExactPanes(n) => Self {
3847 constraint_type: ProtoLayoutConstraint::ExactPanes as i32,
3848 value: Some(n as u32),
3849 },
3850 crate::input::layout::LayoutConstraint::NoConstraint => Self {
3851 constraint_type: ProtoLayoutConstraint::NoConstraint as i32,
3852 value: None,
3853 },
3854 }
3855 }
3856}
3857
3858impl From<crate::input::layout::RunPlugin>
3860 for crate::client_server_contract::client_server_contract::RunPlugin
3861{
3862 fn from(plugin: crate::input::layout::RunPlugin) -> Self {
3863 Self {
3864 allow_exec_host_cmd: plugin._allow_exec_host_cmd,
3865 location: Some(plugin.location.into()),
3866 configuration: Some(plugin.configuration.into()),
3867 initial_cwd: plugin.initial_cwd.map(|p| p.display().to_string()),
3868 }
3869 }
3870}
3871
3872impl From<crate::input::layout::PluginAlias>
3874 for crate::client_server_contract::client_server_contract::PluginAlias
3875{
3876 fn from(plugin: crate::input::layout::PluginAlias) -> Self {
3877 Self {
3878 name: plugin.name,
3879 configuration: plugin.configuration.map(|c| c.into()),
3880 initial_cwd: plugin.initial_cwd.map(|i| i.display().to_string()),
3881 run_plugin: plugin.run_plugin.map(|r| r.into()),
3882 }
3883 }
3884}
3885
3886impl From<crate::input::layout::RunPluginLocation>
3888 for crate::client_server_contract::client_server_contract::RunPluginLocationData
3889{
3890 fn from(location: crate::input::layout::RunPluginLocation) -> Self {
3891 use crate::client_server_contract::client_server_contract::{
3892 run_plugin_location_data::LocationData, RunPluginLocation as ProtoRunPluginLocation,
3893 };
3894 match location {
3895 crate::input::layout::RunPluginLocation::File(path) => Self {
3896 location_type: ProtoRunPluginLocation::File as i32,
3897 location_data: Some(LocationData::FilePath(path.to_string_lossy().to_string())),
3898 },
3899 crate::input::layout::RunPluginLocation::Zellij(tag) => Self {
3900 location_type: ProtoRunPluginLocation::Zellij as i32,
3901 location_data: Some(LocationData::ZellijTag(
3902 crate::client_server_contract::client_server_contract::PluginTag {
3903 tag: tag.to_string(),
3904 },
3905 )),
3906 },
3907 crate::input::layout::RunPluginLocation::Remote(url) => Self {
3908 location_type: ProtoRunPluginLocation::Remote as i32,
3909 location_data: Some(LocationData::RemoteUrl(url)),
3910 },
3911 }
3912 }
3913}
3914
3915impl From<crate::input::layout::RunPluginOrAlias>
3917 for crate::client_server_contract::client_server_contract::RunPluginOrAlias
3918{
3919 fn from(plugin: crate::input::layout::RunPluginOrAlias) -> Self {
3920 use crate::client_server_contract::client_server_contract::run_plugin_or_alias::PluginType;
3921 match plugin {
3922 crate::input::layout::RunPluginOrAlias::RunPlugin(run_plugin) => Self {
3923 plugin_type: Some(PluginType::Plugin(run_plugin.into())),
3924 },
3925 crate::input::layout::RunPluginOrAlias::Alias(alias) => Self {
3926 plugin_type: Some(PluginType::Alias(alias.into())),
3927 },
3928 }
3929 }
3930}
3931
3932impl From<crate::data::CommandOrPlugin>
3934 for crate::client_server_contract::client_server_contract::CommandOrPlugin
3935{
3936 fn from(cmd_or_plugin: crate::data::CommandOrPlugin) -> Self {
3937 use crate::client_server_contract::client_server_contract::command_or_plugin::CommandOrPluginType;
3938 use crate::client_server_contract::client_server_contract::CommandOrPluginFile;
3939 match cmd_or_plugin {
3940 crate::data::CommandOrPlugin::Command(cmd) => Self {
3941 command_or_plugin_type: Some(CommandOrPluginType::Command(cmd.into())),
3942 },
3943 crate::data::CommandOrPlugin::Plugin(plugin) => Self {
3944 command_or_plugin_type: Some(CommandOrPluginType::Plugin(plugin.into())),
3945 },
3946 crate::data::CommandOrPlugin::File(f) => Self {
3947 command_or_plugin_type: Some(CommandOrPluginType::File(CommandOrPluginFile {
3948 path: f.path.display().to_string(),
3949 line_number: f.line_number.map(|n| n as i32),
3950 cwd: f.cwd.map(|c| c.display().to_string()),
3951 })),
3952 },
3953 }
3954 }
3955}
3956
3957impl TryFrom<crate::client_server_contract::client_server_contract::CommandOrPlugin>
3958 for crate::data::CommandOrPlugin
3959{
3960 type Error = anyhow::Error;
3961
3962 fn try_from(
3963 proto: crate::client_server_contract::client_server_contract::CommandOrPlugin,
3964 ) -> Result<Self> {
3965 use crate::client_server_contract::client_server_contract::command_or_plugin::CommandOrPluginType;
3966
3967 let cmd_or_plugin_type = proto
3968 .command_or_plugin_type
3969 .ok_or_else(|| anyhow!("CommandOrPlugin missing command_or_plugin_type"))?;
3970 match cmd_or_plugin_type {
3971 CommandOrPluginType::Command(cmd) => {
3972 Ok(crate::data::CommandOrPlugin::Command(cmd.try_into()?))
3973 },
3974 CommandOrPluginType::Plugin(plugin) => {
3975 Ok(crate::data::CommandOrPlugin::Plugin(plugin.try_into()?))
3976 },
3977 CommandOrPluginType::File(f) => Ok(crate::data::CommandOrPlugin::File(
3978 crate::data::FileToOpen {
3979 path: std::path::PathBuf::from(&f.path),
3980 line_number: f.line_number.map(|n| n as usize),
3981 cwd: f.cwd.map(std::path::PathBuf::from),
3982 },
3983 )),
3984 }
3985 }
3986}
3987
3988impl TryFrom<crate::client_server_contract::client_server_contract::Run>
3990 for crate::input::layout::Run
3991{
3992 type Error = anyhow::Error;
3993
3994 fn try_from(run: crate::client_server_contract::client_server_contract::Run) -> Result<Self> {
3995 use crate::client_server_contract::client_server_contract::run::RunType;
3996
3997 let run_type = run
3998 .run_type
3999 .ok_or_else(|| anyhow!("Run missing run_type"))?;
4000 match run_type {
4001 RunType::Command(cmd) => Ok(crate::input::layout::Run::Command(
4002 crate::input::command::RunCommand {
4003 command: std::path::PathBuf::from(cmd.command),
4004 args: cmd.args,
4005 cwd: cmd.cwd.map(std::path::PathBuf::from),
4006 hold_on_close: cmd.hold_on_close,
4007 hold_on_start: cmd.hold_on_start,
4008 originating_plugin: cmd
4009 .originating_plugin
4010 .map(|op| op.try_into())
4011 .transpose()?,
4012 use_terminal_title: cmd.use_terminal_title,
4013 },
4014 )),
4015 RunType::EditFile(edit) => Ok(crate::input::layout::Run::EditFile(
4016 std::path::PathBuf::from(edit.file_path),
4017 edit.line_number.map(|n| n as usize),
4018 edit.cwd.map(std::path::PathBuf::from),
4019 )),
4020 RunType::Cwd(cwd_str) => Ok(crate::input::layout::Run::Cwd(std::path::PathBuf::from(
4021 cwd_str,
4022 ))),
4023 RunType::Plugin(plugin) => Ok(crate::input::layout::Run::Plugin(plugin.try_into()?)),
4024 }
4025 }
4026}
4027
4028impl TryFrom<crate::client_server_contract::client_server_contract::PercentOrFixed>
4030 for crate::input::layout::PercentOrFixed
4031{
4032 type Error = anyhow::Error;
4033
4034 fn try_from(
4035 value: crate::client_server_contract::client_server_contract::PercentOrFixed,
4036 ) -> Result<Self> {
4037 use crate::client_server_contract::client_server_contract::percent_or_fixed::SizeType;
4038
4039 let size_type = value
4040 .size_type
4041 .ok_or_else(|| anyhow!("PercentOrFixed missing size_type"))?;
4042 match size_type {
4043 SizeType::Percent(percent) => Ok(crate::input::layout::PercentOrFixed::Percent(
4044 percent as usize,
4045 )),
4046 SizeType::Fixed(fixed) => {
4047 Ok(crate::input::layout::PercentOrFixed::Fixed(fixed as usize))
4048 },
4049 }
4050 }
4051}
4052
4053impl TryFrom<crate::client_server_contract::client_server_contract::MouseEvent>
4057 for crate::input::mouse::MouseEvent
4058{
4059 type Error = anyhow::Error;
4060
4061 fn try_from(
4062 event: crate::client_server_contract::client_server_contract::MouseEvent,
4063 ) -> Result<Self> {
4064 use crate::client_server_contract::client_server_contract::MouseEventType as ProtoMouseEventType;
4065
4066 let event_type = match event.event_type {
4067 x if x == ProtoMouseEventType::Press as i32 => {
4068 crate::input::mouse::MouseEventType::Press
4069 },
4070 x if x == ProtoMouseEventType::Release as i32 => {
4071 crate::input::mouse::MouseEventType::Release
4072 },
4073 x if x == ProtoMouseEventType::Motion as i32 => {
4074 crate::input::mouse::MouseEventType::Motion
4075 },
4076 _ => return Err(anyhow!("Invalid MouseEventType: {}", event.event_type)),
4077 };
4078
4079 let position = event
4080 .position
4081 .ok_or_else(|| anyhow!("MouseEvent missing position"))?
4082 .try_into()?;
4083
4084 Ok(crate::input::mouse::MouseEvent {
4085 event_type,
4086 left: event.left,
4087 right: event.right,
4088 middle: event.middle,
4089 wheel_up: event.wheel_up,
4090 wheel_down: event.wheel_down,
4091 shift: event.shift,
4092 alt: event.alt,
4093 ctrl: event.ctrl,
4094 position,
4095 })
4096 }
4097}
4098
4099impl TryFrom<crate::client_server_contract::client_server_contract::RunCommandAction>
4101 for crate::input::command::RunCommandAction
4102{
4103 type Error = anyhow::Error;
4104
4105 fn try_from(
4106 action: crate::client_server_contract::client_server_contract::RunCommandAction,
4107 ) -> Result<Self> {
4108 Ok(crate::input::command::RunCommandAction {
4109 command: std::path::PathBuf::from(action.command),
4110 args: action.args,
4111 cwd: action.cwd.map(std::path::PathBuf::from),
4112 direction: action.direction.map(proto_i32_to_direction).transpose()?,
4113 hold_on_close: action.hold_on_close,
4114 hold_on_start: action.hold_on_start,
4115 originating_plugin: action
4116 .originating_plugin
4117 .map(|op| op.try_into())
4118 .transpose()?,
4119 use_terminal_title: action.use_terminal_title,
4120 })
4121 }
4122}
4123
4124impl TryFrom<crate::client_server_contract::client_server_contract::TiledPaneLayout>
4126 for crate::input::layout::TiledPaneLayout
4127{
4128 type Error = anyhow::Error;
4129
4130 fn try_from(
4131 layout: crate::client_server_contract::client_server_contract::TiledPaneLayout,
4132 ) -> Result<Self> {
4133 use crate::input::layout::{SplitDirection, SplitSize, TiledPaneLayout};
4134
4135 let children_split_direction = match layout.children_split_direction {
4136 x if x
4137 == crate::client_server_contract::client_server_contract::SplitDirection::Horizontal
4138 as i32 =>
4139 {
4140 SplitDirection::Horizontal
4141 },
4142 x if x
4143 == crate::client_server_contract::client_server_contract::SplitDirection::Vertical
4144 as i32 =>
4145 {
4146 SplitDirection::Vertical
4147 },
4148 _ => SplitDirection::Horizontal, };
4150
4151 let children: Result<Vec<_>> = layout.children.into_iter().map(|c| c.try_into()).collect();
4152 let run = layout.run.map(|r| r.try_into()).transpose()?;
4153
4154 let split_size = layout.split_size.and_then(|size| {
4155 use crate::client_server_contract::client_server_contract::split_size::SizeType;
4156 match size.size_type {
4157 Some(SizeType::Percent(percent)) => Some(SplitSize::Percent(percent as usize)),
4158 Some(SizeType::Fixed(fixed)) => Some(SplitSize::Fixed(fixed as usize)),
4159 None => None,
4160 }
4161 });
4162
4163 Ok(TiledPaneLayout {
4164 children_split_direction,
4165 name: layout.name,
4166 children: children?,
4167 split_size,
4168 run,
4169 borderless: layout.borderless,
4170 focus: layout.focus.map(|f| f == "true"), external_children_index: layout.external_children_index.map(|l| l as usize),
4172 children_are_stacked: layout.children_are_stacked,
4173 is_expanded_in_stack: layout.is_expanded_in_stack,
4174 exclude_from_sync: layout.exclude_from_sync,
4175 run_instructions_to_ignore: vec![], hide_floating_panes: layout.hide_floating_panes,
4177 pane_initial_contents: layout.pane_initial_contents,
4178 default_fg: layout.default_fg,
4179 default_bg: layout.default_bg,
4180 })
4181 }
4182}
4183
4184impl TryFrom<crate::client_server_contract::client_server_contract::FloatingPaneLayout>
4186 for crate::input::layout::FloatingPaneLayout
4187{
4188 type Error = anyhow::Error;
4189
4190 fn try_from(
4191 layout: crate::client_server_contract::client_server_contract::FloatingPaneLayout,
4192 ) -> Result<Self> {
4193 let run = layout.run.map(|r| r.try_into()).transpose()?;
4194 let height = layout.height.map(|h| h.try_into()).transpose()?;
4195 let width = layout.width.map(|w| w.try_into()).transpose()?;
4196 let x = layout.x.map(|x| x.try_into()).transpose()?;
4197 let y = layout.y.map(|y| y.try_into()).transpose()?;
4198
4199 Ok(crate::input::layout::FloatingPaneLayout {
4200 name: layout.name,
4201 height,
4202 width,
4203 x,
4204 y,
4205 pinned: layout.pinned,
4206 run,
4207 focus: layout.focus,
4208 already_running: layout.already_running,
4209 pane_initial_contents: layout.pane_initial_contents,
4210 logical_position: layout.logical_position.map(|p| p as usize),
4211 borderless: layout.borderless,
4212 default_fg: layout.default_fg,
4213 default_bg: layout.default_bg,
4214 })
4215 }
4216}
4217
4218impl TryFrom<crate::client_server_contract::client_server_contract::SwapTiledLayout>
4220 for crate::input::layout::SwapTiledLayout
4221{
4222 type Error = anyhow::Error;
4223
4224 fn try_from(
4225 layout: crate::client_server_contract::client_server_contract::SwapTiledLayout,
4226 ) -> Result<Self> {
4227 let constraint_map: Result<BTreeMap<_, _>> = layout
4228 .constraint_map
4229 .into_iter()
4230 .map(|pair| {
4231 Ok((
4232 pair.constraint
4233 .ok_or_else(|| anyhow!("Missing constraint"))?
4234 .try_into()?,
4235 pair.layout
4236 .ok_or_else(|| anyhow!("Missing layout"))?
4237 .try_into()?,
4238 ))
4239 })
4240 .collect();
4241 Ok((constraint_map?, layout.name))
4242 }
4243}
4244
4245impl TryFrom<crate::client_server_contract::client_server_contract::SwapFloatingLayout>
4247 for crate::input::layout::SwapFloatingLayout
4248{
4249 type Error = anyhow::Error;
4250
4251 fn try_from(
4252 layout: crate::client_server_contract::client_server_contract::SwapFloatingLayout,
4253 ) -> Result<Self> {
4254 let constraint_map: Result<BTreeMap<_, _>> = layout
4255 .constraint_map
4256 .into_iter()
4257 .map(|pair| {
4258 let floating_layouts: Result<Vec<_>> =
4259 pair.layouts.into_iter().map(|l| l.try_into()).collect();
4260 Ok((
4261 pair.constraint
4262 .ok_or_else(|| anyhow!("Missing constraint"))?
4263 .try_into()?,
4264 floating_layouts?,
4265 ))
4266 })
4267 .collect();
4268
4269 Ok((constraint_map?, layout.name))
4270 }
4271}
4272
4273impl TryFrom<crate::client_server_contract::client_server_contract::PluginUserConfiguration>
4275 for crate::input::layout::PluginUserConfiguration
4276{
4277 type Error = anyhow::Error;
4278
4279 fn try_from(
4280 config: crate::client_server_contract::client_server_contract::PluginUserConfiguration,
4281 ) -> Result<Self> {
4282 let btree_map: BTreeMap<String, String> = config.configuration.into_iter().collect();
4283 Ok(crate::input::layout::PluginUserConfiguration::new(
4284 btree_map,
4285 ))
4286 }
4287}
4288
4289impl TryFrom<crate::client_server_contract::client_server_contract::LayoutConstraintWithValue>
4291 for crate::input::layout::LayoutConstraint
4292{
4293 type Error = anyhow::Error;
4294
4295 fn try_from(
4296 constraint: crate::client_server_contract::client_server_contract::LayoutConstraintWithValue,
4297 ) -> Result<Self> {
4298 use crate::client_server_contract::client_server_contract::LayoutConstraint as ProtoLayoutConstraint;
4299 match constraint.constraint_type {
4300 x if x == ProtoLayoutConstraint::MaxPanes as i32 => {
4301 let value = constraint
4302 .value
4303 .ok_or_else(|| anyhow!("MaxPanes constraint missing value"))?
4304 as usize;
4305 Ok(crate::input::layout::LayoutConstraint::MaxPanes(value))
4306 },
4307 x if x == ProtoLayoutConstraint::MinPanes as i32 => {
4308 let value = constraint
4309 .value
4310 .ok_or_else(|| anyhow!("MinPanes constraint missing value"))?
4311 as usize;
4312 Ok(crate::input::layout::LayoutConstraint::MinPanes(value))
4313 },
4314 x if x == ProtoLayoutConstraint::ExactPanes as i32 => {
4315 let value = constraint
4316 .value
4317 .ok_or_else(|| anyhow!("ExactPanes constraint missing value"))?
4318 as usize;
4319 Ok(crate::input::layout::LayoutConstraint::ExactPanes(value))
4320 },
4321 x if x == ProtoLayoutConstraint::NoConstraint as i32 => {
4322 Ok(crate::input::layout::LayoutConstraint::NoConstraint)
4323 },
4324 _ => Err(anyhow!(
4325 "Invalid LayoutConstraint type: {}",
4326 constraint.constraint_type
4327 )),
4328 }
4329 }
4330}
4331
4332impl TryFrom<crate::client_server_contract::client_server_contract::RunPlugin>
4334 for crate::input::layout::RunPlugin
4335{
4336 type Error = anyhow::Error;
4337
4338 fn try_from(
4339 plugin: crate::client_server_contract::client_server_contract::RunPlugin,
4340 ) -> Result<Self> {
4341 let location = plugin
4342 .location
4343 .ok_or_else(|| anyhow!("RunPlugin missing location"))?
4344 .try_into()?;
4345 let configuration = plugin
4346 .configuration
4347 .ok_or_else(|| anyhow!("RunPlugin missing configuration"))?
4348 .try_into()?;
4349 let initial_cwd = plugin.initial_cwd.map(std::path::PathBuf::from);
4350
4351 Ok(crate::input::layout::RunPlugin {
4352 _allow_exec_host_cmd: plugin.allow_exec_host_cmd,
4353 location,
4354 configuration,
4355 initial_cwd,
4356 })
4357 }
4358}
4359
4360impl TryFrom<crate::client_server_contract::client_server_contract::PluginAlias>
4362 for crate::input::layout::PluginAlias
4363{
4364 type Error = anyhow::Error;
4365
4366 fn try_from(
4367 plugin_alias: crate::client_server_contract::client_server_contract::PluginAlias,
4368 ) -> Result<Self> {
4369 let run_plugin = plugin_alias.run_plugin.and_then(|r| r.try_into().ok());
4370 let configuration = plugin_alias.configuration.and_then(|c| c.try_into().ok());
4371 let initial_cwd = plugin_alias.initial_cwd.map(std::path::PathBuf::from);
4372 Ok(crate::input::layout::PluginAlias {
4373 name: plugin_alias.name,
4374 configuration,
4375 initial_cwd,
4376 run_plugin,
4377 })
4378 }
4379}
4380
4381impl TryFrom<crate::client_server_contract::client_server_contract::RunPluginLocationData>
4383 for crate::input::layout::RunPluginLocation
4384{
4385 type Error = anyhow::Error;
4386
4387 fn try_from(
4388 location: crate::client_server_contract::client_server_contract::RunPluginLocationData,
4389 ) -> Result<Self> {
4390 use crate::client_server_contract::client_server_contract::{
4391 run_plugin_location_data::LocationData, RunPluginLocation as ProtoRunPluginLocation,
4392 };
4393
4394 let location_data = location
4395 .location_data
4396 .ok_or_else(|| anyhow!("RunPluginLocationData missing location_data"))?;
4397 match location.location_type {
4398 x if x == ProtoRunPluginLocation::File as i32 => {
4399 if let LocationData::FilePath(path) = location_data {
4400 Ok(crate::input::layout::RunPluginLocation::File(
4401 std::path::PathBuf::from(path),
4402 ))
4403 } else {
4404 Err(anyhow!("File location type but wrong data variant"))
4405 }
4406 },
4407 x if x == ProtoRunPluginLocation::Zellij as i32 => {
4408 if let LocationData::ZellijTag(tag) = location_data {
4409 Ok(crate::input::layout::RunPluginLocation::Zellij(
4410 crate::data::PluginTag::new(tag.tag),
4411 ))
4412 } else {
4413 Err(anyhow!("Zellij location type but wrong data variant"))
4414 }
4415 },
4416 x if x == ProtoRunPluginLocation::Remote as i32 => {
4417 if let LocationData::RemoteUrl(url) = location_data {
4418 Ok(crate::input::layout::RunPluginLocation::Remote(url))
4419 } else {
4420 Err(anyhow!("Remote location type but wrong data variant"))
4421 }
4422 },
4423 _ => Err(anyhow!(
4424 "Invalid RunPluginLocation type: {}",
4425 location.location_type
4426 )),
4427 }
4428 }
4429}
4430
4431impl TryFrom<crate::client_server_contract::client_server_contract::RunPluginOrAlias>
4433 for crate::input::layout::RunPluginOrAlias
4434{
4435 type Error = anyhow::Error;
4436
4437 fn try_from(
4438 plugin: crate::client_server_contract::client_server_contract::RunPluginOrAlias,
4439 ) -> Result<Self> {
4440 use crate::client_server_contract::client_server_contract::run_plugin_or_alias::PluginType;
4441
4442 let plugin_type = plugin
4443 .plugin_type
4444 .ok_or_else(|| anyhow!("RunPluginOrAlias missing plugin_type"))?;
4445 match plugin_type {
4446 PluginType::Plugin(run_plugin) => Ok(
4447 crate::input::layout::RunPluginOrAlias::RunPlugin(run_plugin.try_into()?),
4448 ),
4449 PluginType::Alias(plugin_alias) => Ok(crate::input::layout::RunPluginOrAlias::Alias(
4450 plugin_alias.try_into()?,
4451 )),
4452 }
4453 }
4454}