aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-02-21 19:34:38 +0100
committerGitHub <noreply@github.com>2025-02-21 19:34:38 +0100
commit04be2646edc2c35c1e2b7f53a4f0f757d463bda4 (patch)
treec942df962ff482e907bdeb6a3e92b6a4ecb3b972
parentdocs(changelog): pin plugin pane fix (diff)
downloadsl0ppij-04be2646edc2c35c1e2b7f53a4f0f757d463bda4.tar.gz
sl0ppij-04be2646edc2c35c1e2b7f53a4f0f757d463bda4.tar.xz
sl0ppij-04be2646edc2c35c1e2b7f53a4f0f757d463bda4.zip
feat(plugins): add tab history to the `SessionUpdate` Event (#4014)
* feat(plugins): add tab-history to the SessionInfo * update snapshots * style(fmt): rustfmt * update changelog
-rw-r--r--CHANGELOG.md1
-rw-r--r--zellij-server/src/screen.rs1
-rw-r--r--zellij-utils/assets/prost/api.event.rs10
-rw-r--r--zellij-utils/src/data.rs1
-rw-r--r--zellij-utils/src/kdl/mod.rs44
-rw-r--r--zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info.snap4
-rw-r--r--zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info_with_data.snap4
-rw-r--r--zellij-utils/src/plugin_api/event.proto6
-rw-r--r--zellij-utils/src/plugin_api/event.rs45
9 files changed, 106 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 61c20420..dcdae5fc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -34,6 +34,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* fix(clipboard): various clipboard message fixes (https://github.com/zellij-org/zellij/pull/4009)
* fix(logging): fix segfault in chrono crate (https://github.com/zellij-org/zellij/pull/4010)
* fix(floating-panes): reset damage in swap layouts when closing the last pane (https://github.com/zellij-org/zellij/pull/4012)
+* feat(plugins): add tab_history to the session metadata (https://github.com/zellij-org/zellij/pull/4014)
## [0.41.2] - 2024-11-19
* fix(input): keypresses not being identified properly with kitty keyboard protocol in some terminals (https://github.com/zellij-org/zellij/pull/3725)
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs
index 0b9d0c67..16cc3d39 100644
--- a/zellij-server/src/screen.rs
+++ b/zellij-server/src/screen.rs
@@ -1648,6 +1648,7 @@ impl Screen {
is_current_session: true,
available_layouts,
plugins: Default::default(), // these are filled in by the wasm thread
+ tab_history: self.tab_history.clone(),
};
self.bus
.senders
diff --git a/zellij-utils/assets/prost/api.event.rs b/zellij-utils/assets/prost/api.event.rs
index 493e0dc4..46372db5 100644
--- a/zellij-utils/assets/prost/api.event.rs
+++ b/zellij-utils/assets/prost/api.event.rs
@@ -316,6 +316,16 @@ pub struct SessionManifest {
pub available_layouts: ::prost::alloc::vec::Vec<LayoutInfo>,
#[prost(message, repeated, tag = "7")]
pub plugins: ::prost::alloc::vec::Vec<PluginInfo>,
+ #[prost(message, repeated, tag = "8")]
+ pub tab_history: ::prost::alloc::vec::Vec<ClientTabHistory>,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct ClientTabHistory {
+ #[prost(uint32, tag = "1")]
+ pub client_id: u32,
+ #[prost(uint32, repeated, tag = "2")]
+ pub tab_history: ::prost::alloc::vec::Vec<u32>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index a1be6274..368b3e2a 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -1554,6 +1554,7 @@ pub struct SessionInfo {
pub is_current_session: bool,
pub available_layouts: Vec<LayoutInfo>,
pub plugins: BTreeMap<u32, PluginInfo>,
+ pub tab_history: BTreeMap<ClientId, Vec<usize>>,
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Deserialize, Serialize)]
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index 27230c2f..93b111f4 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -4462,6 +4462,29 @@ impl SessionInfo {
})
.ok_or("Failed to parse available_layouts")?;
let is_current_session = name == current_session_name;
+ let mut tab_history = BTreeMap::new();
+ if let Some(kdl_tab_history) = kdl_document.get("tab_history").and_then(|p| p.children()) {
+ for client_node in kdl_tab_history.nodes() {
+ if let Some(client_id) = client_node.children().and_then(|c| {
+ c.get("id")
+ .and_then(|c| c.entries().iter().next().and_then(|e| e.value().as_i64()))
+ }) {
+ let mut history = vec![];
+ if let Some(history_entries) = client_node
+ .children()
+ .and_then(|c| c.get("history"))
+ .map(|h| h.entries())
+ {
+ for entry in history_entries {
+ if let Some(entry) = entry.value().as_i64() {
+ history.push(entry as usize);
+ }
+ }
+ }
+ tab_history.insert(client_id as u16, history);
+ }
+ }
+ }
Ok(SessionInfo {
name,
tabs,
@@ -4470,6 +4493,7 @@ impl SessionInfo {
is_current_session,
available_layouts,
plugins: Default::default(), // we do not serialize plugin information
+ tab_history,
})
}
pub fn to_string(&self) -> String {
@@ -4510,11 +4534,30 @@ impl SessionInfo {
}
available_layouts.set_children(available_layouts_children);
+ let mut tab_history = KdlNode::new("tab_history");
+ let mut tab_history_children = KdlDocument::new();
+ for (client_id, client_tab_history) in &self.tab_history {
+ let mut client_document = KdlDocument::new();
+ let mut client_node = KdlNode::new("client");
+ let mut id = KdlNode::new("id");
+ id.push(*client_id as i64);
+ client_document.nodes_mut().push(id);
+ let mut history = KdlNode::new("history");
+ for entry in client_tab_history {
+ history.push(*entry as i64);
+ }
+ client_document.nodes_mut().push(history);
+ client_node.set_children(client_document);
+ tab_history_children.nodes_mut().push(client_node);
+ }
+ tab_history.set_children(tab_history_children);
+
kdl_document.nodes_mut().push(name);
kdl_document.nodes_mut().push(tabs);
kdl_document.nodes_mut().push(panes);
kdl_document.nodes_mut().push(connected_clients);
kdl_document.nodes_mut().push(available_layouts);
+ kdl_document.nodes_mut().push(tab_history);
kdl_document.fmt();
kdl_document.to_string()
}
@@ -5067,6 +5110,7 @@ fn serialize_and_deserialize_session_info_with_data() {
LayoutInfo::File("layout3".to_owned()),
],
plugins: Default::default(),
+ tab_history: Default::default(),
};
let serialized = session_info.to_string();
let deserealized = SessionInfo::from_string(&serialized, "not this session").unwrap();
diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info.snap
index 32925ec1..aaaa6ba7 100644
--- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info.snap
+++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info.snap
@@ -1,6 +1,6 @@
---
source: zellij-utils/src/kdl/mod.rs
-assertion_line: 2459
+assertion_line: 5000
expression: serialized
---
name ""
@@ -11,4 +11,6 @@ panes {
connected_clients 0
available_layouts {
}
+tab_history {
+}
diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info_with_data.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info_with_data.snap
index 6e0ba4c5..a0401386 100644
--- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info_with_data.snap
+++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__serialize_and_deserialize_session_info_with_data.snap
@@ -1,6 +1,6 @@
---
source: zellij-utils/src/kdl/mod.rs
-assertion_line: 5070
+assertion_line: 5111
expression: serialized
---
name "my session name"
@@ -95,4 +95,6 @@ available_layouts {
layout2 source="built-in"
layout3 source="file"
}
+tab_history {
+}
diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto
index 7269cc47..14eb0c40 100644
--- a/zellij-utils/src/plugin_api/event.proto
+++ b/zellij-utils/src/plugin_api/event.proto
@@ -257,6 +257,12 @@ message SessionManifest {
bool is_current_session = 5;
repeated LayoutInfo available_layouts = 6;
repeated PluginInfo plugins = 7;
+ repeated ClientTabHistory tab_history = 8;
+}
+
+message ClientTabHistory {
+ uint32 client_id = 1;
+ repeated uint32 tab_history = 2;
}
message PluginInfo {
diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs
index 743e1569..4707d657 100644
--- a/zellij-utils/src/plugin_api/event.rs
+++ b/zellij-utils/src/plugin_api/event.rs
@@ -2,14 +2,14 @@ pub use super::generated_api::api::{
action::{Action as ProtobufAction, Position as ProtobufPosition},
event::{
event::Payload as ProtobufEventPayload, ClientInfo as ProtobufClientInfo,
- CopyDestination as ProtobufCopyDestination, Event as ProtobufEvent,
- EventNameList as ProtobufEventNameList, EventType as ProtobufEventType,
- FileMetadata as ProtobufFileMetadata, InputModeKeybinds as ProtobufInputModeKeybinds,
- KeyBind as ProtobufKeyBind, LayoutInfo as ProtobufLayoutInfo,
- ModeUpdatePayload as ProtobufModeUpdatePayload, PaneId as ProtobufPaneId,
- PaneInfo as ProtobufPaneInfo, PaneManifest as ProtobufPaneManifest,
- PaneType as ProtobufPaneType, PluginInfo as ProtobufPluginInfo,
- ResurrectableSession as ProtobufResurrectableSession,
+ ClientTabHistory as ProtobufClientTabHistory, CopyDestination as ProtobufCopyDestination,
+ Event as ProtobufEvent, EventNameList as ProtobufEventNameList,
+ EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata,
+ InputModeKeybinds as ProtobufInputModeKeybinds, KeyBind as ProtobufKeyBind,
+ LayoutInfo as ProtobufLayoutInfo, ModeUpdatePayload as ProtobufModeUpdatePayload,
+ PaneId as ProtobufPaneId, PaneInfo as ProtobufPaneInfo,
+ PaneManifest as ProtobufPaneManifest, PaneType as ProtobufPaneType,
+ PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession,
SessionManifest as ProtobufSessionManifest, TabInfo as ProtobufTabInfo, *,
},
input_mode::InputMode as ProtobufInputMode,
@@ -771,10 +771,23 @@ impl TryFrom<SessionInfo> for ProtobufSessionManifest {
.into_iter()
.map(|p| ProtobufPluginInfo::from(p))
.collect(),
+ tab_history: session_info
+ .tab_history
+ .into_iter()
+ .map(|t| ProtobufClientTabHistory::from(t))
+ .collect(),
})
}
}
+impl From<(u16, Vec<usize>)> for ProtobufClientTabHistory {
+ fn from((client_id, tab_history): (u16, Vec<usize>)) -> ProtobufClientTabHistory {
+ ProtobufClientTabHistory {
+ client_id: client_id as u32,
+ tab_history: tab_history.into_iter().map(|t| t as u32).collect(),
+ }
+ }
+}
impl From<(u32, PluginInfo)> for ProtobufPluginInfo {
fn from((plugin_id, plugin_info): (u32, PluginInfo)) -> ProtobufPluginInfo {
ProtobufPluginInfo {
@@ -821,6 +834,16 @@ impl TryFrom<ProtobufSessionManifest> for SessionInfo {
},
);
}
+ let mut tab_history = BTreeMap::new();
+ for client_tab_history in protobuf_session_manifest.tab_history.into_iter() {
+ let client_id = client_tab_history.client_id;
+ let tab_history_for_client = client_tab_history
+ .tab_history
+ .iter()
+ .map(|t| *t as usize)
+ .collect();
+ tab_history.insert(client_id as u16, tab_history_for_client);
+ }
Ok(SessionInfo {
name: protobuf_session_manifest.name,
tabs: protobuf_session_manifest
@@ -837,6 +860,7 @@ impl TryFrom<ProtobufSessionManifest> for SessionInfo {
.filter_map(|l| LayoutInfo::try_from(l).ok())
.collect(),
plugins,
+ tab_history,
})
}
}
@@ -1921,6 +1945,9 @@ fn serialize_session_update_event_with_non_default_values() {
configuration: plugin_configuration,
},
);
+ let mut tab_history = BTreeMap::new();
+ tab_history.insert(1, vec![1, 2, 3]);
+ tab_history.insert(2, vec![1, 2, 3]);
let session_info_1 = SessionInfo {
name: "session 1".to_owned(),
tabs: tab_infos,
@@ -1933,6 +1960,7 @@ fn serialize_session_update_event_with_non_default_values() {
LayoutInfo::File("layout3".to_owned()),
],
plugins,
+ tab_history,
};
let session_info_2 = SessionInfo {
name: "session 2".to_owned(),
@@ -1948,6 +1976,7 @@ fn serialize_session_update_event_with_non_default_values() {
LayoutInfo::File("layout3".to_owned()),
],
plugins: Default::default(),
+ tab_history: Default::default(),
};
let session_infos = vec![session_info_1, session_info_2];
let resurrectable_sessions = vec![];