diff options
author | Aram Drevekenin <aram@poor.dev> | 2024-02-29 16:26:25 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-29 16:26:25 +0100 |
commit | 896b09aa6f9190b4dc838314b028b63e0f2461b7 (patch) | |
tree | 80aeda55e00e51dfc3d0fd8b6b4f6e6bbf493efd | |
parent | d5bedd0e83dfa531e922f89f9792d20384eb2dc3 (diff) |
feat(plugins): allow specifying the cwd when switching sessions (#3172)
* feat(plugins): allow specifying the cwd when switching sessions
* style(fmt): rustfmt
14 files changed, 160 insertions, 5 deletions
diff --git a/default-plugins/fixture-plugin-for-tests/src/main.rs b/default-plugins/fixture-plugin-for-tests/src/main.rs index 0da45a2f4..cd4fb45a1 100644 --- a/default-plugins/fixture-plugin-for-tests/src/main.rs +++ b/default-plugins/fixture-plugin-for-tests/src/main.rs @@ -299,12 +299,20 @@ impl ZellijPlugin for State { switch_session_with_layout( Some("my_other_new_session"), LayoutInfo::BuiltIn("compact".to_owned()), + None, ); }, Key::Ctrl('8') => { let mut file = std::fs::File::create("/host/hi-from-plugin.txt").unwrap(); file.write_all(b"Hi there!").unwrap(); }, + Key::Ctrl('9') => { + switch_session_with_layout( + Some("my_other_new_session_with_cwd"), + LayoutInfo::BuiltIn("compact".to_owned()), + Some(std::path::PathBuf::from("/tmp")), + ); + }, _ => {}, }, Event::CustomMessage(message, payload) => { diff --git a/default-plugins/session-manager/src/new_session_info.rs b/default-plugins/session-manager/src/new_session_info.rs index 6a2456f11..294f4fbc8 100644 --- a/default-plugins/session-manager/src/new_session_info.rs +++ b/default-plugins/session-manager/src/new_session_info.rs @@ -104,7 +104,7 @@ impl NewSessionInfo { if new_session_name != current_session_name.as_ref().map(|s| s.as_str()) { match new_session_layout { Some(new_session_layout) => { - switch_session_with_layout(new_session_name, new_session_layout) + switch_session_with_layout(new_session_name, new_session_layout, None) }, None => { switch_session(new_session_name); diff --git a/src/commands.rs b/src/commands.rs index 52dff211b..cde96b127 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -450,6 +450,9 @@ pub(crate) fn start_client(opts: CliArgs) { // not want it to mix with the config of this session let (new_layout, new_layout_config) = new_session_layout; layout = new_layout; + if let Some(cwd) = reconnect_to_session.cwd.as_ref() { + layout.add_cwd_to_layout(cwd); + } let mut new_config = config_without_layout.clone(); let _ = new_config.merge(new_layout_config.clone()); config = new_config; diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 8fa262474..65a3799ea 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -6319,6 +6319,87 @@ pub fn switch_session_with_layout_plugin_command() { #[test] #[ignore] +pub fn switch_session_with_layout_and_cwd_plugin_command() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, server_receiver, screen_receiver, teardown) = + create_plugin_thread_with_server_receiver(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + let received_server_instruction = Arc::new(Mutex::new(vec![])); + let server_thread = log_actions_in_thread!( + received_server_instruction, + ServerInstruction::SwitchSession, + server_receiver, + 1 + ); + + 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, + None, + false, + )); + std::thread::sleep(std::time::Duration::from_millis(500)); + + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(Key::Ctrl('9')), // this triggers the enent in the fixture plugin + )])); + std::thread::sleep(std::time::Duration::from_millis(500)); + teardown(); + server_thread.join().unwrap(); // this might take a while if the cache is cold + let switch_session_event = received_server_instruction + .lock() + .unwrap() + .iter() + .rev() + .find_map(|i| { + if let ServerInstruction::SwitchSession(..) = i { + Some(i.clone()) + } else { + None + } + }) + .clone(); + assert_snapshot!(format!("{:#?}", switch_session_event)); +} + +#[test] +#[ignore] pub fn disconnect_other_clients_plugins_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap index f254f0398..db02121d7 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 6051 +assertion_line: 6236 expression: "format!(\"{:#?}\", switch_session_event)" --- Some( @@ -12,6 +12,7 @@ Some( tab_position: None, pane_id: None, layout: None, + cwd: None, }, 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_and_cwd_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_and_cwd_plugin_command.snap new file mode 100644 index 000000000..16c19ce57 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_and_cwd_plugin_command.snap @@ -0,0 +1,25 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +assertion_line: 6398 +expression: "format!(\"{:#?}\", switch_session_event)" +--- +Some( + SwitchSession( + ConnectToSession { + name: Some( + "my_other_new_session_with_cwd", + ), + tab_position: None, + pane_id: None, + layout: Some( + BuiltIn( + "compact", + ), + ), + cwd: Some( + "/tmp", + ), + }, + 1, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap index 46f6819a5..1f2ff843f 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__switch_session_with_layout_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 6131 +assertion_line: 6317 expression: "format!(\"{:#?}\", switch_session_event)" --- Some( @@ -16,6 +16,7 @@ Some( "compact", ), ), + cwd: None, }, 1, ), diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 533d85f2f..2c95de42f 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -229,6 +229,7 @@ fn host_run_plugin_command(env: FunctionEnvMut<ForeignFunctionEnv>) { connect_to_session.tab_position, connect_to_session.pane_id, connect_to_session.layout, + connect_to_session.cwd, )?, PluginCommand::DeleteDeadSession(session_name) => { delete_dead_session(session_name)? @@ -926,6 +927,7 @@ fn switch_session( tab_position: Option<usize>, pane_id: Option<(u32, bool)>, layout: Option<LayoutInfo>, + cwd: Option<PathBuf>, ) -> Result<()> { // pane_id is (id, is_plugin) let err_context = || format!("Failed to switch session"); @@ -936,6 +938,7 @@ fn switch_session( tab_position, pane_id, layout, + cwd, }; env.plugin_env .senders diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index db3e84e39..064a53d85 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -660,10 +660,11 @@ pub fn switch_session(name: Option<&str>) { } /// Switch to a session with the given name, create one if no name is given -pub fn switch_session_with_layout(name: Option<&str>, layout: LayoutInfo) { +pub fn switch_session_with_layout(name: Option<&str>, layout: LayoutInfo, cwd: Option<PathBuf>) { let plugin_command = PluginCommand::SwitchSession(ConnectToSession { name: name.map(|n| n.to_string()), layout: Some(layout), + cwd, ..Default::default() }); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs index 1ed8b3d32..44110ac83 100644 --- a/zellij-utils/assets/prost/api.plugin_command.rs +++ b/zellij-utils/assets/prost/api.plugin_command.rs @@ -183,6 +183,8 @@ pub struct SwitchSessionPayload { pub pane_id_is_plugin: ::core::option::Option<bool>, #[prost(message, optional, tag = "5")] pub layout: ::core::option::Option<super::event::LayoutInfo>, + #[prost(string, optional, tag = "6")] + pub cwd: ::core::option::Option<::prost::alloc::string::String>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index 6e0dce94f..63ccccced 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -1095,6 +1095,7 @@ pub struct ConnectToSession { pub tab_position: Option<usize>, pub pane_id: Option<(u32, bool)>, // (id, is_plugin) pub layout: Option<LayoutInfo>, + pub cwd: Option<PathBuf>, } impl ConnectToSession { diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index 82da8cbf0..74242cff8 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -211,6 +211,16 @@ impl RunPluginOrAlias { } self } + pub fn add_initial_cwd(&mut self, initial_cwd: &PathBuf) { + match self { + RunPluginOrAlias::RunPlugin(ref mut run_plugin) => { + run_plugin.initial_cwd = Some(initial_cwd.clone()); + }, + RunPluginOrAlias::Alias(ref mut alias) => { + alias.initial_cwd = Some(initial_cwd.clone()); + }, + } + } } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -305,7 +315,9 @@ impl Run { Run::Cwd(path) => { *path = cwd.join(&path); }, - _ => {}, // plugins aren't yet supported + Run::Plugin(run_plugin_or_alias) => { + run_plugin_or_alias.add_initial_cwd(&cwd); + }, } } pub fn add_args(&mut self, args: Option<Vec<String>>) { @@ -1365,6 +1377,20 @@ impl Layout { } } } + pub fn add_cwd_to_layout(&mut self, cwd: &PathBuf) { + for (_, tiled_pane_layout, floating_panes) in self.tabs.iter_mut() { + tiled_pane_layout.add_cwd_to_layout(&cwd); + for floating_pane in floating_panes { + floating_pane.add_cwd_to_layout(&cwd); + } + } + if let Some((tiled_pane_layout, floating_panes)) = self.template.as_mut() { + tiled_pane_layout.add_cwd_to_layout(&cwd); + for floating_pane in floating_panes { + floating_pane.add_cwd_to_layout(&cwd); + } + } + } } fn split_space( diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index d85afeed6..eecae43b8 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -194,6 +194,7 @@ message SwitchSessionPayload { optional uint32 pane_id = 3; optional bool pane_id_is_plugin = 4; optional event.LayoutInfo layout = 5; + optional string cwd = 6; } message RequestPluginPermissionPayload { diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index 6ce7422e6..ab9d52940 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -689,6 +689,7 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { tab_position: payload.tab_position.map(|p| p as usize), pane_id, layout: payload.layout.and_then(|l| l.try_into().ok()), + cwd: payload.cwd.map(|c| PathBuf::from(c)), })) }, _ => Err("Mismatched payload for SwitchSession"), @@ -1222,6 +1223,7 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { pane_id: switch_to_session.pane_id.map(|p| p.0), pane_id_is_plugin: switch_to_session.pane_id.map(|p| p.1), layout: switch_to_session.layout.and_then(|l| l.try_into().ok()), + cwd: switch_to_session.cwd.map(|c| c.display().to_string()), })), }), PluginCommand::OpenTerminalInPlace(cwd) => Ok(ProtobufPluginCommand { |