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
This commit is contained in:
Aram Drevekenin 2025-02-21 19:34:38 +01:00 committed by GitHub
parent 834693f0c2
commit 04be2646ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 106 additions and 10 deletions

View file

@ -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)

View file

@ -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

View file

@ -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)]

View file

@ -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)]

View file

@ -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();

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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 {

View file

@ -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![];