feat(plugins): allow specifying the cwd when switching sessions (#3172)
* feat(plugins): allow specifying the cwd when switching sessions * style(fmt): rustfmt
This commit is contained in:
parent
d5bedd0e83
commit
896b09aa6f
14 changed files with 160 additions and 5 deletions
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue