aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils/src/plugin_api/plugin_command.rs
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2026-03-05 21:13:02 +0100
committerGitHub <noreply@github.com>2026-03-05 21:13:02 +0100
commit903cdf5d32476a8d6cc208d2c418a1f2c67e5a53 (patch)
tree9a4647d9dc3efcdea8149fd78fdfa956b3c8d8cb /zellij-utils/src/plugin_api/plugin_command.rs
parentbuild: make test mirror build command for plugins (#4801) (diff)
downloadsl0ppij-903cdf5d32476a8d6cc208d2c418a1f2c67e5a53.tar.gz
sl0ppij-903cdf5d32476a8d6cc208d2c418a1f2c67e5a53.tar.xz
sl0ppij-903cdf5d32476a8d6cc208d2c418a1f2c67e5a53.zip
Click file paths to open in editor, allow plugins to change styles and hover of viewport (#4802)
* initial implementation * implement hover * add styles and foreground/background emphases, fix upsert hover collisions * initial implementation of link plugin * suppress highlighting + clicks on unfocused and mouse mode panes * also make italic * fix env var and ~ expansions * fix regex issues and add defensive validations * fix tests and add plugin assets * add tests * refactor all the things * add pr
Diffstat (limited to 'zellij-utils/src/plugin_api/plugin_command.rs')
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs228
1 files changed, 207 insertions, 21 deletions
diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs
index abd9a994..b535e14a 100644
--- a/zellij-utils/src/plugin_api/plugin_command.rs
+++ b/zellij-utils/src/plugin_api/plugin_command.rs
@@ -7,7 +7,8 @@ pub use super::generated_api::api::{
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, new_tab_response,
+ get_pane_running_command_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,
BreakPanesToNewTabPayload,
@@ -16,17 +17,19 @@ pub use super::generated_api::api::{
BreakPanesToTabWithIdResponse as ProtobufBreakPanesToTabWithIdResponse,
BreakPanesToTabWithIndexPayload,
BreakPanesToTabWithIndexResponse as ProtobufBreakPanesToTabWithIndexResponse,
- ChangeFloatingPanesCoordinatesPayload, ChangeHostFolderPayload,
+ ChangeFloatingPanesCoordinatesPayload, ChangeHostFolderPayload, ClearPaneHighlightsPayload,
ClearScreenForPaneIdPayload, CliPipeOutputPayload, CloseMultiplePanesPayload,
CloseTabWithIdPayload, CloseTabWithIndexPayload, CommandName, ContextItem,
CopyToClipboardPayload, CreateTokenResponse as ProtobufCreateTokenResponse,
CreateTokenResponse, CurrentSessionLastSavedTimePayload,
CurrentSessionLastSavedTimeResponse as ProtobufCurrentSessionLastSavedTimeResponse,
- CursorPosition, DeleteLayoutPayload, DeleteLayoutResponse as ProtobufDeleteLayoutResponse,
- DumpLayoutPayload, DumpLayoutResponse as ProtobufDumpLayoutResponse,
- DumpSessionLayoutPayload, DumpSessionLayoutResponse as ProtobufDumpSessionLayoutResponse,
- EditLayoutPayload, EditLayoutResponse as ProtobufEditLayoutResponse,
- EditScrollbackForPaneWithIdPayload, EmbedMultiplePanesPayload, EnvVariable, ExecCmdPayload,
+ CursorPosition, CustomIndexHighlight as ProtobufCustomIndexHighlight,
+ CustomRgbHighlight as ProtobufCustomRgbHighlight, DeleteLayoutPayload,
+ DeleteLayoutResponse as ProtobufDeleteLayoutResponse, DumpLayoutPayload,
+ DumpLayoutResponse as ProtobufDumpLayoutResponse, DumpSessionLayoutPayload,
+ DumpSessionLayoutResponse as ProtobufDumpSessionLayoutResponse, EditLayoutPayload,
+ EditLayoutResponse as ProtobufEditLayoutResponse, EditScrollbackForPaneWithIdPayload,
+ EmbedMultiplePanesPayload, EnvVariable, ExecCmdPayload,
FixedOrPercent as ProtobufFixedOrPercent,
FixedOrPercentValue as ProtobufFixedOrPercentValue, FloatMultiplePanesPayload,
FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates,
@@ -48,10 +51,11 @@ pub use super::generated_api::api::{
GetTabInfoPayload, GetTabInfoResponse as ProtobufGetTabInfoResponse, GoToTabWithIdPayload,
GroupAndUngroupPanesPayload, HideFloatingPanesPayload as ProtobufHideFloatingPanesPayload,
HideFloatingPanesResponse as ProtobufHideFloatingPanesResponse, HidePaneWithIdPayload,
- HighlightAndUnhighlightPanesPayload, HttpVerb as ProtobufHttpVerb, IdAndNewName,
- KeyToRebind, KeyToUnbind, KillSessionsPayload, ListTokensResponse, LoadNewPluginPayload,
- MessageToPluginPayload, MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload,
- MovePayload, NewPluginArgs as ProtobufNewPluginArgs, NewTabPayload,
+ HighlightAndUnhighlightPanesPayload, HighlightStyle as ProtobufHighlightStyle,
+ HttpVerb as ProtobufHttpVerb, IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload,
+ ListTokensResponse, LoadNewPluginPayload, MessageToPluginPayload,
+ MovePaneWithPaneIdInDirectionPayload, MovePaneWithPaneIdPayload, MovePayload,
+ NewPluginArgs as ProtobufNewPluginArgs, NewTabPayload,
NewTabResponse as ProtobufNewTabResponse, NewTabsResponse as ProtobufNewTabsResponse,
NewTabsWithLayoutInfoPayload,
OpenCommandPaneBackgroundResponse as ProtobufOpenCommandPaneBackgroundResponse,
@@ -92,19 +96,19 @@ pub use super::generated_api::api::{
PageScrollDownInPaneIdPayload, PageScrollUpInPaneIdPayload, PaneId as ProtobufPaneId,
PaneIdAndFloatingPaneCoordinates, PaneType as ProtobufPaneType, ParseLayoutPayload,
ParseLayoutResponse as ProtobufParseLayoutResponse, PluginCommand as ProtobufPluginCommand,
- PluginMessagePayload, RebindKeysPayload, ReconfigurePayload, ReloadPluginPayload,
- RenameLayoutPayload, RenameLayoutResponse as ProtobufRenameLayoutResponse,
- RenameTabWithIdPayload, RenameWebLoginTokenPayload, RenameWebTokenResponse,
- ReplacePaneWithExistingPanePayload, RequestPluginPermissionPayload,
- RerunCommandPanePayload, ResizePaneIdWithDirectionPayload, ResizePayload,
- RevokeAllWebTokensResponse, RevokeTokenResponse, RevokeWebLoginTokenPayload,
+ PluginMessagePayload, RebindKeysPayload, ReconfigurePayload,
+ RegexHighlight as ProtobufRegexHighlight, ReloadPluginPayload, RenameLayoutPayload,
+ RenameLayoutResponse as ProtobufRenameLayoutResponse, RenameTabWithIdPayload,
+ RenameWebLoginTokenPayload, RenameWebTokenResponse, ReplacePaneWithExistingPanePayload,
+ RequestPluginPermissionPayload, RerunCommandPanePayload, ResizePaneIdWithDirectionPayload,
+ ResizePayload, RevokeAllWebTokensResponse, RevokeTokenResponse, RevokeWebLoginTokenPayload,
RunActionPayload, RunCommandPayload, RunningCommand as ProtobufRunningCommand,
SaveLayoutPayload, SaveLayoutResponse as ProtobufSaveLayoutResponse, SaveSessionPayload,
SaveSessionResponse as ProtobufSaveSessionResponse, ScrollDownInPaneIdPayload,
ScrollToBottomInPaneIdPayload, ScrollToTopInPaneIdPayload, ScrollUpInPaneIdPayload,
SetFloatingPanePinnedPayload, SetPaneBorderlessPayload, SetPaneColorPayload,
- SetSelfMouseSelectionSupportPayload, SetTimeoutPayload, ShowCursorPayload,
- ShowFloatingPanesPayload as ProtobufShowFloatingPanesPayload,
+ SetPaneRegexHighlightsPayload, SetSelfMouseSelectionSupportPayload, SetTimeoutPayload,
+ ShowCursorPayload, ShowFloatingPanesPayload as ProtobufShowFloatingPanesPayload,
ShowFloatingPanesResponse as ProtobufShowFloatingPanesResponse, ShowPaneWithIdPayload,
StackPanesPayload, SubscribePayload, SwitchSessionPayload, SwitchTabToIdPayload,
SwitchTabToPayload, TogglePaneBorderlessPayload, TogglePaneEmbedOrEjectForPaneIdPayload,
@@ -118,8 +122,9 @@ pub use super::generated_api::api::{
use crate::data::{
ConnectToSession, DeleteLayoutResponse, EditLayoutResponse, FloatingPaneCoordinates,
GetFocusedPaneInfoResponse, GetPaneCwdResponse, GetPanePidResponse,
- GetPaneRunningCommandResponse, HttpVerb, InputMode, KeyWithModifier, MessageToPlugin,
- NewPluginArgs, PaneId, PermissionType, PluginCommand, RenameLayoutResponse, SaveLayoutResponse,
+ GetPaneRunningCommandResponse, HighlightStyle, HttpVerb, InputMode, KeyWithModifier,
+ MessageToPlugin, NewPluginArgs, PaneId, PermissionType, PluginCommand, RegexHighlight,
+ RenameLayoutResponse, SaveLayoutResponse,
};
use crate::input::actions::Action;
use crate::input::layout::PercentOrFixed;
@@ -2434,6 +2439,100 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
},
_ => Err("Mismatched payload for SetPaneColor"),
},
+ Some(CommandName::SetPaneRegexHighlights) => {
+ match protobuf_plugin_command.payload {
+ Some(Payload::SetPaneRegexHighlightsPayload(p)) => {
+ let pane_id: PaneId = p
+ .pane_id
+ .ok_or("Missing pane_id in SetPaneRegexHighlights")?
+ .try_into()?;
+ let highlights = p
+ .highlights
+ .into_iter()
+ .map(|h| {
+ let style = match h.style.and_then(|s| s.style) {
+ Some(ProtobufHighlightStyleVariant::Emphasis0(_)) => {
+ HighlightStyle::Emphasis0
+ },
+ Some(ProtobufHighlightStyleVariant::Emphasis1(_)) => {
+ HighlightStyle::Emphasis1
+ },
+ Some(ProtobufHighlightStyleVariant::Emphasis2(_)) => {
+ HighlightStyle::Emphasis2
+ },
+ Some(ProtobufHighlightStyleVariant::Emphasis3(_)) => {
+ HighlightStyle::Emphasis3
+ },
+ Some(ProtobufHighlightStyleVariant::CustomRgb(c)) => {
+ HighlightStyle::CustomRgb {
+ fg: match (c.fg_r, c.fg_g, c.fg_b) {
+ (Some(r), Some(g), Some(b)) => {
+ Some((r as u8, g as u8, b as u8))
+ },
+ _ => None,
+ },
+ bg: match (c.bg_r, c.bg_g, c.bg_b) {
+ (Some(r), Some(g), Some(b)) => {
+ Some((r as u8, g as u8, b as u8))
+ },
+ _ => None,
+ },
+ }
+ },
+ Some(ProtobufHighlightStyleVariant::CustomIndex(c)) => {
+ HighlightStyle::CustomIndex {
+ fg: c.fg.map(|v| v as u8),
+ bg: c.bg.map(|v| v as u8),
+ }
+ },
+ Some(ProtobufHighlightStyleVariant::BackgroundEmphasis0(_)) => {
+ HighlightStyle::BackgroundEmphasis0
+ },
+ Some(ProtobufHighlightStyleVariant::BackgroundEmphasis1(_)) => {
+ HighlightStyle::BackgroundEmphasis1
+ },
+ Some(ProtobufHighlightStyleVariant::BackgroundEmphasis2(_)) => {
+ HighlightStyle::BackgroundEmphasis2
+ },
+ Some(ProtobufHighlightStyleVariant::BackgroundEmphasis3(_)) => {
+ HighlightStyle::BackgroundEmphasis3
+ },
+ Some(ProtobufHighlightStyleVariant::None(_)) => {
+ HighlightStyle::None
+ },
+ None => HighlightStyle::Emphasis0, // fallback
+ };
+ let context = h
+ .context
+ .into_iter()
+ .map(|item| (item.name, item.value))
+ .collect();
+ RegexHighlight {
+ pattern: h.pattern,
+ style,
+ context,
+ on_hover: h.on_hover,
+ bold: h.bold,
+ italic: h.italic,
+ underline: h.underline,
+ }
+ })
+ .collect();
+ Ok(PluginCommand::SetPaneRegexHighlights(pane_id, highlights))
+ },
+ _ => Err("Mismatched payload for SetPaneRegexHighlights"),
+ }
+ },
+ Some(CommandName::ClearPaneHighlights) => match protobuf_plugin_command.payload {
+ Some(Payload::ClearPaneHighlightsPayload(p)) => {
+ let pane_id: PaneId = p
+ .pane_id
+ .ok_or("Missing pane_id in ClearPaneHighlights")?
+ .try_into()?;
+ Ok(PluginCommand::ClearPaneHighlights(pane_id))
+ },
+ _ => Err("Mismatched payload for ClearPaneHighlights"),
+ },
None => Err("Unrecognized plugin command"),
}
}
@@ -3994,6 +4093,93 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
bg,
})),
}),
+ PluginCommand::SetPaneRegexHighlights(pane_id, highlights) => {
+ Ok(ProtobufPluginCommand {
+ name: CommandName::SetPaneRegexHighlights as i32,
+ payload: Some(Payload::SetPaneRegexHighlightsPayload(
+ SetPaneRegexHighlightsPayload {
+ pane_id: pane_id.try_into().ok(),
+ highlights: highlights
+ .into_iter()
+ .map(|h| {
+ let style_variant = match h.style {
+ HighlightStyle::Emphasis0 => {
+ ProtobufHighlightStyleVariant::Emphasis0(true)
+ },
+ HighlightStyle::Emphasis1 => {
+ ProtobufHighlightStyleVariant::Emphasis1(true)
+ },
+ HighlightStyle::Emphasis2 => {
+ ProtobufHighlightStyleVariant::Emphasis2(true)
+ },
+ HighlightStyle::Emphasis3 => {
+ ProtobufHighlightStyleVariant::Emphasis3(true)
+ },
+ HighlightStyle::CustomRgb { fg, bg } => {
+ ProtobufHighlightStyleVariant::CustomRgb(
+ ProtobufCustomRgbHighlight {
+ fg_r: fg.map(|(r, _, _)| r as u32),
+ fg_g: fg.map(|(_, g, _)| g as u32),
+ fg_b: fg.map(|(_, _, b)| b as u32),
+ bg_r: bg.map(|(r, _, _)| r as u32),
+ bg_g: bg.map(|(_, g, _)| g as u32),
+ bg_b: bg.map(|(_, _, b)| b as u32),
+ },
+ )
+ },
+ HighlightStyle::CustomIndex { fg, bg } => {
+ ProtobufHighlightStyleVariant::CustomIndex(
+ ProtobufCustomIndexHighlight {
+ fg: fg.map(|v| v as u32),
+ bg: bg.map(|v| v as u32),
+ },
+ )
+ },
+ HighlightStyle::BackgroundEmphasis0 => {
+ ProtobufHighlightStyleVariant::BackgroundEmphasis0(true)
+ },
+ HighlightStyle::BackgroundEmphasis1 => {
+ ProtobufHighlightStyleVariant::BackgroundEmphasis1(true)
+ },
+ HighlightStyle::BackgroundEmphasis2 => {
+ ProtobufHighlightStyleVariant::BackgroundEmphasis2(true)
+ },
+ HighlightStyle::BackgroundEmphasis3 => {
+ ProtobufHighlightStyleVariant::BackgroundEmphasis3(true)
+ },
+ HighlightStyle::None => {
+ ProtobufHighlightStyleVariant::None(true)
+ },
+ };
+ ProtobufRegexHighlight {
+ pattern: h.pattern,
+ style: Some(ProtobufHighlightStyle {
+ style: Some(style_variant),
+ }),
+ context: h
+ .context
+ .into_iter()
+ .map(|(name, value)| ContextItem { name, value })
+ .collect(),
+ on_hover: h.on_hover,
+ bold: h.bold,
+ italic: h.italic,
+ underline: h.underline,
+ }
+ })
+ .collect(),
+ },
+ )),
+ })
+ },
+ PluginCommand::ClearPaneHighlights(pane_id) => Ok(ProtobufPluginCommand {
+ name: CommandName::ClearPaneHighlights as i32,
+ payload: Some(Payload::ClearPaneHighlightsPayload(
+ ClearPaneHighlightsPayload {
+ pane_id: pane_id.try_into().ok(),
+ },
+ )),
+ }),
}
}
}