summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-09-18 16:28:06 +0200
committerGitHub <noreply@github.com>2023-09-18 16:28:06 +0200
commite392a66833046a2958dfcc0e1147257e59454c41 (patch)
tree7792e770ec010ff9ceb52c083882502eabee7d11
parent74a3b6363594d53f78c16a05444814d68e3fd76f (diff)
feat(panes): in place run (#2795)
* prototype * fix tests * add to all the things except plugins * add in-place to plugin commands * fix launch-or-focus should_float and in place behavior * various cleanups * style(fmt): rustfmt
-rw-r--r--default-plugins/status-bar/src/second_line.rs2
-rw-r--r--src/main.rs4
-rw-r--r--zellij-client/src/cli_client.rs5
-rw-r--r--zellij-client/src/input_handler.rs10
-rw-r--r--zellij-client/src/lib.rs1
-rw-r--r--zellij-client/src/os_input_output.rs7
-rw-r--r--zellij-client/src/unit/stdin_tests.rs2
-rw-r--r--zellij-server/src/os_input_output.rs1
-rw-r--r--zellij-server/src/panes/floating_panes/mod.rs5
-rw-r--r--zellij-server/src/panes/tiled_panes/mod.rs1
-rw-r--r--zellij-server/src/plugins/mod.rs49
-rw-r--r--zellij-server/src/plugins/unit/plugin_tests.rs134
-rw-r--r--zellij-server/src/plugins/zellij_exports.rs76
-rw-r--r--zellij-server/src/pty.rs110
-rw-r--r--zellij-server/src/route.rs98
-rw-r--r--zellij-server/src/screen.rs252
-rw-r--r--zellij-server/src/tab/mod.rs126
-rw-r--r--zellij-server/src/tab/unit/tab_integration_tests.rs24
-rw-r--r--zellij-server/src/tab/unit/tab_tests.rs3
-rw-r--r--zellij-server/src/unit/screen_tests.rs9
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap4
-rw-r--r--zellij-tile/src/shim.rs27
-rw-r--r--zellij-utils/assets/prost/api.action.rs2
-rw-r--r--zellij-utils/assets/prost/api.plugin_command.rs17
-rw-r--r--zellij-utils/src/cli.rs50
-rw-r--r--zellij-utils/src/data.rs3
-rw-r--r--zellij-utils/src/errors.rs3
-rw-r--r--zellij-utils/src/input/actions.rs20
-rw-r--r--zellij-utils/src/ipc.rs2
-rw-r--r--zellij-utils/src/kdl/mod.rs9
-rw-r--r--zellij-utils/src/plugin_api/action.proto1
-rw-r--r--zellij-utils/src/plugin_api/action.rs23
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto6
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs55
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap1
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap1
39 files changed, 1034 insertions, 112 deletions
diff --git a/default-plugins/status-bar/src/second_line.rs b/default-plugins/status-bar/src/second_line.rs
index d31218fd3..d33ddad8c 100644
--- a/default-plugins/status-bar/src/second_line.rs
+++ b/default-plugins/status-bar/src/second_line.rs
@@ -245,7 +245,7 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<Key>)> {
action_key(&km, &[A::SearchToggleOption(SOpt::WholeWord)])),
]} else if mi.mode == IM::Session { vec![
(s("Detach"), s("Detach"), action_key(&km, &[Action::Detach])),
- (s("Session Manager"), s("Manager"), action_key(&km, &[A::LaunchOrFocusPlugin(Default::default(), true, true), TO_NORMAL])), // not entirely accurate
+ (s("Session Manager"), s("Manager"), action_key(&km, &[A::LaunchOrFocusPlugin(Default::default(), true, true, false), TO_NORMAL])), // not entirely accurate
(s("Select pane"), s("Select"), to_normal_key),
]} else if mi.mode == IM::Tmux { vec![
(s("Move focus"), s("Move"), action_key_group(&km, &[
diff --git a/src/main.rs b/src/main.rs
index f32d76cd8..da059b7fb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -25,6 +25,7 @@ fn main() {
direction,
cwd,
floating,
+ in_place,
name,
close_on_exit,
start_suspended,
@@ -36,6 +37,7 @@ fn main() {
direction,
cwd,
floating,
+ in_place,
name,
close_on_exit,
start_suspended,
@@ -49,6 +51,7 @@ fn main() {
direction,
line_number,
floating,
+ in_place,
cwd,
})) = opts.command
{
@@ -64,6 +67,7 @@ fn main() {
direction,
line_number,
floating,
+ in_place,
cwd,
};
commands::send_action_to_session(command_cli_action, opts.session, config);
diff --git a/zellij-client/src/cli_client.rs b/zellij-client/src/cli_client.rs
index 197efa141..6ebc10aeb 100644
--- a/zellij-client/src/cli_client.rs
+++ b/zellij-client/src/cli_client.rs
@@ -18,8 +18,11 @@ pub fn start_cli_client(os_input: Box<dyn ClientOsApi>, session_name: &str, acti
sock_dir
};
os_input.connect_to_server(&*zellij_ipc_pipe);
+ let pane_id = os_input
+ .env_variable("ZELLIJ_PANE_ID")
+ .and_then(|e| e.trim().parse().ok());
for action in actions {
- let msg = ClientToServerMsg::Action(action, None);
+ let msg = ClientToServerMsg::Action(action, pane_id, None);
os_input.send_to_server(msg);
}
loop {
diff --git a/zellij-client/src/input_handler.rs b/zellij-client/src/input_handler.rs
index 2781d3afb..cf5b3d326 100644
--- a/zellij-client/src/input_handler.rs
+++ b/zellij-client/src/input_handler.rs
@@ -283,13 +283,13 @@ impl InputHandler {
Action::NoOp => {},
Action::Quit => {
self.os_input
- .send_to_server(ClientToServerMsg::Action(action, client_id));
+ .send_to_server(ClientToServerMsg::Action(action, None, client_id));
self.exit(ExitReason::Normal);
should_break = true;
},
Action::Detach => {
self.os_input
- .send_to_server(ClientToServerMsg::Action(action, client_id));
+ .send_to_server(ClientToServerMsg::Action(action, None, client_id));
self.exit(ExitReason::NormalDetached);
should_break = true;
},
@@ -298,7 +298,7 @@ impl InputHandler {
// server later that atomically changes the mode as well
self.mode = mode;
self.os_input
- .send_to_server(ClientToServerMsg::Action(action, None));
+ .send_to_server(ClientToServerMsg::Action(action, None, None));
},
Action::CloseFocus
| Action::ClearScreen
@@ -318,7 +318,7 @@ impl InputHandler {
| Action::MoveFocusOrTab(_) => {
self.command_is_executing.blocking_input_thread();
self.os_input
- .send_to_server(ClientToServerMsg::Action(action, client_id));
+ .send_to_server(ClientToServerMsg::Action(action, None, client_id));
self.command_is_executing
.wait_until_input_thread_is_unblocked();
},
@@ -333,7 +333,7 @@ impl InputHandler {
},
_ => self
.os_input
- .send_to_server(ClientToServerMsg::Action(action, client_id)),
+ .send_to_server(ClientToServerMsg::Action(action, None, client_id)),
}
should_break
diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs
index 6aeb22e5a..a472cd1dc 100644
--- a/zellij-client/src/lib.rs
+++ b/zellij-client/src/lib.rs
@@ -316,6 +316,7 @@ pub fn start_client(
os_api.send_to_server(ClientToServerMsg::Action(
on_force_close.into(),
None,
+ None,
));
}
}),
diff --git a/zellij-client/src/os_input_output.rs b/zellij-client/src/os_input_output.rs
index 212ed2f7d..d6fb3b30a 100644
--- a/zellij-client/src/os_input_output.rs
+++ b/zellij-client/src/os_input_output.rs
@@ -114,6 +114,9 @@ pub trait ClientOsApi: Send + Sync {
fn disable_mouse(&self) -> Result<()>;
// Repeatedly send action, until stdin is readable again
fn stdin_poller(&self) -> StdinPoller;
+ fn env_variable(&self, _name: &str) -> Option<String> {
+ None
+ }
}
impl ClientOsApi for ClientOsInputOutput {
@@ -282,6 +285,10 @@ impl ClientOsApi for ClientOsInputOutput {
fn stdin_poller(&self) -> StdinPoller {
StdinPoller::default()
}
+
+ fn env_variable(&self, name: &str) -> Option<String> {
+ std::env::var(name).ok()
+ }
}
impl Clone for Box<dyn ClientOsApi> {
diff --git a/zellij-client/src/unit/stdin_tests.rs b/zellij-client/src/unit/stdin_tests.rs
index 31c7fe075..3091af50d 100644
--- a/zellij-client/src/unit/stdin_tests.rs
+++ b/zellij-client/src/unit/stdin_tests.rs
@@ -199,7 +199,7 @@ fn extract_actions_sent_to_server(
) -> Vec<Action> {
let events_sent_to_server = events_sent_to_server.lock().unwrap();
events_sent_to_server.iter().fold(vec![], |mut acc, event| {
- if let ClientToServerMsg::Action(action, None) = event {
+ if let ClientToServerMsg::Action(action, None, None) = event {
acc.push(action.clone());
}
acc
diff --git a/zellij-server/src/os_input_output.rs b/zellij-server/src/os_input_output.rs
index f4cbf9b4a..28cb124c8 100644
--- a/zellij-server/src/os_input_output.rs
+++ b/zellij-server/src/os_input_output.rs
@@ -183,6 +183,7 @@ fn handle_openpty(
}
command
.args(&cmd.args)
+ .env("ZELLIJ_PANE_ID", &format!("{}", terminal_id))
.pre_exec(move || -> std::io::Result<()> {
if libc::login_tty(pid_secondary) != 0 {
panic!("failed to set controlling terminal");
diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs
index ed21b010a..61205668e 100644
--- a/zellij-server/src/panes/floating_panes/mod.rs
+++ b/zellij-server/src/panes/floating_panes/mod.rs
@@ -157,6 +157,7 @@ impl FloatingPanes {
// move clients from the previously active pane to the new pane we just inserted
self.move_clients_between_panes(pane_id, with_pane_id);
+ self.set_pane_frames();
removed_pane
}
pub fn remove_pane(&mut self, pane_id: PaneId) -> Option<Box<dyn Pane>> {
@@ -295,7 +296,7 @@ impl FloatingPanes {
pane.render_full_viewport();
}
}
- pub fn set_pane_frames(&mut self, _os_api: &mut Box<dyn ServerOsApi>) -> Result<()> {
+ pub fn set_pane_frames(&mut self) -> Result<()> {
let err_context =
|pane_id: &PaneId| format!("failed to activate frame on pane {pane_id:?}");
@@ -640,7 +641,7 @@ impl FloatingPanes {
current_position.set_geom_override(geom);
}
current_position.set_should_render(true);
- let _ = self.set_pane_frames(os_api);
+ let _ = self.set_pane_frames();
}
}
pub fn move_clients_out_of_pane(&mut self, pane_id: PaneId) {
diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs
index 71a53a330..6477a8af0 100644
--- a/zellij-server/src/panes/tiled_panes/mod.rs
+++ b/zellij-server/src/panes/tiled_panes/mod.rs
@@ -159,6 +159,7 @@ impl TiledPanes {
// move clients from the previously active pane to the new pane we just inserted
self.move_clients_between_panes(pane_id, with_pane_id);
+ self.reapply_pane_frames();
removed_pane
}
pub fn insert_pane(&mut self, pane_id: PaneId, pane: Box<dyn Pane>) {
diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs
index c72356699..deb368c18 100644
--- a/zellij-server/src/plugins/mod.rs
+++ b/zellij-server/src/plugins/mod.rs
@@ -12,6 +12,7 @@ use std::{
};
use wasmer::Store;
+use crate::panes::PaneId;
use crate::screen::ScreenInstruction;
use crate::{pty::PtyInstruction, thread_bus::Bus, ClientId, ServerInstruction};
@@ -38,9 +39,11 @@ pub type PluginId = u32;
pub enum PluginInstruction {
Load(
Option<bool>, // should float
+ bool, // should be opened in place
Option<String>, // pane title
RunPlugin,
- usize, // tab index
+ usize, // tab index
+ Option<PaneId>, // pane id to replace if this is to be opened "in-place"
ClientId,
Size,
),
@@ -156,21 +159,31 @@ pub(crate) fn plugin_thread_main(
let (event, mut err_ctx) = bus.recv().expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Plugin((&event).into()));
match event {
- PluginInstruction::Load(should_float, pane_title, run, tab_index, client_id, size) => {
- match wasm_bridge.load_plugin(&run, tab_index, size, Some(client_id)) {
- Ok(plugin_id) => {
- drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin(
- should_float,
- run,
- pane_title,
- tab_index,
- plugin_id,
- )));
- },
- Err(e) => {
- log::error!("Failed to load plugin: {e}");
- },
- }
+ PluginInstruction::Load(
+ should_float,
+ should_be_open_in_place,
+ pane_title,
+ run,
+ tab_index,
+ pane_id_to_replace,
+ client_id,
+ size,
+ ) => match wasm_bridge.load_plugin(&run, tab_index, size, Some(client_id)) {
+ Ok(plugin_id) => {
+ drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin(
+ should_float,
+ should_be_open_in_place,
+ run,
+ pane_title,
+ tab_index,
+ plugin_id,
+ pane_id_to_replace,
+ Some(client_id),
+ )));
+ },
+ Err(e) => {
+ log::error!("Failed to load plugin: {e}");
+ },
},
PluginInstruction::Update(updates) => {
wasm_bridge.update_plugins(updates)?;
@@ -192,12 +205,16 @@ pub(crate) fn plugin_thread_main(
// the cli who spawned the command and is not an existing client_id
match wasm_bridge.load_plugin(&run, tab_index, size, None) {
Ok(plugin_id) => {
+ let should_be_open_in_place = false;
drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin(
should_float,
+ should_be_open_in_place,
run,
pane_title,
tab_index,
plugin_id,
+ None,
+ None,
)));
},
Err(e) => {
diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs
index 222b14c65..5c0600cac 100644
--- a/zellij-server/src/plugins/unit/plugin_tests.rs
+++ b/zellij-server/src/plugins/unit/plugin_tests.rs
@@ -533,9 +533,11 @@ pub fn load_new_plugin_from_hd() {
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
let _ = plugin_thread_sender.send(PluginInstruction::Load(
plugin_should_float,
+ false,
plugin_title,
run_plugin,
tab_index,
+ None,
client_id,
size,
));
@@ -601,9 +603,11 @@ pub fn plugin_workers() {
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
let _ = plugin_thread_sender.send(PluginInstruction::Load(
plugin_should_float,
+ false,
plugin_title,
run_plugin,
tab_index,
+ None,
client_id,
size,
));
@@ -672,9 +676,11 @@ pub fn plugin_workers_persist_state() {
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
let _ = plugin_thread_sender.send(PluginInstruction::Load(
plugin_should_float,
+ false,
plugin_title,
run_plugin,
tab_index,
+ None,
client_id,
size,
));
@@ -747,9 +753,11 @@ pub fn can_subscribe_to_hd_events() {
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
let _ = plugin_thread_sender.send(PluginInstruction::Load(
plugin_should_float,
+ false,
plugin_title,
run_plugin,
tab_index,
+ None,
client_id,
size,
));
@@ -817,9 +825,11 @@ pub fn switch_to_mode_plugin_command() {
let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id));
let _ = plugin_thread_sender.send(PluginInstruction::Load(
plugin_should_float,
+ false,
plugin_title,
run_plugin,
tab_index,
+ None,
client_id,
size,
));
@@ -885,9 +895,11 @@ pub fn switch_to_mode_plugin_command_permission_denied() {
let _ = plugin_thread_sender.send