diff options
author | Aram Drevekenin <aram@poor.dev> | 2023-09-18 16:28:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-18 16:28:06 +0200 |
commit | e392a66833046a2958dfcc0e1147257e59454c41 (patch) | |
tree | 7792e770ec010ff9ceb52c083882502eabee7d11 | |
parent | 74a3b6363594d53f78c16a05444814d68e3fd76f (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
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 |