diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-04-17 14:08:48 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-17 14:08:48 +0200 |
| commit | aa29cbaf6631af0afca6aae427a97b3e478393b3 (patch) | |
| tree | 0ee1cab0f7bdc66cf151f38341252701338c1853 /zellij-utils/src/plugin_api | |
| parent | fix(windows): skip modifier re-encoding for Char keys in cast_crossterm_key (... (diff) | |
| download | sl0ppij-aa29cbaf6631af0afca6aae427a97b3e478393b3.tar.gz sl0ppij-aa29cbaf6631af0afca6aae427a97b3e478393b3.tar.xz sl0ppij-aa29cbaf6631af0afca6aae427a97b3e478393b3.zip | |
Some idle CPU and disk/io fixes, new CommandChanged plugin Event (#5063)
* initial implementation
* fix mouse cpu spam
* prevent excess metadata write and prune sessions on startup
* consolidate CommandChanged and PaneCommandChanged
* tests
* rustfmt
* add pr
Diffstat (limited to 'zellij-utils/src/plugin_api')
| -rw-r--r-- | zellij-utils/src/plugin_api/event.proto | 9 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/event.rs | 41 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.proto | 16 | ||||
| -rw-r--r-- | zellij-utils/src/plugin_api/plugin_command.rs | 94 |
4 files changed, 150 insertions, 10 deletions
diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto index ce9eb8ff..3c3a8490 100644 --- a/zellij-utils/src/plugin_api/event.proto +++ b/zellij-utils/src/plugin_api/event.proto @@ -67,6 +67,7 @@ enum EventType { HighlightClicked = 42; PaneRenderReportWithAnsi = 43; InitialKeybinds = 44; + CommandChanged = 45; } message EventNameList { @@ -113,6 +114,7 @@ message Event { HighlightClickedPayload highlight_clicked_payload = 36; PaneRenderReportPayload pane_render_report_with_ansi_payload = 37; InitialKeybindsPayload initial_keybinds_payload = 38; + CommandChangedPayload command_changed_payload = 39; } } @@ -122,6 +124,13 @@ message CwdChangedPayload { repeated uint32 focused_client_ids = 3; } +message CommandChangedPayload { + PaneId pane_id = 1; + repeated string command = 2; + bool is_foreground = 3; + repeated uint32 focused_client_ids = 4; +} + message FailedToStartWebServerPayload { string error = 1; } diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs index 93b28365..6f138742 100644 --- a/zellij-utils/src/plugin_api/event.rs +++ b/zellij-utils/src/plugin_api/event.rs @@ -6,7 +6,8 @@ pub use super::generated_api::api::{ pane_scrollback_response, ActionCompletePayload as ProtobufActionCompletePayload, AvailableLayoutInfoPayload as ProtobufAvailableLayoutInfoPayload, ClientInfo as ProtobufClientInfo, ClientPaneHistory as ProtobufClientPaneHistory, - ClientTabHistory as ProtobufClientTabHistory, ContextItem as ProtobufContextItem, + ClientTabHistory as ProtobufClientTabHistory, + CommandChangedPayload as ProtobufCommandChangedPayload, ContextItem as ProtobufContextItem, CopyDestination as ProtobufCopyDestination, CwdChangedPayload as ProtobufCwdChangedPayload, Event as ProtobufEvent, EventNameList as ProtobufEventNameList, EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata, @@ -474,6 +475,27 @@ impl TryFrom<ProtobufEvent> for Event { }, _ => Err("Malformed payload for the CwdChanged Event"), }, + Some(ProtobufEventType::CommandChanged) => match protobuf_event.payload { + Some(ProtobufEventPayload::CommandChangedPayload(p)) => { + let pane_id: PaneId = p + .pane_id + .ok_or("Missing pane_id in CommandChanged payload")? + .try_into() + .map_err(|_| "Failed to convert PaneId in CommandChanged payload")?; + let focused_client_ids: Vec<ClientId> = p + .focused_client_ids + .into_iter() + .map(|id| id as u16) + .collect(); + Ok(Event::CommandChanged( + pane_id, + p.command, + p.is_foreground, + focused_client_ids, + )) + }, + _ => Err("Malformed payload for the CommandChanged Event"), + }, Some(ProtobufEventType::AvailableLayoutInfo) => match protobuf_event.payload { Some(ProtobufEventPayload::AvailableLayoutInfoPayload( available_layout_info_payload, @@ -1014,6 +1036,21 @@ impl TryFrom<Event> for ProtobufEvent { payload: Some(event::Payload::CwdChangedPayload(cwd_changed_payload)), }) }, + Event::CommandChanged(pane_id, command, is_foreground, focused_client_ids) => { + let protobuf_pane_id: ProtobufPaneId = pane_id.try_into()?; + let focused_client_ids_u32: Vec<u32> = + focused_client_ids.into_iter().map(|id| id as u32).collect(); + let payload = ProtobufCommandChangedPayload { + pane_id: Some(protobuf_pane_id), + command, + is_foreground, + focused_client_ids: focused_client_ids_u32, + }; + Ok(ProtobufEvent { + name: ProtobufEventType::CommandChanged as i32, + payload: Some(event::Payload::CommandChangedPayload(payload)), + }) + }, Event::AvailableLayoutInfo(available_layouts, layouts_with_errors) => { let mut protobuf_available_layouts = vec![]; let mut protobuf_layouts_with_errors = vec![]; @@ -2015,6 +2052,7 @@ impl TryFrom<ProtobufEventType> for EventType { ProtobufEventType::UserAction => EventType::UserAction, ProtobufEventType::ActionComplete => EventType::ActionComplete, ProtobufEventType::CwdChanged => EventType::CwdChanged, + ProtobufEventType::CommandChanged => EventType::CommandChanged, ProtobufEventType::AvailableLayoutInfo => EventType::AvailableLayoutInfo, ProtobufEventType::PluginConfigurationChanged => EventType::PluginConfigurationChanged, ProtobufEventType::HighlightClicked => EventType::HighlightClicked, @@ -2067,6 +2105,7 @@ impl TryFrom<EventType> for ProtobufEventType { EventType::UserAction => ProtobufEventType::UserAction, EventType::ActionComplete => ProtobufEventType::ActionComplete, EventType::CwdChanged => ProtobufEventType::CwdChanged, + EventType::CommandChanged => ProtobufEventType::CommandChanged, EventType::AvailableLayoutInfo => ProtobufEventType::AvailableLayoutInfo, EventType::PluginConfigurationChanged => ProtobufEventType::PluginConfigurationChanged, EventType::HighlightClicked => ProtobufEventType::HighlightClicked, diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index 63baa443..0b768838 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -203,6 +203,7 @@ enum CommandName { ClearPaneHighlights = 208; OpenPluginPaneFloating = 209; ListWindowsVolumes = 210; + GetSessionList = 211; } message PluginCommand { @@ -354,6 +355,7 @@ message PluginCommand { SetPaneRegexHighlightsPayload set_pane_regex_highlights_payload = 158; ClearPaneHighlightsPayload clear_pane_highlights_payload = 159; OpenPluginPaneFloatingPayload open_plugin_pane_floating_payload = 160; + GetSessionListPayload get_session_list_payload = 161; } } @@ -1295,3 +1297,17 @@ message OpenPluginPaneFloatingPayload { message OpenPluginPaneFloatingResponse { optional PaneId pane_id = 1; } + +message GetSessionListPayload {} + +message SessionListSnapshot { + repeated event.SessionManifest live_sessions = 1; + repeated event.ResurrectableSession resurrectable_sessions = 2; +} + +message GetSessionListResponse { + oneof result { + SessionListSnapshot snapshot = 1; + string error = 2; + } +} diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index a457f720..5bfb2b42 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -1,13 +1,17 @@ pub use super::generated_api::api::{ action::{Action as ProtobufAction, PaneIdAndShouldFloat, SwitchToModePayload}, - event::{EventNameList as ProtobufEventNameList, Header}, + event::{ + EventNameList as ProtobufEventNameList, Header, + ResurrectableSession as ProtobufResurrectableSession, + SessionManifest as ProtobufSessionManifest, + }, input_mode::InputMode as ProtobufInputMode, plugin_command::{ break_panes_to_new_tab_response, break_panes_to_tab_with_id_response, break_panes_to_tab_with_index_response, delete_layout_response, dump_layout_response, dump_session_layout_response, edit_layout_response, focus_or_create_tab_response, get_focused_pane_info_response, get_pane_cwd_response, get_pane_pid_response, - get_pane_running_command_response, hide_floating_panes_response, + get_pane_running_command_response, get_session_list_response, hide_floating_panes_response, highlight_style::Style as ProtobufHighlightStyleVariant, new_tab_response, parse_layout_response, plugin_command::Payload, rename_layout_response, save_layout_response, save_session_response, show_floating_panes_response, @@ -48,7 +52,9 @@ pub use super::generated_api::api::{ GetPaneScrollbackPayload, GetSessionEnvironmentVariablesPayload as ProtobufGetSessionEnvironmentVariablesPayload, GetSessionEnvironmentVariablesResponse as ProtobufGetSessionEnvironmentVariablesResponse, - GetTabInfoPayload, GetTabInfoResponse as ProtobufGetTabInfoResponse, GoToTabWithIdPayload, + GetSessionListPayload as ProtobufGetSessionListPayload, + GetSessionListResponse as ProtobufGetSessionListResponse, GetTabInfoPayload, + GetTabInfoResponse as ProtobufGetTabInfoResponse, GoToTabWithIdPayload, GroupAndUngroupPanesPayload, HideFloatingPanesPayload as ProtobufHideFloatingPanesPayload, HideFloatingPanesResponse as ProtobufHideFloatingPanesResponse, HidePaneWithIdPayload, HighlightAndUnhighlightPanesPayload, HighlightLayer as ProtobufHighlightLayer, @@ -108,9 +114,10 @@ pub use super::generated_api::api::{ SaveLayoutPayload, SaveLayoutResponse as ProtobufSaveLayoutResponse, SaveSessionPayload, SaveSessionResponse as ProtobufSaveSessionResponse, ScrollDownInPaneIdPayload, ScrollToBottomInPaneIdPayload, ScrollToTopInPaneIdPayload, ScrollUpInPaneIdPayload, - SetFloatingPanePinnedPayload, SetPaneBorderlessPayload, SetPaneColorPayload, - SetPaneRegexHighlightsPayload, SetSelfMouseSelectionSupportPayload, SetTimeoutPayload, - ShowCursorPayload, ShowFloatingPanesPayload as ProtobufShowFloatingPanesPayload, + SessionListSnapshot as ProtobufSessionListSnapshot, SetFloatingPanePinnedPayload, + SetPaneBorderlessPayload, SetPaneColorPayload, SetPaneRegexHighlightsPayload, + SetSelfMouseSelectionSupportPayload, SetTimeoutPayload, ShowCursorPayload, + ShowFloatingPanesPayload as ProtobufShowFloatingPanesPayload, ShowFloatingPanesResponse as ProtobufShowFloatingPanesResponse, ShowPaneWithIdPayload, StackPanesPayload, SubscribePayload, SwitchSessionPayload, SwitchTabToIdPayload, SwitchTabToPayload, TogglePaneBorderlessPayload, TogglePaneEmbedOrEjectForPaneIdPayload, @@ -124,9 +131,10 @@ pub use super::generated_api::api::{ use crate::data::{ ConnectToSession, DeleteLayoutResponse, EditLayoutResponse, FloatingPaneCoordinates, GetFocusedPaneInfoResponse, GetPaneCwdResponse, GetPanePidResponse, - GetPaneRunningCommandResponse, HighlightLayer, HighlightStyle, HttpVerb, InputMode, - KeyWithModifier, MessageToPlugin, NewPluginArgs, PaneId, PermissionType, PluginCommand, - RegexHighlight, RenameLayoutResponse, SaveLayoutResponse, + GetPaneRunningCommandResponse, GetSessionListResponse, HighlightLayer, HighlightStyle, + HttpVerb, InputMode, KeyWithModifier, MessageToPlugin, NewPluginArgs, PaneId, PermissionType, + PluginCommand, RegexHighlight, RenameLayoutResponse, SaveLayoutResponse, SessionInfo, + SessionListSnapshot, }; use crate::input::actions::Action; use crate::input::layout::PercentOrFixed; @@ -329,6 +337,63 @@ impl From<GetPaneRunningCommandResponse> for ProtobufGetPaneRunningCommandRespon } } +impl From<GetSessionListResponse> for ProtobufGetSessionListResponse { + fn from(response: GetSessionListResponse) -> Self { + match response { + GetSessionListResponse::Ok(snapshot) => { + let live_sessions = snapshot + .live_sessions + .into_iter() + .filter_map(|si| ProtobufSessionManifest::try_from(si).ok()) + .collect(); + let resurrectable_sessions = snapshot + .resurrectable_sessions + .into_iter() + .map(|entry| ProtobufResurrectableSession::from(entry)) + .collect(); + ProtobufGetSessionListResponse { + result: Some(get_session_list_response::Result::Snapshot( + ProtobufSessionListSnapshot { + live_sessions, + resurrectable_sessions, + }, + )), + } + }, + GetSessionListResponse::Err(err) => ProtobufGetSessionListResponse { + result: Some(get_session_list_response::Result::Error(err)), + }, + } + } +} + +impl TryFrom<ProtobufGetSessionListResponse> for GetSessionListResponse { + type Error = &'static str; + fn try_from(protobuf_response: ProtobufGetSessionListResponse) -> Result<Self, &'static str> { + match protobuf_response.result { + Some(get_session_list_response::Result::Snapshot(snapshot)) => { + let mut live_sessions: Vec<SessionInfo> = Vec::new(); + for manifest in snapshot.live_sessions { + live_sessions.push(SessionInfo::try_from(manifest)?); + } + let resurrectable_sessions = snapshot + .resurrectable_sessions + .into_iter() + .map(<(String, std::time::Duration)>::from) + .collect(); + Ok(GetSessionListResponse::Ok(SessionListSnapshot { + live_sessions, + resurrectable_sessions, + })) + }, + Some(get_session_list_response::Result::Error(err)) => { + Ok(GetSessionListResponse::Err(err)) + }, + None => Err("Empty GetSessionListResponse"), + } + } +} + impl From<GetPaneCwdResponse> for ProtobufGetPaneCwdResponse { fn from(response: GetPaneCwdResponse) -> Self { match response { @@ -1300,6 +1365,11 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { Some(_) => Err("ListWindowsVolumes should have no payload"), None => Ok(PluginCommand::ListWindowsVolumes), }, + Some(CommandName::GetSessionList) => match protobuf_plugin_command.payload { + Some(Payload::GetSessionListPayload(_)) => Ok(PluginCommand::GetSessionList), + None => Ok(PluginCommand::GetSessionList), + _ => Err("Mismatched payload for GetSessionList"), + }, Some(CommandName::DumpSessionLayout) => match protobuf_plugin_command.payload { Some(Payload::DumpSessionLayoutPayload(payload)) => { Ok(PluginCommand::DumpSessionLayout { @@ -3145,6 +3215,12 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { name: CommandName::ListWindowsVolumes as i32, payload: None, }), + PluginCommand::GetSessionList => Ok(ProtobufPluginCommand { + name: CommandName::GetSessionList as i32, + payload: Some(Payload::GetSessionListPayload( + ProtobufGetSessionListPayload {}, + )), + }), PluginCommand::DumpSessionLayout { tab_index } => Ok(ProtobufPluginCommand { name: CommandName::DumpSessionLayout as i32, payload: tab_index.map(|idx| { |
