Skip to content

Commit

Permalink
feat(plugins): allow specifying the cwd when switching sessions (#3172)
Browse files Browse the repository at this point in the history
* feat(plugins): allow specifying the cwd when switching sessions

* style(fmt): rustfmt
  • Loading branch information
imsnif authored Feb 29, 2024
1 parent d5bedd0 commit 896b09a
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 5 deletions.
8 changes: 8 additions & 0 deletions default-plugins/fixture-plugin-for-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
2 changes: 1 addition & 1 deletion default-plugins/session-manager/src/new_session_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
81 changes: 81 additions & 0 deletions zellij-server/src/plugins/unit/plugin_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6317,6 +6317,87 @@ pub fn switch_session_with_layout_plugin_command() {
assert_snapshot!(format!("{:#?}", switch_session_event));
}

#[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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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(
Expand All @@ -12,6 +12,7 @@ Some(
tab_position: None,
pane_id: None,
layout: None,
cwd: None,
},
1,
),
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
),
)
Original file line number Diff line number Diff line change
@@ -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(
Expand All @@ -16,6 +16,7 @@ Some(
"compact",
),
),
cwd: None,
},
1,
),
Expand Down
3 changes: 3 additions & 0 deletions zellij-server/src/plugins/zellij_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?
Expand Down Expand Up @@ -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");
Expand All @@ -936,6 +938,7 @@ fn switch_session(
tab_position,
pane_id,
layout,
cwd,
};
env.plugin_env
.senders
Expand Down
3 changes: 2 additions & 1 deletion zellij-tile/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions zellij-utils/assets/prost/api.plugin_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
1 change: 1 addition & 0 deletions zellij-utils/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
28 changes: 27 additions & 1 deletion zellij-utils/src/input/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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>>) {
Expand Down Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions zellij-utils/src/plugin_api/plugin_command.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions zellij-utils/src/plugin_api/plugin_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 896b09a

Please sign in to comment.