aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils/src/plugin_api
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2026-03-14 08:35:00 +0100
committerGitHub <noreply@github.com>2026-03-14 08:35:00 +0100
commita1e224754759252778d8d3c30050e10bc9a82f84 (patch)
tree326ed657bbbb34ed98006f6bbc36fd918fdb1b0a /zellij-utils/src/plugin_api
parentAdd `--pane-id` and `--tab-id` to all relevant CLI commands (#4846) (diff)
downloadsl0ppij-a1e224754759252778d8d3c30050e10bc9a82f84.tar.gz
sl0ppij-a1e224754759252778d8d3c30050e10bc9a82f84.tar.xz
sl0ppij-a1e224754759252778d8d3c30050e10bc9a82f84.zip
Ansi dump support (#4848)
* add missing pane-id and tab-id arguments to all cli actions * rustfmt * dump-screen --ansi * edit-scrollback --ansi * add --ansi to subscribe * add tests for ansi additions * add ansi render report to plugins * rustfmt * fix e2e tests * add pr
Diffstat (limited to 'zellij-utils/src/plugin_api')
-rw-r--r--zellij-utils/src/plugin_api/action.proto1
-rw-r--r--zellij-utils/src/plugin_api/action.rs7
-rw-r--r--zellij-utils/src/plugin_api/event.proto2
-rw-r--r--zellij-utils/src/plugin_api/event.rs63
4 files changed, 71 insertions, 2 deletions
diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto
index 57442e6c..5f92ad94 100644
--- a/zellij-utils/src/plugin_api/action.proto
+++ b/zellij-utils/src/plugin_api/action.proto
@@ -383,6 +383,7 @@ message DumpScreenPayload {
bool include_scrollback = 2;
optional PaneId pane_id = 3;
bool dump_to_stdout = 4;
+ bool ansi = 5;
}
enum ActionName {
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs
index 9117bee5..3ac937b2 100644
--- a/zellij-utils/src/plugin_api/action.rs
+++ b/zellij-utils/src/plugin_api/action.rs
@@ -222,13 +222,14 @@ impl TryFrom<ProtobufAction> for Action {
file_path,
include_scrollback,
pane_id,
+ ansi: payload.ansi,
})
},
_ => Err("Wrong payload for Action::DumpScreen"),
},
Some(ProtobufActionName::EditScrollback) => match protobuf_action.optional_payload {
Some(_) => Err("EditScrollback should not have a payload"),
- None => Ok(Action::EditScrollback),
+ None => Ok(Action::EditScrollback { ansi: false }),
},
Some(ProtobufActionName::ScrollUp) => match protobuf_action.optional_payload {
Some(_) => Err("ScrollUp should not have a payload"),
@@ -1178,6 +1179,7 @@ impl TryFrom<Action> for ProtobufAction {
file_path,
include_scrollback,
pane_id,
+ ansi,
} => {
let dump_to_stdout = file_path.is_none();
Ok(ProtobufAction {
@@ -1187,10 +1189,11 @@ impl TryFrom<Action> for ProtobufAction {
include_scrollback,
pane_id: pane_id.and_then(|p| p.try_into().ok()),
dump_to_stdout,
+ ansi,
})),
})
},
- Action::EditScrollback => Ok(ProtobufAction {
+ Action::EditScrollback { .. } => Ok(ProtobufAction {
name: ProtobufActionName::EditScrollback as i32,
optional_payload: None,
}),
diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto
index 349a800a..1ecfa484 100644
--- a/zellij-utils/src/plugin_api/event.proto
+++ b/zellij-utils/src/plugin_api/event.proto
@@ -65,6 +65,7 @@ enum EventType {
AvailableLayoutInfo = 40;
PluginConfigurationChanged = 41;
HighlightClicked = 42;
+ PaneRenderReportWithAnsi = 43;
}
message EventNameList {
@@ -109,6 +110,7 @@ message Event {
AvailableLayoutInfoPayload available_layout_info_payload = 34;
PluginConfigurationChangedPayload plugin_configuration_changed_payload = 35;
HighlightClickedPayload highlight_clicked_payload = 36;
+ PaneRenderReportPayload pane_render_report_with_ansi_payload = 37;
}
}
diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs
index 883fcb4f..bb5b43d3 100644
--- a/zellij-utils/src/plugin_api/event.rs
+++ b/zellij-utils/src/plugin_api/event.rs
@@ -409,6 +409,14 @@ impl TryFrom<ProtobufEvent> for Event {
},
_ => Err("Malformed payload for the PaneRenderReport Event"),
},
+ Some(ProtobufEventType::PaneRenderReportWithAnsi) => match protobuf_event.payload {
+ Some(ProtobufEventPayload::PaneRenderReportWithAnsiPayload(protobuf_payload)) => {
+ Ok(Event::PaneRenderReportWithAnsi(
+ protobuf_payload.try_into()?,
+ ))
+ },
+ _ => Err("Malformed payload for the PaneRenderReportWithAnsi Event"),
+ },
Some(ProtobufEventType::UserAction) => match protobuf_event.payload {
Some(ProtobufEventPayload::UserActionPayload(protobuf_payload)) => {
let action: Action = protobuf_payload
@@ -920,6 +928,12 @@ impl TryFrom<Event> for ProtobufEvent {
pane_contents_map.try_into()?,
)),
}),
+ Event::PaneRenderReportWithAnsi(pane_contents_map) => Ok(ProtobufEvent {
+ name: ProtobufEventType::PaneRenderReportWithAnsi as i32,
+ payload: Some(event::Payload::PaneRenderReportWithAnsiPayload(
+ pane_contents_map.try_into()?,
+ )),
+ }),
Event::UserAction(action, client_id, terminal_id, cli_client_id) => {
let protobuf_action: ProtobufAction = action
.try_into()
@@ -1937,6 +1951,7 @@ impl TryFrom<ProtobufEventType> for EventType {
ProtobufEventType::FailedToStartWebServer => EventType::FailedToStartWebServer,
ProtobufEventType::InterceptedKeyPress => EventType::InterceptedKeyPress,
ProtobufEventType::PaneRenderReport => EventType::PaneRenderReport,
+ ProtobufEventType::PaneRenderReportWithAnsi => EventType::PaneRenderReportWithAnsi,
ProtobufEventType::UserAction => EventType::UserAction,
ProtobufEventType::ActionComplete => EventType::ActionComplete,
ProtobufEventType::CwdChanged => EventType::CwdChanged,
@@ -1987,6 +2002,7 @@ impl TryFrom<EventType> for ProtobufEventType {
EventType::FailedToStartWebServer => ProtobufEventType::FailedToStartWebServer,
EventType::InterceptedKeyPress => ProtobufEventType::InterceptedKeyPress,
EventType::PaneRenderReport => ProtobufEventType::PaneRenderReport,
+ EventType::PaneRenderReportWithAnsi => ProtobufEventType::PaneRenderReportWithAnsi,
EventType::UserAction => ProtobufEventType::UserAction,
EventType::ActionComplete => ProtobufEventType::ActionComplete,
EventType::CwdChanged => ProtobufEventType::CwdChanged,
@@ -2913,3 +2929,50 @@ impl TryFrom<SelectedText> for ProtobufSelectedText {
})
}
}
+
+#[test]
+fn serialize_pane_render_report_with_ansi_event() {
+ use prost::Message;
+ let pane_render_report_with_ansi_event = Event::PaneRenderReportWithAnsi(Default::default());
+ let protobuf_event: ProtobufEvent = pane_render_report_with_ansi_event
+ .clone()
+ .try_into()
+ .unwrap();
+ let serialized_protobuf_event = protobuf_event.encode_to_vec();
+ let deserialized_protobuf_event: ProtobufEvent =
+ Message::decode(serialized_protobuf_event.as_slice()).unwrap();
+ let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
+ assert_eq!(
+ pane_render_report_with_ansi_event, deserialized_event,
+ "Event properly serialized/deserialized without change"
+ );
+}
+
+#[test]
+fn serialize_pane_render_report_with_ansi_event_with_data() {
+ use prost::Message;
+ use std::collections::HashMap;
+ let mut pane_contents_map = HashMap::new();
+ pane_contents_map.insert(
+ PaneId::Terminal(1),
+ PaneContents {
+ viewport: vec![
+ "\x1b[31mred text\x1b[0m".to_owned(),
+ "\x1b[1mbold text\x1b[0m".to_owned(),
+ ],
+ selected_text: None,
+ lines_above_viewport: vec![],
+ lines_below_viewport: vec![],
+ },
+ );
+ let event = Event::PaneRenderReportWithAnsi(pane_contents_map);
+ let protobuf_event: ProtobufEvent = event.clone().try_into().unwrap();
+ let serialized_protobuf_event = protobuf_event.encode_to_vec();
+ let deserialized_protobuf_event: ProtobufEvent =
+ Message::decode(serialized_protobuf_event.as_slice()).unwrap();
+ let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap();
+ assert_eq!(
+ event, deserialized_event,
+ "PaneRenderReportWithAnsi event with ANSI data properly serialized/deserialized"
+ );
+}