Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(plugins): allow specifying the cwd when switching sessions #3172

Merged
merged 2 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading