aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-server
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2026-03-20 17:28:36 +0100
committerGitHub <noreply@github.com>2026-03-20 17:28:36 +0100
commit4ba41c085ab9207ed31e72a1ba331bff2bebed99 (patch)
treeaf832d3e2b1c4577525f0276bda83fc9a12612b3 /zellij-server
parentadjust badges location in readme (diff)
downloadsl0ppij-4ba41c085ab9207ed31e72a1ba331bff2bebed99.tar.gz
sl0ppij-4ba41c085ab9207ed31e72a1ba331bff2bebed99.tar.xz
sl0ppij-4ba41c085ab9207ed31e72a1ba331bff2bebed99.zip
Release notes and fixes (#4879)
* release notes * fix some link issues * rustfmt * fix click wording
Diffstat (limited to 'zellij-server')
-rw-r--r--zellij-server/src/panes/grid.rs29
-rw-r--r--zellij-server/src/plugins/zellij_exports.rs80
2 files changed, 97 insertions, 12 deletions
diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs
index 0f0e3fb4..07752542 100644
--- a/zellij-server/src/panes/grid.rs
+++ b/zellij-server/src/panes/grid.rs
@@ -458,6 +458,15 @@ fn match_to_selection(
Some((sel, start_row, start_col, end_row, end_col))
}
+/// Extract the effective match from a set of captures.
+/// If capture group 1 exists, it is used (allowing patterns to include
+/// context such as surrounding whitespace in the full match while
+/// highlighting only the content in group 1). Otherwise the full match
+/// (group 0) is returned.
+fn highlight_match<'t>(captures: &regex::Captures<'t>) -> Option<regex::Match<'t>> {
+ captures.get(1).or_else(|| captures.get(0))
+}
+
/// Check whether a (row, col) position falls within a display span.
/// The span is inclusive at start and exclusive at end.
fn position_in_span(
@@ -2163,7 +2172,10 @@ impl Grid {
)> = None;
for (plugin_id, pattern_map) in &self.plugin_highlights {
for (pattern, compiled) in pattern_map {
- for mat in compiled.regex.find_iter(&logical_text) {
+ for captures in compiled.regex.captures_iter(&logical_text) {
+ let Some(mat) = highlight_match(&captures) else {
+ continue;
+ };
if let Some((_sel, start_row, start_col, end_row, end_col)) =
match_to_selection(&mat, &boundaries, &self.viewport)
{
@@ -2250,7 +2262,10 @@ impl Grid {
if !compiled.on_hover || compiled.tooltip_text.is_none() {
continue;
}
- for mat in compiled.regex.find_iter(&logical_text) {
+ for captures in compiled.regex.captures_iter(&logical_text) {
+ let Some(mat) = highlight_match(&captures) else {
+ continue;
+ };
if let Some((_sel, start_row, start_col, end_row, end_col)) =
match_to_selection(&mat, &boundaries, &self.viewport)
{
@@ -2306,7 +2321,10 @@ impl Grid {
if !compiled.on_hover || !compiled.has_visual_effect() {
continue;
}
- for mat in compiled.regex.find_iter(&logical_text) {
+ for captures in compiled.regex.captures_iter(&logical_text) {
+ let Some(mat) = highlight_match(&captures) else {
+ continue;
+ };
if let Some((sel, start_row, start_col, end_row, end_col)) =
match_to_selection(&mat, &boundaries, &self.viewport)
{
@@ -2340,7 +2358,10 @@ impl Grid {
if compiled.on_hover || !compiled.has_visual_effect() {
continue;
}
- for mat in compiled.regex.find_iter(&logical_text) {
+ for captures in compiled.regex.captures_iter(&logical_text) {
+ let Some(mat) = highlight_match(&captures) else {
+ continue;
+ };
if let Some((sel, _, _, _, _)) =
match_to_selection(&mat, &boundaries, &self.viewport)
{
diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs
index c96f028d..9b6f022f 100644
--- a/zellij-server/src/plugins/zellij_exports.rs
+++ b/zellij-server/src/plugins/zellij_exports.rs
@@ -33,8 +33,8 @@ use zellij_utils::data::{
OpenEditPaneInPlaceOfPaneIdResponse, OpenFileFloatingNearPluginResponse,
OpenFileFloatingResponse, OpenFileInPlaceOfPluginResponse, OpenFileInPlaceResponse,
OpenFileNearPluginResponse, OpenFileResponse, OpenPaneInNewTabResponse,
- OpenTerminalFloatingNearPluginResponse, OpenTerminalFloatingResponse,
- OpenTerminalInPlaceOfPluginResponse, OpenTerminalInPlaceResponse,
+ OpenPluginPaneFloatingResponse, OpenTerminalFloatingNearPluginResponse,
+ OpenTerminalFloatingResponse, OpenTerminalInPlaceOfPluginResponse, OpenTerminalInPlaceResponse,
OpenTerminalNearPluginResponse, OpenTerminalPaneInPlaceOfPaneIdResponse, OpenTerminalResponse,
OriginatingPlugin, PaneScrollbackResponse, PermissionStatus, PermissionType, PluginPermission,
RegexHighlight, RenameLayoutResponse, SaveLayoutResponse, TabMetadata,
@@ -94,9 +94,10 @@ use zellij_utils::{
ProtobufOpenFileFloatingNearPluginResponse, ProtobufOpenFileFloatingResponse,
ProtobufOpenFileInPlaceOfPluginResponse, ProtobufOpenFileInPlaceResponse,
ProtobufOpenFileNearPluginResponse, ProtobufOpenFileResponse,
- ProtobufOpenPaneInNewTabResponse, ProtobufOpenTerminalFloatingNearPluginResponse,
- ProtobufOpenTerminalFloatingResponse, ProtobufOpenTerminalInPlaceOfPluginResponse,
- ProtobufOpenTerminalInPlaceResponse, ProtobufOpenTerminalNearPluginResponse,
+ ProtobufOpenPaneInNewTabResponse, ProtobufOpenPluginPaneFloatingResponse,
+ ProtobufOpenTerminalFloatingNearPluginResponse, ProtobufOpenTerminalFloatingResponse,
+ ProtobufOpenTerminalInPlaceOfPluginResponse, ProtobufOpenTerminalInPlaceResponse,
+ ProtobufOpenTerminalNearPluginResponse,
ProtobufOpenTerminalPaneInPlaceOfPaneIdResponse, ProtobufOpenTerminalResponse,
ProtobufParseLayoutResponse, ProtobufPluginCommand, ProtobufRenameLayoutResponse,
ProtobufSaveLayoutResponse, ProtobufSaveSessionResponse,
@@ -700,6 +701,20 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) {
} => {
open_plugin_pane_in_new_tab(env, plugin_url, configuration, context);
},
+ PluginCommand::OpenPluginPaneFloating {
+ plugin_url,
+ configuration,
+ floating_pane_coordinates,
+ context,
+ } => {
+ open_plugin_pane_floating(
+ env,
+ plugin_url,
+ configuration,
+ floating_pane_coordinates,
+ context,
+ );
+ },
PluginCommand::OpenEditorPaneInNewTab(file_to_open, context) => {
open_editor_pane_in_new_tab(env, file_to_open, context);
},
@@ -1113,6 +1128,53 @@ fn open_plugin_pane_in_new_tab(
.non_fatal();
}
+fn open_plugin_pane_floating(
+ env: &PluginEnv,
+ plugin_url: String,
+ configuration: BTreeMap<String, String>,
+ floating_pane_coordinates: Option<FloatingPaneCoordinates>,
+ context: BTreeMap<String, String>,
+) {
+ let run_plugin_or_alias = RunPluginOrAlias::from_url(
+ &plugin_url,
+ &Some(configuration),
+ None,
+ Some(env.plugin_cwd.clone()),
+ );
+ let run_plugin_or_alias = match run_plugin_or_alias {
+ Ok(r) => r,
+ Err(e) => {
+ log::error!("Failed to parse plugin url '{}': {}", plugin_url, e);
+ let response = ProtobufOpenPluginPaneFloatingResponse::from(
+ OpenPluginPaneFloatingResponse::default(),
+ );
+ wasi_write_object(env, &response.encode_to_vec())
+ .with_context(|| {
+ format!("failed to write open_plugin_pane_floating error response")
+ })
+ .non_fatal();
+ return;
+ },
+ };
+ let _ = context; // context is not currently used for plugin panes
+ let action = Action::NewFloatingPluginPane {
+ plugin: run_plugin_or_alias,
+ pane_name: None,
+ skip_cache: false,
+ cwd: Some(env.plugin_cwd.clone()),
+ coordinates: floating_pane_coordinates,
+ };
+ let error_msg = || format!("Failed to open floating plugin pane");
+ let result = apply_action!(action, error_msg, env);
+
+ let pane_id: OpenPluginPaneFloatingResponse =
+ result.and_then(|r| r.affected_pane_id).map(|p| p.into());
+ let response = ProtobufOpenPluginPaneFloatingResponse::from(pane_id);
+ wasi_write_object(env, &response.encode_to_vec())
+ .with_context(|| format!("failed to write open_plugin_pane_floating response"))
+ .non_fatal();
+}
+
fn open_editor_pane_in_new_tab(
env: &PluginEnv,
file_to_open: FileToOpen,
@@ -5014,6 +5076,8 @@ fn check_command_permission(
| PluginCommand::OpenTerminalFloatingNearPlugin(..)
| PluginCommand::OpenTerminalInPlace(..)
| PluginCommand::OpenTerminalInPlaceOfPlugin(..)
+ | PluginCommand::OpenPluginPaneInNewTab { .. }
+ | PluginCommand::OpenPluginPaneFloating { .. }
| PluginCommand::OpenTerminalPaneInPlaceOfPaneId(..) => {
PermissionType::OpenTerminalsOrPlugins
},
@@ -5173,9 +5237,9 @@ fn check_command_permission(
PluginCommand::GetSessionEnvironmentVariables => {
PermissionType::ReadSessionEnvironmentVariables
},
- PluginCommand::OpenCommandPaneInNewTab(..)
- | PluginCommand::OpenPluginPaneInNewTab { .. }
- | PluginCommand::OpenEditorPaneInNewTab(..) => PermissionType::ChangeApplicationState,
+ PluginCommand::OpenCommandPaneInNewTab(..) | PluginCommand::OpenEditorPaneInNewTab(..) => {
+ PermissionType::ChangeApplicationState
+ },
_ => return (PermissionStatus::Granted, None),
};