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