Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement a dump_screen plugin shim function #3920

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions zellij-server/src/plugins/zellij_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
},
PluginCommand::WatchFilesystem => watch_filesystem(env),
PluginCommand::DumpSessionLayout => dump_session_layout(env),
PluginCommand::DumpScreen(full) => dump_screen(env, full),
PluginCommand::CloseSelf => close_self(env),
PluginCommand::Reconfigure(new_config, write_config_to_disk) => {
reconfigure(env, new_config, write_config_to_disk)?
Expand Down Expand Up @@ -1496,6 +1497,16 @@ fn dump_session_layout(env: &PluginEnv) {
.map(|sender| sender.send(ScreenInstruction::DumpLayoutToPlugin(env.plugin_id)));
}

fn dump_screen(env: &PluginEnv, full: bool) {
let _ = env.senders.to_screen.as_ref().map(|sender| {
sender.send(ScreenInstruction::DumpScreenToPlugin(
env.plugin_id,
env.client_id,
full,
))
});
}

fn list_clients(env: &PluginEnv) {
let _ = env.senders.to_screen.as_ref().map(|sender| {
sender.send(ScreenInstruction::ListClientsToPlugin(
Expand Down
28 changes: 28 additions & 0 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ pub enum ScreenInstruction {
DumpLayout(Option<PathBuf>, ClientId), // PathBuf is the default configured
// shell
DumpLayoutToPlugin(PluginId),
DumpScreenToPlugin(PluginId, ClientId, bool),
EditScrollback(ClientId),
ScrollUp(ClientId),
ScrollUpAt(Position, ClientId),
Expand Down Expand Up @@ -471,6 +472,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::Exit => ScreenContext::Exit,
ScreenInstruction::ClearScreen(..) => ScreenContext::ClearScreen,
ScreenInstruction::DumpScreen(..) => ScreenContext::DumpScreen,
ScreenInstruction::DumpScreenToPlugin(..) => ScreenContext::DumpScreenToPlugin,
ScreenInstruction::DumpLayout(..) => ScreenContext::DumpLayout,
ScreenInstruction::DumpLayoutToPlugin(..) => ScreenContext::DumpLayoutToPlugin,
ScreenInstruction::EditScrollback(..) => ScreenContext::EditScrollback,
Expand Down Expand Up @@ -3161,6 +3163,32 @@ pub(crate) fn screen_thread_main(
screen.render(None)?;
screen.unblock_input()?;
},
ScreenInstruction::DumpScreenToPlugin(plugin_id, client_id, full) => {
let err_context = || format!("Failed to dump screen");
let mut dump = None;
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| {
if let Some(active_pane) =
tab.get_active_pane_or_floating_pane_mut(client_id)
{
dump = Some(active_pane.dump_screen(full));
}
}
);
if let Some(dump) = dump {
screen
.bus
.senders
.send_to_plugin(PluginInstruction::Update(vec![(
Some(plugin_id),
Some(client_id),
Event::ScreenContents(dump),
)]))
.with_context(err_context)?;
}
},
ScreenInstruction::DumpLayout(default_shell, client_id) => {
let err_context = || format!("Failed to dump layout");
let session_layout_metadata = screen.get_layout_metadata(default_shell);
Expand Down
8 changes: 8 additions & 0 deletions zellij-tile/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,14 @@ pub fn dump_session_layout() {
unsafe { host_run_plugin_command() };
}

/// Get the screen contents as a ScreenContents event
pub fn dump_screen(full: bool) {
let plugin_command = PluginCommand::DumpScreen(full);
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
unsafe { host_run_plugin_command() };
}

/// Get a list of clients, their focused pane and running command or focused plugin back as an
/// Event::ListClients (note: this event must be subscribed to)
pub fn list_clients() {
Expand Down
7 changes: 6 additions & 1 deletion zellij-utils/assets/prost/api.event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct Event {
pub name: i32,
#[prost(
oneof = "event::Payload",
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25"
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26"
)]
pub payload: ::core::option::Option<event::Payload>,
}
Expand Down Expand Up @@ -68,6 +68,8 @@ pub mod event {
HostFolderChangedPayload(super::HostFolderChangedPayload),
#[prost(message, tag = "25")]
FailedToChangeHostFolderPayload(super::FailedToChangeHostFolderPayload),
#[prost(string, tag = "26")]
ScreenContentsPayload(::prost::alloc::string::String),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
Expand Down Expand Up @@ -486,6 +488,7 @@ pub enum EventType {
ListClients = 26,
HostFolderChanged = 27,
FailedToChangeHostFolder = 28,
ScreenContents = 29,
}
impl EventType {
/// String value of the enum field names used in the ProtoBuf definition.
Expand Down Expand Up @@ -523,6 +526,7 @@ impl EventType {
EventType::ListClients => "ListClients",
EventType::HostFolderChanged => "HostFolderChanged",
EventType::FailedToChangeHostFolder => "FailedToChangeHostFolder",
EventType::ScreenContents => "ScreenContents",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
Expand Down Expand Up @@ -557,6 +561,7 @@ impl EventType {
"ListClients" => Some(Self::ListClients),
"HostFolderChanged" => Some(Self::HostFolderChanged),
"FailedToChangeHostFolder" => Some(Self::FailedToChangeHostFolder),
"ScreenContents" => Some(Self::ScreenContents),
_ => None,
}
}
Expand Down
7 changes: 6 additions & 1 deletion zellij-utils/assets/prost/api.plugin_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub struct PluginCommand {
pub name: i32,
#[prost(
oneof = "plugin_command::Payload",
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91"
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92"
)]
pub payload: ::core::option::Option<plugin_command::Payload>,
}
Expand Down Expand Up @@ -180,6 +180,8 @@ pub mod plugin_command {
SetFloatingPanePinnedPayload(super::SetFloatingPanePinnedPayload),
#[prost(message, tag = "91")]
StackPanesPayload(super::StackPanesPayload),
#[prost(bool, tag = "92")]
DumpScreenPayload(bool),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
Expand Down Expand Up @@ -747,6 +749,7 @@ pub enum CommandName {
ChangeHostFolder = 114,
SetFloatingPanePinned = 115,
StackPanes = 116,
DumpScreen = 117,
}
impl CommandName {
/// String value of the enum field names used in the ProtoBuf definition.
Expand Down Expand Up @@ -874,6 +877,7 @@ impl CommandName {
CommandName::ChangeHostFolder => "ChangeHostFolder",
CommandName::SetFloatingPanePinned => "SetFloatingPanePinned",
CommandName::StackPanes => "StackPanes",
CommandName::DumpScreen => "DumpScreen",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
Expand Down Expand Up @@ -998,6 +1002,7 @@ impl CommandName {
"ChangeHostFolder" => Some(Self::ChangeHostFolder),
"SetFloatingPanePinned" => Some(Self::SetFloatingPanePinned),
"StackPanes" => Some(Self::StackPanes),
"DumpScreen" => Some(Self::DumpScreen),
_ => None,
}
}
Expand Down
3 changes: 3 additions & 0 deletions zellij-utils/assets/prost/api.plugin_permission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum PermissionType {
MessageAndLaunchOtherPlugins = 8,
Reconfigure = 9,
FullHdAccess = 10,
ReadScreen = 11,
}
impl PermissionType {
/// String value of the enum field names used in the ProtoBuf definition.
Expand All @@ -33,6 +34,7 @@ impl PermissionType {
}
PermissionType::Reconfigure => "Reconfigure",
PermissionType::FullHdAccess => "FullHdAccess",
PermissionType::ReadScreen => "ReadScreen",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
Expand All @@ -49,6 +51,7 @@ impl PermissionType {
"MessageAndLaunchOtherPlugins" => Some(Self::MessageAndLaunchOtherPlugins),
"Reconfigure" => Some(Self::Reconfigure),
"FullHdAccess" => Some(Self::FullHdAccess),
"ReadScreen" => Some(Self::ReadScreen),
_ => None,
}
}
Expand Down
6 changes: 6 additions & 0 deletions zellij-utils/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,7 @@ pub enum Event {
ListClients(Vec<ClientInfo>),
HostFolderChanged(PathBuf), // PathBuf -> new host folder
FailedToChangeHostFolder(Option<String>), // String -> the error we got when changing
ScreenContents(String),
}

#[derive(
Expand Down Expand Up @@ -945,6 +946,7 @@ pub enum Permission {
MessageAndLaunchOtherPlugins,
Reconfigure,
FullHdAccess,
ReadScreen,
}

impl PermissionType {
Expand All @@ -967,6 +969,9 @@ impl PermissionType {
},
PermissionType::Reconfigure => "Change Zellij runtime configuration".to_owned(),
PermissionType::FullHdAccess => "Full access to the hard-drive".to_owned(),
PermissionType::ReadScreen => {
"Read contents of the terminal screen and scrollback".to_owned()
},
}
}
}
Expand Down Expand Up @@ -1857,6 +1862,7 @@ pub enum PluginCommand {
ScanHostFolder(PathBuf), // TODO: rename to ScanHostFolder
WatchFilesystem,
DumpSessionLayout,
DumpScreen(bool),
CloseSelf,
NewTabsWithLayoutInfo(LayoutInfo),
Reconfigure(String, bool), // String -> stringified configuration, bool -> save configuration
Expand Down
2 changes: 2 additions & 0 deletions zellij-utils/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ pub enum ScreenContext {
Exit,
ClearScreen,
DumpScreen,
DumpScreenToPlugin,
DumpLayout,
EditScrollback,
ScrollUp,
Expand Down Expand Up @@ -425,6 +426,7 @@ pub enum PluginContext {
PluginSubscribedToEvents,
PermissionRequestResult,
DumpLayout,
DumpScreen,
LogLayoutToHd,
CliPipe,
Message,
Expand Down
2 changes: 2 additions & 0 deletions zellij-utils/src/plugin_api/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ enum EventType {
ListClients = 26;
HostFolderChanged = 27;
FailedToChangeHostFolder = 28;
ScreenContents = 29;
}

message EventNameList {
Expand Down Expand Up @@ -85,6 +86,7 @@ message Event {
ListClientsPayload list_clients_payload = 23;
HostFolderChangedPayload host_folder_changed_payload = 24;
FailedToChangeHostFolderPayload failed_to_change_host_folder_payload = 25;
string ScreenContentsPayload = 26;
}
}

Expand Down
12 changes: 12 additions & 0 deletions zellij-utils/src/plugin_api/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,12 @@ impl TryFrom<ProtobufEvent> for Event {
)),
_ => Err("Malformed payload for the FailedToChangeHostFolder Event"),
},
Some(ProtobufEventType::ScreenContents) => match protobuf_event.payload {
Some(ProtobufEventPayload::ScreenContentsPayload(dump)) => {
Ok(Event::ScreenContents(dump))
},
_ => Err("Malformed payload for the ScreenContents Event"),
},
None => Err("Unknown Protobuf Event"),
}
}
Expand Down Expand Up @@ -713,6 +719,10 @@ impl TryFrom<Event> for ProtobufEvent {
FailedToChangeHostFolderPayload { error_message },
)),
}),
Event::ScreenContents(dump) => Ok(ProtobufEvent {
name: ProtobufEventType::ScreenContents as i32,
payload: Some(event::Payload::ScreenContentsPayload(dump)),
}),
}
}
}
Expand Down Expand Up @@ -1260,6 +1270,7 @@ impl TryFrom<ProtobufEventType> for EventType {
ProtobufEventType::ListClients => EventType::ListClients,
ProtobufEventType::HostFolderChanged => EventType::HostFolderChanged,
ProtobufEventType::FailedToChangeHostFolder => EventType::FailedToChangeHostFolder,
ProtobufEventType::ScreenContents => EventType::ScreenContents,
})
}
}
Expand Down Expand Up @@ -1297,6 +1308,7 @@ impl TryFrom<EventType> for ProtobufEventType {
EventType::ListClients => ProtobufEventType::ListClients,
EventType::HostFolderChanged => ProtobufEventType::HostFolderChanged,
EventType::FailedToChangeHostFolder => ProtobufEventType::FailedToChangeHostFolder,
EventType::ScreenContents => ProtobufEventType::ScreenContents,
})
}
}
Expand Down
2 changes: 2 additions & 0 deletions zellij-utils/src/plugin_api/plugin_command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ enum CommandName {
ChangeHostFolder = 114;
SetFloatingPanePinned = 115;
StackPanes = 116;
DumpScreen = 117;
}

message PluginCommand {
Expand Down Expand Up @@ -216,6 +217,7 @@ message PluginCommand {
ChangeHostFolderPayload change_host_folder_payload = 89;
SetFloatingPanePinnedPayload set_floating_pane_pinned_payload = 90;
StackPanesPayload stack_panes_payload = 91;
bool dump_screen_payload = 92;
}
}

Expand Down
8 changes: 8 additions & 0 deletions zellij-utils/src/plugin_api/plugin_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,10 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
Some(_) => Err("DumpSessionLayout should have no payload, found a payload"),
None => Ok(PluginCommand::DumpSessionLayout),
},
Some(CommandName::DumpScreen) => match protobuf_plugin_command.payload {
Some(Payload::DumpScreenPayload(full)) => Ok(PluginCommand::DumpScreen(full)),
_ => Err("Mismatched payload for DumpScreen"),
},
Some(CommandName::CloseSelf) => match protobuf_plugin_command.payload {
Some(_) => Err("CloseSelf should have no payload, found a payload"),
None => Ok(PluginCommand::CloseSelf),
Expand Down Expand Up @@ -1897,6 +1901,10 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
name: CommandName::DumpSessionLayout as i32,
payload: None,
}),
PluginCommand::DumpScreen(full) => Ok(ProtobufPluginCommand {
name: CommandName::DumpScreen as i32,
payload: Some(Payload::DumpScreenPayload(full)),
}),
PluginCommand::CloseSelf => Ok(ProtobufPluginCommand {
name: CommandName::CloseSelf as i32,
payload: None,
Expand Down
1 change: 1 addition & 0 deletions zellij-utils/src/plugin_api/plugin_permission.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ enum PermissionType {
MessageAndLaunchOtherPlugins = 8;
Reconfigure = 9;
FullHdAccess = 10;
ReadScreen = 11;
}
2 changes: 2 additions & 0 deletions zellij-utils/src/plugin_api/plugin_permission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ impl TryFrom<ProtobufPermissionType> for PermissionType {
},
ProtobufPermissionType::Reconfigure => Ok(PermissionType::Reconfigure),
ProtobufPermissionType::FullHdAccess => Ok(PermissionType::FullHdAccess),
ProtobufPermissionType::ReadScreen => Ok(PermissionType::ReadScreen),
}
}
}
Expand Down Expand Up @@ -53,6 +54,7 @@ impl TryFrom<PermissionType> for ProtobufPermissionType {
},
PermissionType::Reconfigure => Ok(ProtobufPermissionType::Reconfigure),
PermissionType::FullHdAccess => Ok(ProtobufPermissionType::FullHdAccess),
PermissionType::ReadScreen => Ok(ProtobufPermissionType::ReadScreen),
}
}
}