1pub use super::generated_api::api::{
2 action::{Action as ProtobufAction, Position as ProtobufPosition},
3 event::{
4 event::Payload as ProtobufEventPayload,
5 layout_parsing_error::ErrorType as ProtobufLayoutParsingErrorType,
6 pane_scrollback_response, ActionCompletePayload as ProtobufActionCompletePayload,
7 ActivePaneScrollPayload as ProtobufActivePaneScrollPayload,
8 AvailableLayoutInfoPayload as ProtobufAvailableLayoutInfoPayload,
9 ClientInfo as ProtobufClientInfo, ClientPaneHistory as ProtobufClientPaneHistory,
10 ClientTabHistory as ProtobufClientTabHistory,
11 CommandChangedPayload as ProtobufCommandChangedPayload, ContextItem as ProtobufContextItem,
12 CopyDestination as ProtobufCopyDestination, CwdChangedPayload as ProtobufCwdChangedPayload,
13 Event as ProtobufEvent, EventNameList as ProtobufEventNameList,
14 EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata,
15 HintTextPayload as ProtobufHintTextPayload,
16 HostTerminalThemeChangedPayload as ProtobufHostTerminalThemeChangedPayload,
17 HostTerminalThemeIndication as ProtobufHostTerminalThemeIndication,
18 InputModeKeybinds as ProtobufInputModeKeybinds, KdlError as ProtobufKdlError,
19 KdlErrorVariant as ProtobufKdlErrorVariant, KeyBind as ProtobufKeyBind,
20 LayoutInfo as ProtobufLayoutInfo, LayoutMetadata as ProtobufLayoutMetadata,
21 LayoutParsingError as ProtobufLayoutParsingError,
22 LayoutWithError as ProtobufLayoutWithError, ModeUpdatePayload as ProtobufModeUpdatePayload,
23 PaneContents as ProtobufPaneContents, PaneContentsEntry as ProtobufPaneContentsEntry,
24 PaneFrameStyle as ProtobufPaneFrameStyle, PaneId as ProtobufPaneId,
25 PaneInfo as ProtobufPaneInfo, PaneManifest as ProtobufPaneManifest,
26 PaneMetadata as ProtobufPaneMetadata,
27 PaneRenderReportPayload as ProtobufPaneRenderReportPayload,
28 PaneScrollbackResponse as ProtobufPaneScrollbackResponse, PaneType as ProtobufPaneType,
29 PluginConfigurationChangedPayload as ProtobufPluginConfigurationChangedPayload,
30 PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession,
31 SelectedText as ProtobufSelectedText, SessionManifest as ProtobufSessionManifest,
32 SoftKeyboardVisibilityChangedPayload as ProtobufSoftKeyboardVisibilityChangedPayload,
33 StyledText as ProtobufStyledText, StyledTextIndices as ProtobufStyledTextIndices,
34 SyntaxError as ProtobufSyntaxError, TabInfo as ProtobufTabInfo,
35 TabMetadata as ProtobufTabMetadata, UserActionPayload as ProtobufUserActionPayload,
36 WebServerStatusPayload as ProtobufWebServerStatusPayload, WebSharing as ProtobufWebSharing,
37 *,
38 },
39 input_mode::InputMode as ProtobufInputMode,
40 key::Key as ProtobufKey,
41 style::Style as ProtobufStyle,
42};
43#[allow(hidden_glob_reexports)]
44use crate::data::{
45 ClientId, ClientInfo, CopyDestination, Event, EventType, FileMetadata, HostTerminalThemeMode,
46 InputMode, KeyWithModifier, LayoutInfo, LayoutMetadata, ModeInfo, Mouse, PaneContents, PaneId,
47 PaneInfo, PaneManifest, PaneMetadata, PaneScrollbackResponse, PermissionStatus,
48 PluginCapabilities, PluginInfo, SelectedText, SessionInfo, Style, StyledText, TabInfo,
49 TabMetadata, WebServerStatus, WebSharing,
50};
51
52use crate::errors::prelude::*;
53use crate::input::actions::Action;
54
55use std::collections::{BTreeMap, HashMap, HashSet};
56use std::convert::TryFrom;
57use std::net::IpAddr;
58use std::path::PathBuf;
59use std::str::FromStr;
60use std::time::Duration;
61
62impl TryFrom<ProtobufEvent> for Event {
63 type Error = &'static str;
64 fn try_from(protobuf_event: ProtobufEvent) -> Result<Self, &'static str> {
65 match ProtobufEventType::try_from(protobuf_event.name).ok() {
66 Some(ProtobufEventType::ModeUpdate) => match protobuf_event.payload {
67 Some(ProtobufEventPayload::ModeUpdatePayload(protobuf_mode_update_payload)) => {
68 let mode_info: ModeInfo = protobuf_mode_update_payload.try_into()?;
69 Ok(Event::ModeUpdate(mode_info))
70 },
71 _ => Err("Malformed payload for the ModeUpdate Event"),
72 },
73 Some(ProtobufEventType::TabUpdate) => match protobuf_event.payload {
74 Some(ProtobufEventPayload::TabUpdatePayload(protobuf_tab_info_payload)) => {
75 let mut tab_infos: Vec<TabInfo> = vec![];
76 for protobuf_tab_info in protobuf_tab_info_payload.tab_info {
77 tab_infos.push(TabInfo::try_from(protobuf_tab_info)?);
78 }
79 Ok(Event::TabUpdate(tab_infos))
80 },
81 _ => Err("Malformed payload for the TabUpdate Event"),
82 },
83 Some(ProtobufEventType::PaneUpdate) => match protobuf_event.payload {
84 Some(ProtobufEventPayload::PaneUpdatePayload(protobuf_pane_update_payload)) => {
85 let mut pane_manifest: HashMap<usize, Vec<PaneInfo>> = HashMap::new();
86 for protobuf_pane_manifest in protobuf_pane_update_payload.pane_manifest {
87 let tab_index = protobuf_pane_manifest.tab_index as usize;
88 let mut panes = vec![];
89 for protobuf_pane_info in protobuf_pane_manifest.panes {
90 panes.push(protobuf_pane_info.try_into()?);
91 }
92 if pane_manifest.contains_key(&tab_index) {
93 return Err("Duplicate tab definition in pane manifest");
94 }
95 pane_manifest.insert(tab_index, panes);
96 }
97 Ok(Event::PaneUpdate(PaneManifest {
98 panes: pane_manifest,
99 }))
100 },
101 _ => Err("Malformed payload for the PaneUpdate Event"),
102 },
103 Some(ProtobufEventType::Key) => match protobuf_event.payload {
104 Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => {
105 Ok(Event::Key(protobuf_key.try_into()?))
106 },
107 _ => Err("Malformed payload for the Key Event"),
108 },
109 Some(ProtobufEventType::Mouse) => match protobuf_event.payload {
110 Some(ProtobufEventPayload::MouseEventPayload(protobuf_mouse)) => {
111 Ok(Event::Mouse(protobuf_mouse.try_into()?))
112 },
113 _ => Err("Malformed payload for the Mouse Event"),
114 },
115 Some(ProtobufEventType::Timer) => match protobuf_event.payload {
116 Some(ProtobufEventPayload::TimerPayload(seconds)) => {
117 Ok(Event::Timer(seconds as f64))
118 },
119 _ => Err("Malformed payload for the Timer Event"),
120 },
121 Some(ProtobufEventType::CopyToClipboard) => match protobuf_event.payload {
122 Some(ProtobufEventPayload::CopyToClipboardPayload(copy_to_clipboard)) => {
123 let protobuf_copy_to_clipboard =
124 ProtobufCopyDestination::try_from(copy_to_clipboard)
125 .ok()
126 .ok_or("Malformed copy to clipboard payload")?;
127 Ok(Event::CopyToClipboard(
128 protobuf_copy_to_clipboard.try_into()?,
129 ))
130 },
131 _ => Err("Malformed payload for the Copy To Clipboard Event"),
132 },
133 Some(ProtobufEventType::SystemClipboardFailure) => match protobuf_event.payload {
134 None => Ok(Event::SystemClipboardFailure),
135 _ => Err("Malformed payload for the system clipboard failure Event"),
136 },
137 Some(ProtobufEventType::InputReceived) => match protobuf_event.payload {
138 None => Ok(Event::InputReceived),
139 _ => Err("Malformed payload for the input received Event"),
140 },
141 Some(ProtobufEventType::Visible) => match protobuf_event.payload {
142 Some(ProtobufEventPayload::VisiblePayload(is_visible)) => {
143 Ok(Event::Visible(is_visible))
144 },
145 _ => Err("Malformed payload for the visible Event"),
146 },
147 Some(ProtobufEventType::CustomMessage) => match protobuf_event.payload {
148 Some(ProtobufEventPayload::CustomMessagePayload(custom_message_payload)) => {
149 Ok(Event::CustomMessage(
150 custom_message_payload.message_name,
151 custom_message_payload.payload,
152 ))
153 },
154 _ => Err("Malformed payload for the custom message Event"),
155 },
156 Some(ProtobufEventType::FileSystemCreate) => match protobuf_event.payload {
157 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
158 let file_paths = file_list_payload
159 .paths
160 .iter()
161 .zip(file_list_payload.paths_metadata.iter())
162 .map(|(p, m)| (PathBuf::from(p), m.into()))
163 .collect();
164 Ok(Event::FileSystemCreate(file_paths))
165 },
166 _ => Err("Malformed payload for the file system create Event"),
167 },
168 Some(ProtobufEventType::FileSystemRead) => match protobuf_event.payload {
169 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
170 let file_paths = file_list_payload
171 .paths
172 .iter()
173 .zip(file_list_payload.paths_metadata.iter())
174 .map(|(p, m)| (PathBuf::from(p), m.into()))
175 .collect();
176 Ok(Event::FileSystemRead(file_paths))
177 },
178 _ => Err("Malformed payload for the file system read Event"),
179 },
180 Some(ProtobufEventType::FileSystemUpdate) => match protobuf_event.payload {
181 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
182 let file_paths = file_list_payload
183 .paths
184 .iter()
185 .zip(file_list_payload.paths_metadata.iter())
186 .map(|(p, m)| (PathBuf::from(p), m.into()))
187 .collect();
188 Ok(Event::FileSystemUpdate(file_paths))
189 },
190 _ => Err("Malformed payload for the file system update Event"),
191 },
192 Some(ProtobufEventType::FileSystemDelete) => match protobuf_event.payload {
193 Some(ProtobufEventPayload::FileListPayload(file_list_payload)) => {
194 let file_paths = file_list_payload
195 .paths
196 .iter()
197 .zip(file_list_payload.paths_metadata.iter())
198 .map(|(p, m)| (PathBuf::from(p), m.into()))
199 .collect();
200 Ok(Event::FileSystemDelete(file_paths))
201 },
202 _ => Err("Malformed payload for the file system delete Event"),
203 },
204 Some(ProtobufEventType::PermissionRequestResult) => match protobuf_event.payload {
205 Some(ProtobufEventPayload::PermissionRequestResultPayload(payload)) => {
206 if payload.granted {
207 Ok(Event::PermissionRequestResult(PermissionStatus::Granted))
208 } else {
209 Ok(Event::PermissionRequestResult(PermissionStatus::Denied))
210 }
211 },
212 _ => Err("Malformed payload for the file system delete Event"),
213 },
214 Some(ProtobufEventType::SessionUpdate) => match protobuf_event.payload {
215 Some(ProtobufEventPayload::SessionUpdatePayload(
216 protobuf_session_update_payload,
217 )) => {
218 let mut session_infos: Vec<SessionInfo> = vec![];
219 let mut resurrectable_sessions: Vec<(String, Duration)> = vec![];
220 for protobuf_session_info in protobuf_session_update_payload.session_manifests {
221 session_infos.push(SessionInfo::try_from(protobuf_session_info)?);
222 }
223 for protobuf_resurrectable_session in
224 protobuf_session_update_payload.resurrectable_sessions
225 {
226 resurrectable_sessions.push(protobuf_resurrectable_session.into());
227 }
228 Ok(Event::SessionUpdate(
229 session_infos,
230 resurrectable_sessions.into(),
231 ))
232 },
233 _ => Err("Malformed payload for the SessionUpdate Event"),
234 },
235 Some(ProtobufEventType::RunCommandResult) => match protobuf_event.payload {
236 Some(ProtobufEventPayload::RunCommandResultPayload(run_command_result_payload)) => {
237 Ok(Event::RunCommandResult(
238 run_command_result_payload.exit_code,
239 run_command_result_payload.stdout,
240 run_command_result_payload.stderr,
241 run_command_result_payload
242 .context
243 .into_iter()
244 .map(|c_i| (c_i.name, c_i.value))
245 .collect(),
246 ))
247 },
248 _ => Err("Malformed payload for the RunCommandResult Event"),
249 },
250 Some(ProtobufEventType::WebRequestResult) => match protobuf_event.payload {
251 Some(ProtobufEventPayload::WebRequestResultPayload(web_request_result_payload)) => {
252 Ok(Event::WebRequestResult(
253 web_request_result_payload.status as u16,
254 web_request_result_payload
255 .headers
256 .into_iter()
257 .map(|h| (h.name, h.value))
258 .collect(),
259 web_request_result_payload.body,
260 web_request_result_payload
261 .context
262 .into_iter()
263 .map(|c_i| (c_i.name, c_i.value))
264 .collect(),
265 ))
266 },
267 _ => Err("Malformed payload for the WebRequestResult Event"),
268 },
269 Some(ProtobufEventType::CommandPaneOpened) => match protobuf_event.payload {
270 Some(ProtobufEventPayload::CommandPaneOpenedPayload(
271 command_pane_opened_payload,
272 )) => Ok(Event::CommandPaneOpened(
273 command_pane_opened_payload.terminal_pane_id,
274 command_pane_opened_payload
275 .context
276 .into_iter()
277 .map(|c_i| (c_i.name, c_i.value))
278 .collect(),
279 )),
280 _ => Err("Malformed payload for the CommandPaneOpened Event"),
281 },
282 Some(ProtobufEventType::CommandPaneExited) => match protobuf_event.payload {
283 Some(ProtobufEventPayload::CommandPaneExitedPayload(
284 command_pane_exited_payload,
285 )) => Ok(Event::CommandPaneExited(
286 command_pane_exited_payload.terminal_pane_id,
287 command_pane_exited_payload.exit_code,
288 command_pane_exited_payload
289 .context
290 .into_iter()
291 .map(|c_i| (c_i.name, c_i.value))
292 .collect(),
293 )),
294 _ => Err("Malformed payload for the CommandPaneExited Event"),
295 },
296 Some(ProtobufEventType::PaneClosed) => match protobuf_event.payload {
297 Some(ProtobufEventPayload::PaneClosedPayload(pane_closed_payload)) => {
298 let pane_id = pane_closed_payload
299 .pane_id
300 .ok_or("Malformed payload for the PaneClosed Event")?;
301 Ok(Event::PaneClosed(PaneId::try_from(pane_id)?))
302 },
303 _ => Err("Malformed payload for the PaneClosed Event"),
304 },
305 Some(ProtobufEventType::EditPaneOpened) => match protobuf_event.payload {
306 Some(ProtobufEventPayload::EditPaneOpenedPayload(command_pane_opened_payload)) => {
307 Ok(Event::EditPaneOpened(
308 command_pane_opened_payload.terminal_pane_id,
309 command_pane_opened_payload
310 .context
311 .into_iter()
312 .map(|c_i| (c_i.name, c_i.value))
313 .collect(),
314 ))
315 },
316 _ => Err("Malformed payload for the EditPaneOpened Event"),
317 },
318 Some(ProtobufEventType::EditPaneExited) => match protobuf_event.payload {
319 Some(ProtobufEventPayload::EditPaneExitedPayload(command_pane_exited_payload)) => {
320 Ok(Event::EditPaneExited(
321 command_pane_exited_payload.terminal_pane_id,
322 command_pane_exited_payload.exit_code,
323 command_pane_exited_payload
324 .context
325 .into_iter()
326 .map(|c_i| (c_i.name, c_i.value))
327 .collect(),
328 ))
329 },
330 _ => Err("Malformed payload for the EditPaneExited Event"),
331 },
332 Some(ProtobufEventType::CommandPaneReRun) => match protobuf_event.payload {
333 Some(ProtobufEventPayload::CommandPaneRerunPayload(command_pane_rerun_payload)) => {
334 Ok(Event::CommandPaneReRun(
335 command_pane_rerun_payload.terminal_pane_id,
336 command_pane_rerun_payload
337 .context
338 .into_iter()
339 .map(|c_i| (c_i.name, c_i.value))
340 .collect(),
341 ))
342 },
343 _ => Err("Malformed payload for the CommandPaneReRun Event"),
344 },
345 Some(ProtobufEventType::FailedToWriteConfigToDisk) => match protobuf_event.payload {
346 Some(ProtobufEventPayload::FailedToWriteConfigToDiskPayload(
347 failed_to_write_configuration_payload,
348 )) => Ok(Event::FailedToWriteConfigToDisk(
349 failed_to_write_configuration_payload.file_path,
350 )),
351 _ => Err("Malformed payload for the FailedToWriteConfigToDisk Event"),
352 },
353 Some(ProtobufEventType::ListClients) => match protobuf_event.payload {
354 Some(ProtobufEventPayload::ListClientsPayload(mut list_clients_payload)) => {
355 Ok(Event::ListClients(
356 list_clients_payload
357 .client_info
358 .drain(..)
359 .filter_map(|c| c.try_into().ok())
360 .collect(),
361 ))
362 },
363 _ => Err("Malformed payload for the FailedToWriteConfigToDisk Event"),
364 },
365 Some(ProtobufEventType::HostFolderChanged) => match protobuf_event.payload {
366 Some(ProtobufEventPayload::HostFolderChangedPayload(
367 host_folder_changed_payload,
368 )) => Ok(Event::HostFolderChanged(PathBuf::from(
369 host_folder_changed_payload.new_host_folder_path,
370 ))),
371 _ => Err("Malformed payload for the HostFolderChanged Event"),
372 },
373 Some(ProtobufEventType::FailedToChangeHostFolder) => match protobuf_event.payload {
374 Some(ProtobufEventPayload::FailedToChangeHostFolderPayload(
375 failed_to_change_host_folder_payload,
376 )) => Ok(Event::FailedToChangeHostFolder(
377 failed_to_change_host_folder_payload.error_message,
378 )),
379 _ => Err("Malformed payload for the FailedToChangeHostFolder Event"),
380 },
381 Some(ProtobufEventType::PastedText) => match protobuf_event.payload {
382 Some(ProtobufEventPayload::PastedTextPayload(pasted_text_payload)) => {
383 Ok(Event::PastedText(pasted_text_payload.pasted_text))
384 },
385 _ => Err("Malformed payload for the PastedText Event"),
386 },
387 Some(ProtobufEventType::ConfigWasWrittenToDisk) => match protobuf_event.payload {
388 None => Ok(Event::ConfigWasWrittenToDisk),
389 _ => Err("Malformed payload for the ConfigWasWrittenToDisk Event"),
390 },
391 Some(ProtobufEventType::WebServerStatus) => match protobuf_event.payload {
392 Some(ProtobufEventPayload::WebServerStatusPayload(web_server_status)) => {
393 Ok(Event::WebServerStatus(web_server_status.try_into()?))
394 },
395 _ => Err("Malformed payload for the WebServerStatus Event"),
396 },
397 Some(ProtobufEventType::BeforeClose) => match protobuf_event.payload {
398 None => Ok(Event::BeforeClose),
399 _ => Err("Malformed payload for the BeforeClose Event"),
400 },
401 Some(ProtobufEventType::FailedToStartWebServer) => match protobuf_event.payload {
402 Some(ProtobufEventPayload::FailedToStartWebServerPayload(
403 failed_to_start_web_server_payload,
404 )) => Ok(Event::FailedToStartWebServer(
405 failed_to_start_web_server_payload.error,
406 )),
407 _ => Err("Malformed payload for the FailedToStartWebServer Event"),
408 },
409 Some(ProtobufEventType::InterceptedKeyPress) => match protobuf_event.payload {
410 Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => {
411 Ok(Event::InterceptedKeyPress(protobuf_key.try_into()?))
412 },
413 _ => Err("Malformed payload for the InterceptedKeyPress Event"),
414 },
415 Some(ProtobufEventType::PaneRenderReport) => match protobuf_event.payload {
416 Some(ProtobufEventPayload::PaneRenderReportPayload(protobuf_payload)) => {
417 Ok(Event::PaneRenderReport(protobuf_payload.try_into()?))
418 },
419 _ => Err("Malformed payload for the PaneRenderReport Event"),
420 },
421 Some(ProtobufEventType::UserAction) => match protobuf_event.payload {
422 Some(ProtobufEventPayload::UserActionPayload(protobuf_payload)) => {
423 let action: Action = protobuf_payload
424 .action
425 .ok_or("Missing action in UserAction payload")?
426 .try_into()
427 .map_err(|_| "Failed to convert Action in UserAction payload")?;
428 let client_id = protobuf_payload.client_id as u16;
429 let terminal_id = protobuf_payload.terminal_id;
430 let cli_client_id = protobuf_payload.cli_client_id.map(|id| id as u16);
431 Ok(Event::UserAction(
432 action,
433 client_id,
434 terminal_id,
435 cli_client_id,
436 ))
437 },
438 _ => Err("Malformed payload for the UserAction Event"),
439 },
440 Some(ProtobufEventType::ActionComplete) => match protobuf_event.payload {
441 Some(ProtobufEventPayload::ActionCompletePayload(protobuf_payload)) => {
442 let action: Action = protobuf_payload
443 .action
444 .ok_or("Missing action in ActionComplete payload")?
445 .try_into()
446 .map_err(|_| "Failed to convert Action in ActionComplete payload")?;
447 let pane_id = protobuf_payload
448 .pane_id
449 .map(|id| id.try_into())
450 .transpose()
451 .map_err(|_| "Failed to convert PaneId in ActionComplete payload")?;
452 let context: BTreeMap<String, String> = protobuf_payload
453 .context
454 .into_iter()
455 .map(|item| (item.name, item.value))
456 .collect();
457 Ok(Event::ActionComplete(action, pane_id, context))
458 },
459 _ => Err("Malformed payload for the ActionComplete Event"),
460 },
461 Some(ProtobufEventType::CwdChanged) => match protobuf_event.payload {
462 Some(ProtobufEventPayload::CwdChangedPayload(protobuf_payload)) => {
463 let pane_id: PaneId = protobuf_payload
464 .pane_id
465 .ok_or("Missing pane_id in CwdChanged payload")?
466 .try_into()
467 .map_err(|_| "Failed to convert PaneId in CwdChanged payload")?;
468 let new_cwd = PathBuf::from(protobuf_payload.new_cwd);
469 let focused_client_ids: Vec<ClientId> = protobuf_payload
470 .focused_client_ids
471 .into_iter()
472 .map(|id| id as u16)
473 .collect();
474 Ok(Event::CwdChanged(pane_id, new_cwd, focused_client_ids))
475 },
476 _ => Err("Malformed payload for the CwdChanged Event"),
477 },
478 Some(ProtobufEventType::CommandChanged) => match protobuf_event.payload {
479 Some(ProtobufEventPayload::CommandChangedPayload(p)) => {
480 let pane_id: PaneId = p
481 .pane_id
482 .ok_or("Missing pane_id in CommandChanged payload")?
483 .try_into()
484 .map_err(|_| "Failed to convert PaneId in CommandChanged payload")?;
485 let focused_client_ids: Vec<ClientId> = p
486 .focused_client_ids
487 .into_iter()
488 .map(|id| id as u16)
489 .collect();
490 Ok(Event::CommandChanged(
491 pane_id,
492 p.command,
493 p.is_foreground,
494 focused_client_ids,
495 ))
496 },
497 _ => Err("Malformed payload for the CommandChanged Event"),
498 },
499 Some(ProtobufEventType::AvailableLayoutInfo) => match protobuf_event.payload {
500 Some(ProtobufEventPayload::AvailableLayoutInfoPayload(
501 available_layout_info_payload,
502 )) => {
503 let mut available_layouts: Vec<LayoutInfo> = vec![];
504 let mut layouts_with_errors: Vec<crate::data::LayoutWithError> = vec![];
505
506 for protobuf_layout_info in available_layout_info_payload.available_layouts {
507 available_layouts.push(LayoutInfo::try_from(protobuf_layout_info)?);
508 }
509
510 for protobuf_error in available_layout_info_payload.layouts_with_errors {
511 layouts_with_errors
512 .push(crate::data::LayoutWithError::try_from(protobuf_error)?);
513 }
514
515 Ok(Event::AvailableLayoutInfo(
516 available_layouts,
517 layouts_with_errors,
518 ))
519 },
520 _ => Err("Malformed payload for the AvailableLayoutInfo Event"),
521 },
522 Some(ProtobufEventType::PluginConfigurationChanged) => match protobuf_event.payload {
523 Some(ProtobufEventPayload::PluginConfigurationChangedPayload(payload)) => {
524 let configuration = payload
525 .configuration
526 .into_iter()
527 .map(|item| (item.name, item.value))
528 .collect();
529 Ok(Event::PluginConfigurationChanged(configuration))
530 },
531 _ => Err("Malformed payload for PluginConfigurationChanged Event"),
532 },
533 Some(ProtobufEventType::HighlightClicked) => match protobuf_event.payload {
534 Some(ProtobufEventPayload::HighlightClickedPayload(p)) => {
535 let pane_id = p
536 .pane_id
537 .ok_or("Missing pane_id in HighlightClicked")?
538 .try_into()?;
539 let context = p
540 .context
541 .into_iter()
542 .map(|item| (item.name, item.value))
543 .collect();
544 Ok(Event::HighlightClicked {
545 pane_id,
546 pattern: p.pattern,
547 matched_string: p.matched_string,
548 context,
549 })
550 },
551 _ => Err("Malformed payload for HighlightClicked Event"),
552 },
553 Some(ProtobufEventType::InitialKeybinds) => match protobuf_event.payload {
554 Some(ProtobufEventPayload::InitialKeybindsPayload(p)) => {
555 let keybinds = p
556 .keybinds
557 .into_iter()
558 .filter_map(|imk| {
559 let mode: InputMode = ProtobufInputMode::try_from(imk.mode)
560 .ok()?
561 .try_into()
562 .ok()?;
563 let key_binds: Vec<(KeyWithModifier, Vec<Action>)> = imk
564 .key_bind
565 .into_iter()
566 .filter_map(|kb| {
567 let key: KeyWithModifier = kb.key?.try_into().ok()?;
568 let actions: Vec<Action> = kb
569 .action
570 .into_iter()
571 .filter_map(|a| a.try_into().ok())
572 .collect();
573 Some((key, actions))
574 })
575 .collect();
576 Some((mode, key_binds))
577 })
578 .collect();
579 Ok(Event::InitialKeybinds(keybinds))
580 },
581 _ => Err("Malformed payload for InitialKeybinds Event"),
582 },
583 Some(ProtobufEventType::HostTerminalThemeChanged) => match protobuf_event.payload {
584 Some(ProtobufEventPayload::HostTerminalThemeChangedPayload(p)) => {
585 let mode = ProtobufHostTerminalThemeIndication::try_from(p.mode)
586 .ok()
587 .ok_or("Unknown HostTerminalThemeIndication")?;
588 Ok(Event::HostTerminalThemeChanged(mode.into()))
589 },
590 _ => Err("Malformed payload for HostTerminalThemeChanged Event"),
591 },
592 Some(ProtobufEventType::SoftKeyboardVisibilityChanged) => {
593 match protobuf_event.payload {
594 Some(ProtobufEventPayload::SoftKeyboardVisibilityChangedPayload(p)) => {
595 Ok(Event::SoftKeyboardVisibilityChanged(p.visible))
596 },
597 _ => Err("Malformed payload for SoftKeyboardVisibilityChanged Event"),
598 }
599 },
600 Some(ProtobufEventType::HintText) => match protobuf_event.payload {
601 Some(ProtobufEventPayload::HintTextPayload(p)) => {
602 let mut hint_text = BTreeMap::new();
603 for (width, styled_text) in p.hint_text {
604 hint_text.insert(width as usize, StyledText::from(styled_text));
605 }
606 Ok(Event::HintText(hint_text))
607 },
608 _ => Err("Malformed payload for HintText Event"),
609 },
610 Some(ProtobufEventType::ActivePaneScroll) => match protobuf_event.payload {
611 Some(ProtobufEventPayload::ActivePaneScrollPayload(p)) => {
612 let scroll = match (p.position, p.length) {
613 (Some(position), Some(length)) => {
614 Some((position as usize, length as usize))
615 },
616 _ => None,
617 };
618 Ok(Event::ActivePaneScroll(scroll))
619 },
620 _ => Err("Malformed payload for ActivePaneScroll Event"),
621 },
622 None => Err("Unknown Protobuf Event"),
623 }
624 }
625}
626
627impl TryFrom<ProtobufClientInfo> for ClientInfo {
628 type Error = &'static str;
629 fn try_from(protobuf_client_info: ProtobufClientInfo) -> Result<Self, &'static str> {
630 Ok(ClientInfo::new(
631 protobuf_client_info.client_id as u16,
632 protobuf_client_info
633 .pane_id
634 .ok_or("No pane id found")?
635 .try_into()?,
636 protobuf_client_info.running_command,
637 protobuf_client_info.is_current_client,
638 ))
639 }
640}
641
642impl TryFrom<ClientInfo> for ProtobufClientInfo {
643 type Error = &'static str;
644 fn try_from(client_info: ClientInfo) -> Result<Self, &'static str> {
645 Ok(ProtobufClientInfo {
646 client_id: client_info.client_id as u32,
647 pane_id: Some(client_info.pane_id.try_into()?),
648 running_command: client_info.running_command,
649 is_current_client: client_info.is_current_client,
650 })
651 }
652}
653
654impl TryFrom<Event> for ProtobufEvent {
655 type Error = &'static str;
656 fn try_from(event: Event) -> Result<Self, &'static str> {
657 match event {
658 Event::ModeUpdate(mode_info) => {
659 let protobuf_mode_update_payload = mode_info.try_into()?;
660 Ok(ProtobufEvent {
661 name: ProtobufEventType::ModeUpdate as i32,
662 payload: Some(event::Payload::ModeUpdatePayload(
663 protobuf_mode_update_payload,
664 )),
665 })
666 },
667 Event::TabUpdate(tab_infos) => {
668 let mut protobuf_tab_infos = vec![];
669 for tab_info in tab_infos {
670 protobuf_tab_infos.push(tab_info.try_into()?);
671 }
672 let tab_update_payload = TabUpdatePayload {
673 tab_info: protobuf_tab_infos,
674 };
675 Ok(ProtobufEvent {
676 name: ProtobufEventType::TabUpdate as i32,
677 payload: Some(event::Payload::TabUpdatePayload(tab_update_payload)),
678 })
679 },
680 Event::PaneUpdate(pane_manifest) => {
681 let mut protobuf_pane_manifests = vec![];
682 for (tab_index, pane_infos) in pane_manifest.panes {
683 let mut protobuf_pane_infos = vec![];
684 for pane_info in pane_infos {
685 protobuf_pane_infos.push(pane_info.try_into()?);
686 }
687 protobuf_pane_manifests.push(ProtobufPaneManifest {
688 tab_index: tab_index as u32,
689 panes: protobuf_pane_infos,
690 });
691 }
692 Ok(ProtobufEvent {
693 name: ProtobufEventType::PaneUpdate as i32,
694 payload: Some(event::Payload::PaneUpdatePayload(PaneUpdatePayload {
695 pane_manifest: protobuf_pane_manifests,
696 })),
697 })
698 },
699 Event::Key(key) => Ok(ProtobufEvent {
700 name: ProtobufEventType::Key as i32,
701 payload: Some(event::Payload::KeyPayload(key.try_into()?)),
702 }),
703 Event::Mouse(mouse_event) => {
704 let protobuf_mouse_payload = mouse_event.try_into()?;
705 Ok(ProtobufEvent {
706 name: ProtobufEventType::Mouse as i32,
707 payload: Some(event::Payload::MouseEventPayload(protobuf_mouse_payload)),
708 })
709 },
710 Event::Timer(seconds) => Ok(ProtobufEvent {
711 name: ProtobufEventType::Timer as i32,
712 payload: Some(event::Payload::TimerPayload(seconds as f32)),
713 }),
714 Event::CopyToClipboard(clipboard_destination) => {
715 let protobuf_copy_destination: ProtobufCopyDestination =
716 clipboard_destination.try_into()?;
717 Ok(ProtobufEvent {
718 name: ProtobufEventType::CopyToClipboard as i32,
719 payload: Some(event::Payload::CopyToClipboardPayload(
720 protobuf_copy_destination as i32,
721 )),
722 })
723 },
724 Event::SystemClipboardFailure => Ok(ProtobufEvent {
725 name: ProtobufEventType::SystemClipboardFailure as i32,
726 payload: None,
727 }),
728 Event::InputReceived => Ok(ProtobufEvent {
729 name: ProtobufEventType::InputReceived as i32,
730 payload: None,
731 }),
732 Event::Visible(is_visible) => Ok(ProtobufEvent {
733 name: ProtobufEventType::Visible as i32,
734 payload: Some(event::Payload::VisiblePayload(is_visible)),
735 }),
736 Event::CustomMessage(message, payload) => Ok(ProtobufEvent {
737 name: ProtobufEventType::CustomMessage as i32,
738 payload: Some(event::Payload::CustomMessagePayload(CustomMessagePayload {
739 message_name: message,
740 payload,
741 })),
742 }),
743 Event::FileSystemCreate(event_paths) => {
744 let mut paths = vec![];
745 let mut paths_metadata = vec![];
746 for (path, path_metadata) in event_paths {
747 paths.push(path.display().to_string());
748 paths_metadata.push(path_metadata.into());
749 }
750 let file_list_payload = FileListPayload {
751 paths,
752 paths_metadata,
753 };
754 Ok(ProtobufEvent {
755 name: ProtobufEventType::FileSystemCreate as i32,
756 payload: Some(event::Payload::FileListPayload(file_list_payload)),
757 })
758 },
759 Event::FileSystemRead(event_paths) => {
760 let mut paths = vec![];
761 let mut paths_metadata = vec![];
762 for (path, path_metadata) in event_paths {
763 paths.push(path.display().to_string());
764 paths_metadata.push(path_metadata.into());
765 }
766 let file_list_payload = FileListPayload {
767 paths,
768 paths_metadata,
769 };
770 Ok(ProtobufEvent {
771 name: ProtobufEventType::FileSystemRead as i32,
772 payload: Some(event::Payload::FileListPayload(file_list_payload)),
773 })
774 },
775 Event::FileSystemUpdate(event_paths) => {
776 let mut paths = vec![];
777 let mut paths_metadata = vec![];
778 for (path, path_metadata) in event_paths {
779 paths.push(path.display().to_string());
780 paths_metadata.push(path_metadata.into());
781 }
782 let file_list_payload = FileListPayload {
783 paths,
784 paths_metadata,
785 };
786 Ok(ProtobufEvent {
787 name: ProtobufEventType::FileSystemUpdate as i32,
788 payload: Some(event::Payload::FileListPayload(file_list_payload)),
789 })
790 },
791 Event::FileSystemDelete(event_paths) => {
792 let mut paths = vec![];
793 let mut paths_metadata = vec![];
794 for (path, path_metadata) in event_paths {
795 paths.push(path.display().to_string());
796 paths_metadata.push(path_metadata.into());
797 }
798 let file_list_payload = FileListPayload {
799 paths,
800 paths_metadata,
801 };
802 Ok(ProtobufEvent {
803 name: ProtobufEventType::FileSystemDelete as i32,
804 payload: Some(event::Payload::FileListPayload(file_list_payload)),
805 })
806 },
807 Event::PermissionRequestResult(permission_status) => {
808 let granted = match permission_status {
809 PermissionStatus::Granted => true,
810 PermissionStatus::Denied => false,
811 };
812 Ok(ProtobufEvent {
813 name: ProtobufEventType::PermissionRequestResult as i32,
814 payload: Some(event::Payload::PermissionRequestResultPayload(
815 PermissionRequestResultPayload { granted },
816 )),
817 })
818 },
819 Event::SessionUpdate(session_infos, resurrectable_sessions) => {
820 let mut protobuf_session_manifests = vec![];
821 for session_info in session_infos {
822 protobuf_session_manifests.push(session_info.try_into()?);
823 }
824 let mut protobuf_resurrectable_sessions = vec![];
825 for resurrectable_session in resurrectable_sessions {
826 protobuf_resurrectable_sessions.push(resurrectable_session.into());
827 }
828 let session_update_payload = SessionUpdatePayload {
829 session_manifests: protobuf_session_manifests,
830 resurrectable_sessions: protobuf_resurrectable_sessions,
831 };
832 Ok(ProtobufEvent {
833 name: ProtobufEventType::SessionUpdate as i32,
834 payload: Some(event::Payload::SessionUpdatePayload(session_update_payload)),
835 })
836 },
837 Event::RunCommandResult(exit_code, stdout, stderr, context) => {
838 let run_command_result_payload = RunCommandResultPayload {
839 exit_code,
840 stdout,
841 stderr,
842 context: context
843 .into_iter()
844 .map(|(name, value)| ContextItem { name, value })
845 .collect(),
846 };
847 Ok(ProtobufEvent {
848 name: ProtobufEventType::RunCommandResult as i32,
849 payload: Some(event::Payload::RunCommandResultPayload(
850 run_command_result_payload,
851 )),
852 })
853 },
854 Event::WebRequestResult(status, headers, body, context) => {
855 let web_request_result_payload = WebRequestResultPayload {
856 status: status as i32,
857 headers: headers
858 .into_iter()
859 .map(|(name, value)| Header { name, value })
860 .collect(),
861 body,
862 context: context
863 .into_iter()
864 .map(|(name, value)| ContextItem { name, value })
865 .collect(),
866 };
867 Ok(ProtobufEvent {
868 name: ProtobufEventType::WebRequestResult as i32,
869 payload: Some(event::Payload::WebRequestResultPayload(
870 web_request_result_payload,
871 )),
872 })
873 },
874 Event::CommandPaneOpened(terminal_pane_id, context) => {
875 let command_pane_opened_payload = CommandPaneOpenedPayload {
876 terminal_pane_id,
877 context: context
878 .into_iter()
879 .map(|(name, value)| ContextItem { name, value })
880 .collect(),
881 };
882 Ok(ProtobufEvent {
883 name: ProtobufEventType::CommandPaneOpened as i32,
884 payload: Some(event::Payload::CommandPaneOpenedPayload(
885 command_pane_opened_payload,
886 )),
887 })
888 },
889 Event::CommandPaneExited(terminal_pane_id, exit_code, context) => {
890 let command_pane_exited_payload = CommandPaneExitedPayload {
891 terminal_pane_id,
892 exit_code,
893 context: context
894 .into_iter()
895 .map(|(name, value)| ContextItem { name, value })
896 .collect(),
897 };
898 Ok(ProtobufEvent {
899 name: ProtobufEventType::CommandPaneExited as i32,
900 payload: Some(event::Payload::CommandPaneExitedPayload(
901 command_pane_exited_payload,
902 )),
903 })
904 },
905 Event::PaneClosed(pane_id) => Ok(ProtobufEvent {
906 name: ProtobufEventType::PaneClosed as i32,
907 payload: Some(event::Payload::PaneClosedPayload(PaneClosedPayload {
908 pane_id: Some(pane_id.try_into()?),
909 })),
910 }),
911 Event::EditPaneOpened(terminal_pane_id, context) => {
912 let command_pane_opened_payload = EditPaneOpenedPayload {
913 terminal_pane_id,
914 context: context
915 .into_iter()
916 .map(|(name, value)| ContextItem { name, value })
917 .collect(),
918 };
919 Ok(ProtobufEvent {
920 name: ProtobufEventType::EditPaneOpened as i32,
921 payload: Some(event::Payload::EditPaneOpenedPayload(
922 command_pane_opened_payload,
923 )),
924 })
925 },
926 Event::EditPaneExited(terminal_pane_id, exit_code, context) => {
927 let command_pane_exited_payload = EditPaneExitedPayload {
928 terminal_pane_id,
929 exit_code,
930 context: context
931 .into_iter()
932 .map(|(name, value)| ContextItem { name, value })
933 .collect(),
934 };
935 Ok(ProtobufEvent {
936 name: ProtobufEventType::EditPaneExited as i32,
937 payload: Some(event::Payload::EditPaneExitedPayload(
938 command_pane_exited_payload,
939 )),
940 })
941 },
942 Event::CommandPaneReRun(terminal_pane_id, context) => {
943 let command_pane_rerun_payload = CommandPaneReRunPayload {
944 terminal_pane_id,
945 context: context
946 .into_iter()
947 .map(|(name, value)| ContextItem { name, value })
948 .collect(),
949 };
950 Ok(ProtobufEvent {
951 name: ProtobufEventType::CommandPaneReRun as i32,
952 payload: Some(event::Payload::CommandPaneRerunPayload(
953 command_pane_rerun_payload,
954 )),
955 })
956 },
957 Event::FailedToWriteConfigToDisk(file_path) => Ok(ProtobufEvent {
958 name: ProtobufEventType::FailedToWriteConfigToDisk as i32,
959 payload: Some(event::Payload::FailedToWriteConfigToDiskPayload(
960 FailedToWriteConfigToDiskPayload { file_path },
961 )),
962 }),
963 Event::ListClients(mut client_info_list) => Ok(ProtobufEvent {
964 name: ProtobufEventType::ListClients as i32,
965 payload: Some(event::Payload::ListClientsPayload(ListClientsPayload {
966 client_info: client_info_list
967 .drain(..)
968 .filter_map(|c| c.try_into().ok())
969 .collect(),
970 })),
971 }),
972 Event::HostFolderChanged(new_host_folder_path) => Ok(ProtobufEvent {
973 name: ProtobufEventType::HostFolderChanged as i32,
974 payload: Some(event::Payload::HostFolderChangedPayload(
975 HostFolderChangedPayload {
976 new_host_folder_path: new_host_folder_path.display().to_string(),
977 },
978 )),
979 }),
980 Event::FailedToChangeHostFolder(error_message) => Ok(ProtobufEvent {
981 name: ProtobufEventType::FailedToChangeHostFolder as i32,
982 payload: Some(event::Payload::FailedToChangeHostFolderPayload(
983 FailedToChangeHostFolderPayload { error_message },
984 )),
985 }),
986 Event::PastedText(pasted_text) => Ok(ProtobufEvent {
987 name: ProtobufEventType::PastedText as i32,
988 payload: Some(event::Payload::PastedTextPayload(PastedTextPayload {
989 pasted_text,
990 })),
991 }),
992 Event::ConfigWasWrittenToDisk => Ok(ProtobufEvent {
993 name: ProtobufEventType::ConfigWasWrittenToDisk as i32,
994 payload: None,
995 }),
996 Event::WebServerStatus(web_server_status) => Ok(ProtobufEvent {
997 name: ProtobufEventType::WebServerStatus as i32,
998 payload: Some(event::Payload::WebServerStatusPayload(
999 ProtobufWebServerStatusPayload::try_from(web_server_status)?,
1000 )),
1001 }),
1002 Event::BeforeClose => Ok(ProtobufEvent {
1003 name: ProtobufEventType::BeforeClose as i32,
1004 payload: None,
1005 }),
1006 Event::FailedToStartWebServer(error) => Ok(ProtobufEvent {
1007 name: ProtobufEventType::FailedToStartWebServer as i32,
1008 payload: Some(event::Payload::FailedToStartWebServerPayload(
1009 FailedToStartWebServerPayload { error },
1010 )),
1011 }),
1012 Event::InterceptedKeyPress(key) => Ok(ProtobufEvent {
1013 name: ProtobufEventType::InterceptedKeyPress as i32,
1014 payload: Some(event::Payload::KeyPayload(key.try_into()?)),
1015 }),
1016 Event::PaneRenderReport(pane_contents_map) => Ok(ProtobufEvent {
1017 name: ProtobufEventType::PaneRenderReport as i32,
1018 payload: Some(event::Payload::PaneRenderReportPayload(
1019 pane_contents_map.try_into()?,
1020 )),
1021 }),
1022 Event::UserAction(action, client_id, terminal_id, cli_client_id) => {
1023 let protobuf_action: ProtobufAction = action
1024 .try_into()
1025 .map_err(|_| "Failed to convert Action to protobuf")?;
1026 let protobuf_payload = ProtobufUserActionPayload {
1027 action: Some(protobuf_action),
1028 client_id: client_id as u32,
1029 terminal_id,
1030 cli_client_id: cli_client_id.map(|id| id as u32),
1031 };
1032 Ok(ProtobufEvent {
1033 name: ProtobufEventType::UserAction as i32,
1034 payload: Some(event::Payload::UserActionPayload(protobuf_payload)),
1035 })
1036 },
1037 Event::ActionComplete(action, pane_id, context) => {
1038 let protobuf_action = action.try_into()?;
1039 let protobuf_pane_id = pane_id.map(|id| id.try_into()).transpose()?;
1040 let context_items: Vec<ProtobufContextItem> = context
1041 .into_iter()
1042 .map(|(name, value)| ProtobufContextItem { name, value })
1043 .collect();
1044 let action_complete_payload = ProtobufActionCompletePayload {
1045 action: Some(protobuf_action),
1046 pane_id: protobuf_pane_id,
1047 context: context_items,
1048 };
1049 Ok(ProtobufEvent {
1050 name: ProtobufEventType::ActionComplete as i32,
1051 payload: Some(event::Payload::ActionCompletePayload(
1052 action_complete_payload,
1053 )),
1054 })
1055 },
1056 Event::CwdChanged(pane_id, new_cwd, focused_client_ids) => {
1057 let protobuf_pane_id: ProtobufPaneId = pane_id.try_into()?;
1058 let new_cwd_string = new_cwd
1059 .to_str()
1060 .ok_or("Failed to convert PathBuf to string")?
1061 .to_string();
1062 let focused_client_ids_u32: Vec<u32> =
1063 focused_client_ids.into_iter().map(|id| id as u32).collect();
1064 let cwd_changed_payload = ProtobufCwdChangedPayload {
1065 pane_id: Some(protobuf_pane_id),
1066 new_cwd: new_cwd_string,
1067 focused_client_ids: focused_client_ids_u32,
1068 };
1069 Ok(ProtobufEvent {
1070 name: ProtobufEventType::CwdChanged as i32,
1071 payload: Some(event::Payload::CwdChangedPayload(cwd_changed_payload)),
1072 })
1073 },
1074 Event::CommandChanged(pane_id, command, is_foreground, focused_client_ids) => {
1075 let protobuf_pane_id: ProtobufPaneId = pane_id.try_into()?;
1076 let focused_client_ids_u32: Vec<u32> =
1077 focused_client_ids.into_iter().map(|id| id as u32).collect();
1078 let payload = ProtobufCommandChangedPayload {
1079 pane_id: Some(protobuf_pane_id),
1080 command,
1081 is_foreground,
1082 focused_client_ids: focused_client_ids_u32,
1083 };
1084 Ok(ProtobufEvent {
1085 name: ProtobufEventType::CommandChanged as i32,
1086 payload: Some(event::Payload::CommandChangedPayload(payload)),
1087 })
1088 },
1089 Event::AvailableLayoutInfo(available_layouts, layouts_with_errors) => {
1090 let mut protobuf_available_layouts = vec![];
1091 let mut protobuf_layouts_with_errors = vec![];
1092
1093 for layout_info in available_layouts {
1094 protobuf_available_layouts.push(layout_info.try_into()?);
1095 }
1096
1097 for layout_error in layouts_with_errors {
1098 protobuf_layouts_with_errors.push(layout_error.try_into()?);
1099 }
1100
1101 let available_layout_info_payload = ProtobufAvailableLayoutInfoPayload {
1102 available_layouts: protobuf_available_layouts,
1103 layouts_with_errors: protobuf_layouts_with_errors,
1104 };
1105
1106 Ok(ProtobufEvent {
1107 name: ProtobufEventType::AvailableLayoutInfo as i32,
1108 payload: Some(event::Payload::AvailableLayoutInfoPayload(
1109 available_layout_info_payload,
1110 )),
1111 })
1112 },
1113 Event::PluginConfigurationChanged(configuration) => {
1114 let configuration_items: Vec<ProtobufContextItem> = configuration
1115 .into_iter()
1116 .map(|(name, value)| ProtobufContextItem { name, value })
1117 .collect();
1118
1119 let payload = ProtobufPluginConfigurationChangedPayload {
1120 configuration: configuration_items,
1121 };
1122
1123 Ok(ProtobufEvent {
1124 name: ProtobufEventType::PluginConfigurationChanged as i32,
1125 payload: Some(event::Payload::PluginConfigurationChangedPayload(payload)),
1126 })
1127 },
1128 Event::HighlightClicked {
1129 pane_id,
1130 pattern,
1131 matched_string,
1132 context,
1133 } => Ok(ProtobufEvent {
1134 name: ProtobufEventType::HighlightClicked as i32,
1135 payload: Some(event::Payload::HighlightClickedPayload(
1136 HighlightClickedPayload {
1137 pane_id: pane_id.try_into().ok(),
1138 pattern,
1139 matched_string,
1140 context: context
1141 .into_iter()
1142 .map(|(name, value)| ProtobufContextItem { name, value })
1143 .collect(),
1144 },
1145 )),
1146 }),
1147 Event::HostTerminalThemeChanged(mode) => {
1148 let proto_mode: ProtobufHostTerminalThemeIndication = mode.into();
1149 let payload = ProtobufHostTerminalThemeChangedPayload {
1150 mode: proto_mode as i32,
1151 };
1152 Ok(ProtobufEvent {
1153 name: ProtobufEventType::HostTerminalThemeChanged as i32,
1154 payload: Some(event::Payload::HostTerminalThemeChangedPayload(payload)),
1155 })
1156 },
1157 Event::SoftKeyboardVisibilityChanged(visible) => {
1158 let payload = ProtobufSoftKeyboardVisibilityChangedPayload { visible };
1159 Ok(ProtobufEvent {
1160 name: ProtobufEventType::SoftKeyboardVisibilityChanged as i32,
1161 payload: Some(event::Payload::SoftKeyboardVisibilityChangedPayload(
1162 payload,
1163 )),
1164 })
1165 },
1166 Event::HintText(hint_text) => {
1167 let mut proto_hint_text = HashMap::new();
1168 for (width, styled_text) in hint_text {
1169 proto_hint_text.insert(width as u32, ProtobufStyledText::from(styled_text));
1170 }
1171 let payload = ProtobufHintTextPayload {
1172 hint_text: proto_hint_text,
1173 };
1174 Ok(ProtobufEvent {
1175 name: ProtobufEventType::HintText as i32,
1176 payload: Some(event::Payload::HintTextPayload(payload)),
1177 })
1178 },
1179 Event::ActivePaneScroll(scroll) => {
1180 let payload = match scroll {
1181 Some((position, length)) => ProtobufActivePaneScrollPayload {
1182 position: Some(position as u32),
1183 length: Some(length as u32),
1184 },
1185 None => ProtobufActivePaneScrollPayload {
1186 position: None,
1187 length: None,
1188 },
1189 };
1190 Ok(ProtobufEvent {
1191 name: ProtobufEventType::ActivePaneScroll as i32,
1192 payload: Some(event::Payload::ActivePaneScrollPayload(payload)),
1193 })
1194 },
1195 Event::InitialKeybinds(keybinds) => {
1196 let mut protobuf_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
1197 for (input_mode, input_mode_keybinds) in keybinds {
1198 let mode: ProtobufInputMode = input_mode.try_into()?;
1199 let mut key_binds: Vec<ProtobufKeyBind> = vec![];
1200 for (key, actions) in input_mode_keybinds {
1201 let protobuf_key: ProtobufKey = key.try_into()?;
1202 let mut protobuf_actions: Vec<ProtobufAction> = vec![];
1203 for action in actions {
1204 if let Ok(protobuf_action) = action.try_into() {
1205 protobuf_actions.push(protobuf_action);
1206 }
1207 }
1208 key_binds.push(ProtobufKeyBind {
1209 key: Some(protobuf_key),
1210 action: protobuf_actions,
1211 });
1212 }
1213 protobuf_keybinds.push(ProtobufInputModeKeybinds {
1214 mode: mode as i32,
1215 key_bind: key_binds,
1216 });
1217 }
1218 Ok(ProtobufEvent {
1219 name: ProtobufEventType::InitialKeybinds as i32,
1220 payload: Some(event::Payload::InitialKeybindsPayload(
1221 InitialKeybindsPayload {
1222 keybinds: protobuf_keybinds,
1223 },
1224 )),
1225 })
1226 },
1227 }
1228 }
1229}
1230
1231impl TryFrom<SessionInfo> for ProtobufSessionManifest {
1232 type Error = &'static str;
1233 fn try_from(session_info: SessionInfo) -> Result<Self, &'static str> {
1234 let mut protobuf_pane_manifests = vec![];
1235 for (tab_index, pane_infos) in session_info.panes.panes {
1236 let mut protobuf_pane_infos = vec![];
1237 for pane_info in pane_infos {
1238 protobuf_pane_infos.push(pane_info.try_into()?);
1239 }
1240 protobuf_pane_manifests.push(ProtobufPaneManifest {
1241 tab_index: tab_index as u32,
1242 panes: protobuf_pane_infos,
1243 });
1244 }
1245 Ok(ProtobufSessionManifest {
1246 name: session_info.name,
1247 panes: protobuf_pane_manifests,
1248 tabs: session_info
1249 .tabs
1250 .iter()
1251 .filter_map(|t| t.clone().try_into().ok())
1252 .collect(),
1253 connected_clients: session_info.connected_clients as u32,
1254 is_current_session: session_info.is_current_session,
1255 available_layouts: session_info
1256 .available_layouts
1257 .into_iter()
1258 .filter_map(|l| ProtobufLayoutInfo::try_from(l).ok())
1259 .collect(),
1260 plugins: session_info
1261 .plugins
1262 .into_iter()
1263 .map(|p| ProtobufPluginInfo::from(p))
1264 .collect(),
1265 web_clients_allowed: session_info.web_clients_allowed,
1266 web_client_count: session_info.web_client_count as u32,
1267 tab_history: session_info
1268 .tab_history
1269 .into_iter()
1270 .map(|t| ProtobufClientTabHistory::from(t))
1271 .collect(),
1272 pane_history: session_info
1273 .pane_history
1274 .into_iter()
1275 .map(|p| ProtobufClientPaneHistory::from(p))
1276 .collect(),
1277 creation_time: session_info.creation_time.as_secs(),
1278 })
1279 }
1280}
1281
1282impl From<(u16, Vec<usize>)> for ProtobufClientTabHistory {
1283 fn from((client_id, tab_history): (u16, Vec<usize>)) -> ProtobufClientTabHistory {
1284 ProtobufClientTabHistory {
1285 client_id: client_id as u32,
1286 tab_history: tab_history.into_iter().map(|t| t as u32).collect(),
1287 }
1288 }
1289}
1290
1291impl From<(u16, Vec<PaneId>)> for ProtobufClientPaneHistory {
1292 fn from((client_id, pane_history): (u16, Vec<PaneId>)) -> ProtobufClientPaneHistory {
1293 ProtobufClientPaneHistory {
1294 client_id: client_id as u32,
1295 pane_history: pane_history
1296 .into_iter()
1297 .filter_map(|p| p.try_into().ok())
1298 .collect(),
1299 }
1300 }
1301}
1302impl From<(u32, PluginInfo)> for ProtobufPluginInfo {
1303 fn from((plugin_id, plugin_info): (u32, PluginInfo)) -> ProtobufPluginInfo {
1304 ProtobufPluginInfo {
1305 plugin_id,
1306 plugin_url: plugin_info.location,
1307 plugin_config: plugin_info
1308 .configuration
1309 .into_iter()
1310 .map(|(name, value)| ContextItem { name, value })
1311 .collect(),
1312 }
1313 }
1314}
1315
1316impl TryFrom<ProtobufSessionManifest> for SessionInfo {
1317 type Error = &'static str;
1318 fn try_from(protobuf_session_manifest: ProtobufSessionManifest) -> Result<Self, &'static str> {
1319 let mut pane_manifest: HashMap<usize, Vec<PaneInfo>> = HashMap::new();
1320 for protobuf_pane_manifest in protobuf_session_manifest.panes {
1321 let tab_index = protobuf_pane_manifest.tab_index as usize;
1322 let mut panes = vec![];
1323 for protobuf_pane_info in protobuf_pane_manifest.panes {
1324 panes.push(protobuf_pane_info.try_into()?);
1325 }
1326 if pane_manifest.contains_key(&tab_index) {
1327 return Err("Duplicate tab definition in pane manifest");
1328 }
1329 pane_manifest.insert(tab_index, panes);
1330 }
1331 let panes = PaneManifest {
1332 panes: pane_manifest,
1333 };
1334 let mut plugins = BTreeMap::new();
1335 for plugin_info in protobuf_session_manifest.plugins.into_iter() {
1336 let mut configuration = BTreeMap::new();
1337 for context_item in plugin_info.plugin_config.into_iter() {
1338 configuration.insert(context_item.name, context_item.value);
1339 }
1340 plugins.insert(
1341 plugin_info.plugin_id,
1342 PluginInfo {
1343 location: plugin_info.plugin_url,
1344 configuration,
1345 },
1346 );
1347 }
1348 let mut tab_history = BTreeMap::new();
1349 for client_tab_history in protobuf_session_manifest.tab_history.into_iter() {
1350 let client_id = client_tab_history.client_id;
1351 let tab_history_for_client = client_tab_history
1352 .tab_history
1353 .iter()
1354 .map(|t| *t as usize)
1355 .collect();
1356 tab_history.insert(client_id as u16, tab_history_for_client);
1357 }
1358 let mut pane_history = BTreeMap::new();
1359 for client_pane_history in protobuf_session_manifest.pane_history.into_iter() {
1360 let client_id = client_pane_history.client_id;
1361 let pane_history_for_client = client_pane_history
1362 .pane_history
1363 .into_iter()
1364 .filter_map(|p| p.try_into().ok())
1365 .collect();
1366 pane_history.insert(client_id as u16, pane_history_for_client);
1367 }
1368 Ok(SessionInfo {
1369 name: protobuf_session_manifest.name,
1370 tabs: protobuf_session_manifest
1371 .tabs
1372 .iter()
1373 .filter_map(|t| t.clone().try_into().ok())
1374 .collect(),
1375 panes,
1376 connected_clients: protobuf_session_manifest.connected_clients as usize,
1377 is_current_session: protobuf_session_manifest.is_current_session,
1378 available_layouts: protobuf_session_manifest
1379 .available_layouts
1380 .into_iter()
1381 .filter_map(|l| LayoutInfo::try_from(l).ok())
1382 .collect(),
1383 plugins,
1384 web_clients_allowed: protobuf_session_manifest.web_clients_allowed,
1385 web_client_count: protobuf_session_manifest.web_client_count as usize,
1386 tab_history,
1387 pane_history,
1388 creation_time: Duration::from_secs(protobuf_session_manifest.creation_time),
1389 })
1390 }
1391}
1392
1393impl TryFrom<LayoutInfo> for ProtobufLayoutInfo {
1394 type Error = &'static str;
1395 fn try_from(layout_info: LayoutInfo) -> Result<Self, &'static str> {
1396 match layout_info {
1397 LayoutInfo::File(name, layout_metadata) => Ok(ProtobufLayoutInfo {
1398 source: "file".to_owned(),
1399 name,
1400 layout_metadata: Some(layout_metadata.try_into()?),
1401 }),
1402 LayoutInfo::BuiltIn(name) => Ok(ProtobufLayoutInfo {
1403 source: "built-in".to_owned(),
1404 name,
1405 layout_metadata: None,
1406 }),
1407 LayoutInfo::Url(name) => Ok(ProtobufLayoutInfo {
1408 source: "url".to_owned(),
1409 name,
1410 layout_metadata: None,
1411 }),
1412 LayoutInfo::Stringified(stringified_layout) => Ok(ProtobufLayoutInfo {
1413 source: "stringified".to_owned(),
1414 name: stringified_layout.clone(),
1415 layout_metadata: None,
1416 }),
1417 }
1418 }
1419}
1420
1421impl TryFrom<ProtobufLayoutInfo> for LayoutInfo {
1422 type Error = &'static str;
1423 fn try_from(protobuf_layout_info: ProtobufLayoutInfo) -> Result<Self, &'static str> {
1424 match protobuf_layout_info.source.as_str() {
1425 "file" => {
1426 let layout_metadata = protobuf_layout_info
1427 .layout_metadata
1428 .map(|m| m.try_into())
1429 .transpose()?
1430 .unwrap_or_default();
1431 Ok(LayoutInfo::File(protobuf_layout_info.name, layout_metadata))
1432 },
1433 "built-in" => Ok(LayoutInfo::BuiltIn(protobuf_layout_info.name)),
1434 "url" => Ok(LayoutInfo::Url(protobuf_layout_info.name)),
1435 "stringified" => Ok(LayoutInfo::Stringified(protobuf_layout_info.name)),
1436 _ => Err("Unknown source for layout"),
1437 }
1438 }
1439}
1440
1441impl TryFrom<ProtobufLayoutMetadata> for LayoutMetadata {
1442 type Error = &'static str;
1443 fn try_from(protobuf_metadata: ProtobufLayoutMetadata) -> Result<Self, &'static str> {
1444 let tabs = protobuf_metadata
1445 .tabs
1446 .into_iter()
1447 .map(|t| t.try_into())
1448 .collect::<Result<Vec<_>, _>>()?;
1449 Ok(LayoutMetadata {
1450 tabs,
1451 creation_time: protobuf_metadata.creation_time,
1452 update_time: protobuf_metadata.update_time,
1453 })
1454 }
1455}
1456
1457impl TryFrom<LayoutMetadata> for ProtobufLayoutMetadata {
1458 type Error = &'static str;
1459 fn try_from(metadata: LayoutMetadata) -> Result<Self, &'static str> {
1460 let tabs = metadata
1461 .tabs
1462 .into_iter()
1463 .map(|t| t.try_into())
1464 .collect::<Result<Vec<_>, _>>()?;
1465 Ok(ProtobufLayoutMetadata {
1466 tabs,
1467 creation_time: metadata.creation_time,
1468 update_time: metadata.update_time,
1469 })
1470 }
1471}
1472
1473impl TryFrom<ProtobufTabMetadata> for TabMetadata {
1474 type Error = &'static str;
1475 fn try_from(protobuf_metadata: ProtobufTabMetadata) -> Result<Self, &'static str> {
1476 let panes = protobuf_metadata
1477 .pane_metadata
1478 .into_iter()
1479 .map(|p| p.try_into())
1480 .collect::<Result<Vec<_>, _>>()?;
1481 Ok(TabMetadata {
1482 panes,
1483 name: protobuf_metadata.name,
1484 })
1485 }
1486}
1487
1488impl TryFrom<TabMetadata> for ProtobufTabMetadata {
1489 type Error = &'static str;
1490 fn try_from(metadata: TabMetadata) -> Result<Self, &'static str> {
1491 let pane_metadata = metadata
1492 .panes
1493 .into_iter()
1494 .map(|p| p.try_into())
1495 .collect::<Result<Vec<_>, _>>()?;
1496 Ok(ProtobufTabMetadata {
1497 pane_metadata,
1498 name: metadata.name,
1499 })
1500 }
1501}
1502
1503impl TryFrom<ProtobufPaneMetadata> for PaneMetadata {
1504 type Error = &'static str;
1505 fn try_from(protobuf_metadata: ProtobufPaneMetadata) -> Result<Self, &'static str> {
1506 Ok(PaneMetadata {
1507 name: protobuf_metadata.name,
1508 is_plugin: protobuf_metadata.is_plugin,
1509 is_builtin_plugin: protobuf_metadata.is_builtin_plugin,
1510 })
1511 }
1512}
1513
1514impl TryFrom<PaneMetadata> for ProtobufPaneMetadata {
1515 type Error = &'static str;
1516 fn try_from(metadata: PaneMetadata) -> Result<Self, &'static str> {
1517 Ok(ProtobufPaneMetadata {
1518 name: metadata.name,
1519 is_plugin: metadata.is_plugin,
1520 is_builtin_plugin: metadata.is_builtin_plugin,
1521 })
1522 }
1523}
1524
1525impl TryFrom<ProtobufLayoutWithError> for crate::data::LayoutWithError {
1527 type Error = &'static str;
1528 fn try_from(protobuf: ProtobufLayoutWithError) -> Result<Self, Self::Error> {
1529 Ok(crate::data::LayoutWithError {
1530 layout_name: protobuf.layout_name,
1531 error: protobuf.error.ok_or("Missing error field")?.try_into()?,
1532 })
1533 }
1534}
1535
1536impl TryFrom<crate::data::LayoutWithError> for ProtobufLayoutWithError {
1537 type Error = &'static str;
1538 fn try_from(layout_error: crate::data::LayoutWithError) -> Result<Self, Self::Error> {
1539 Ok(ProtobufLayoutWithError {
1540 layout_name: layout_error.layout_name,
1541 error: Some(layout_error.error.try_into()?),
1542 })
1543 }
1544}
1545
1546impl TryFrom<ProtobufLayoutParsingError> for crate::data::LayoutParsingError {
1548 type Error = &'static str;
1549 fn try_from(protobuf: ProtobufLayoutParsingError) -> Result<Self, Self::Error> {
1550 match protobuf.error_type.ok_or("Missing error_type")? {
1551 ProtobufLayoutParsingErrorType::KdlError(kdl_variant) => {
1552 Ok(crate::data::LayoutParsingError::KdlError {
1553 kdl_error: kdl_variant
1554 .kdl_error
1555 .ok_or("Missing kdl_error")?
1556 .try_into()?,
1557 file_name: kdl_variant.file_name,
1558 source_code: kdl_variant.source_code,
1559 })
1560 },
1561 ProtobufLayoutParsingErrorType::SyntaxError(_) => {
1562 Ok(crate::data::LayoutParsingError::SyntaxError)
1563 },
1564 }
1565 }
1566}
1567
1568impl TryFrom<crate::data::LayoutParsingError> for ProtobufLayoutParsingError {
1569 type Error = &'static str;
1570 fn try_from(error: crate::data::LayoutParsingError) -> Result<Self, Self::Error> {
1571 let error_type = match error {
1572 crate::data::LayoutParsingError::KdlError {
1573 kdl_error,
1574 file_name,
1575 source_code,
1576 } => ProtobufLayoutParsingErrorType::KdlError(ProtobufKdlErrorVariant {
1577 kdl_error: Some(kdl_error.try_into()?),
1578 file_name,
1579 source_code,
1580 }),
1581 crate::data::LayoutParsingError::SyntaxError => {
1582 ProtobufLayoutParsingErrorType::SyntaxError(ProtobufSyntaxError {})
1583 },
1584 };
1585 Ok(ProtobufLayoutParsingError {
1586 error_type: Some(error_type),
1587 })
1588 }
1589}
1590
1591impl TryFrom<ProtobufKdlError> for crate::input::config::KdlError {
1593 type Error = &'static str;
1594 fn try_from(protobuf: ProtobufKdlError) -> Result<Self, Self::Error> {
1595 Ok(crate::input::config::KdlError {
1596 error_message: protobuf.error_message,
1597 src: None, offset: protobuf.offset.map(|o| o as usize),
1599 len: protobuf.len.map(|l| l as usize),
1600 help_message: protobuf.help_message,
1601 })
1602 }
1603}
1604
1605impl TryFrom<crate::input::config::KdlError> for ProtobufKdlError {
1606 type Error = &'static str;
1607 fn try_from(kdl: crate::input::config::KdlError) -> Result<Self, Self::Error> {
1608 Ok(ProtobufKdlError {
1609 error_message: kdl.error_message,
1610 offset: kdl.offset.map(|o| o as u64),
1612 len: kdl.len.map(|l| l as u64),
1613 help_message: kdl.help_message,
1614 })
1615 }
1616}
1617
1618impl TryFrom<CopyDestination> for ProtobufCopyDestination {
1619 type Error = &'static str;
1620 fn try_from(copy_destination: CopyDestination) -> Result<Self, &'static str> {
1621 match copy_destination {
1622 CopyDestination::Command => Ok(ProtobufCopyDestination::Command),
1623 CopyDestination::Primary => Ok(ProtobufCopyDestination::Primary),
1624 CopyDestination::System => Ok(ProtobufCopyDestination::System),
1625 }
1626 }
1627}
1628
1629impl TryFrom<ProtobufCopyDestination> for CopyDestination {
1630 type Error = &'static str;
1631 fn try_from(protobuf_copy_destination: ProtobufCopyDestination) -> Result<Self, &'static str> {
1632 match protobuf_copy_destination {
1633 ProtobufCopyDestination::Command => Ok(CopyDestination::Command),
1634 ProtobufCopyDestination::Primary => Ok(CopyDestination::Primary),
1635 ProtobufCopyDestination::System => Ok(CopyDestination::System),
1636 }
1637 }
1638}
1639
1640impl TryFrom<MouseEventPayload> for Mouse {
1641 type Error = &'static str;
1642 fn try_from(mouse_event_payload: MouseEventPayload) -> Result<Self, &'static str> {
1643 match MouseEventName::try_from(mouse_event_payload.mouse_event_name).ok() {
1644 Some(MouseEventName::MouseScrollUp) => match mouse_event_payload.mouse_event_payload {
1645 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
1646 Ok(Mouse::ScrollUp(line_count as usize))
1647 },
1648 _ => Err("Malformed payload for mouse scroll up"),
1649 },
1650 Some(MouseEventName::MouseScrollDown) => {
1651 match mouse_event_payload.mouse_event_payload {
1652 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
1653 Ok(Mouse::ScrollDown(line_count as usize))
1654 },
1655 _ => Err("Malformed payload for mouse scroll down"),
1656 }
1657 },
1658 Some(MouseEventName::MouseLeftClick) => match mouse_event_payload.mouse_event_payload {
1659 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1660 Mouse::LeftClick(position.line as isize, position.column as usize),
1661 ),
1662 _ => Err("Malformed payload for mouse left click"),
1663 },
1664 Some(MouseEventName::MouseRightClick) => {
1665 match mouse_event_payload.mouse_event_payload {
1666 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1667 Mouse::RightClick(position.line as isize, position.column as usize),
1668 ),
1669 _ => Err("Malformed payload for mouse right click"),
1670 }
1671 },
1672 Some(MouseEventName::MouseHold) => match mouse_event_payload.mouse_event_payload {
1673 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1674 Mouse::Hold(position.line as isize, position.column as usize),
1675 ),
1676 _ => Err("Malformed payload for mouse hold"),
1677 },
1678 Some(MouseEventName::MouseRelease) => match mouse_event_payload.mouse_event_payload {
1679 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1680 Mouse::Release(position.line as isize, position.column as usize),
1681 ),
1682 _ => Err("Malformed payload for mouse release"),
1683 },
1684 Some(MouseEventName::MouseHover) => match mouse_event_payload.mouse_event_payload {
1685 Some(mouse_event_payload::MouseEventPayload::Position(position)) => Ok(
1686 Mouse::Hover(position.line as isize, position.column as usize),
1687 ),
1688 _ => Err("Malformed payload for mouse hover"),
1689 },
1690 Some(MouseEventName::MouseScrollLeft) => {
1691 match mouse_event_payload.mouse_event_payload {
1692 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
1693 Ok(Mouse::ScrollLeft(line_count as usize))
1694 },
1695 _ => Err("Malformed payload for mouse scroll left"),
1696 }
1697 },
1698 Some(MouseEventName::MouseScrollRight) => {
1699 match mouse_event_payload.mouse_event_payload {
1700 Some(mouse_event_payload::MouseEventPayload::LineCount(line_count)) => {
1701 Ok(Mouse::ScrollRight(line_count as usize))
1702 },
1703 _ => Err("Malformed payload for mouse scroll right"),
1704 }
1705 },
1706 None => Err("Malformed payload for MouseEventName"),
1707 }
1708 }
1709}
1710
1711impl TryFrom<Mouse> for MouseEventPayload {
1712 type Error = &'static str;
1713 fn try_from(mouse: Mouse) -> Result<Self, &'static str> {
1714 match mouse {
1715 Mouse::ScrollUp(number_of_lines) => Ok(MouseEventPayload {
1716 mouse_event_name: MouseEventName::MouseScrollUp as i32,
1717 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
1718 number_of_lines as u32,
1719 )),
1720 }),
1721 Mouse::ScrollDown(number_of_lines) => Ok(MouseEventPayload {
1722 mouse_event_name: MouseEventName::MouseScrollDown as i32,
1723 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
1724 number_of_lines as u32,
1725 )),
1726 }),
1727 Mouse::LeftClick(line, column) => Ok(MouseEventPayload {
1728 mouse_event_name: MouseEventName::MouseLeftClick as i32,
1729 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1730 ProtobufPosition {
1731 line: line as i64,
1732 column: column as i64,
1733 },
1734 )),
1735 }),
1736 Mouse::RightClick(line, column) => Ok(MouseEventPayload {
1737 mouse_event_name: MouseEventName::MouseRightClick as i32,
1738 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1739 ProtobufPosition {
1740 line: line as i64,
1741 column: column as i64,
1742 },
1743 )),
1744 }),
1745 Mouse::Hold(line, column) => Ok(MouseEventPayload {
1746 mouse_event_name: MouseEventName::MouseHold as i32,
1747 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1748 ProtobufPosition {
1749 line: line as i64,
1750 column: column as i64,
1751 },
1752 )),
1753 }),
1754 Mouse::Release(line, column) => Ok(MouseEventPayload {
1755 mouse_event_name: MouseEventName::MouseRelease as i32,
1756 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1757 ProtobufPosition {
1758 line: line as i64,
1759 column: column as i64,
1760 },
1761 )),
1762 }),
1763 Mouse::Hover(line, column) => Ok(MouseEventPayload {
1764 mouse_event_name: MouseEventName::MouseHover as i32,
1765 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::Position(
1766 ProtobufPosition {
1767 line: line as i64,
1768 column: column as i64,
1769 },
1770 )),
1771 }),
1772 Mouse::ScrollLeft(cols) => Ok(MouseEventPayload {
1773 mouse_event_name: MouseEventName::MouseScrollLeft as i32,
1774 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
1775 cols as u32,
1776 )),
1777 }),
1778 Mouse::ScrollRight(cols) => Ok(MouseEventPayload {
1779 mouse_event_name: MouseEventName::MouseScrollRight as i32,
1780 mouse_event_payload: Some(mouse_event_payload::MouseEventPayload::LineCount(
1781 cols as u32,
1782 )),
1783 }),
1784 }
1785 }
1786}
1787
1788impl TryFrom<ProtobufPaneInfo> for PaneInfo {
1789 type Error = &'static str;
1790 fn try_from(protobuf_pane_info: ProtobufPaneInfo) -> Result<Self, &'static str> {
1791 Ok(PaneInfo {
1792 id: protobuf_pane_info.id,
1793 is_plugin: protobuf_pane_info.is_plugin,
1794 is_focused: protobuf_pane_info.is_focused,
1795 is_fullscreen: protobuf_pane_info.is_fullscreen,
1796 is_floating: protobuf_pane_info.is_floating,
1797 is_suppressed: protobuf_pane_info.is_suppressed,
1798 title: protobuf_pane_info.title,
1799 exited: protobuf_pane_info.exited,
1800 exit_status: protobuf_pane_info.exit_status,
1801 is_held: protobuf_pane_info.is_held,
1802 pane_x: protobuf_pane_info.pane_x as usize,
1803 pane_content_x: protobuf_pane_info.pane_content_x as usize,
1804 pane_y: protobuf_pane_info.pane_y as usize,
1805 pane_content_y: protobuf_pane_info.pane_content_y as usize,
1806 pane_rows: protobuf_pane_info.pane_rows as usize,
1807 pane_content_rows: protobuf_pane_info.pane_content_rows as usize,
1808 pane_columns: protobuf_pane_info.pane_columns as usize,
1809 pane_content_columns: protobuf_pane_info.pane_content_columns as usize,
1810 cursor_coordinates_in_pane: protobuf_pane_info
1811 .cursor_coordinates_in_pane
1812 .map(|position| (position.column as usize, position.line as usize)),
1813 terminal_command: protobuf_pane_info.terminal_command,
1814 plugin_url: protobuf_pane_info.plugin_url,
1815 is_selectable: protobuf_pane_info.is_selectable,
1816 index_in_pane_group: protobuf_pane_info
1817 .index_in_pane_group
1818 .iter()
1819 .map(|index_in_pane_group| {
1820 (
1821 index_in_pane_group.client_id as u16,
1822 index_in_pane_group.index as usize,
1823 )
1824 })
1825 .collect(),
1826 default_fg: protobuf_pane_info.default_fg,
1827 default_bg: protobuf_pane_info.default_bg,
1828 })
1829 }
1830}
1831
1832impl TryFrom<PaneInfo> for ProtobufPaneInfo {
1833 type Error = &'static str;
1834 fn try_from(pane_info: PaneInfo) -> Result<Self, &'static str> {
1835 Ok(ProtobufPaneInfo {
1836 id: pane_info.id,
1837 is_plugin: pane_info.is_plugin,
1838 is_focused: pane_info.is_focused,
1839 is_fullscreen: pane_info.is_fullscreen,
1840 is_floating: pane_info.is_floating,
1841 is_suppressed: pane_info.is_suppressed,
1842 title: pane_info.title,
1843 exited: pane_info.exited,
1844 exit_status: pane_info.exit_status,
1845 is_held: pane_info.is_held,
1846 pane_x: pane_info.pane_x as u32,
1847 pane_content_x: pane_info.pane_content_x as u32,
1848 pane_y: pane_info.pane_y as u32,
1849 pane_content_y: pane_info.pane_content_y as u32,
1850 pane_rows: pane_info.pane_rows as u32,
1851 pane_content_rows: pane_info.pane_content_rows as u32,
1852 pane_columns: pane_info.pane_columns as u32,
1853 pane_content_columns: pane_info.pane_content_columns as u32,
1854 cursor_coordinates_in_pane: pane_info.cursor_coordinates_in_pane.map(|(x, y)| {
1855 ProtobufPosition {
1856 column: x as i64,
1857 line: y as i64,
1858 }
1859 }),
1860 terminal_command: pane_info.terminal_command,
1861 plugin_url: pane_info.plugin_url,
1862 is_selectable: pane_info.is_selectable,
1863 index_in_pane_group: pane_info
1864 .index_in_pane_group
1865 .iter()
1866 .map(|(&client_id, &index)| IndexInPaneGroup {
1867 client_id: client_id as u32,
1868 index: index as u32,
1869 })
1870 .collect(),
1871 default_fg: pane_info.default_fg,
1872 default_bg: pane_info.default_bg,
1873 })
1874 }
1875}
1876
1877impl TryFrom<ProtobufTabInfo> for TabInfo {
1878 type Error = &'static str;
1879 fn try_from(protobuf_tab_info: ProtobufTabInfo) -> Result<Self, &'static str> {
1880 Ok(TabInfo {
1881 position: protobuf_tab_info.position as usize,
1882 name: protobuf_tab_info.name,
1883 active: protobuf_tab_info.active,
1884 panes_to_hide: protobuf_tab_info.panes_to_hide as usize,
1885 is_fullscreen_active: protobuf_tab_info.is_fullscreen_active,
1886 is_sync_panes_active: protobuf_tab_info.is_sync_panes_active,
1887 are_floating_panes_visible: protobuf_tab_info.are_floating_panes_visible,
1888 other_focused_clients: protobuf_tab_info
1889 .other_focused_clients
1890 .iter()
1891 .map(|c| *c as u16)
1892 .collect(),
1893 active_swap_layout_name: protobuf_tab_info.active_swap_layout_name,
1894 is_swap_layout_dirty: protobuf_tab_info.is_swap_layout_dirty,
1895 viewport_rows: protobuf_tab_info.viewport_rows as usize,
1896 viewport_columns: protobuf_tab_info.viewport_columns as usize,
1897 display_area_rows: protobuf_tab_info.display_area_rows as usize,
1898 display_area_columns: protobuf_tab_info.display_area_columns as usize,
1899 selectable_tiled_panes_count: protobuf_tab_info.selectable_tiled_panes_count as usize,
1900 selectable_floating_panes_count: protobuf_tab_info.selectable_floating_panes_count
1901 as usize,
1902 tab_id: protobuf_tab_info.tab_id as usize,
1903 has_bell_notification: protobuf_tab_info.has_bell_notification,
1904 is_flashing_bell: protobuf_tab_info.is_flashing_bell,
1905 })
1906 }
1907}
1908
1909impl TryFrom<TabInfo> for ProtobufTabInfo {
1910 type Error = &'static str;
1911 fn try_from(tab_info: TabInfo) -> Result<Self, &'static str> {
1912 Ok(ProtobufTabInfo {
1913 position: tab_info.position as u32,
1914 name: tab_info.name,
1915 active: tab_info.active,
1916 panes_to_hide: tab_info.panes_to_hide as u32,
1917 is_fullscreen_active: tab_info.is_fullscreen_active,
1918 is_sync_panes_active: tab_info.is_sync_panes_active,
1919 are_floating_panes_visible: tab_info.are_floating_panes_visible,
1920 other_focused_clients: tab_info
1921 .other_focused_clients
1922 .iter()
1923 .map(|c| *c as u32)
1924 .collect(),
1925 active_swap_layout_name: tab_info.active_swap_layout_name,
1926 is_swap_layout_dirty: tab_info.is_swap_layout_dirty,
1927 viewport_rows: tab_info.viewport_rows as u32,
1928 viewport_columns: tab_info.viewport_columns as u32,
1929 display_area_rows: tab_info.display_area_rows as u32,
1930 display_area_columns: tab_info.display_area_columns as u32,
1931 selectable_tiled_panes_count: tab_info.selectable_tiled_panes_count as u32,
1932 selectable_floating_panes_count: tab_info.selectable_floating_panes_count as u32,
1933 tab_id: tab_info.tab_id as u32,
1934 has_bell_notification: tab_info.has_bell_notification,
1935 is_flashing_bell: tab_info.is_flashing_bell,
1936 })
1937 }
1938}
1939
1940impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
1941 type Error = &'static str;
1942 fn try_from(
1943 mut protobuf_mode_update_payload: ProtobufModeUpdatePayload,
1944 ) -> Result<Self, &'static str> {
1945 let current_mode: InputMode =
1946 ProtobufInputMode::try_from(protobuf_mode_update_payload.current_mode)
1947 .ok()
1948 .ok_or("Malformed InputMode in the ModeUpdate Event")?
1949 .try_into()?;
1950 let base_mode: Option<InputMode> = protobuf_mode_update_payload
1951 .base_mode
1952 .and_then(|b_m| ProtobufInputMode::try_from(b_m).ok()?.try_into().ok());
1953 let keybinds: Vec<(InputMode, Vec<(KeyWithModifier, Vec<Action>)>)> =
1954 protobuf_mode_update_payload
1955 .keybinds
1956 .iter_mut()
1957 .filter_map(|k| {
1958 let input_mode: InputMode = ProtobufInputMode::try_from(k.mode)
1959 .ok()
1960 .ok_or("Malformed InputMode in the ModeUpdate Event")
1961 .ok()?
1962 .try_into()
1963 .ok()?;
1964 let mut keybinds: Vec<(KeyWithModifier, Vec<Action>)> = vec![];
1965 for mut protobuf_keybind in k.key_bind.drain(..) {
1966 let key: KeyWithModifier = protobuf_keybind.key.unwrap().try_into().ok()?;
1967 let mut actions: Vec<Action> = vec![];
1968 for action in protobuf_keybind.action.drain(..) {
1969 if let Ok(action) = action.try_into() {
1970 actions.push(action);
1971 }
1972 }
1973 keybinds.push((key, actions));
1974 }
1975 Some((input_mode, keybinds))
1976 })
1977 .collect();
1978 let style: Style = protobuf_mode_update_payload
1979 .style
1980 .and_then(|m| m.try_into().ok())
1981 .ok_or("malformed payload for mode_info")?;
1982 let session_name = protobuf_mode_update_payload.session_name;
1983 let editor = protobuf_mode_update_payload
1984 .editor
1985 .map(|e| PathBuf::from(e));
1986 let shell = protobuf_mode_update_payload.shell.map(|s| PathBuf::from(s));
1987 let web_clients_allowed = protobuf_mode_update_payload.web_clients_allowed;
1988 let web_sharing = protobuf_mode_update_payload
1989 .web_sharing
1990 .and_then(|w| ProtobufWebSharing::try_from(w).ok())
1991 .map(|w| w.into());
1992 let capabilities = PluginCapabilities {
1993 arrow_fonts: protobuf_mode_update_payload.arrow_fonts_support,
1994 };
1995 let currently_marking_pane_group =
1996 protobuf_mode_update_payload.currently_marking_pane_group;
1997 let is_web_client = protobuf_mode_update_payload.is_web_client;
1998
1999 let web_server_ip = protobuf_mode_update_payload
2000 .web_server_ip
2001 .as_ref()
2002 .and_then(|web_server_ip| IpAddr::from_str(web_server_ip).ok());
2003
2004 let web_server_port = protobuf_mode_update_payload
2005 .web_server_port
2006 .map(|w| w as u16);
2007
2008 let web_server_capability = protobuf_mode_update_payload.web_server_capability;
2009
2010 let pane_frame_style = protobuf_mode_update_payload
2011 .pane_frame_style
2012 .and_then(|p| ProtobufPaneFrameStyle::try_from(p).ok())
2013 .map(|p| p.into());
2014
2015 let session_dimmed = protobuf_mode_update_payload.session_dimmed;
2016
2017 let session_ancestry = protobuf_mode_update_payload.ancestry;
2018
2019 let host_fullscreen = protobuf_mode_update_payload.host_fullscreen;
2020
2021 let nested_ascend_keys = protobuf_mode_update_payload
2022 .nested_ascend_keys
2023 .iter()
2024 .filter_map(|key| KeyWithModifier::from_str(key).ok())
2025 .collect();
2026
2027 let session_ascended = protobuf_mode_update_payload.session_ascended;
2028
2029 let nested_descend_keys = protobuf_mode_update_payload
2030 .nested_descend_keys
2031 .iter()
2032 .filter_map(|key| KeyWithModifier::from_str(key).ok())
2033 .collect();
2034
2035 let mode_info = ModeInfo {
2036 mode: current_mode,
2037 keybinds,
2038 style,
2039 capabilities,
2040 session_name,
2041 base_mode,
2042 editor,
2043 shell,
2044 web_clients_allowed,
2045 web_sharing,
2046 currently_marking_pane_group,
2047 is_web_client,
2048 web_server_ip,
2049 web_server_port,
2050 web_server_capability,
2051 pane_frame_style,
2052 session_dimmed,
2053 session_ancestry,
2054 host_fullscreen,
2055 nested_ascend_keys,
2056 session_ascended,
2057 nested_descend_keys,
2058 };
2059 Ok(mode_info)
2060 }
2061}
2062
2063impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
2064 type Error = &'static str;
2065 fn try_from(mode_info: ModeInfo) -> Result<Self, &'static str> {
2066 let current_mode: ProtobufInputMode = mode_info.mode.try_into()?;
2067 let base_mode: Option<ProtobufInputMode> = mode_info
2068 .base_mode
2069 .and_then(|mode| ProtobufInputMode::try_from(mode).ok());
2070 let style: ProtobufStyle = mode_info.style.try_into()?;
2071 let arrow_fonts_support: bool = mode_info.capabilities.arrow_fonts;
2072 let session_name = mode_info.session_name;
2073 let editor = mode_info.editor.map(|e| e.display().to_string());
2074 let shell = mode_info.shell.map(|s| s.display().to_string());
2075 let web_clients_allowed = mode_info.web_clients_allowed;
2076 let web_sharing = mode_info.web_sharing.map(|w| w as i32);
2077 let currently_marking_pane_group = mode_info.currently_marking_pane_group;
2078 let is_web_client = mode_info.is_web_client;
2079 let web_server_ip = mode_info.web_server_ip.map(|i| format!("{}", i));
2080 let web_server_port = mode_info.web_server_port.map(|p| p as u32);
2081 let web_server_capability = mode_info.web_server_capability;
2082 let pane_frame_style = mode_info.pane_frame_style.map(|p| {
2083 let protobuf_pane_frame_style: ProtobufPaneFrameStyle = p.into();
2084 protobuf_pane_frame_style as i32
2085 });
2086 let session_dimmed = mode_info.session_dimmed;
2087 let session_ancestry = mode_info.session_ancestry;
2088 let host_fullscreen = mode_info.host_fullscreen;
2089 let nested_ascend_keys = mode_info
2090 .nested_ascend_keys
2091 .iter()
2092 .map(|key| key.to_kdl())
2093 .collect();
2094 let session_ascended = mode_info.session_ascended;
2095 let nested_descend_keys = mode_info
2096 .nested_descend_keys
2097 .iter()
2098 .map(|key| key.to_kdl())
2099 .collect();
2100 let mut protobuf_input_mode_keybinds: Vec<ProtobufInputModeKeybinds> = vec![];
2101 for (input_mode, input_mode_keybinds) in mode_info.keybinds {
2102 let mode: ProtobufInputMode = input_mode.try_into()?;
2103 let mut keybinds: Vec<ProtobufKeyBind> = vec![];
2104 for (key, actions) in input_mode_keybinds {
2105 let protobuf_key: ProtobufKey = key.try_into()?;
2106 let mut protobuf_actions: Vec<ProtobufAction> = vec![];
2107 for action in actions {
2108 if let Ok(protobuf_action) = action.try_into() {
2109 protobuf_actions.push(protobuf_action);
2110 }
2111 }
2112 let key_bind = ProtobufKeyBind {
2113 key: Some(protobuf_key),
2114 action: protobuf_actions,
2115 };
2116 keybinds.push(key_bind);
2117 }
2118 let input_mode_keybind = ProtobufInputModeKeybinds {
2119 mode: mode as i32,
2120 key_bind: keybinds,
2121 };
2122 protobuf_input_mode_keybinds.push(input_mode_keybind);
2123 }
2124 Ok(ProtobufModeUpdatePayload {
2125 current_mode: current_mode as i32,
2126 style: Some(style),
2127 keybinds: protobuf_input_mode_keybinds,
2128 arrow_fonts_support,
2129 session_name,
2130 base_mode: base_mode.map(|b_m| b_m as i32),
2131 editor,
2132 shell,
2133 web_clients_allowed,
2134 web_sharing,
2135 currently_marking_pane_group,
2136 is_web_client,
2137 web_server_ip,
2138 web_server_port,
2139 web_server_capability,
2140 pane_frame_style,
2141 session_dimmed,
2142 ancestry: session_ancestry,
2143 host_fullscreen,
2144 nested_ascend_keys,
2145 session_ascended,
2146 nested_descend_keys,
2147 })
2148 }
2149}
2150
2151impl TryFrom<ProtobufEventNameList> for HashSet<EventType> {
2152 type Error = &'static str;
2153 fn try_from(protobuf_event_name_list: ProtobufEventNameList) -> Result<Self, &'static str> {
2154 let event_types: Vec<ProtobufEventType> = protobuf_event_name_list
2155 .event_types
2156 .iter()
2157 .filter_map(|i| ProtobufEventType::try_from(*i).ok())
2158 .collect();
2159 let event_types: Vec<EventType> = event_types
2160 .iter()
2161 .filter_map(|e| EventType::try_from(*e).ok())
2162 .collect();
2163 Ok(event_types.into_iter().collect())
2164 }
2165}
2166
2167impl TryFrom<HashSet<EventType>> for ProtobufEventNameList {
2168 type Error = &'static str;
2169 fn try_from(event_types: HashSet<EventType>) -> Result<Self, &'static str> {
2170 let protobuf_event_name_list = ProtobufEventNameList {
2171 event_types: event_types
2172 .iter()
2173 .filter_map(|e| ProtobufEventType::try_from(*e).ok())
2174 .map(|e| e as i32)
2175 .collect(),
2176 };
2177 Ok(protobuf_event_name_list)
2178 }
2179}
2180
2181impl TryFrom<ProtobufEventType> for EventType {
2182 type Error = &'static str;
2183 fn try_from(protobuf_event_type: ProtobufEventType) -> Result<Self, &'static str> {
2184 Ok(match protobuf_event_type {
2185 ProtobufEventType::ModeUpdate => EventType::ModeUpdate,
2186 ProtobufEventType::TabUpdate => EventType::TabUpdate,
2187 ProtobufEventType::PaneUpdate => EventType::PaneUpdate,
2188 ProtobufEventType::Key => EventType::Key,
2189 ProtobufEventType::Mouse => EventType::Mouse,
2190 ProtobufEventType::Timer => EventType::Timer,
2191 ProtobufEventType::CopyToClipboard => EventType::CopyToClipboard,
2192 ProtobufEventType::SystemClipboardFailure => EventType::SystemClipboardFailure,
2193 ProtobufEventType::InputReceived => EventType::InputReceived,
2194 ProtobufEventType::Visible => EventType::Visible,
2195 ProtobufEventType::CustomMessage => EventType::CustomMessage,
2196 ProtobufEventType::FileSystemCreate => EventType::FileSystemCreate,
2197 ProtobufEventType::FileSystemRead => EventType::FileSystemRead,
2198 ProtobufEventType::FileSystemUpdate => EventType::FileSystemUpdate,
2199 ProtobufEventType::FileSystemDelete => EventType::FileSystemDelete,
2200 ProtobufEventType::PermissionRequestResult => EventType::PermissionRequestResult,
2201 ProtobufEventType::SessionUpdate => EventType::SessionUpdate,
2202 ProtobufEventType::RunCommandResult => EventType::RunCommandResult,
2203 ProtobufEventType::WebRequestResult => EventType::WebRequestResult,
2204 ProtobufEventType::CommandPaneOpened => EventType::CommandPaneOpened,
2205 ProtobufEventType::CommandPaneExited => EventType::CommandPaneExited,
2206 ProtobufEventType::PaneClosed => EventType::PaneClosed,
2207 ProtobufEventType::EditPaneOpened => EventType::EditPaneOpened,
2208 ProtobufEventType::EditPaneExited => EventType::EditPaneExited,
2209 ProtobufEventType::CommandPaneReRun => EventType::CommandPaneReRun,
2210 ProtobufEventType::FailedToWriteConfigToDisk => EventType::FailedToWriteConfigToDisk,
2211 ProtobufEventType::ListClients => EventType::ListClients,
2212 ProtobufEventType::HostFolderChanged => EventType::HostFolderChanged,
2213 ProtobufEventType::FailedToChangeHostFolder => EventType::FailedToChangeHostFolder,
2214 ProtobufEventType::PastedText => EventType::PastedText,
2215 ProtobufEventType::ConfigWasWrittenToDisk => EventType::ConfigWasWrittenToDisk,
2216 ProtobufEventType::WebServerStatus => EventType::WebServerStatus,
2217 ProtobufEventType::BeforeClose => EventType::BeforeClose,
2218 ProtobufEventType::FailedToStartWebServer => EventType::FailedToStartWebServer,
2219 ProtobufEventType::InterceptedKeyPress => EventType::InterceptedKeyPress,
2220 ProtobufEventType::PaneRenderReport => EventType::PaneRenderReport,
2221 ProtobufEventType::UserAction => EventType::UserAction,
2222 ProtobufEventType::ActionComplete => EventType::ActionComplete,
2223 ProtobufEventType::CwdChanged => EventType::CwdChanged,
2224 ProtobufEventType::CommandChanged => EventType::CommandChanged,
2225 ProtobufEventType::AvailableLayoutInfo => EventType::AvailableLayoutInfo,
2226 ProtobufEventType::PluginConfigurationChanged => EventType::PluginConfigurationChanged,
2227 ProtobufEventType::HighlightClicked => EventType::HighlightClicked,
2228 ProtobufEventType::InitialKeybinds => EventType::InitialKeybinds,
2229 ProtobufEventType::HostTerminalThemeChanged => EventType::HostTerminalThemeChanged,
2230 ProtobufEventType::SoftKeyboardVisibilityChanged => {
2231 EventType::SoftKeyboardVisibilityChanged
2232 },
2233 ProtobufEventType::HintText => EventType::HintText,
2234 ProtobufEventType::ActivePaneScroll => EventType::ActivePaneScroll,
2235 })
2236 }
2237}
2238
2239impl TryFrom<EventType> for ProtobufEventType {
2240 type Error = &'static str;
2241 fn try_from(event_type: EventType) -> Result<Self, &'static str> {
2242 Ok(match event_type {
2243 EventType::ModeUpdate => ProtobufEventType::ModeUpdate,
2244 EventType::TabUpdate => ProtobufEventType::TabUpdate,
2245 EventType::PaneUpdate => ProtobufEventType::PaneUpdate,
2246 EventType::Key => ProtobufEventType::Key,
2247 EventType::Mouse => ProtobufEventType::Mouse,
2248 EventType::Timer => ProtobufEventType::Timer,
2249 EventType::CopyToClipboard => ProtobufEventType::CopyToClipboard,
2250 EventType::SystemClipboardFailure => ProtobufEventType::SystemClipboardFailure,
2251 EventType::InputReceived => ProtobufEventType::InputReceived,
2252 EventType::Visible => ProtobufEventType::Visible,
2253 EventType::CustomMessage => ProtobufEventType::CustomMessage,
2254 EventType::FileSystemCreate => ProtobufEventType::FileSystemCreate,
2255 EventType::FileSystemRead => ProtobufEventType::FileSystemRead,
2256 EventType::FileSystemUpdate => ProtobufEventType::FileSystemUpdate,
2257 EventType::FileSystemDelete => ProtobufEventType::FileSystemDelete,
2258 EventType::PermissionRequestResult => ProtobufEventType::PermissionRequestResult,
2259 EventType::SessionUpdate => ProtobufEventType::SessionUpdate,
2260 EventType::RunCommandResult => ProtobufEventType::RunCommandResult,
2261 EventType::WebRequestResult => ProtobufEventType::WebRequestResult,
2262 EventType::CommandPaneOpened => ProtobufEventType::CommandPaneOpened,
2263 EventType::CommandPaneExited => ProtobufEventType::CommandPaneExited,
2264 EventType::PaneClosed => ProtobufEventType::PaneClosed,
2265 EventType::EditPaneOpened => ProtobufEventType::EditPaneOpened,
2266 EventType::EditPaneExited => ProtobufEventType::EditPaneExited,
2267 EventType::CommandPaneReRun => ProtobufEventType::CommandPaneReRun,
2268 EventType::FailedToWriteConfigToDisk => ProtobufEventType::FailedToWriteConfigToDisk,
2269 EventType::ListClients => ProtobufEventType::ListClients,
2270 EventType::HostFolderChanged => ProtobufEventType::HostFolderChanged,
2271 EventType::FailedToChangeHostFolder => ProtobufEventType::FailedToChangeHostFolder,
2272 EventType::PastedText => ProtobufEventType::PastedText,
2273 EventType::ConfigWasWrittenToDisk => ProtobufEventType::ConfigWasWrittenToDisk,
2274 EventType::WebServerStatus => ProtobufEventType::WebServerStatus,
2275 EventType::BeforeClose => ProtobufEventType::BeforeClose,
2276 EventType::FailedToStartWebServer => ProtobufEventType::FailedToStartWebServer,
2277 EventType::InterceptedKeyPress => ProtobufEventType::InterceptedKeyPress,
2278 EventType::PaneRenderReport => ProtobufEventType::PaneRenderReport,
2279 EventType::UserAction => ProtobufEventType::UserAction,
2280 EventType::ActionComplete => ProtobufEventType::ActionComplete,
2281 EventType::CwdChanged => ProtobufEventType::CwdChanged,
2282 EventType::CommandChanged => ProtobufEventType::CommandChanged,
2283 EventType::AvailableLayoutInfo => ProtobufEventType::AvailableLayoutInfo,
2284 EventType::PluginConfigurationChanged => ProtobufEventType::PluginConfigurationChanged,
2285 EventType::HighlightClicked => ProtobufEventType::HighlightClicked,
2286 EventType::InitialKeybinds => ProtobufEventType::InitialKeybinds,
2287 EventType::HostTerminalThemeChanged => ProtobufEventType::HostTerminalThemeChanged,
2288 EventType::SoftKeyboardVisibilityChanged => {
2289 ProtobufEventType::SoftKeyboardVisibilityChanged
2290 },
2291 EventType::HintText => ProtobufEventType::HintText,
2292 EventType::ActivePaneScroll => ProtobufEventType::ActivePaneScroll,
2293 })
2294 }
2295}
2296
2297impl From<StyledText> for ProtobufStyledText {
2298 fn from(styled_text: StyledText) -> Self {
2299 ProtobufStyledText {
2300 text: styled_text.text,
2301 indices: styled_text
2302 .indices
2303 .into_iter()
2304 .map(|inner| ProtobufStyledTextIndices {
2305 indices: inner.into_iter().map(|i| i as u32).collect(),
2306 })
2307 .collect(),
2308 }
2309 }
2310}
2311
2312impl From<ProtobufStyledText> for StyledText {
2313 fn from(styled_text: ProtobufStyledText) -> Self {
2314 StyledText {
2315 text: styled_text.text,
2316 indices: styled_text
2317 .indices
2318 .into_iter()
2319 .map(|inner| inner.indices.into_iter().map(|i| i as usize).collect())
2320 .collect(),
2321 }
2322 }
2323}
2324
2325impl From<HostTerminalThemeMode> for ProtobufHostTerminalThemeIndication {
2326 fn from(mode: HostTerminalThemeMode) -> Self {
2327 match mode {
2328 HostTerminalThemeMode::Dark => ProtobufHostTerminalThemeIndication::Dark,
2329 HostTerminalThemeMode::Light => ProtobufHostTerminalThemeIndication::Light,
2330 }
2331 }
2332}
2333
2334impl From<ProtobufHostTerminalThemeIndication> for HostTerminalThemeMode {
2335 fn from(mode: ProtobufHostTerminalThemeIndication) -> Self {
2336 match mode {
2337 ProtobufHostTerminalThemeIndication::Dark => HostTerminalThemeMode::Dark,
2338 ProtobufHostTerminalThemeIndication::Light => HostTerminalThemeMode::Light,
2339 }
2340 }
2341}
2342
2343impl From<ProtobufResurrectableSession> for (String, Duration) {
2344 fn from(protobuf_resurrectable_session: ProtobufResurrectableSession) -> (String, Duration) {
2345 (
2346 protobuf_resurrectable_session.name,
2347 Duration::from_secs(protobuf_resurrectable_session.creation_time),
2348 )
2349 }
2350}
2351
2352impl From<(String, Duration)> for ProtobufResurrectableSession {
2353 fn from(session_name_and_creation_time: (String, Duration)) -> ProtobufResurrectableSession {
2354 ProtobufResurrectableSession {
2355 name: session_name_and_creation_time.0,
2356 creation_time: session_name_and_creation_time.1.as_secs(),
2357 }
2358 }
2359}
2360
2361impl From<&ProtobufFileMetadata> for Option<FileMetadata> {
2362 fn from(protobuf_file_metadata: &ProtobufFileMetadata) -> Option<FileMetadata> {
2363 if protobuf_file_metadata.metadata_is_set {
2364 Some(FileMetadata {
2365 is_file: protobuf_file_metadata.is_file,
2366 is_dir: protobuf_file_metadata.is_dir,
2367 is_symlink: protobuf_file_metadata.is_symlink,
2368 len: protobuf_file_metadata.len,
2369 })
2370 } else {
2371 None
2372 }
2373 }
2374}
2375
2376impl From<Option<FileMetadata>> for ProtobufFileMetadata {
2377 fn from(file_metadata: Option<FileMetadata>) -> ProtobufFileMetadata {
2378 match file_metadata {
2379 Some(file_metadata) => ProtobufFileMetadata {
2380 metadata_is_set: true,
2381 is_file: file_metadata.is_file,
2382 is_dir: file_metadata.is_dir,
2383 is_symlink: file_metadata.is_symlink,
2384 len: file_metadata.len,
2385 },
2386 None => ProtobufFileMetadata {
2387 metadata_is_set: false,
2388 ..Default::default()
2389 },
2390 }
2391 }
2392}
2393
2394#[test]
2395fn serialize_mode_update_event() {
2396 use prost::Message;
2397 let mode_update_event = Event::ModeUpdate(Default::default());
2398 let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
2399 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2400 let deserialized_protobuf_event: ProtobufEvent =
2401 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2402 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2403 assert_eq!(
2404 mode_update_event, deserialized_event,
2405 "Event properly serialized/deserialized without change"
2406 );
2407}
2408
2409#[test]
2410fn serialize_mode_update_event_with_non_default_values() {
2411 use crate::data::{BareKey, Palette, PaletteColor, ThemeHue};
2412 use prost::Message;
2413 let mode_update_event = Event::ModeUpdate(ModeInfo {
2414 mode: InputMode::Locked,
2415 keybinds: vec![
2416 (
2417 InputMode::Locked,
2418 vec![(
2419 KeyWithModifier::new(BareKey::Char('b')).with_alt_modifier(),
2420 vec![Action::SwitchToMode {
2421 input_mode: InputMode::Normal,
2422 }],
2423 )],
2424 ),
2425 (
2426 InputMode::Tab,
2427 vec![(
2428 KeyWithModifier::new(BareKey::Up).with_alt_modifier(),
2429 vec![Action::SwitchToMode {
2430 input_mode: InputMode::Pane,
2431 }],
2432 )],
2433 ),
2434 (
2435 InputMode::Pane,
2436 vec![
2437 (
2438 KeyWithModifier::new(BareKey::Char('b')).with_ctrl_modifier(),
2439 vec![
2440 Action::SwitchToMode {
2441 input_mode: InputMode::Tmux,
2442 },
2443 Action::Write {
2444 key_with_modifier: None,
2445 bytes: vec![10],
2446 is_kitty_keyboard_protocol: false,
2447 },
2448 ],
2449 ),
2450 (
2451 KeyWithModifier::new(BareKey::Char('a')),
2452 vec![Action::WriteChars {
2453 chars: "foo".to_owned(),
2454 }],
2455 ),
2456 ],
2457 ),
2458 ],
2459 style: Style {
2460 colors: Palette {
2461 source: crate::data::PaletteSource::Default,
2462 theme_hue: ThemeHue::Light,
2463 fg: PaletteColor::Rgb((1, 1, 1)),
2464 bg: PaletteColor::Rgb((200, 200, 200)),
2465 black: PaletteColor::EightBit(1),
2466 red: PaletteColor::EightBit(2),
2467 green: PaletteColor::EightBit(2),
2468 yellow: PaletteColor::EightBit(2),
2469 blue: PaletteColor::EightBit(2),
2470 magenta: PaletteColor::EightBit(2),
2471 cyan: PaletteColor::EightBit(2),
2472 white: PaletteColor::EightBit(2),
2473 orange: PaletteColor::EightBit(2),
2474 gray: PaletteColor::EightBit(2),
2475 purple: PaletteColor::EightBit(2),
2476 gold: PaletteColor::EightBit(2),
2477 silver: PaletteColor::EightBit(2),
2478 pink: PaletteColor::EightBit(2),
2479 brown: PaletteColor::Rgb((222, 221, 220)),
2480 }
2481 .into(),
2482 rounded_corners: true,
2484 hide_session_name: false,
2485 },
2486 capabilities: PluginCapabilities { arrow_fonts: false },
2487 session_name: Some("my awesome test session".to_owned()),
2488 base_mode: Some(InputMode::Locked),
2489 editor: Some(PathBuf::from("my_awesome_editor")),
2490 shell: Some(PathBuf::from("my_awesome_shell")),
2491 web_clients_allowed: Some(true),
2492 web_sharing: Some(WebSharing::default()),
2493 currently_marking_pane_group: Some(false),
2494 is_web_client: Some(false),
2495 web_server_ip: IpAddr::from_str("127.0.0.1").ok(),
2496 web_server_port: Some(8082),
2497 web_server_capability: Some(true),
2498 pane_frame_style: Some(crate::input::options::PaneFrameStyle::Titles),
2499 session_dimmed: Some(true),
2500 session_ancestry: vec!["work".to_owned(), "prod".to_owned()],
2501 host_fullscreen: Some(true),
2502 nested_ascend_keys: vec![
2503 KeyWithModifier::new(BareKey::Char('o')).with_ctrl_modifier(),
2504 KeyWithModifier::new(BareKey::Up),
2505 ],
2506 session_ascended: Some(true),
2507 nested_descend_keys: vec![
2508 KeyWithModifier::new(BareKey::Char('o')).with_ctrl_modifier(),
2509 KeyWithModifier::new(BareKey::Down),
2510 ],
2511 });
2512 let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
2513 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2514 let deserialized_protobuf_event: ProtobufEvent =
2515 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2516 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2517 assert_eq!(
2518 mode_update_event, deserialized_event,
2519 "Event properly serialized/deserialized without change"
2520 );
2521}
2522
2523#[test]
2524fn serialize_tab_update_event() {
2525 use prost::Message;
2526 let tab_update_event = Event::TabUpdate(Default::default());
2527 let protobuf_event: ProtobufEvent = tab_update_event.clone().try_into().unwrap();
2528 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2529 let deserialized_protobuf_event: ProtobufEvent =
2530 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2531 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2532 assert_eq!(
2533 tab_update_event, deserialized_event,
2534 "Event properly serialized/deserialized without change"
2535 );
2536}
2537
2538#[test]
2539fn serialize_tab_update_event_with_non_default_values() {
2540 use prost::Message;
2541 let tab_update_event = Event::TabUpdate(vec![
2542 TabInfo {
2543 position: 0,
2544 name: "First tab".to_owned(),
2545 active: true,
2546 panes_to_hide: 2,
2547 is_fullscreen_active: true,
2548 is_sync_panes_active: false,
2549 are_floating_panes_visible: true,
2550 other_focused_clients: vec![2, 3, 4],
2551 active_swap_layout_name: Some("my cool swap layout".to_owned()),
2552 is_swap_layout_dirty: false,
2553 viewport_rows: 10,
2554 viewport_columns: 10,
2555 display_area_rows: 10,
2556 display_area_columns: 10,
2557 selectable_tiled_panes_count: 10,
2558 selectable_floating_panes_count: 10,
2559 tab_id: 0,
2560 has_bell_notification: false,
2561 is_flashing_bell: false,
2562 },
2563 TabInfo {
2564 position: 1,
2565 name: "Secondtab".to_owned(),
2566 active: false,
2567 panes_to_hide: 5,
2568 is_fullscreen_active: false,
2569 is_sync_panes_active: true,
2570 are_floating_panes_visible: true,
2571 other_focused_clients: vec![1, 5, 111],
2572 active_swap_layout_name: None,
2573 is_swap_layout_dirty: true,
2574 viewport_rows: 10,
2575 viewport_columns: 10,
2576 display_area_rows: 10,
2577 display_area_columns: 10,
2578 selectable_tiled_panes_count: 10,
2579 selectable_floating_panes_count: 10,
2580 tab_id: 1,
2581 has_bell_notification: false,
2582 is_flashing_bell: false,
2583 },
2584 TabInfo::default(),
2585 ]);
2586 let protobuf_event: ProtobufEvent = tab_update_event.clone().try_into().unwrap();
2587 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2588 let deserialized_protobuf_event: ProtobufEvent =
2589 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2590 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2591 assert_eq!(
2592 tab_update_event, deserialized_event,
2593 "Event properly serialized/deserialized without change"
2594 );
2595}
2596
2597#[test]
2598fn serialize_pane_update_event() {
2599 use prost::Message;
2600 let pane_update_event = Event::PaneUpdate(Default::default());
2601 let protobuf_event: ProtobufEvent = pane_update_event.clone().try_into().unwrap();
2602 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2603 let deserialized_protobuf_event: ProtobufEvent =
2604 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2605 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2606 assert_eq!(
2607 pane_update_event, deserialized_event,
2608 "Event properly serialized/deserialized without change"
2609 );
2610}
2611
2612#[test]
2613fn serialize_hint_text_event() {
2614 use prost::Message;
2615 let hint_text_event = Event::HintText(BTreeMap::from([
2616 (
2617 10,
2618 StyledText {
2619 text: "group".to_owned(),
2620 indices: vec![vec![0]],
2621 },
2622 ),
2623 (
2624 42,
2625 StyledText {
2626 text: "resize".to_owned(),
2627 indices: vec![vec![0, 1], vec![3]],
2628 },
2629 ),
2630 ]));
2631 let protobuf_event: ProtobufEvent = hint_text_event.clone().try_into().unwrap();
2632 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2633 let deserialized_protobuf_event: ProtobufEvent =
2634 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2635 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2636 assert_eq!(
2637 hint_text_event, deserialized_event,
2638 "Event properly serialized/deserialized without change"
2639 );
2640}
2641
2642#[test]
2643fn serialize_active_pane_scroll_event() {
2644 use prost::Message;
2645 for active_pane_scroll_event in [
2646 Event::ActivePaneScroll(Some((3, 12))),
2647 Event::ActivePaneScroll(None),
2648 ] {
2649 let protobuf_event: ProtobufEvent = active_pane_scroll_event.clone().try_into().unwrap();
2650 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2651 let deserialized_protobuf_event: ProtobufEvent =
2652 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2653 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2654 assert_eq!(
2655 active_pane_scroll_event, deserialized_event,
2656 "Event properly serialized/deserialized without change"
2657 );
2658 }
2659}
2660
2661#[test]
2662fn serialize_key_event() {
2663 use crate::data::BareKey;
2664 use prost::Message;
2665 let key_event = Event::Key(KeyWithModifier::new(BareKey::Char('a')).with_ctrl_modifier());
2666 let protobuf_event: ProtobufEvent = key_event.clone().try_into().unwrap();
2667 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2668 let deserialized_protobuf_event: ProtobufEvent =
2669 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2670 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2671 assert_eq!(
2672 key_event, deserialized_event,
2673 "Event properly serialized/deserialized without change"
2674 );
2675}
2676
2677#[test]
2678fn serialize_mouse_event() {
2679 use prost::Message;
2680 let mouse_event = Event::Mouse(Mouse::LeftClick(1, 1));
2681 let protobuf_event: ProtobufEvent = mouse_event.clone().try_into().unwrap();
2682 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2683 let deserialized_protobuf_event: ProtobufEvent =
2684 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2685 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2686 assert_eq!(
2687 mouse_event, deserialized_event,
2688 "Event properly serialized/deserialized without change"
2689 );
2690}
2691
2692#[test]
2693fn serialize_mouse_event_without_position() {
2694 use prost::Message;
2695 let mouse_event = Event::Mouse(Mouse::ScrollUp(17));
2696 let protobuf_event: ProtobufEvent = mouse_event.clone().try_into().unwrap();
2697 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2698 let deserialized_protobuf_event: ProtobufEvent =
2699 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2700 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2701 assert_eq!(
2702 mouse_event, deserialized_event,
2703 "Event properly serialized/deserialized without change"
2704 );
2705}
2706
2707#[test]
2708fn serialize_timer_event() {
2709 use prost::Message;
2710 let timer_event = Event::Timer(1.5);
2711 let protobuf_event: ProtobufEvent = timer_event.clone().try_into().unwrap();
2712 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2713 let deserialized_protobuf_event: ProtobufEvent =
2714 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2715 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2716 assert_eq!(
2717 timer_event, deserialized_event,
2718 "Event properly serialized/deserialized without change"
2719 );
2720}
2721
2722#[test]
2723fn serialize_copy_to_clipboard_event() {
2724 use prost::Message;
2725 let copy_event = Event::CopyToClipboard(CopyDestination::Primary);
2726 let protobuf_event: ProtobufEvent = copy_event.clone().try_into().unwrap();
2727 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2728 let deserialized_protobuf_event: ProtobufEvent =
2729 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2730 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2731 assert_eq!(
2732 copy_event, deserialized_event,
2733 "Event properly serialized/deserialized without change"
2734 );
2735}
2736
2737#[test]
2738fn serialize_clipboard_failure_event() {
2739 use prost::Message;
2740 let copy_event = Event::SystemClipboardFailure;
2741 let protobuf_event: ProtobufEvent = copy_event.clone().try_into().unwrap();
2742 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2743 let deserialized_protobuf_event: ProtobufEvent =
2744 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2745 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2746 assert_eq!(
2747 copy_event, deserialized_event,
2748 "Event properly serialized/deserialized without change"
2749 );
2750}
2751
2752#[test]
2753fn serialize_input_received_event() {
2754 use prost::Message;
2755 let input_received_event = Event::InputReceived;
2756 let protobuf_event: ProtobufEvent = input_received_event.clone().try_into().unwrap();
2757 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2758 let deserialized_protobuf_event: ProtobufEvent =
2759 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2760 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2761 assert_eq!(
2762 input_received_event, deserialized_event,
2763 "Event properly serialized/deserialized without change"
2764 );
2765}
2766
2767#[test]
2768fn serialize_visible_event() {
2769 use prost::Message;
2770 let visible_event = Event::Visible(true);
2771 let protobuf_event: ProtobufEvent = visible_event.clone().try_into().unwrap();
2772 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2773 let deserialized_protobuf_event: ProtobufEvent =
2774 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2775 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2776 assert_eq!(
2777 visible_event, deserialized_event,
2778 "Event properly serialized/deserialized without change"
2779 );
2780}
2781
2782#[test]
2783fn serialize_custom_message_event() {
2784 use prost::Message;
2785 let custom_message_event = Event::CustomMessage("foo".to_owned(), "bar".to_owned());
2786 let protobuf_event: ProtobufEvent = custom_message_event.clone().try_into().unwrap();
2787 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2788 let deserialized_protobuf_event: ProtobufEvent =
2789 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2790 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2791 assert_eq!(
2792 custom_message_event, deserialized_event,
2793 "Event properly serialized/deserialized without change"
2794 );
2795}
2796
2797#[test]
2798fn serialize_file_system_create_event() {
2799 use prost::Message;
2800 let file_system_event = Event::FileSystemCreate(vec![
2801 ("/absolute/path".into(), None),
2802 ("./relative_path".into(), Default::default()),
2803 ]);
2804 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2805 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2806 let deserialized_protobuf_event: ProtobufEvent =
2807 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2808 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2809 assert_eq!(
2810 file_system_event, deserialized_event,
2811 "Event properly serialized/deserialized without change"
2812 );
2813}
2814
2815#[test]
2816fn serialize_file_system_read_event() {
2817 use prost::Message;
2818 let file_system_event = Event::FileSystemRead(vec![
2819 ("/absolute/path".into(), None),
2820 ("./relative_path".into(), Default::default()),
2821 ]);
2822 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2823 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2824 let deserialized_protobuf_event: ProtobufEvent =
2825 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2826 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2827 assert_eq!(
2828 file_system_event, deserialized_event,
2829 "Event properly serialized/deserialized without change"
2830 );
2831}
2832
2833#[test]
2834fn serialize_file_system_update_event() {
2835 use prost::Message;
2836 let file_system_event = Event::FileSystemUpdate(vec![
2837 ("/absolute/path".into(), None),
2838 ("./relative_path".into(), Some(Default::default())),
2839 ]);
2840 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2841 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2842 let deserialized_protobuf_event: ProtobufEvent =
2843 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2844 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2845 assert_eq!(
2846 file_system_event, deserialized_event,
2847 "Event properly serialized/deserialized without change"
2848 );
2849}
2850
2851#[test]
2852fn serialize_file_system_delete_event() {
2853 use prost::Message;
2854 let file_system_event = Event::FileSystemDelete(vec![
2855 ("/absolute/path".into(), None),
2856 ("./relative_path".into(), Default::default()),
2857 ]);
2858 let protobuf_event: ProtobufEvent = file_system_event.clone().try_into().unwrap();
2859 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2860 let deserialized_protobuf_event: ProtobufEvent =
2861 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2862 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2863 assert_eq!(
2864 file_system_event, deserialized_event,
2865 "Event properly serialized/deserialized without change"
2866 );
2867}
2868
2869#[test]
2870fn serialize_session_update_event() {
2871 use prost::Message;
2872 let session_update_event = Event::SessionUpdate(Default::default(), Default::default());
2873 let protobuf_event: ProtobufEvent = session_update_event.clone().try_into().unwrap();
2874 let serialized_protobuf_event = protobuf_event.encode_to_vec();
2875 let deserialized_protobuf_event: ProtobufEvent =
2876 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
2877 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
2878 assert_eq!(
2879 session_update_event, deserialized_event,
2880 "Event properly serialized/deserialized without change"
2881 );
2882}
2883
2884#[test]
2885fn serialize_session_update_event_with_non_default_values() {
2886 use prost::Message;
2887 let tab_infos = vec![
2888 TabInfo {
2889 position: 0,
2890 name: "First tab".to_owned(),
2891 active: true,
2892 panes_to_hide: 2,
2893 is_fullscreen_active: true,
2894 is_sync_panes_active: false,
2895 are_floating_panes_visible: true,
2896 other_focused_clients: vec![2, 3, 4],
2897 active_swap_layout_name: Some("my cool swap layout".to_owned()),
2898 is_swap_layout_dirty: false,
2899 viewport_rows: 10,
2900 viewport_columns: 10,
2901 display_area_rows: 10,
2902 display_area_columns: 10,
2903 selectable_tiled_panes_count: 10,
2904 selectable_floating_panes_count: 10,
2905 tab_id: 0,
2906 has_bell_notification: false,
2907 is_flashing_bell: false,
2908 },
2909 TabInfo {
2910 position: 1,
2911 name: "Secondtab".to_owned(),
2912 active: false,
2913 panes_to_hide: 5,
2914 is_fullscreen_active: false,
2915 is_sync_panes_active: true,
2916 are_floating_panes_visible: true,
2917 other_focused_clients: vec![1, 5, 111],
2918 active_swap_layout_name: None,
2919 is_swap_layout_dirty: true,
2920 viewport_rows: 10,
2921 viewport_columns: 10,
2922 display_area_rows: 10,
2923 display_area_columns: 10,
2924 selectable_tiled_panes_count: 10,
2925 selectable_floating_panes_count: 10,
2926 tab_id: 1,
2927 has_bell_notification: false,
2928 is_flashing_bell: false,
2929 },
2930 TabInfo::default(),
2931 ];
2932 let mut panes = HashMap::new();
2933 let mut index_in_pane_group_1 = BTreeMap::new();
2934 index_in_pane_group_1.insert(1, 0);
2935 index_in_pane_group_1.insert(2, 0);
2936 index_in_pane_group_1.insert(3, 0);
2937 let mut index_in_pane_group_2 = BTreeMap::new();
2938 index_in_pane_group_2.insert(1, 1);
2939 index_in_pane_group_2.insert(2, 1);
2940 index_in_pane_group_2.insert(3, 1);
2941 let panes_list = vec![
2942 PaneInfo {
2943 id: 1,
2944 is_plugin: false,
2945 is_focused: true,
2946 is_fullscreen: true,
2947 is_floating: false,
2948 is_suppressed: false,
2949 title: "pane 1".to_owned(),
2950 exited: false,
2951 exit_status: None,
2952 is_held: false,
2953 pane_x: 0,
2954 pane_content_x: 1,
2955 pane_y: 0,
2956 pane_content_y: 1,
2957 pane_rows: 5,
2958 pane_content_rows: 4,
2959 pane_columns: 22,
2960 pane_content_columns: 21,
2961 cursor_coordinates_in_pane: Some((0, 0)),
2962 terminal_command: Some("foo".to_owned()),
2963 plugin_url: None,
2964 is_selectable: true,
2965 index_in_pane_group: index_in_pane_group_1,
2966 default_fg: None,
2967 default_bg: None,
2968 },
2969 PaneInfo {
2970 id: 1,
2971 is_plugin: true,
2972 is_focused: true,
2973 is_fullscreen: true,
2974 is_floating: false,
2975 is_suppressed: false,
2976 title: "pane 1".to_owned(),
2977 exited: false,
2978 exit_status: None,
2979 is_held: false,
2980 pane_x: 0,
2981 pane_content_x: 1,
2982 pane_y: 0,
2983 pane_content_y: 1,
2984 pane_rows: 5,
2985 pane_content_rows: 4,
2986 pane_columns: 22,
2987 pane_content_columns: 21,
2988 cursor_coordinates_in_pane: Some((0, 0)),
2989 terminal_command: None,
2990 plugin_url: Some("i_am_a_fake_plugin".to_owned()),
2991 is_selectable: true,
2992 index_in_pane_group: index_in_pane_group_2,
2993 default_fg: None,
2994 default_bg: None,
2995 },
2996 ];
2997 panes.insert(0, panes_list);
2998 let mut plugins = BTreeMap::new();
2999 let mut plugin_configuration = BTreeMap::new();
3000 plugin_configuration.insert("config_key".to_owned(), "config_value".to_owned());
3001 plugins.insert(
3002 1,
3003 PluginInfo {
3004 location: "https://example.com/my-plugin.wasm".to_owned(),
3005 configuration: plugin_configuration,
3006 },
3007 );
3008 let mut tab_history = BTreeMap::new();
3009 tab_history.insert(1, vec![1, 2, 3]);
3010 tab_history.insert(2, vec![1, 2, 3]);
3011 let session_info_1 = SessionInfo {
3012 name: "session 1".to_owned(),
3013 tabs: tab_infos,
3014 panes: PaneManifest { panes },
3015 connected_clients: 2,
3016 is_current_session: true,
3017 available_layouts: vec![
3018 LayoutInfo::File(
3019 "layout 1".to_owned(),
3020 LayoutMetadata {
3021 tabs: vec![],
3022 creation_time: "0".to_owned(),
3023 update_time: "0".to_owned(),
3024 },
3025 ),
3026 LayoutInfo::BuiltIn("layout2".to_owned()),
3027 LayoutInfo::File(
3028 "layout3".to_owned(),
3029 LayoutMetadata {
3030 tabs: vec![],
3031 creation_time: "0".to_owned(),
3032 update_time: "0".to_owned(),
3033 },
3034 ),
3035 ],
3036 plugins,
3037 web_clients_allowed: false,
3038 web_client_count: 1,
3039 tab_history,
3040 pane_history: Default::default(),
3041 creation_time: Duration::from_secs(100),
3042 };
3043 let session_info_2 = SessionInfo {
3044 name: "session 2".to_owned(),
3045 tabs: vec![],
3046 panes: PaneManifest {
3047 panes: HashMap::new(),
3048 },
3049 connected_clients: 0,
3050 is_current_session: false,
3051 available_layouts: vec![
3052 LayoutInfo::File(
3053 "layout 1".to_owned(),
3054 LayoutMetadata {
3055 tabs: vec![],
3056 creation_time: "0".to_owned(),
3057 update_time: "0".to_owned(),
3058 },
3059 ),
3060 LayoutInfo::BuiltIn("layout2".to_owned()),
3061 LayoutInfo::File(
3062 "layout3".to_owned(),
3063 LayoutMetadata {
3064 tabs: vec![],
3065 creation_time: "0".to_owned(),
3066 update_time: "0".to_owned(),
3067 },
3068 ),
3069 ],
3070 plugins: Default::default(),
3071 web_clients_allowed: false,
3072 web_client_count: 0,
3073 tab_history: Default::default(),
3074 pane_history: Default::default(),
3075 creation_time: Duration::from_secs(200),
3076 };
3077 let session_infos = vec![session_info_1, session_info_2];
3078 let resurrectable_sessions = vec![];
3079
3080 let session_update_event = Event::SessionUpdate(session_infos, resurrectable_sessions);
3081 let protobuf_event: ProtobufEvent = session_update_event.clone().try_into().unwrap();
3082 let serialized_protobuf_event = protobuf_event.encode_to_vec();
3083 let deserialized_protobuf_event: ProtobufEvent =
3084 Message::decode(serialized_protobuf_event.as_slice()).unwrap();
3085 let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
3086 assert_eq!(
3087 session_update_event, deserialized_event,
3088 "Event properly serialized/deserialized without change"
3089 );
3090}
3091
3092impl TryFrom<ProtobufPaneId> for PaneId {
3096 type Error = &'static str;
3097 fn try_from(protobuf_pane_id: ProtobufPaneId) -> Result<Self, &'static str> {
3098 match ProtobufPaneType::try_from(protobuf_pane_id.pane_type).ok() {
3099 Some(ProtobufPaneType::Terminal) => Ok(PaneId::Terminal(protobuf_pane_id.id)),
3100 Some(ProtobufPaneType::Plugin) => Ok(PaneId::Plugin(protobuf_pane_id.id)),
3101 None => Err("Failed to convert PaneId"),
3102 }
3103 }
3104}
3105
3106impl TryFrom<PaneId> for ProtobufPaneId {
3110 type Error = &'static str;
3111 fn try_from(pane_id: PaneId) -> Result<Self, &'static str> {
3112 match pane_id {
3113 PaneId::Terminal(id) => Ok(ProtobufPaneId {
3114 pane_type: ProtobufPaneType::Terminal as i32,
3115 id,
3116 }),
3117 PaneId::Plugin(id) => Ok(ProtobufPaneId {
3118 pane_type: ProtobufPaneType::Plugin as i32,
3119 id,
3120 }),
3121 }
3122 }
3123}
3124
3125impl Into<ProtobufWebSharing> for WebSharing {
3126 fn into(self) -> ProtobufWebSharing {
3127 match self {
3128 WebSharing::On => ProtobufWebSharing::On,
3129 WebSharing::Off => ProtobufWebSharing::Off,
3130 WebSharing::Disabled => ProtobufWebSharing::Disabled,
3131 }
3132 }
3133}
3134
3135impl Into<WebSharing> for ProtobufWebSharing {
3136 fn into(self) -> WebSharing {
3137 match self {
3138 ProtobufWebSharing::On => WebSharing::On,
3139 ProtobufWebSharing::Off => WebSharing::Off,
3140 ProtobufWebSharing::Disabled => WebSharing::Disabled,
3141 }
3142 }
3143}
3144
3145impl Into<ProtobufPaneFrameStyle> for crate::input::options::PaneFrameStyle {
3146 fn into(self) -> ProtobufPaneFrameStyle {
3147 match self {
3148 crate::input::options::PaneFrameStyle::Full => ProtobufPaneFrameStyle::Full,
3149 crate::input::options::PaneFrameStyle::Titles => ProtobufPaneFrameStyle::Titles,
3150 crate::input::options::PaneFrameStyle::None => ProtobufPaneFrameStyle::None,
3151 }
3152 }
3153}
3154
3155impl Into<crate::input::options::PaneFrameStyle> for ProtobufPaneFrameStyle {
3156 fn into(self) -> crate::input::options::PaneFrameStyle {
3157 match self {
3158 ProtobufPaneFrameStyle::Full => crate::input::options::PaneFrameStyle::Full,
3159 ProtobufPaneFrameStyle::Titles => crate::input::options::PaneFrameStyle::Titles,
3160 ProtobufPaneFrameStyle::None => crate::input::options::PaneFrameStyle::None,
3161 }
3162 }
3163}
3164
3165impl TryFrom<WebServerStatus> for ProtobufWebServerStatusPayload {
3166 type Error = &'static str;
3167 fn try_from(web_server_status: WebServerStatus) -> Result<Self, &'static str> {
3168 match web_server_status {
3169 WebServerStatus::Online(url) => Ok(ProtobufWebServerStatusPayload {
3170 web_server_status_indication: WebServerStatusIndication::Online as i32,
3171 payload: Some(url),
3172 }),
3173 WebServerStatus::DifferentVersion(version) => Ok(ProtobufWebServerStatusPayload {
3174 web_server_status_indication: WebServerStatusIndication::DifferentVersion as i32,
3175 payload: Some(format!("{}", version)),
3176 }),
3177 WebServerStatus::Offline => Ok(ProtobufWebServerStatusPayload {
3178 web_server_status_indication: WebServerStatusIndication::Offline as i32,
3179 payload: None,
3180 }),
3181 }
3182 }
3183}
3184
3185impl TryFrom<ProtobufWebServerStatusPayload> for WebServerStatus {
3186 type Error = &'static str;
3187 fn try_from(
3188 protobuf_web_server_status: ProtobufWebServerStatusPayload,
3189 ) -> Result<Self, &'static str> {
3190 match WebServerStatusIndication::try_from(
3191 protobuf_web_server_status.web_server_status_indication,
3192 )
3193 .ok()
3194 {
3195 Some(WebServerStatusIndication::Online) => {
3196 let payload = protobuf_web_server_status
3197 .payload
3198 .ok_or("payload_not_found")?;
3199 Ok(WebServerStatus::Online(payload))
3200 },
3201 Some(WebServerStatusIndication::DifferentVersion) => {
3202 let payload = protobuf_web_server_status
3203 .payload
3204 .ok_or("payload_not_found")?;
3205 Ok(WebServerStatus::DifferentVersion(payload))
3206 },
3207 Some(WebServerStatusIndication::Offline) => Ok(WebServerStatus::Offline),
3208 None => Err("Unknown status"),
3209 }
3210 }
3211}
3212
3213impl TryFrom<ProtobufPaneRenderReportPayload> for HashMap<PaneId, PaneContents> {
3214 type Error = &'static str;
3215 fn try_from(protobuf_payload: ProtobufPaneRenderReportPayload) -> Result<Self, &'static str> {
3216 let mut pane_contents_map = HashMap::new();
3217
3218 for entry in protobuf_payload.pane_contents {
3219 let pane_id = entry
3220 .pane_id
3221 .ok_or("Missing pane_id in PaneContentsEntry")?
3222 .try_into()?;
3223 let pane_contents = entry
3224 .pane_contents
3225 .ok_or("Missing pane_contents in PaneContentsEntry")?
3226 .try_into()?;
3227 pane_contents_map.insert(pane_id, pane_contents);
3228 }
3229
3230 Ok(pane_contents_map)
3231 }
3232}
3233
3234impl TryFrom<HashMap<PaneId, PaneContents>> for ProtobufPaneRenderReportPayload {
3235 type Error = &'static str;
3236 fn try_from(pane_contents_map: HashMap<PaneId, PaneContents>) -> Result<Self, &'static str> {
3237 let mut pane_contents_vec = vec![];
3238
3239 for (pane_id, pane_contents) in pane_contents_map {
3240 pane_contents_vec.push(ProtobufPaneContentsEntry {
3241 pane_id: Some(pane_id.try_into()?),
3242 pane_contents: Some(pane_contents.try_into()?),
3243 });
3244 }
3245
3246 Ok(ProtobufPaneRenderReportPayload {
3247 pane_contents: pane_contents_vec,
3248 })
3249 }
3250}
3251
3252impl TryFrom<ProtobufPaneContents> for PaneContents {
3253 type Error = &'static str;
3254 fn try_from(protobuf_contents: ProtobufPaneContents) -> Result<Self, &'static str> {
3255 let selected_text = protobuf_contents
3256 .selected_text
3257 .map(|st| st.try_into())
3258 .transpose()?;
3259 let cursor = protobuf_contents
3260 .cursor
3261 .map(|p| (p.column as usize, p.line as usize));
3262
3263 Ok(PaneContents {
3264 viewport: protobuf_contents.viewport,
3265 selected_text,
3266 lines_above_viewport: protobuf_contents.lines_above_viewport,
3267 lines_below_viewport: protobuf_contents.lines_below_viewport,
3268 cursor,
3269 })
3270 }
3271}
3272
3273impl TryFrom<PaneContents> for ProtobufPaneContents {
3274 type Error = &'static str;
3275 fn try_from(pane_contents: PaneContents) -> Result<Self, &'static str> {
3276 let selected_text = pane_contents
3277 .selected_text
3278 .map(|st| st.try_into())
3279 .transpose()?;
3280 let cursor = pane_contents.cursor.map(|(x, y)| ProtobufPosition {
3281 line: y as i64,
3282 column: x as i64,
3283 });
3284
3285 Ok(ProtobufPaneContents {
3286 viewport: pane_contents.viewport,
3287 selected_text,
3288 lines_above_viewport: pane_contents.lines_above_viewport,
3289 lines_below_viewport: pane_contents.lines_below_viewport,
3290 cursor,
3291 })
3292 }
3293}
3294
3295impl TryFrom<ProtobufPaneScrollbackResponse> for PaneScrollbackResponse {
3296 type Error = &'static str;
3297 fn try_from(protobuf_response: ProtobufPaneScrollbackResponse) -> Result<Self, &'static str> {
3298 match protobuf_response.response {
3299 Some(pane_scrollback_response::Response::Ok(pane_contents)) => {
3300 Ok(PaneScrollbackResponse::Ok(pane_contents.try_into()?))
3301 },
3302 Some(pane_scrollback_response::Response::Err(error_msg)) => {
3303 Ok(PaneScrollbackResponse::Err(error_msg))
3304 },
3305 None => Err("PaneScrollbackResponse missing response field"),
3306 }
3307 }
3308}
3309
3310impl TryFrom<PaneScrollbackResponse> for ProtobufPaneScrollbackResponse {
3311 type Error = &'static str;
3312 fn try_from(response: PaneScrollbackResponse) -> Result<Self, &'static str> {
3313 let response_field = match response {
3314 PaneScrollbackResponse::Ok(pane_contents) => {
3315 pane_scrollback_response::Response::Ok(pane_contents.try_into()?)
3316 },
3317 PaneScrollbackResponse::Err(error_msg) => {
3318 pane_scrollback_response::Response::Err(error_msg)
3319 },
3320 };
3321 Ok(ProtobufPaneScrollbackResponse {
3322 response: Some(response_field),
3323 })
3324 }
3325}
3326
3327impl TryFrom<ProtobufSelectedText> for SelectedText {
3328 type Error = &'static str;
3329 fn try_from(protobuf_selected_text: ProtobufSelectedText) -> Result<Self, &'static str> {
3330 Ok(SelectedText {
3331 start: protobuf_selected_text
3332 .start
3333 .ok_or("Missing start in SelectedText")?
3334 .try_into()?,
3335 end: protobuf_selected_text
3336 .end
3337 .ok_or("Missing end in SelectedText")?
3338 .try_into()?,
3339 })
3340 }
3341}
3342
3343impl TryFrom<SelectedText> for ProtobufSelectedText {
3344 type Error = &'static str;
3345 fn try_from(selected_text: SelectedText) -> Result<Self, &'static str> {
3346 Ok(ProtobufSelectedText {
3347 start: Some(selected_text.start.try_into()?),
3348 end: Some(selected_text.end.try_into()?),
3349 })
3350 }
3351}