feat(plugins): command pane re-run event (#3553)

This commit is contained in:
Aram Drevekenin 2024-08-14 16:47:46 +02:00 committed by GitHub
parent affbd9237e
commit a3ad621dc7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 92 additions and 4 deletions

View File

@ -1332,6 +1332,7 @@ fn check_event_permission(
| Event::PaneClosed(..)
| Event::EditPaneOpened(..)
| Event::EditPaneExited(..)
| Event::CommandPaneReRun(..)
| Event::InputReceived => PermissionType::ReadApplicationState,
_ => return (PermissionStatus::Granted, None),
};

View File

@ -10,11 +10,15 @@ use crate::{
};
use async_std::task::{self, JoinHandle};
use std::sync::Arc;
use std::{collections::HashMap, os::unix::io::RawFd, path::PathBuf};
use std::{
collections::{BTreeMap, HashMap},
os::unix::io::RawFd,
path::PathBuf,
};
use zellij_utils::nix::unistd::Pid;
use zellij_utils::{
async_std,
data::{Event, FloatingPaneCoordinates},
data::{Event, FloatingPaneCoordinates, OriginatingPlugin},
errors::prelude::*,
errors::{ContextType, PtyContext},
input::{
@ -128,6 +132,7 @@ pub(crate) struct Pty {
pub active_panes: HashMap<ClientId, PaneId>,
pub bus: Bus<PtyInstruction>,
pub id_to_child_pid: HashMap<u32, RawFd>, // terminal_id => child raw fd
originating_plugins: HashMap<u32, OriginatingPlugin>,
debug_to_file: bool,
task_handles: HashMap<u32, JoinHandle<()>>, // terminal_id to join-handle
default_editor: Option<PathBuf>,
@ -189,6 +194,8 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
if let Some(originating_plugin) =
run_command.and_then(|r| r.originating_plugin)
{
pty.originating_plugins
.insert(pid, originating_plugin.clone());
let update_event =
Event::CommandPaneOpened(pid, originating_plugin.context.clone());
pty.bus
@ -777,6 +784,7 @@ impl Pty {
debug_to_file,
task_handles: HashMap::new(),
default_editor,
originating_plugins: HashMap::new(),
}
}
pub fn get_default_terminal(
@ -1348,19 +1356,37 @@ impl Pty {
pub fn rerun_command_in_pane(
&mut self,
pane_id: PaneId,
run_command: RunCommand,
mut run_command: RunCommand,
) -> Result<()> {
let err_context = || format!("failed to rerun command in pane {:?}", pane_id);
match pane_id {
PaneId::Terminal(id) => {
if let Some(originating_plugins) = self.originating_plugins.get(&id) {
run_command.originating_plugin = Some(originating_plugins.clone());
}
let _ = self.task_handles.remove(&id); // if all is well, this shouldn't be here
let _ = self.id_to_child_pid.remove(&id); // if all is wlel, this shouldn't be here
let hold_on_close = run_command.hold_on_close;
let originating_plugin = Arc::new(run_command.originating_plugin.clone());
let quit_cb = Box::new({
let senders = self.bus.senders.clone();
move |pane_id, exit_status, command| {
if let PaneId::Terminal(pane_id) = pane_id {
if let Some(originating_plugin) = originating_plugin.as_ref() {
let update_event = Event::CommandPaneExited(
pane_id,
exit_status,
originating_plugin.context.clone(),
);
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
Some(originating_plugin.plugin_id),
Some(originating_plugin.client_id),
update_event,
)]));
}
}
if hold_on_close {
let _ = senders.send_to_screen(ScreenInstruction::HoldPane(
pane_id,
@ -1407,6 +1433,16 @@ impl Pty {
self.task_handles.insert(id, terminal_bytes);
self.id_to_child_pid.insert(id, child_fd);
if let Some(originating_plugin) = self.originating_plugins.get(&id) {
self.bus
.senders
.send_to_plugin(PluginInstruction::Update(vec![(
Some(originating_plugin.plugin_id),
Some(originating_plugin.client_id),
Event::CommandPaneReRun(id, originating_plugin.context.clone()),
)]))
.with_context(err_context)?;
}
Ok(())
},
_ => Err(anyhow!("cannot respawn plugin panes")).with_context(err_context),

View File

@ -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"
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21"
)]
pub payload: ::core::option::Option<event::Payload>,
}
@ -58,10 +58,20 @@ pub mod event {
EditPaneOpenedPayload(super::EditPaneOpenedPayload),
#[prost(message, tag = "20")]
EditPaneExitedPayload(super::EditPaneExitedPayload),
#[prost(message, tag = "21")]
CommandPaneRerunPayload(super::CommandPaneReRunPayload),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct CommandPaneReRunPayload {
#[prost(uint32, tag = "1")]
pub terminal_pane_id: u32,
#[prost(message, repeated, tag = "3")]
pub context: ::prost::alloc::vec::Vec<ContextItem>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PaneClosedPayload {
#[prost(message, optional, tag = "1")]
pub pane_id: ::core::option::Option<PaneId>,
@ -415,6 +425,7 @@ pub enum EventType {
PaneClosed = 21,
EditPaneOpened = 22,
EditPaneExited = 23,
CommandPaneReRun = 24,
}
impl EventType {
/// String value of the enum field names used in the ProtoBuf definition.
@ -447,6 +458,7 @@ impl EventType {
EventType::PaneClosed => "PaneClosed",
EventType::EditPaneOpened => "EditPaneOpened",
EventType::EditPaneExited => "EditPaneExited",
EventType::CommandPaneReRun => "CommandPaneReRun",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@ -476,6 +488,7 @@ impl EventType {
"PaneClosed" => Some(Self::PaneClosed),
"EditPaneOpened" => Some(Self::EditPaneOpened),
"EditPaneExited" => Some(Self::EditPaneExited),
"CommandPaneReRun" => Some(Self::CommandPaneReRun),
_ => None,
}
}

View File

@ -919,6 +919,7 @@ pub enum Event {
PaneClosed(PaneId),
EditPaneOpened(u32, Context), // u32 - terminal_pane_id
EditPaneExited(u32, Option<i32>, Context), // u32 - terminal_pane_id, Option<i32> - exit code
CommandPaneReRun(u32, Context), // u32 - terminal_pane_id, Option<i32> -
}
#[derive(

View File

@ -47,6 +47,7 @@ enum EventType {
PaneClosed = 21;
EditPaneOpened = 22;
EditPaneExited = 23;
CommandPaneReRun = 24;
}
message EventNameList {
@ -75,9 +76,15 @@ message Event {
PaneClosedPayload pane_closed_payload = 18;
EditPaneOpenedPayload edit_pane_opened_payload = 19;
EditPaneExitedPayload edit_pane_exited_payload = 20;
CommandPaneReRunPayload command_pane_rerun_payload = 21;
}
}
message CommandPaneReRunPayload {
uint32 terminal_pane_id = 1;
repeated ContextItem context = 3;
}
message PaneClosedPayload {
PaneId pane_id = 1;
}

View File

@ -299,6 +299,19 @@ impl TryFrom<ProtobufEvent> for Event {
},
_ => Err("Malformed payload for the EditPaneExited Event"),
},
Some(ProtobufEventType::CommandPaneReRun) => match protobuf_event.payload {
Some(ProtobufEventPayload::CommandPaneRerunPayload(command_pane_rerun_payload)) => {
Ok(Event::CommandPaneReRun(
command_pane_rerun_payload.terminal_pane_id,
command_pane_rerun_payload
.context
.into_iter()
.map(|c_i| (c_i.name, c_i.value))
.collect(),
))
},
_ => Err("Malformed payload for the CommandPaneReRun Event"),
},
None => Err("Unknown Protobuf Event"),
}
}
@ -592,6 +605,21 @@ impl TryFrom<Event> for ProtobufEvent {
)),
})
},
Event::CommandPaneReRun(terminal_pane_id, context) => {
let command_pane_rerun_payload = CommandPaneReRunPayload {
terminal_pane_id,
context: context
.into_iter()
.map(|(name, value)| ContextItem { name, value })
.collect(),
};
Ok(ProtobufEvent {
name: ProtobufEventType::CommandPaneReRun as i32,
payload: Some(event::Payload::CommandPaneRerunPayload(
command_pane_rerun_payload,
)),
})
},
}
}
}
@ -1100,6 +1128,7 @@ impl TryFrom<ProtobufEventType> for EventType {
ProtobufEventType::PaneClosed => EventType::PaneClosed,
ProtobufEventType::EditPaneOpened => EventType::EditPaneOpened,
ProtobufEventType::EditPaneExited => EventType::EditPaneExited,
ProtobufEventType::CommandPaneReRun => EventType::CommandPaneReRun,
})
}
}
@ -1132,6 +1161,7 @@ impl TryFrom<EventType> for ProtobufEventType {
EventType::PaneClosed => ProtobufEventType::PaneClosed,
EventType::EditPaneOpened => ProtobufEventType::EditPaneOpened,
EventType::EditPaneExited => ProtobufEventType::EditPaneExited,
EventType::CommandPaneReRun => ProtobufEventType::CommandPaneReRun,
})
}
}