fix(plugins): forward CWD when opening new panes (#4290)

* use plugin cwd as last focused pane cwd when starting plugins

* fix strider to use the new change_host_folder method

* start terminals in same cwd as plugin pane if focused

* style(fmt): rustfmt
This commit is contained in:
Aram Drevekenin 2025-07-15 10:27:43 +02:00 committed by GitHub
parent 118d5fb877
commit d4f5975527
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 280 additions and 98 deletions

View file

@ -2,7 +2,7 @@ use crate::shared::{calculate_list_bounds, render_list_tip};
use crate::state::{refresh_directory, ROOT}; use crate::state::{refresh_directory, ROOT};
use pretty_bytes::converter::convert as pretty_bytes; use pretty_bytes::converter::convert as pretty_bytes;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::{Path, PathBuf};
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use zellij_tile::prelude::*; use zellij_tile::prelude::*;
@ -18,7 +18,7 @@ impl Default for FileListView {
fn default() -> Self { fn default() -> Self {
FileListView { FileListView {
path_is_dir: true, path_is_dir: true,
path: Default::default(), path: PathBuf::new(),
files: Default::default(), files: Default::default(),
cursor_hist: Default::default(), cursor_hist: Default::default(),
} }
@ -27,30 +27,48 @@ impl Default for FileListView {
impl FileListView { impl FileListView {
pub fn descend_to_previous_path(&mut self) { pub fn descend_to_previous_path(&mut self) {
self.path.pop(); if let Some(parent) = self.path.parent() {
self.path = parent.to_path_buf();
} else {
self.path = PathBuf::new();
}
self.path_is_dir = true; self.path_is_dir = true;
self.files.clear(); self.files.clear();
self.clear_selected(); self.clear_selected();
refresh_directory(&self.path); refresh_directory(&self.path);
} }
pub fn descend_to_root_path(&mut self) {
self.path.clear(); pub fn descend_to_root_path(&mut self, initial_cwd: &PathBuf) {
self.path = initial_cwd.clone();
self.path_is_dir = true; self.path_is_dir = true;
self.files.clear(); self.files.clear();
self.clear_selected(); self.clear_selected();
refresh_directory(&self.path);
} }
pub fn enter_dir(&mut self, entry: &FsEntry) { pub fn enter_dir(&mut self, entry: &FsEntry) {
let is_dir = entry.is_folder(); let is_dir = entry.is_folder();
let path = entry.get_pathbuf_without_root_prefix(); let path = entry.get_full_pathbuf();
self.path = path; self.path = path;
self.path_is_dir = is_dir; self.path_is_dir = is_dir;
self.files.clear(); self.files.clear();
self.clear_selected(); self.clear_selected();
} }
pub fn clear_selected(&mut self) { pub fn clear_selected(&mut self) {
self.cursor_hist.remove(&self.path); self.cursor_hist.remove(&self.path);
} }
pub fn get_relative_path(&self) -> PathBuf {
if let Some(initial_cwd_part) = self.path.iter().next() {
self.path
.strip_prefix(initial_cwd_part)
.unwrap_or(&self.path)
.to_path_buf()
} else {
PathBuf::new()
}
}
pub fn update_files( pub fn update_files(
&mut self, &mut self,
paths: Vec<(PathBuf, Option<FileMetadata>)>, paths: Vec<(PathBuf, Option<FileMetadata>)>,
@ -58,8 +76,11 @@ impl FileListView {
) { ) {
let mut files = vec![]; let mut files = vec![];
for (entry, entry_metadata) in paths { for (entry, entry_metadata) in paths {
let entry = self
.path
.join(entry.strip_prefix("/host").unwrap_or(&entry));
if entry_metadata.map(|e| e.is_symlink).unwrap_or(false) { if entry_metadata.map(|e| e.is_symlink).unwrap_or(false) {
continue; // ignore symlinks continue;
} }
let entry = if entry_metadata.map(|e| e.is_dir).unwrap_or(false) { let entry = if entry_metadata.map(|e| e.is_dir).unwrap_or(false) {
FsEntry::Dir(entry) FsEntry::Dir(entry)
@ -74,20 +95,25 @@ impl FileListView {
self.files = files; self.files = files;
self.files.sort_unstable(); self.files.sort_unstable();
} }
pub fn get_selected_entry(&self) -> Option<FsEntry> { pub fn get_selected_entry(&self) -> Option<FsEntry> {
self.selected().and_then(|f| self.files.get(f).cloned()) self.selected().and_then(|f| self.files.get(f).cloned())
} }
pub fn selected_mut(&mut self) -> &mut usize { pub fn selected_mut(&mut self) -> &mut usize {
self.cursor_hist.entry(self.path.clone()).or_default() self.cursor_hist.entry(self.path.clone()).or_default()
} }
pub fn selected(&self) -> Option<usize> { pub fn selected(&self) -> Option<usize> {
self.cursor_hist.get(&self.path).copied() self.cursor_hist.get(&self.path).copied()
} }
pub fn move_selection_up(&mut self) { pub fn move_selection_up(&mut self) {
if let Some(selected) = self.selected() { if let Some(selected) = self.selected() {
*self.selected_mut() = selected.saturating_sub(1); *self.selected_mut() = selected.saturating_sub(1);
} }
} }
pub fn move_selection_down(&mut self) { pub fn move_selection_down(&mut self) {
if let Some(selected) = self.selected() { if let Some(selected) = self.selected() {
let next = selected.saturating_add(1); let next = selected.saturating_add(1);
@ -96,6 +122,7 @@ impl FileListView {
*self.selected_mut() = 0; *self.selected_mut() = 0;
} }
} }
pub fn render(&mut self, rows: usize, cols: usize) { pub fn render(&mut self, rows: usize, cols: usize) {
let (start_index, selected_index_in_range, end_index) = let (start_index, selected_index_in_range, end_index) =
calculate_list_bounds(self.files.len(), rows.saturating_sub(1), self.selected()); calculate_list_bounds(self.files.len(), rows.saturating_sub(1), self.selected());
@ -121,7 +148,6 @@ impl FileListView {
); );
format!("{}{}{}", file_or_folder_name, padding, size) format!("{}{}{}", file_or_folder_name, padding, size)
} else { } else {
// drop the size, no room for it
let padding = " ".repeat(cols.saturating_sub(file_or_folder_name_width)); let padding = " ".repeat(cols.saturating_sub(file_or_folder_name_width));
format!("{}{}", file_or_folder_name, padding) format!("{}{}", file_or_folder_name, padding)
}; };
@ -159,12 +185,14 @@ impl FsEntry {
}; };
path.file_name().unwrap().to_string_lossy().into_owned() path.file_name().unwrap().to_string_lossy().into_owned()
} }
pub fn size(&self) -> Option<u64> { pub fn size(&self) -> Option<u64> {
match self { match self {
FsEntry::Dir(_p) => None, FsEntry::Dir(_p) => None,
FsEntry::File(_, size) => Some(*size), FsEntry::File(_, size) => Some(*size),
} }
} }
pub fn get_pathbuf_without_root_prefix(&self) -> PathBuf { pub fn get_pathbuf_without_root_prefix(&self) -> PathBuf {
match self { match self {
FsEntry::Dir(p) => p FsEntry::Dir(p) => p
@ -178,14 +206,18 @@ impl FsEntry {
} }
} }
pub fn get_full_pathbuf(&self) -> PathBuf {
match self {
FsEntry::Dir(p) => p.clone(),
FsEntry::File(p, _) => p.clone(),
}
}
pub fn is_hidden_file(&self) -> bool { pub fn is_hidden_file(&self) -> bool {
self.name().starts_with('.') self.name().starts_with('.')
} }
pub fn is_folder(&self) -> bool { pub fn is_folder(&self) -> bool {
match self { matches!(self, FsEntry::Dir(_))
FsEntry::Dir(_) => true,
_ => false,
}
} }
} }

View file

@ -31,29 +31,24 @@ impl ZellijPlugin for State {
EventType::CustomMessage, EventType::CustomMessage,
EventType::Timer, EventType::Timer,
EventType::FileSystemUpdate, EventType::FileSystemUpdate,
EventType::HostFolderChanged,
EventType::PermissionRequestResult,
]); ]);
self.file_list_view.clear_selected(); self.file_list_view.clear_selected();
// the caller_cwd might be different from the initial_cwd if this plugin was defined as an
// alias, with access to a certain part of the file system (often broader) and was called match configuration.get("caller_cwd").map(|c| PathBuf::from(c)) {
// from an individual pane somewhere inside this broad scope - in this case, we want to Some(caller_cwd) => {
// start in the same cwd as the caller, giving them the full access we were granted self.file_list_view.path = caller_cwd;
match configuration
.get("caller_cwd")
.map(|c| PathBuf::from(c))
.and_then(|c| {
c.strip_prefix(&self.initial_cwd)
.ok()
.map(|c| PathBuf::from(c))
}) {
Some(relative_caller_path) => {
let relative_caller_path = FsEntry::Dir(relative_caller_path.to_path_buf());
self.file_list_view.enter_dir(&relative_caller_path);
refresh_directory(&self.file_list_view.path);
}, },
None => { None => {
refresh_directory(&std::path::Path::new("/")); self.file_list_view.path = self.initial_cwd.clone();
}, },
} }
if self.initial_cwd != self.file_list_view.path {
change_host_folder(self.file_list_view.path.clone());
} else {
scan_host_folder(&"/host");
}
} }
fn update(&mut self, event: Event) -> bool { fn update(&mut self, event: Event) -> bool {
@ -63,6 +58,10 @@ impl ZellijPlugin for State {
self.update_files(paths); self.update_files(paths);
should_render = true; should_render = true;
}, },
Event::HostFolderChanged(new_host_folder) => {
scan_host_folder(&"/host");
should_render = true;
},
Event::Key(key) => match key.bare_key { Event::Key(key) => match key.bare_key {
BareKey::Char(character) if key.has_no_modifiers() => { BareKey::Char(character) if key.has_no_modifiers() => {
self.update_search_term(character); self.update_search_term(character);
@ -137,11 +136,10 @@ impl ZellijPlugin for State {
}; };
should_render should_render
} }
fn pipe(&mut self, pipe_message: PipeMessage) -> bool { fn pipe(&mut self, pipe_message: PipeMessage) -> bool {
if pipe_message.is_private && pipe_message.name == "filepicker" { if pipe_message.is_private && pipe_message.name == "filepicker" {
if let PipeSource::Cli(pipe_id) = &pipe_message.source { if let PipeSource::Cli(pipe_id) = &pipe_message.source {
// here we block the cli pipe input because we want it to wait until the user chose
// a file
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
block_cli_pipe_input(pipe_id); block_cli_pipe_input(pipe_id);
} }
@ -157,7 +155,6 @@ impl ZellijPlugin for State {
let rows_for_list = rows.saturating_sub(6); let rows_for_list = rows.saturating_sub(6);
render_search_term(&self.search_term); render_search_term(&self.search_term);
render_current_path( render_current_path(
&self.initial_cwd,
&self.file_list_view.path, &self.file_list_view.path,
self.file_list_view.path_is_dir, self.file_list_view.path_is_dir,
self.handling_filepick_request_from.is_some(), self.handling_filepick_request_from.is_some(),

View file

@ -31,7 +31,6 @@ pub fn render_list_tip(y: usize, max_cols: usize) {
print_text_with_coordinates(tip, 0, y, Some(max_cols), None); print_text_with_coordinates(tip, 0, y, Some(max_cols), None);
} }
// returns the list (start_index, selected_index_in_range, end_index)
pub fn calculate_list_bounds( pub fn calculate_list_bounds(
result_count: usize, result_count: usize,
max_result_count: usize, max_result_count: usize,
@ -48,17 +47,17 @@ pub fn calculate_list_bounds(
break; break;
} }
if !alternate && start_index > 0 { if !alternate && start_index > 0 {
start_index -= 1; start_index = start_index.saturating_sub(1);
room_in_list -= 1; room_in_list = room_in_list.saturating_sub(1);
} else if alternate && end_index < result_count { } else if alternate && end_index < result_count {
end_index += 1; end_index += 1;
room_in_list -= 1; room_in_list = room_in_list.saturating_sub(1);
} else if start_index > 0 { } else if start_index > 0 {
start_index -= 1; start_index = start_index.saturating_sub(1);
room_in_list -= 1; room_in_list = room_in_list.saturating_sub(1);
} else if end_index < result_count { } else if end_index < result_count {
end_index += 1; end_index += 1;
room_in_list -= 1; room_in_list = room_in_list.saturating_sub(1);
} else { } else {
break; break;
} }
@ -80,15 +79,13 @@ pub fn render_search_term(search_term: &str) {
} }
pub fn render_current_path( pub fn render_current_path(
initial_cwd: &PathBuf, full_path: &PathBuf,
path: &PathBuf,
path_is_dir: bool, path_is_dir: bool,
handling_filepick: bool, handling_filepick: bool,
max_cols: usize, max_cols: usize,
) { ) {
let prompt = "PATH: "; let prompt = "PATH: ";
let current_path = initial_cwd.join(path); let current_path = full_path.display().to_string();
let current_path = current_path.display().to_string();
let prompt_len = prompt.width(); let prompt_len = prompt.width();
let current_path_len = current_path.width(); let current_path_len = current_path.width();
@ -118,7 +115,7 @@ pub fn render_current_path(
current_path current_path
} else { } else {
truncate_path( truncate_path(
initial_cwd.join(path), full_path.clone(),
current_path_len.saturating_sub(max_path_len), current_path_len.saturating_sub(max_path_len),
) )
}; };

View file

@ -16,7 +16,7 @@ pub struct State {
pub hide_hidden_files: bool, pub hide_hidden_files: bool,
pub current_rows: Option<usize>, pub current_rows: Option<usize>,
pub handling_filepick_request_from: Option<(PipeSource, BTreeMap<String, String>)>, pub handling_filepick_request_from: Option<(PipeSource, BTreeMap<String, String>)>,
pub initial_cwd: PathBuf, // TODO: get this from zellij pub initial_cwd: PathBuf,
pub is_searching: bool, pub is_searching: bool,
pub search_term: String, pub search_term: String,
pub close_on_selection: bool, pub close_on_selection: bool,
@ -137,7 +137,7 @@ impl State {
pub fn descend_to_root_path(&mut self) { pub fn descend_to_root_path(&mut self) {
self.search_term.clear(); self.search_term.clear();
self.search_view.clear_and_reset_selection(); self.search_view.clear_and_reset_selection();
self.file_list_view.descend_to_root_path(); self.file_list_view.descend_to_root_path(&self.initial_cwd);
refresh_directory(&self.file_list_view.path); refresh_directory(&self.file_list_view.path);
} }
pub fn toggle_hidden_files(&mut self) { pub fn toggle_hidden_files(&mut self) {
@ -214,13 +214,7 @@ impl State {
} }
} }
pub fn send_filepick_response(&mut self) { pub fn send_filepick_response(&mut self) {
let selected_path = self.initial_cwd.join( let selected_path = &self.file_list_view.path;
self.file_list_view
.path
.strip_prefix(ROOT)
.map(|p| p.to_path_buf())
.unwrap_or_else(|_| self.file_list_view.path.clone()),
);
match &self.handling_filepick_request_from { match &self.handling_filepick_request_from {
Some((PipeSource::Plugin(plugin_id), args)) => { Some((PipeSource::Plugin(plugin_id), args)) => {
pipe_message_to_plugin( pipe_message_to_plugin(
@ -245,7 +239,6 @@ impl State {
} }
} }
pub(crate) fn refresh_directory(path: &Path) { pub(crate) fn refresh_directory(full_path: &Path) {
let path_on_host = Path::new(ROOT).join(path.strip_prefix("/").unwrap_or(path)); change_host_folder(PathBuf::from(full_path));
scan_host_folder(&path_on_host);
} }

View file

@ -55,6 +55,7 @@ pub enum PluginInstruction {
ClientId, ClientId,
Size, Size,
Option<PathBuf>, // cwd Option<PathBuf>, // cwd
Option<PluginId>, // the focused plugin id if relevant
bool, // skip cache bool, // skip cache
Option<bool>, // should focus plugin Option<bool>, // should focus plugin
Option<FloatingPaneCoordinates>, Option<FloatingPaneCoordinates>,
@ -253,7 +254,7 @@ pub(crate) fn plugin_thread_main(
engine, engine,
plugin_dir, plugin_dir,
path_to_default_shell, path_to_default_shell,
zellij_cwd, zellij_cwd.clone(),
capabilities, capabilities,
client_attributes, client_attributes,
default_shell, default_shell,
@ -287,12 +288,19 @@ pub(crate) fn plugin_thread_main(
client_id, client_id,
size, size,
cwd, cwd,
focused_plugin_id,
skip_cache, skip_cache,
should_focus_plugin, should_focus_plugin,
floating_pane_coordinates, floating_pane_coordinates,
) => { ) => {
run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases); run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases);
let cwd = run_plugin_or_alias.get_initial_cwd().or(cwd); let cwd = run_plugin_or_alias.get_initial_cwd().or(cwd).or_else(|| {
if let Some(plugin_id) = focused_plugin_id {
wasm_bridge.get_plugin_cwd(plugin_id, client_id)
} else {
None
}
});
let run_plugin = run_plugin_or_alias.get_run_plugin(); let run_plugin = run_plugin_or_alias.get_run_plugin();
let start_suppressed = false; let start_suppressed = false;
match wasm_bridge.load_plugin( match wasm_bridge.load_plugin(
@ -313,12 +321,17 @@ pub(crate) fn plugin_thread_main(
tab_index, tab_index,
plugin_id, plugin_id,
pane_id_to_replace, pane_id_to_replace,
cwd, cwd.clone(),
start_suppressed, start_suppressed,
floating_pane_coordinates, floating_pane_coordinates,
should_focus_plugin, should_focus_plugin,
Some(client_id), Some(client_id),
))); )));
drop(bus.senders.send_to_pty(PtyInstruction::ReportPluginCwd(
plugin_id,
cwd.unwrap_or_else(|| zellij_cwd.clone()),
)));
}, },
Err(e) => { Err(e) => {
log::error!("Failed to load plugin: {e}"); log::error!("Failed to load plugin: {e}");
@ -916,9 +929,18 @@ pub(crate) fn plugin_thread_main(
wasm_bridge.start_fs_watcher_if_not_started(); wasm_bridge.start_fs_watcher_if_not_started();
}, },
PluginInstruction::ChangePluginHostDir(new_host_folder, plugin_id, client_id) => { PluginInstruction::ChangePluginHostDir(new_host_folder, plugin_id, client_id) => {
wasm_bridge if let Ok(_) = wasm_bridge.change_plugin_host_dir(
.change_plugin_host_dir(new_host_folder, plugin_id, client_id) new_host_folder.clone(),
.non_fatal(); plugin_id,
client_id,
) {
drop(
bus.senders.send_to_pty(PtyInstruction::ReportPluginCwd(
plugin_id,
new_host_folder,
)),
);
}
}, },
PluginInstruction::WebServerStarted(base_url) => { PluginInstruction::WebServerStarted(base_url) => {
let updates = vec![( let updates = vec![(

View file

@ -713,6 +713,7 @@ pub fn load_new_plugin_from_hd() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -795,6 +796,7 @@ pub fn load_new_plugin_with_plugin_alias() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -873,6 +875,7 @@ pub fn plugin_workers() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -955,6 +958,7 @@ pub fn plugin_workers_persist_state() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1047,6 +1051,7 @@ pub fn can_subscribe_to_hd_events() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1127,6 +1132,7 @@ pub fn switch_to_mode_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1201,6 +1207,7 @@ pub fn switch_to_mode_plugin_command_permission_denied() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1275,6 +1282,7 @@ pub fn new_tabs_with_layout_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1363,6 +1371,7 @@ pub fn new_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1437,6 +1446,7 @@ pub fn go_to_next_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1510,6 +1520,7 @@ pub fn go_to_previous_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1583,6 +1594,7 @@ pub fn resize_focused_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1656,6 +1668,7 @@ pub fn resize_focused_pane_with_direction_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1729,6 +1742,7 @@ pub fn focus_next_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1802,6 +1816,7 @@ pub fn focus_previous_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1875,6 +1890,7 @@ pub fn move_focus_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -1948,6 +1964,7 @@ pub fn move_focus_or_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2021,6 +2038,7 @@ pub fn edit_scrollback_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2094,6 +2112,7 @@ pub fn write_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2167,6 +2186,7 @@ pub fn write_chars_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2240,6 +2260,7 @@ pub fn toggle_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2313,6 +2334,7 @@ pub fn move_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2386,6 +2408,7 @@ pub fn move_pane_with_direction_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2460,6 +2483,7 @@ pub fn clear_screen_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2534,6 +2558,7 @@ pub fn scroll_up_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2607,6 +2632,7 @@ pub fn scroll_down_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2680,6 +2706,7 @@ pub fn scroll_to_top_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2753,6 +2780,7 @@ pub fn scroll_to_bottom_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2826,6 +2854,7 @@ pub fn page_scroll_up_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2899,6 +2928,7 @@ pub fn page_scroll_down_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -2972,6 +3002,7 @@ pub fn toggle_focus_fullscreen_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3045,6 +3076,7 @@ pub fn toggle_pane_frames_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3118,6 +3150,7 @@ pub fn toggle_pane_embed_or_eject_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3191,6 +3224,7 @@ pub fn undo_rename_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3264,6 +3298,7 @@ pub fn close_focus_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3337,6 +3372,7 @@ pub fn toggle_active_tab_sync_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3410,6 +3446,7 @@ pub fn close_focused_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3483,6 +3520,7 @@ pub fn undo_rename_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3556,6 +3594,7 @@ pub fn previous_swap_layout_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3629,6 +3668,7 @@ pub fn next_swap_layout_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3702,6 +3742,7 @@ pub fn go_to_tab_name_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3775,6 +3816,7 @@ pub fn focus_or_create_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3848,6 +3890,7 @@ pub fn go_to_tab() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -3921,6 +3964,7 @@ pub fn start_or_reload_plugin() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4001,6 +4045,7 @@ pub fn quit_zellij_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4081,6 +4126,7 @@ pub fn detach_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4161,6 +4207,7 @@ pub fn open_file_floating_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4245,6 +4292,7 @@ pub fn open_file_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4330,6 +4378,7 @@ pub fn open_file_with_line_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4414,6 +4463,7 @@ pub fn open_file_with_line_floating_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4498,6 +4548,7 @@ pub fn open_terminal_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4578,6 +4629,7 @@ pub fn open_terminal_floating_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4658,6 +4710,7 @@ pub fn open_command_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4738,6 +4791,7 @@ pub fn open_command_pane_floating_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4811,6 +4865,7 @@ pub fn switch_to_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4884,6 +4939,7 @@ pub fn hide_self_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -4956,6 +5012,7 @@ pub fn show_self_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5029,6 +5086,7 @@ pub fn close_terminal_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5102,6 +5160,7 @@ pub fn close_plugin_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5175,6 +5234,7 @@ pub fn focus_terminal_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5248,6 +5308,7 @@ pub fn focus_plugin_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5321,6 +5382,7 @@ pub fn rename_terminal_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5394,6 +5456,7 @@ pub fn rename_plugin_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5467,6 +5530,7 @@ pub fn rename_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5549,6 +5613,7 @@ pub fn send_configuration_to_plugins() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5619,6 +5684,7 @@ pub fn request_plugin_permissions() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5713,6 +5779,7 @@ pub fn granted_permission_request_result() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5806,6 +5873,7 @@ pub fn denied_permission_request_result() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5879,6 +5947,7 @@ pub fn run_command_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -5959,6 +6028,7 @@ pub fn run_command_with_env_vars_and_cwd_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6039,6 +6109,7 @@ pub fn web_request_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6112,6 +6183,7 @@ pub fn unblock_input_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6196,6 +6268,7 @@ pub fn block_input_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6288,6 +6361,7 @@ pub fn pipe_output_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6373,6 +6447,7 @@ pub fn pipe_message_to_plugin_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6469,6 +6544,7 @@ pub fn switch_session_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6552,6 +6628,7 @@ pub fn switch_session_with_layout_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6635,6 +6712,7 @@ pub fn switch_session_with_layout_and_cwd_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6718,6 +6796,7 @@ pub fn disconnect_other_clients_plugins_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6801,6 +6880,7 @@ pub fn reconfigure_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6888,6 +6968,7 @@ pub fn run_plugin_in_specific_cwd() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -6964,6 +7045,7 @@ pub fn hide_pane_with_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7037,6 +7119,7 @@ pub fn show_pane_with_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7117,6 +7200,7 @@ pub fn open_command_pane_background_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7194,6 +7278,7 @@ pub fn rerun_command_pane_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7267,6 +7352,7 @@ pub fn resize_pane_with_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7340,6 +7426,7 @@ pub fn edit_scrollback_for_pane_with_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7413,6 +7500,7 @@ pub fn write_to_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7486,6 +7574,7 @@ pub fn write_chars_to_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7559,6 +7648,7 @@ pub fn move_pane_with_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7632,6 +7722,7 @@ pub fn move_pane_with_pane_id_in_direction_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7705,6 +7796,7 @@ pub fn clear_screen_for_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7778,6 +7870,7 @@ pub fn scroll_up_in_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7851,6 +7944,7 @@ pub fn scroll_down_in_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7924,6 +8018,7 @@ pub fn scroll_to_top_in_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -7997,6 +8092,7 @@ pub fn scroll_to_bottom_in_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8070,6 +8166,7 @@ pub fn page_scroll_up_in_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8143,6 +8240,7 @@ pub fn page_scroll_down_in_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8216,6 +8314,7 @@ pub fn toggle_pane_id_fullscreen_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8289,6 +8388,7 @@ pub fn toggle_pane_embed_or_eject_for_pane_id_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8362,6 +8462,7 @@ pub fn close_tab_with_index_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8435,6 +8536,7 @@ pub fn break_panes_to_new_tab_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8508,6 +8610,7 @@ pub fn break_panes_to_tab_with_index_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8581,6 +8684,7 @@ pub fn reload_plugin_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8654,6 +8758,7 @@ pub fn load_new_plugin_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8734,6 +8839,7 @@ pub fn rebind_keys_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8810,6 +8916,7 @@ pub fn list_clients_plugin_command() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,
@ -8883,6 +8990,7 @@ pub fn before_close_plugin_event() {
client_id, client_id,
size, size,
None, None,
None,
false, false,
None, None,
None, None,

View file

@ -775,6 +775,27 @@ impl WasmBridge {
} }
Ok(()) Ok(())
} }
pub fn get_plugin_cwd(&self, plugin_id: PluginId, client_id: ClientId) -> Option<PathBuf> {
self.plugin_map
.lock()
.unwrap()
.running_plugins()
.iter()
.find_map(|(p_id, c_id, running_plugin)| {
if p_id == &plugin_id && c_id == &client_id {
let plugin_cwd = running_plugin
.lock()
.unwrap()
.store
.data()
.plugin_cwd
.clone();
Some(plugin_cwd)
} else {
None
}
})
}
pub fn change_plugin_host_dir( pub fn change_plugin_host_dir(
&mut self, &mut self,
new_host_dir: PathBuf, new_host_dir: PathBuf,
@ -793,12 +814,6 @@ impl WasmBridge {
.running_plugins_and_subscriptions() .running_plugins_and_subscriptions()
.iter() .iter()
.cloned() .cloned()
.filter(|(plugin_id, _client_id, _running_plugin, _subscriptions)| {
// TODO: cache this somehow in this case...
!&self
.cached_events_for_pending_plugins
.contains_key(&plugin_id)
})
.collect(); .collect();
task::spawn({ task::spawn({
let senders = self.senders.clone(); let senders = self.senders.clone();

View file

@ -2222,6 +2222,7 @@ fn load_new_plugin(
client_id, client_id,
size, size,
cwd, cwd,
None,
skip_cache, skip_cache,
None, None,
None, None,

View file

@ -176,6 +176,7 @@ pub enum PtyInstruction {
post_command_discovery_hook: Option<String>, post_command_discovery_hook: Option<String>,
}, },
ListClientsToPlugin(SessionLayoutMetadata, PluginId, ClientId), ListClientsToPlugin(SessionLayoutMetadata, PluginId, ClientId),
ReportPluginCwd(PluginId, PathBuf),
Exit, Exit,
} }
@ -199,6 +200,7 @@ impl From<&PtyInstruction> for PtyContext {
PtyInstruction::ListClientsMetadata(..) => PtyContext::ListClientsMetadata, PtyInstruction::ListClientsMetadata(..) => PtyContext::ListClientsMetadata,
PtyInstruction::Reconfigure { .. } => PtyContext::Reconfigure, PtyInstruction::Reconfigure { .. } => PtyContext::Reconfigure,
PtyInstruction::ListClientsToPlugin(..) => PtyContext::ListClientsToPlugin, PtyInstruction::ListClientsToPlugin(..) => PtyContext::ListClientsToPlugin,
PtyInstruction::ReportPluginCwd(..) => PtyContext::ReportPluginCwd,
PtyInstruction::Exit => PtyContext::Exit, PtyInstruction::Exit => PtyContext::Exit,
} }
} }
@ -213,6 +215,7 @@ pub(crate) struct Pty {
task_handles: HashMap<u32, JoinHandle<()>>, // terminal_id to join-handle task_handles: HashMap<u32, JoinHandle<()>>, // terminal_id to join-handle
default_editor: Option<PathBuf>, default_editor: Option<PathBuf>,
post_command_discovery_hook: Option<String>, post_command_discovery_hook: Option<String>,
plugin_cwds: HashMap<u32, PathBuf>, // plugin_id -> cwd
} }
pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> { pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
@ -676,6 +679,9 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
.with_context(err_context) .with_context(err_context)
.non_fatal(); .non_fatal();
}, },
PtyInstruction::ReportPluginCwd(plugin_id, cwd) => {
pty.plugin_cwds.insert(plugin_id, cwd);
},
PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => { PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => {
let err_context = || format!("Failed to dump layout"); let err_context = || format!("Failed to dump layout");
pty.populate_session_layout_metadata(&mut session_layout_metadata); pty.populate_session_layout_metadata(&mut session_layout_metadata);
@ -755,6 +761,7 @@ impl Pty {
default_editor, default_editor,
originating_plugins: HashMap::new(), originating_plugins: HashMap::new(),
post_command_discovery_hook, post_command_discovery_hook,
plugin_cwds: HashMap::new(),
} }
} }
pub fn get_default_terminal( pub fn get_default_terminal(
@ -803,27 +810,31 @@ impl Pty {
.active_panes .active_panes
.get(&client_id) .get(&client_id)
.and_then(|pane| match pane { .and_then(|pane| match pane {
PaneId::Plugin(..) => None, PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(),
PaneId::Terminal(id) => self.id_to_child_pid.get(id), PaneId::Terminal(id) => self.id_to_child_pid.get(id).and_then(|&id| {
})
.and_then(|&id| {
self.bus self.bus
.os_input .os_input
.as_ref() .as_ref()
.and_then(|input| input.get_cwd(Pid::from_raw(id))) .and_then(|input| input.get_cwd(Pid::from_raw(id)))
}); }),
})
}; };
}; };
} }
fn fill_cwd_from_pane_id(&self, terminal_action: &mut TerminalAction, pane_id: &u32) { fn fill_cwd_from_pane_id(&self, terminal_action: &mut TerminalAction, pane_id: &PaneId) {
if let TerminalAction::RunCommand(run_command) = terminal_action { if let TerminalAction::RunCommand(run_command) = terminal_action {
if run_command.cwd.is_none() { if run_command.cwd.is_none() {
run_command.cwd = self.id_to_child_pid.get(pane_id).and_then(|&id| { run_command.cwd = match pane_id {
PaneId::Terminal(terminal_pane_id) => {
self.id_to_child_pid.get(terminal_pane_id).and_then(|&id| {
self.bus self.bus
.os_input .os_input
.as_ref() .as_ref()
.and_then(|input| input.get_cwd(Pid::from_raw(id))) .and_then(|input| input.get_cwd(Pid::from_raw(id)))
}); })
},
PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(),
};
}; };
}; };
} }
@ -849,9 +860,7 @@ impl Pty {
ClientTabIndexOrPaneId::PaneId(pane_id) => { ClientTabIndexOrPaneId::PaneId(pane_id) => {
let mut terminal_action = let mut terminal_action =
terminal_action.unwrap_or_else(|| self.get_default_terminal(None, None)); terminal_action.unwrap_or_else(|| self.get_default_terminal(None, None));
if let PaneId::Terminal(terminal_pane_id) = pane_id { self.fill_cwd_from_pane_id(&mut terminal_action, &pane_id);
self.fill_cwd_from_pane_id(&mut terminal_action, &terminal_pane_id);
}
terminal_action terminal_action
}, },
}; };
@ -1482,18 +1491,24 @@ impl Pty {
self.active_panes self.active_panes
.get(&client_id) .get(&client_id)
.and_then(|pane| match pane { .and_then(|pane| match pane {
PaneId::Plugin(..) => None, PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(),
PaneId::Terminal(id) => self.id_to_child_pid.get(id), PaneId::Terminal(id) => self.id_to_child_pid.get(id).and_then(|&id| {
})
.and_then(|&id| {
self.bus self.bus
.os_input .os_input
.as_ref() .as_ref()
.and_then(|input| input.get_cwd(Pid::from_raw(id))) .and_then(|input| input.get_cwd(Pid::from_raw(id)))
}),
}) })
}; };
let cwd = cwd.or_else(get_focused_cwd); let cwd = cwd.or_else(get_focused_cwd);
let focused_plugin_id = self
.active_panes
.get(&client_id)
.and_then(|pane| match pane {
PaneId::Plugin(plugin_id) => Some(*plugin_id),
_ => None,
});
if let RunPluginOrAlias::Alias(alias) = &mut run { if let RunPluginOrAlias::Alias(alias) = &mut run {
let cwd = get_focused_cwd(); let cwd = get_focused_cwd();
@ -1509,6 +1524,7 @@ impl Pty {
client_id, client_id,
size, size,
cwd, cwd,
focused_plugin_id,
skip_cache, skip_cache,
should_focus_plugin, should_focus_plugin,
floating_pane_coordinates, floating_pane_coordinates,

View file

@ -412,6 +412,7 @@ pub enum PtyContext {
ListClientsMetadata, ListClientsMetadata,
Reconfigure, Reconfigure,
ListClientsToPlugin, ListClientsToPlugin,
ReportPluginCwd,
Exit, Exit,
} }