feat(plugins): add api to dump the current session layout to a plugin (#3227)
This commit is contained in:
parent
b24dd87b80
commit
2eaa50cc44
10 changed files with 95 additions and 2 deletions
|
|
@ -37,6 +37,7 @@ use zellij_utils::{
|
||||||
},
|
},
|
||||||
ipc::ClientAttributes,
|
ipc::ClientAttributes,
|
||||||
pane_size::Size,
|
pane_size::Size,
|
||||||
|
session_serialization,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type PluginId = u32;
|
pub type PluginId = u32;
|
||||||
|
|
@ -104,6 +105,7 @@ pub enum PluginInstruction {
|
||||||
Option<PathBuf>,
|
Option<PathBuf>,
|
||||||
),
|
),
|
||||||
DumpLayout(SessionLayoutMetadata, ClientId),
|
DumpLayout(SessionLayoutMetadata, ClientId),
|
||||||
|
DumpLayoutToPlugin(SessionLayoutMetadata, PluginId),
|
||||||
LogLayoutToHd(SessionLayoutMetadata),
|
LogLayoutToHd(SessionLayoutMetadata),
|
||||||
CliPipe {
|
CliPipe {
|
||||||
pipe_id: String,
|
pipe_id: String,
|
||||||
|
|
@ -178,6 +180,7 @@ impl From<&PluginInstruction> for PluginContext {
|
||||||
PluginInstruction::UnblockCliPipes { .. } => PluginContext::UnblockCliPipes,
|
PluginInstruction::UnblockCliPipes { .. } => PluginContext::UnblockCliPipes,
|
||||||
PluginInstruction::WatchFilesystem => PluginContext::WatchFilesystem,
|
PluginInstruction::WatchFilesystem => PluginContext::WatchFilesystem,
|
||||||
PluginInstruction::KeybindPipe { .. } => PluginContext::KeybindPipe,
|
PluginInstruction::KeybindPipe { .. } => PluginContext::KeybindPipe,
|
||||||
|
PluginInstruction::DumpLayoutToPlugin(..) => PluginContext::DumpLayoutToPlugin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -484,6 +487,32 @@ pub(crate) fn plugin_thread_main(
|
||||||
client_id,
|
client_id,
|
||||||
)));
|
)));
|
||||||
},
|
},
|
||||||
|
PluginInstruction::DumpLayoutToPlugin(mut session_layout_metadata, plugin_id) => {
|
||||||
|
populate_session_layout_metadata(&mut session_layout_metadata, &wasm_bridge);
|
||||||
|
match session_serialization::serialize_session_layout(
|
||||||
|
session_layout_metadata.into(),
|
||||||
|
) {
|
||||||
|
Ok((layout, _pane_contents)) => {
|
||||||
|
let updates = vec![(
|
||||||
|
Some(plugin_id),
|
||||||
|
None,
|
||||||
|
Event::CustomMessage("session_layout".to_owned(), layout),
|
||||||
|
)];
|
||||||
|
wasm_bridge.update_plugins(updates, shutdown_send.clone())?;
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
let updates = vec![(
|
||||||
|
Some(plugin_id),
|
||||||
|
None,
|
||||||
|
Event::CustomMessage(
|
||||||
|
"session_layout_error".to_owned(),
|
||||||
|
format!("{}", e),
|
||||||
|
),
|
||||||
|
)];
|
||||||
|
wasm_bridge.update_plugins(updates, shutdown_send.clone())?;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
PluginInstruction::LogLayoutToHd(mut session_layout_metadata) => {
|
PluginInstruction::LogLayoutToHd(mut session_layout_metadata) => {
|
||||||
populate_session_layout_metadata(&mut session_layout_metadata, &wasm_bridge);
|
populate_session_layout_metadata(&mut session_layout_metadata, &wasm_bridge);
|
||||||
drop(
|
drop(
|
||||||
|
|
|
||||||
|
|
@ -263,6 +263,7 @@ fn host_run_plugin_command(env: FunctionEnvMut<ForeignFunctionEnv>) {
|
||||||
scan_host_folder(env, folder_to_scan)
|
scan_host_folder(env, folder_to_scan)
|
||||||
},
|
},
|
||||||
PluginCommand::WatchFilesystem => watch_filesystem(env),
|
PluginCommand::WatchFilesystem => watch_filesystem(env),
|
||||||
|
PluginCommand::DumpSessionLayout => dump_session_layout(env),
|
||||||
},
|
},
|
||||||
(PermissionStatus::Denied, permission) => {
|
(PermissionStatus::Denied, permission) => {
|
||||||
log::error!(
|
log::error!(
|
||||||
|
|
@ -1340,6 +1341,14 @@ fn watch_filesystem(env: &ForeignFunctionEnv) {
|
||||||
.map(|sender| sender.send(PluginInstruction::WatchFilesystem));
|
.map(|sender| sender.send(PluginInstruction::WatchFilesystem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dump_session_layout(env: &ForeignFunctionEnv) {
|
||||||
|
let _ = env.plugin_env.senders.to_screen.as_ref().map(|sender| {
|
||||||
|
sender.send(ScreenInstruction::DumpLayoutToPlugin(
|
||||||
|
env.plugin_env.plugin_id,
|
||||||
|
))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn scan_host_folder(env: &ForeignFunctionEnv, folder_to_scan: PathBuf) {
|
fn scan_host_folder(env: &ForeignFunctionEnv, folder_to_scan: PathBuf) {
|
||||||
if !folder_to_scan.starts_with("/host") {
|
if !folder_to_scan.starts_with("/host") {
|
||||||
log::error!(
|
log::error!(
|
||||||
|
|
@ -1542,6 +1551,7 @@ fn check_command_permission(
|
||||||
| PluginCommand::BlockCliPipeInput(..)
|
| PluginCommand::BlockCliPipeInput(..)
|
||||||
| PluginCommand::CliPipeOutput(..) => PermissionType::ReadCliPipes,
|
| PluginCommand::CliPipeOutput(..) => PermissionType::ReadCliPipes,
|
||||||
PluginCommand::MessageToPlugin(..) => PermissionType::MessageAndLaunchOtherPlugins,
|
PluginCommand::MessageToPlugin(..) => PermissionType::MessageAndLaunchOtherPlugins,
|
||||||
|
PluginCommand::DumpSessionLayout => PermissionType::ReadApplicationState,
|
||||||
_ => return (PermissionStatus::Granted, None),
|
_ => return (PermissionStatus::Granted, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::background_jobs::BackgroundJob;
|
||||||
use crate::terminal_bytes::TerminalBytes;
|
use crate::terminal_bytes::TerminalBytes;
|
||||||
use crate::{
|
use crate::{
|
||||||
panes::PaneId,
|
panes::PaneId,
|
||||||
plugins::PluginInstruction,
|
plugins::{PluginId, PluginInstruction},
|
||||||
screen::ScreenInstruction,
|
screen::ScreenInstruction,
|
||||||
session_layout_metadata::SessionLayoutMetadata,
|
session_layout_metadata::SessionLayoutMetadata,
|
||||||
thread_bus::{Bus, ThreadSenders},
|
thread_bus::{Bus, ThreadSenders},
|
||||||
|
|
@ -77,6 +77,7 @@ pub enum PtyInstruction {
|
||||||
ClientTabIndexOrPaneId,
|
ClientTabIndexOrPaneId,
|
||||||
), // String is an optional pane name
|
), // String is an optional pane name
|
||||||
DumpLayout(SessionLayoutMetadata, ClientId),
|
DumpLayout(SessionLayoutMetadata, ClientId),
|
||||||
|
DumpLayoutToPlugin(SessionLayoutMetadata, PluginId),
|
||||||
LogLayoutToHd(SessionLayoutMetadata),
|
LogLayoutToHd(SessionLayoutMetadata),
|
||||||
FillPluginCwd(
|
FillPluginCwd(
|
||||||
Option<bool>, // should float
|
Option<bool>, // should float
|
||||||
|
|
@ -110,6 +111,7 @@ impl From<&PtyInstruction> for PtyContext {
|
||||||
PtyInstruction::DropToShellInPane { .. } => PtyContext::DropToShellInPane,
|
PtyInstruction::DropToShellInPane { .. } => PtyContext::DropToShellInPane,
|
||||||
PtyInstruction::SpawnInPlaceTerminal(..) => PtyContext::SpawnInPlaceTerminal,
|
PtyInstruction::SpawnInPlaceTerminal(..) => PtyContext::SpawnInPlaceTerminal,
|
||||||
PtyInstruction::DumpLayout(..) => PtyContext::DumpLayout,
|
PtyInstruction::DumpLayout(..) => PtyContext::DumpLayout,
|
||||||
|
PtyInstruction::DumpLayoutToPlugin(..) => PtyContext::DumpLayoutToPlugin,
|
||||||
PtyInstruction::LogLayoutToHd(..) => PtyContext::LogLayoutToHd,
|
PtyInstruction::LogLayoutToHd(..) => PtyContext::LogLayoutToHd,
|
||||||
PtyInstruction::FillPluginCwd(..) => PtyContext::FillPluginCwd,
|
PtyInstruction::FillPluginCwd(..) => PtyContext::FillPluginCwd,
|
||||||
PtyInstruction::Exit => PtyContext::Exit,
|
PtyInstruction::Exit => PtyContext::Exit,
|
||||||
|
|
@ -630,6 +632,18 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
PtyInstruction::DumpLayoutToPlugin(mut session_layout_metadata, plugin_id) => {
|
||||||
|
let err_context = || format!("Failed to dump layout");
|
||||||
|
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
||||||
|
pty.bus
|
||||||
|
.senders
|
||||||
|
.send_to_plugin(PluginInstruction::DumpLayoutToPlugin(
|
||||||
|
session_layout_metadata,
|
||||||
|
plugin_id,
|
||||||
|
))
|
||||||
|
.with_context(err_context)
|
||||||
|
.non_fatal();
|
||||||
|
},
|
||||||
PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => {
|
PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => {
|
||||||
let err_context = || format!("Failed to dump layout");
|
let err_context = || format!("Failed to dump layout");
|
||||||
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ use crate::{
|
||||||
output::Output,
|
output::Output,
|
||||||
panes::sixel::SixelImageStore,
|
panes::sixel::SixelImageStore,
|
||||||
panes::PaneId,
|
panes::PaneId,
|
||||||
plugins::{PluginInstruction, PluginRenderAsset},
|
plugins::{PluginId, PluginInstruction, PluginRenderAsset},
|
||||||
pty::{ClientTabIndexOrPaneId, PtyInstruction, VteBytes},
|
pty::{ClientTabIndexOrPaneId, PtyInstruction, VteBytes},
|
||||||
tab::Tab,
|
tab::Tab,
|
||||||
thread_bus::Bus,
|
thread_bus::Bus,
|
||||||
|
|
@ -180,6 +180,7 @@ pub enum ScreenInstruction {
|
||||||
DumpScreen(String, ClientId, bool),
|
DumpScreen(String, ClientId, bool),
|
||||||
DumpLayout(Option<PathBuf>, ClientId), // PathBuf is the default configured
|
DumpLayout(Option<PathBuf>, ClientId), // PathBuf is the default configured
|
||||||
// shell
|
// shell
|
||||||
|
DumpLayoutToPlugin(PluginId),
|
||||||
EditScrollback(ClientId),
|
EditScrollback(ClientId),
|
||||||
ScrollUp(ClientId),
|
ScrollUp(ClientId),
|
||||||
ScrollUpAt(Position, ClientId),
|
ScrollUpAt(Position, ClientId),
|
||||||
|
|
@ -421,6 +422,7 @@ impl From<&ScreenInstruction> for ScreenContext {
|
||||||
ScreenInstruction::ClearScreen(..) => ScreenContext::ClearScreen,
|
ScreenInstruction::ClearScreen(..) => ScreenContext::ClearScreen,
|
||||||
ScreenInstruction::DumpScreen(..) => ScreenContext::DumpScreen,
|
ScreenInstruction::DumpScreen(..) => ScreenContext::DumpScreen,
|
||||||
ScreenInstruction::DumpLayout(..) => ScreenContext::DumpLayout,
|
ScreenInstruction::DumpLayout(..) => ScreenContext::DumpLayout,
|
||||||
|
ScreenInstruction::DumpLayoutToPlugin(..) => ScreenContext::DumpLayoutToPlugin,
|
||||||
ScreenInstruction::EditScrollback(..) => ScreenContext::EditScrollback,
|
ScreenInstruction::EditScrollback(..) => ScreenContext::EditScrollback,
|
||||||
ScreenInstruction::ScrollUp(..) => ScreenContext::ScrollUp,
|
ScreenInstruction::ScrollUp(..) => ScreenContext::ScrollUp,
|
||||||
ScreenInstruction::ScrollDown(..) => ScreenContext::ScrollDown,
|
ScreenInstruction::ScrollDown(..) => ScreenContext::ScrollDown,
|
||||||
|
|
@ -2630,6 +2632,20 @@ pub(crate) fn screen_thread_main(
|
||||||
))
|
))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
},
|
},
|
||||||
|
ScreenInstruction::DumpLayoutToPlugin(plugin_id) => {
|
||||||
|
let err_context = || format!("Failed to dump layout");
|
||||||
|
let session_layout_metadata =
|
||||||
|
screen.get_layout_metadata(screen.default_shell.clone());
|
||||||
|
screen
|
||||||
|
.bus
|
||||||
|
.senders
|
||||||
|
.send_to_pty(PtyInstruction::DumpLayoutToPlugin(
|
||||||
|
session_layout_metadata,
|
||||||
|
plugin_id,
|
||||||
|
))
|
||||||
|
.with_context(err_context)
|
||||||
|
.non_fatal();
|
||||||
|
},
|
||||||
ScreenInstruction::EditScrollback(client_id) => {
|
ScreenInstruction::EditScrollback(client_id) => {
|
||||||
active_tab_and_connected_client_id!(
|
active_tab_and_connected_client_id!(
|
||||||
screen,
|
screen,
|
||||||
|
|
|
||||||
|
|
@ -784,6 +784,14 @@ pub fn watch_filesystem() {
|
||||||
unsafe { host_run_plugin_command() };
|
unsafe { host_run_plugin_command() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the serialized session layout in KDL format as a CustomMessage Event
|
||||||
|
pub fn dump_session_layout() {
|
||||||
|
let plugin_command = PluginCommand::DumpSessionLayout;
|
||||||
|
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||||
|
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||||
|
unsafe { host_run_plugin_command() };
|
||||||
|
}
|
||||||
|
|
||||||
// Utility Functions
|
// Utility Functions
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|
|
||||||
|
|
@ -420,6 +420,7 @@ pub enum CommandName {
|
||||||
KillSessions = 81,
|
KillSessions = 81,
|
||||||
ScanHostFolder = 82,
|
ScanHostFolder = 82,
|
||||||
WatchFilesystem = 83,
|
WatchFilesystem = 83,
|
||||||
|
DumpSessionLayout = 84,
|
||||||
}
|
}
|
||||||
impl CommandName {
|
impl CommandName {
|
||||||
/// String value of the enum field names used in the ProtoBuf definition.
|
/// String value of the enum field names used in the ProtoBuf definition.
|
||||||
|
|
@ -512,6 +513,7 @@ impl CommandName {
|
||||||
CommandName::KillSessions => "KillSessions",
|
CommandName::KillSessions => "KillSessions",
|
||||||
CommandName::ScanHostFolder => "ScanHostFolder",
|
CommandName::ScanHostFolder => "ScanHostFolder",
|
||||||
CommandName::WatchFilesystem => "WatchFilesystem",
|
CommandName::WatchFilesystem => "WatchFilesystem",
|
||||||
|
CommandName::DumpSessionLayout => "DumpSessionLayout",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||||
|
|
@ -601,6 +603,7 @@ impl CommandName {
|
||||||
"KillSessions" => Some(Self::KillSessions),
|
"KillSessions" => Some(Self::KillSessions),
|
||||||
"ScanHostFolder" => Some(Self::ScanHostFolder),
|
"ScanHostFolder" => Some(Self::ScanHostFolder),
|
||||||
"WatchFilesystem" => Some(Self::WatchFilesystem),
|
"WatchFilesystem" => Some(Self::WatchFilesystem),
|
||||||
|
"DumpSessionLayout" => Some(Self::DumpSessionLayout),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1378,4 +1378,5 @@ pub enum PluginCommand {
|
||||||
KillSessions(Vec<String>), // one or more session names
|
KillSessions(Vec<String>), // one or more session names
|
||||||
ScanHostFolder(PathBuf), // TODO: rename to ScanHostFolder
|
ScanHostFolder(PathBuf), // TODO: rename to ScanHostFolder
|
||||||
WatchFilesystem,
|
WatchFilesystem,
|
||||||
|
DumpSessionLayout,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -351,6 +351,7 @@ pub enum ScreenContext {
|
||||||
NewInPlacePluginPane,
|
NewInPlacePluginPane,
|
||||||
DumpLayoutToHd,
|
DumpLayoutToHd,
|
||||||
RenameSession,
|
RenameSession,
|
||||||
|
DumpLayoutToPlugin,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stack call representations corresponding to the different types of [`PtyInstruction`]s.
|
/// Stack call representations corresponding to the different types of [`PtyInstruction`]s.
|
||||||
|
|
@ -371,6 +372,7 @@ pub enum PtyContext {
|
||||||
DumpLayout,
|
DumpLayout,
|
||||||
LogLayoutToHd,
|
LogLayoutToHd,
|
||||||
FillPluginCwd,
|
FillPluginCwd,
|
||||||
|
DumpLayoutToPlugin,
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -402,6 +404,7 @@ pub enum PluginContext {
|
||||||
UnblockCliPipes,
|
UnblockCliPipes,
|
||||||
WatchFilesystem,
|
WatchFilesystem,
|
||||||
KeybindPipe,
|
KeybindPipe,
|
||||||
|
DumpLayoutToPlugin,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stack call representations corresponding to the different types of [`ClientInstruction`]s.
|
/// Stack call representations corresponding to the different types of [`ClientInstruction`]s.
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ enum CommandName {
|
||||||
KillSessions = 81;
|
KillSessions = 81;
|
||||||
ScanHostFolder = 82;
|
ScanHostFolder = 82;
|
||||||
WatchFilesystem = 83;
|
WatchFilesystem = 83;
|
||||||
|
DumpSessionLayout = 84;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PluginCommand {
|
message PluginCommand {
|
||||||
|
|
|
||||||
|
|
@ -867,6 +867,10 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
||||||
Some(_) => Err("WatchFilesystem should have no payload, found a payload"),
|
Some(_) => Err("WatchFilesystem should have no payload, found a payload"),
|
||||||
None => Ok(PluginCommand::WatchFilesystem),
|
None => Ok(PluginCommand::WatchFilesystem),
|
||||||
},
|
},
|
||||||
|
Some(CommandName::DumpSessionLayout) => match protobuf_plugin_command.payload {
|
||||||
|
Some(_) => Err("DumpSessionLayout should have no payload, found a payload"),
|
||||||
|
None => Ok(PluginCommand::DumpSessionLayout),
|
||||||
|
},
|
||||||
None => Err("Unrecognized plugin command"),
|
None => Err("Unrecognized plugin command"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1381,6 +1385,10 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
||||||
name: CommandName::WatchFilesystem as i32,
|
name: CommandName::WatchFilesystem as i32,
|
||||||
payload: None,
|
payload: None,
|
||||||
}),
|
}),
|
||||||
|
PluginCommand::DumpSessionLayout => Ok(ProtobufPluginCommand {
|
||||||
|
name: CommandName::DumpSessionLayout as i32,
|
||||||
|
payload: None,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue