aboutsummaryrefslogtreecommitdiffstats
path: root/zellij-utils
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2026-03-09 15:37:42 +0100
committerGitHub <noreply@github.com>2026-03-09 15:37:42 +0100
commit47ba6331c36f1b55f1a7d7ad3c0ab511629586a3 (patch)
tree37faab2182e15a2bc137991d37f282439df9ebc6 /zellij-utils
parentdocs(changelog): dump viewport of pane id (diff)
downloadsl0ppij-47ba6331c36f1b55f1a7d7ad3c0ab511629586a3.tar.gz
sl0ppij-47ba6331c36f1b55f1a7d7ad3c0ab511629586a3.tar.xz
sl0ppij-47ba6331c36f1b55f1a7d7ad3c0ab511629586a3.zip
allow dumping screen to STDOUT as well (#4823)
Diffstat (limited to 'zellij-utils')
-rw-r--r--zellij-utils/assets/prost/api.action.rs2
-rw-r--r--zellij-utils/assets/prost_ipc/client_server_contract.rs2
-rw-r--r--zellij-utils/src/cli.rs6
-rw-r--r--zellij-utils/src/client_server_contract/common_types.proto1
-rw-r--r--zellij-utils/src/input/actions.rs8
-rw-r--r--zellij-utils/src/ipc/protobuf_conversion.rs21
-rw-r--r--zellij-utils/src/ipc/tests/roundtrip_tests.rs16
-rw-r--r--zellij-utils/src/kdl/mod.rs7
-rw-r--r--zellij-utils/src/plugin_api/action.proto1
-rw-r--r--zellij-utils/src/plugin_api/action.rs28
10 files changed, 66 insertions, 26 deletions
diff --git a/zellij-utils/assets/prost/api.action.rs b/zellij-utils/assets/prost/api.action.rs
index 07303884..53e3b898 100644
--- a/zellij-utils/assets/prost/api.action.rs
+++ b/zellij-utils/assets/prost/api.action.rs
@@ -621,6 +621,8 @@ pub struct DumpScreenPayload {
pub include_scrollback: bool,
#[prost(message, optional, tag="3")]
pub pane_id: ::core::option::Option<PaneId>,
+ #[prost(bool, tag="4")]
+ pub dump_to_stdout: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
diff --git a/zellij-utils/assets/prost_ipc/client_server_contract.rs b/zellij-utils/assets/prost_ipc/client_server_contract.rs
index 2bb51289..9eabb990 100644
--- a/zellij-utils/assets/prost_ipc/client_server_contract.rs
+++ b/zellij-utils/assets/prost_ipc/client_server_contract.rs
@@ -696,6 +696,8 @@ pub struct DumpScreenAction {
pub include_scrollback: bool,
#[prost(message, optional, tag="3")]
pub pane_id: ::core::option::Option<PaneId>,
+ #[prost(bool, tag="4")]
+ pub dump_to_stdout: bool,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs
index 70aa10ac..1d6cd7ac 100644
--- a/zellij-utils/src/cli.rs
+++ b/zellij-utils/src/cli.rs
@@ -738,9 +738,11 @@ pub enum CliAction {
MovePaneBackwards,
/// Clear all buffers for a focused pane
Clear,
- /// Dumps the viewport and optionally scrollback of a pane to STDOUT
+ /// Dumps the viewport and optionally scrollback of a pane to a file or STDOUT
DumpScreen {
- path: PathBuf,
+ /// File path to dump the pane content to. If omitted, prints to STDOUT.
+ #[clap(long, value_parser)]
+ path: Option<PathBuf>,
/// Dump the pane with full scrollback
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
diff --git a/zellij-utils/src/client_server_contract/common_types.proto b/zellij-utils/src/client_server_contract/common_types.proto
index 4e770a90..430a1369 100644
--- a/zellij-utils/src/client_server_contract/common_types.proto
+++ b/zellij-utils/src/client_server_contract/common_types.proto
@@ -392,6 +392,7 @@ message DumpScreenAction {
string file_path = 1;
bool include_scrollback = 2;
optional PaneId pane_id = 3;
+ bool dump_to_stdout = 4;
}
message ScrollUpAtAction {
diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs
index ac311480..d56389c8 100644
--- a/zellij-utils/src/input/actions.rs
+++ b/zellij-utils/src/input/actions.rs
@@ -174,9 +174,9 @@ pub enum Action {
MovePaneBackwards,
/// Clear all buffers of a current screen
ClearScreen,
- /// Dumps the screen to a file
+ /// Dumps the screen to a file or STDOUT
DumpScreen {
- file_path: String,
+ file_path: Option<String>,
include_scrollback: bool,
pane_id: Option<PaneId>,
},
@@ -714,7 +714,7 @@ impl Action {
match parsed_pane_id {
Ok(parsed_pane_id) => {
Ok(vec![Action::DumpScreen {
- file_path: path.as_os_str().to_string_lossy().into(),
+ file_path: path.map(|p| p.as_os_str().to_string_lossy().into()),
include_scrollback: full,
pane_id: Some(parsed_pane_id),
}])
@@ -728,7 +728,7 @@ impl Action {
}
},
None => Ok(vec![Action::DumpScreen {
- file_path: path.as_os_str().to_string_lossy().into(),
+ file_path: path.map(|p| p.as_os_str().to_string_lossy().into()),
include_scrollback: full,
pane_id: None,
}]),
diff --git a/zellij-utils/src/ipc/protobuf_conversion.rs b/zellij-utils/src/ipc/protobuf_conversion.rs
index 3551895d..cc2a3555 100644
--- a/zellij-utils/src/ipc/protobuf_conversion.rs
+++ b/zellij-utils/src/ipc/protobuf_conversion.rs
@@ -891,11 +891,15 @@ impl From<crate::input::actions::Action>
file_path,
include_scrollback,
pane_id,
- } => ActionType::DumpScreen(DumpScreenAction {
- file_path,
- include_scrollback,
- pane_id: pane_id.map(|p| p.into()),
- }),
+ } => {
+ let dump_to_stdout = file_path.is_none();
+ ActionType::DumpScreen(DumpScreenAction {
+ file_path: file_path.unwrap_or_default(),
+ include_scrollback,
+ pane_id: pane_id.map(|p| p.into()),
+ dump_to_stdout,
+ })
+ },
crate::input::actions::Action::DumpLayout => {
ActionType::DumpLayout(DumpLayoutAction {})
},
@@ -1569,8 +1573,13 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Action>
},
ActionType::ClearScreen(_) => Ok(crate::input::actions::Action::ClearScreen),
ActionType::DumpScreen(dump_screen_action) => {
+ let file_path = if dump_screen_action.dump_to_stdout {
+ None
+ } else {
+ Some(dump_screen_action.file_path)
+ };
Ok(crate::input::actions::Action::DumpScreen {
- file_path: dump_screen_action.file_path,
+ file_path,
include_scrollback: dump_screen_action.include_scrollback,
pane_id: dump_screen_action.pane_id.and_then(|p| p.try_into().ok()),
})
diff --git a/zellij-utils/src/ipc/tests/roundtrip_tests.rs b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
index 8b018c16..8abd3040 100644
--- a/zellij-utils/src/ipc/tests/roundtrip_tests.rs
+++ b/zellij-utils/src/ipc/tests/roundtrip_tests.rs
@@ -873,7 +873,7 @@ fn test_client_messages() {
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::DumpScreen {
- file_path: "/path/to/file".to_owned(),
+ file_path: Some("/path/to/file".to_owned()),
include_scrollback: false,
pane_id: None,
},
@@ -883,7 +883,7 @@ fn test_client_messages() {
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::DumpScreen {
- file_path: "/path/to/file".to_owned(),
+ file_path: Some("/path/to/file".to_owned()),
include_scrollback: true,
pane_id: None,
},
@@ -893,7 +893,7 @@ fn test_client_messages() {
});
test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::DumpScreen {
- file_path: "/path/to/file".to_owned(),
+ file_path: Some("/path/to/file".to_owned()),
include_scrollback: true,
pane_id: Some(PaneId::Terminal(5)),
},
@@ -902,6 +902,16 @@ fn test_client_messages() {
is_cli_client: true,
});
test_client_roundtrip!(ClientToServerMsg::Action {
+ action: Action::DumpScreen {
+ file_path: None,
+ include_scrollback: false,
+ pane_id: None,
+ },
+ terminal_id: Some(1),
+ client_id: Some(100),
+ is_cli_client: true,
+ });
+ test_client_roundtrip!(ClientToServerMsg::Action {
action: Action::DumpLayout,
terminal_id: Some(1),
client_id: Some(100),
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
index 0a9a1d75..7408c3a4 100644
--- a/zellij-utils/src/kdl/mod.rs
+++ b/zellij-utils/src/kdl/mod.rs
@@ -541,7 +541,7 @@ impl Action {
},
"MovePaneBackwards" => Ok(Action::MovePaneBackwards),
"DumpScreen" => Ok(Action::DumpScreen {
- file_path: string,
+ file_path: Some(string),
include_scrollback: false,
pane_id: None,
}),
@@ -693,7 +693,7 @@ impl Action {
},
Action::MovePaneBackwards => Some(KdlNode::new("MovePaneBackwards")),
Action::DumpScreen {
- file_path: file,
+ file_path: Some(file),
include_scrollback: _,
pane_id: _,
} => {
@@ -701,6 +701,9 @@ impl Action {
node.push(file.clone());
Some(node)
},
+ Action::DumpScreen {
+ file_path: None, ..
+ } => None,
Action::DumpLayout => Some(KdlNode::new("DumpLayout")),
Action::EditScrollback => Some(KdlNode::new("EditScrollback")),
Action::EditScrollbackRaw => Some(KdlNode::new("EditScrollbackRaw")),
diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto
index 169bc24f..57442e6c 100644
--- a/zellij-utils/src/plugin_api/action.proto
+++ b/zellij-utils/src/plugin_api/action.proto
@@ -382,6 +382,7 @@ message DumpScreenPayload {
string file_path = 1;
bool include_scrollback = 2;
optional PaneId pane_id = 3;
+ bool dump_to_stdout = 4;
}
enum ActionName {
diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs
index 5ccd349c..aef9d881 100644
--- a/zellij-utils/src/plugin_api/action.rs
+++ b/zellij-utils/src/plugin_api/action.rs
@@ -211,7 +211,11 @@ impl TryFrom<ProtobufAction> for Action {
},
Some(ProtobufActionName::DumpScreen) => match protobuf_action.optional_payload {
Some(OptionalPayload::DumpScreenPayload(payload)) => {
- let file_path = payload.file_path;
+ let file_path = if payload.dump_to_stdout {
+ None
+ } else {
+ Some(payload.file_path)
+ };
let include_scrollback = payload.include_scrollback;
let pane_id = payload.pane_id.and_then(|p| p.try_into().ok());
Ok(Action::DumpScreen {
@@ -1149,14 +1153,20 @@ impl TryFrom<Action> for ProtobufAction {
file_path,
include_scrollback,
pane_id,
- } => Ok(ProtobufAction {
- name: ProtobufActionName::DumpScreen as i32,
- optional_payload: Some(OptionalPayload::DumpScreenPayload(DumpScreenPayload {
- file_path,
- include_scrollback,
- pane_id: pane_id.and_then(|p| p.try_into().ok()),
- })),
- }),
+ } => {
+ let dump_to_stdout = file_path.is_none();
+ Ok(ProtobufAction {
+ name: ProtobufActionName::DumpScreen as i32,
+ optional_payload: Some(OptionalPayload::DumpScreenPayload(
+ DumpScreenPayload {
+ file_path: file_path.unwrap_or_default(),
+ include_scrollback,
+ pane_id: pane_id.and_then(|p| p.try_into().ok()),
+ dump_to_stdout,
+ },
+ )),
+ })
+ },
Action::EditScrollback => Ok(ProtobufAction {
name: ProtobufActionName::EditScrollback as i32,
optional_payload: None,