diff --git a/default-plugins/strider/src/file_list_view.rs b/default-plugins/strider/src/file_list_view.rs index ccbbe292..a5a0bfa9 100644 --- a/default-plugins/strider/src/file_list_view.rs +++ b/default-plugins/strider/src/file_list_view.rs @@ -2,7 +2,7 @@ use crate::shared::{calculate_list_bounds, render_list_tip}; use crate::state::{refresh_directory, ROOT}; use pretty_bytes::converter::convert as pretty_bytes; use std::collections::HashMap; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use unicode_width::UnicodeWidthStr; use zellij_tile::prelude::*; @@ -18,7 +18,7 @@ impl Default for FileListView { fn default() -> Self { FileListView { path_is_dir: true, - path: Default::default(), + path: PathBuf::new(), files: Default::default(), cursor_hist: Default::default(), } @@ -27,30 +27,48 @@ impl Default for FileListView { impl FileListView { 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.files.clear(); self.clear_selected(); 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.files.clear(); self.clear_selected(); - refresh_directory(&self.path); } + pub fn enter_dir(&mut self, entry: &FsEntry) { 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_is_dir = is_dir; self.files.clear(); self.clear_selected(); } + pub fn clear_selected(&mut self) { 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( &mut self, paths: Vec<(PathBuf, Option)>, @@ -58,8 +76,11 @@ impl FileListView { ) { let mut files = vec![]; 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) { - continue; // ignore symlinks + continue; } let entry = if entry_metadata.map(|e| e.is_dir).unwrap_or(false) { FsEntry::Dir(entry) @@ -74,20 +95,25 @@ impl FileListView { self.files = files; self.files.sort_unstable(); } + pub fn get_selected_entry(&self) -> Option { self.selected().and_then(|f| self.files.get(f).cloned()) } + pub fn selected_mut(&mut self) -> &mut usize { self.cursor_hist.entry(self.path.clone()).or_default() } + pub fn selected(&self) -> Option { self.cursor_hist.get(&self.path).copied() } + pub fn move_selection_up(&mut self) { if let Some(selected) = self.selected() { *self.selected_mut() = selected.saturating_sub(1); } } + pub fn move_selection_down(&mut self) { if let Some(selected) = self.selected() { let next = selected.saturating_add(1); @@ -96,6 +122,7 @@ impl FileListView { *self.selected_mut() = 0; } } + pub fn render(&mut self, rows: usize, cols: usize) { let (start_index, selected_index_in_range, end_index) = 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) } else { - // drop the size, no room for it let padding = " ".repeat(cols.saturating_sub(file_or_folder_name_width)); format!("{}{}", file_or_folder_name, padding) }; @@ -159,12 +185,14 @@ impl FsEntry { }; path.file_name().unwrap().to_string_lossy().into_owned() } + pub fn size(&self) -> Option { match self { FsEntry::Dir(_p) => None, FsEntry::File(_, size) => Some(*size), } } + pub fn get_pathbuf_without_root_prefix(&self) -> PathBuf { match self { 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 { self.name().starts_with('.') } pub fn is_folder(&self) -> bool { - match self { - FsEntry::Dir(_) => true, - _ => false, - } + matches!(self, FsEntry::Dir(_)) } } diff --git a/default-plugins/strider/src/main.rs b/default-plugins/strider/src/main.rs index cd9dda4d..d770e495 100644 --- a/default-plugins/strider/src/main.rs +++ b/default-plugins/strider/src/main.rs @@ -31,29 +31,24 @@ impl ZellijPlugin for State { EventType::CustomMessage, EventType::Timer, EventType::FileSystemUpdate, + EventType::HostFolderChanged, + EventType::PermissionRequestResult, ]); 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 - // from an individual pane somewhere inside this broad scope - in this case, we want to - // start in the same cwd as the caller, giving them the full access we were granted - 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); + + match configuration.get("caller_cwd").map(|c| PathBuf::from(c)) { + Some(caller_cwd) => { + self.file_list_view.path = caller_cwd; }, 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 { @@ -63,6 +58,10 @@ impl ZellijPlugin for State { self.update_files(paths); should_render = true; }, + Event::HostFolderChanged(new_host_folder) => { + scan_host_folder(&"/host"); + should_render = true; + }, Event::Key(key) => match key.bare_key { BareKey::Char(character) if key.has_no_modifiers() => { self.update_search_term(character); @@ -137,11 +136,10 @@ impl ZellijPlugin for State { }; should_render } + fn pipe(&mut self, pipe_message: PipeMessage) -> bool { if pipe_message.is_private && pipe_message.name == "filepicker" { 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")] block_cli_pipe_input(pipe_id); } @@ -157,7 +155,6 @@ impl ZellijPlugin for State { let rows_for_list = rows.saturating_sub(6); render_search_term(&self.search_term); render_current_path( - &self.initial_cwd, &self.file_list_view.path, self.file_list_view.path_is_dir, self.handling_filepick_request_from.is_some(), diff --git a/default-plugins/strider/src/shared.rs b/default-plugins/strider/src/shared.rs index c51cb312..19728034 100644 --- a/default-plugins/strider/src/shared.rs +++ b/default-plugins/strider/src/shared.rs @@ -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); } -// returns the list (start_index, selected_index_in_range, end_index) pub fn calculate_list_bounds( result_count: usize, max_result_count: usize, @@ -48,17 +47,17 @@ pub fn calculate_list_bounds( break; } if !alternate && start_index > 0 { - start_index -= 1; - room_in_list -= 1; + start_index = start_index.saturating_sub(1); + room_in_list = room_in_list.saturating_sub(1); } else if alternate && end_index < result_count { end_index += 1; - room_in_list -= 1; + room_in_list = room_in_list.saturating_sub(1); } else if start_index > 0 { - start_index -= 1; - room_in_list -= 1; + start_index = start_index.saturating_sub(1); + room_in_list = room_in_list.saturating_sub(1); } else if end_index < result_count { end_index += 1; - room_in_list -= 1; + room_in_list = room_in_list.saturating_sub(1); } else { break; } @@ -80,15 +79,13 @@ pub fn render_search_term(search_term: &str) { } pub fn render_current_path( - initial_cwd: &PathBuf, - path: &PathBuf, + full_path: &PathBuf, path_is_dir: bool, handling_filepick: bool, max_cols: usize, ) { let prompt = "PATH: "; - let current_path = initial_cwd.join(path); - let current_path = current_path.display().to_string(); + let current_path = full_path.display().to_string(); let prompt_len = prompt.width(); let current_path_len = current_path.width(); @@ -118,7 +115,7 @@ pub fn render_current_path( current_path } else { truncate_path( - initial_cwd.join(path), + full_path.clone(), current_path_len.saturating_sub(max_path_len), ) }; diff --git a/default-plugins/strider/src/state.rs b/default-plugins/strider/src/state.rs index 0bf5b268..93c6cf1b 100644 --- a/default-plugins/strider/src/state.rs +++ b/default-plugins/strider/src/state.rs @@ -16,7 +16,7 @@ pub struct State { pub hide_hidden_files: bool, pub current_rows: Option, pub handling_filepick_request_from: Option<(PipeSource, BTreeMap)>, - pub initial_cwd: PathBuf, // TODO: get this from zellij + pub initial_cwd: PathBuf, pub is_searching: bool, pub search_term: String, pub close_on_selection: bool, @@ -137,7 +137,7 @@ impl State { pub fn descend_to_root_path(&mut self) { self.search_term.clear(); 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); } pub fn toggle_hidden_files(&mut self) { @@ -214,13 +214,7 @@ impl State { } } pub fn send_filepick_response(&mut self) { - let selected_path = self.initial_cwd.join( - self.file_list_view - .path - .strip_prefix(ROOT) - .map(|p| p.to_path_buf()) - .unwrap_or_else(|_| self.file_list_view.path.clone()), - ); + let selected_path = &self.file_list_view.path; match &self.handling_filepick_request_from { Some((PipeSource::Plugin(plugin_id), args)) => { pipe_message_to_plugin( @@ -245,7 +239,6 @@ impl State { } } -pub(crate) fn refresh_directory(path: &Path) { - let path_on_host = Path::new(ROOT).join(path.strip_prefix("/").unwrap_or(path)); - scan_host_folder(&path_on_host); +pub(crate) fn refresh_directory(full_path: &Path) { + change_host_folder(PathBuf::from(full_path)); } diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs index 48620a99..6e84649a 100644 --- a/zellij-server/src/plugins/mod.rs +++ b/zellij-server/src/plugins/mod.rs @@ -54,9 +54,10 @@ pub enum PluginInstruction { Option, // pane id to replace if this is to be opened "in-place" ClientId, Size, - Option, // cwd - bool, // skip cache - Option, // should focus plugin + Option, // cwd + Option, // the focused plugin id if relevant + bool, // skip cache + Option, // should focus plugin Option, ), LoadBackgroundPlugin(RunPluginOrAlias, ClientId), @@ -253,7 +254,7 @@ pub(crate) fn plugin_thread_main( engine, plugin_dir, path_to_default_shell, - zellij_cwd, + zellij_cwd.clone(), capabilities, client_attributes, default_shell, @@ -287,12 +288,19 @@ pub(crate) fn plugin_thread_main( client_id, size, cwd, + focused_plugin_id, skip_cache, should_focus_plugin, floating_pane_coordinates, ) => { 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 start_suppressed = false; match wasm_bridge.load_plugin( @@ -313,12 +321,17 @@ pub(crate) fn plugin_thread_main( tab_index, plugin_id, pane_id_to_replace, - cwd, + cwd.clone(), start_suppressed, floating_pane_coordinates, should_focus_plugin, Some(client_id), ))); + + drop(bus.senders.send_to_pty(PtyInstruction::ReportPluginCwd( + plugin_id, + cwd.unwrap_or_else(|| zellij_cwd.clone()), + ))); }, Err(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(); }, PluginInstruction::ChangePluginHostDir(new_host_folder, plugin_id, client_id) => { - wasm_bridge - .change_plugin_host_dir(new_host_folder, plugin_id, client_id) - .non_fatal(); + if let Ok(_) = wasm_bridge.change_plugin_host_dir( + new_host_folder.clone(), + plugin_id, + client_id, + ) { + drop( + bus.senders.send_to_pty(PtyInstruction::ReportPluginCwd( + plugin_id, + new_host_folder, + )), + ); + } }, PluginInstruction::WebServerStarted(base_url) => { let updates = vec![( diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 276461d9..700011c8 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -713,6 +713,7 @@ pub fn load_new_plugin_from_hd() { client_id, size, None, + None, false, None, None, @@ -795,6 +796,7 @@ pub fn load_new_plugin_with_plugin_alias() { client_id, size, None, + None, false, None, None, @@ -873,6 +875,7 @@ pub fn plugin_workers() { client_id, size, None, + None, false, None, None, @@ -955,6 +958,7 @@ pub fn plugin_workers_persist_state() { client_id, size, None, + None, false, None, None, @@ -1047,6 +1051,7 @@ pub fn can_subscribe_to_hd_events() { client_id, size, None, + None, false, None, None, @@ -1127,6 +1132,7 @@ pub fn switch_to_mode_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1201,6 +1207,7 @@ pub fn switch_to_mode_plugin_command_permission_denied() { client_id, size, None, + None, false, None, None, @@ -1275,6 +1282,7 @@ pub fn new_tabs_with_layout_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1363,6 +1371,7 @@ pub fn new_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1437,6 +1446,7 @@ pub fn go_to_next_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1510,6 +1520,7 @@ pub fn go_to_previous_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1583,6 +1594,7 @@ pub fn resize_focused_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1656,6 +1668,7 @@ pub fn resize_focused_pane_with_direction_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1729,6 +1742,7 @@ pub fn focus_next_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1802,6 +1816,7 @@ pub fn focus_previous_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1875,6 +1890,7 @@ pub fn move_focus_plugin_command() { client_id, size, None, + None, false, None, None, @@ -1948,6 +1964,7 @@ pub fn move_focus_or_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2021,6 +2038,7 @@ pub fn edit_scrollback_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2094,6 +2112,7 @@ pub fn write_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2167,6 +2186,7 @@ pub fn write_chars_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2240,6 +2260,7 @@ pub fn toggle_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2313,6 +2334,7 @@ pub fn move_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2386,6 +2408,7 @@ pub fn move_pane_with_direction_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2460,6 +2483,7 @@ pub fn clear_screen_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2534,6 +2558,7 @@ pub fn scroll_up_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2607,6 +2632,7 @@ pub fn scroll_down_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2680,6 +2706,7 @@ pub fn scroll_to_top_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2753,6 +2780,7 @@ pub fn scroll_to_bottom_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2826,6 +2854,7 @@ pub fn page_scroll_up_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2899,6 +2928,7 @@ pub fn page_scroll_down_plugin_command() { client_id, size, None, + None, false, None, None, @@ -2972,6 +3002,7 @@ pub fn toggle_focus_fullscreen_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3045,6 +3076,7 @@ pub fn toggle_pane_frames_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3118,6 +3150,7 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3191,6 +3224,7 @@ pub fn undo_rename_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3264,6 +3298,7 @@ pub fn close_focus_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3337,6 +3372,7 @@ pub fn toggle_active_tab_sync_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3410,6 +3446,7 @@ pub fn close_focused_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3483,6 +3520,7 @@ pub fn undo_rename_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3556,6 +3594,7 @@ pub fn previous_swap_layout_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3629,6 +3668,7 @@ pub fn next_swap_layout_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3702,6 +3742,7 @@ pub fn go_to_tab_name_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3775,6 +3816,7 @@ pub fn focus_or_create_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -3848,6 +3890,7 @@ pub fn go_to_tab() { client_id, size, None, + None, false, None, None, @@ -3921,6 +3964,7 @@ pub fn start_or_reload_plugin() { client_id, size, None, + None, false, None, None, @@ -4001,6 +4045,7 @@ pub fn quit_zellij_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4081,6 +4126,7 @@ pub fn detach_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4161,6 +4207,7 @@ pub fn open_file_floating_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4245,6 +4292,7 @@ pub fn open_file_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4330,6 +4378,7 @@ pub fn open_file_with_line_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4414,6 +4463,7 @@ pub fn open_file_with_line_floating_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4498,6 +4548,7 @@ pub fn open_terminal_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4578,6 +4629,7 @@ pub fn open_terminal_floating_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4658,6 +4710,7 @@ pub fn open_command_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4738,6 +4791,7 @@ pub fn open_command_pane_floating_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4811,6 +4865,7 @@ pub fn switch_to_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4884,6 +4939,7 @@ pub fn hide_self_plugin_command() { client_id, size, None, + None, false, None, None, @@ -4956,6 +5012,7 @@ pub fn show_self_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5029,6 +5086,7 @@ pub fn close_terminal_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5102,6 +5160,7 @@ pub fn close_plugin_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5175,6 +5234,7 @@ pub fn focus_terminal_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5248,6 +5308,7 @@ pub fn focus_plugin_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5321,6 +5382,7 @@ pub fn rename_terminal_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5394,6 +5456,7 @@ pub fn rename_plugin_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5467,6 +5530,7 @@ pub fn rename_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5549,6 +5613,7 @@ pub fn send_configuration_to_plugins() { client_id, size, None, + None, false, None, None, @@ -5619,6 +5684,7 @@ pub fn request_plugin_permissions() { client_id, size, None, + None, false, None, None, @@ -5713,6 +5779,7 @@ pub fn granted_permission_request_result() { client_id, size, None, + None, false, None, None, @@ -5806,6 +5873,7 @@ pub fn denied_permission_request_result() { client_id, size, None, + None, false, None, None, @@ -5879,6 +5947,7 @@ pub fn run_command_plugin_command() { client_id, size, None, + None, false, None, None, @@ -5959,6 +6028,7 @@ pub fn run_command_with_env_vars_and_cwd_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6039,6 +6109,7 @@ pub fn web_request_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6112,6 +6183,7 @@ pub fn unblock_input_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6196,6 +6268,7 @@ pub fn block_input_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6288,6 +6361,7 @@ pub fn pipe_output_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6373,6 +6447,7 @@ pub fn pipe_message_to_plugin_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6469,6 +6544,7 @@ pub fn switch_session_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6552,6 +6628,7 @@ pub fn switch_session_with_layout_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6635,6 +6712,7 @@ pub fn switch_session_with_layout_and_cwd_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6718,6 +6796,7 @@ pub fn disconnect_other_clients_plugins_command() { client_id, size, None, + None, false, None, None, @@ -6801,6 +6880,7 @@ pub fn reconfigure_plugin_command() { client_id, size, None, + None, false, None, None, @@ -6888,6 +6968,7 @@ pub fn run_plugin_in_specific_cwd() { client_id, size, None, + None, false, None, None, @@ -6964,6 +7045,7 @@ pub fn hide_pane_with_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7037,6 +7119,7 @@ pub fn show_pane_with_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7117,6 +7200,7 @@ pub fn open_command_pane_background_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7194,6 +7278,7 @@ pub fn rerun_command_pane_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7267,6 +7352,7 @@ pub fn resize_pane_with_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7340,6 +7426,7 @@ pub fn edit_scrollback_for_pane_with_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7413,6 +7500,7 @@ pub fn write_to_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7486,6 +7574,7 @@ pub fn write_chars_to_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7559,6 +7648,7 @@ pub fn move_pane_with_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7632,6 +7722,7 @@ pub fn move_pane_with_pane_id_in_direction_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7705,6 +7796,7 @@ pub fn clear_screen_for_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7778,6 +7870,7 @@ pub fn scroll_up_in_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7851,6 +7944,7 @@ pub fn scroll_down_in_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7924,6 +8018,7 @@ pub fn scroll_to_top_in_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -7997,6 +8092,7 @@ pub fn scroll_to_bottom_in_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8070,6 +8166,7 @@ pub fn page_scroll_up_in_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8143,6 +8240,7 @@ pub fn page_scroll_down_in_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8216,6 +8314,7 @@ pub fn toggle_pane_id_fullscreen_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8289,6 +8388,7 @@ pub fn toggle_pane_embed_or_eject_for_pane_id_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8362,6 +8462,7 @@ pub fn close_tab_with_index_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8435,6 +8536,7 @@ pub fn break_panes_to_new_tab_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8508,6 +8610,7 @@ pub fn break_panes_to_tab_with_index_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8581,6 +8684,7 @@ pub fn reload_plugin_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8654,6 +8758,7 @@ pub fn load_new_plugin_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8734,6 +8839,7 @@ pub fn rebind_keys_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8810,6 +8916,7 @@ pub fn list_clients_plugin_command() { client_id, size, None, + None, false, None, None, @@ -8883,6 +8990,7 @@ pub fn before_close_plugin_event() { client_id, size, None, + None, false, None, None, diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index fd4b0d36..9ccd7c1d 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -775,6 +775,27 @@ impl WasmBridge { } Ok(()) } + pub fn get_plugin_cwd(&self, plugin_id: PluginId, client_id: ClientId) -> Option { + 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( &mut self, new_host_dir: PathBuf, @@ -793,12 +814,6 @@ impl WasmBridge { .running_plugins_and_subscriptions() .iter() .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(); task::spawn({ let senders = self.senders.clone(); diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 3b61f445..ebed4cbb 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -2222,6 +2222,7 @@ fn load_new_plugin( client_id, size, cwd, + None, skip_cache, None, None, diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index 26fe7203..88bfee7d 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -176,6 +176,7 @@ pub enum PtyInstruction { post_command_discovery_hook: Option, }, ListClientsToPlugin(SessionLayoutMetadata, PluginId, ClientId), + ReportPluginCwd(PluginId, PathBuf), Exit, } @@ -199,6 +200,7 @@ impl From<&PtyInstruction> for PtyContext { PtyInstruction::ListClientsMetadata(..) => PtyContext::ListClientsMetadata, PtyInstruction::Reconfigure { .. } => PtyContext::Reconfigure, PtyInstruction::ListClientsToPlugin(..) => PtyContext::ListClientsToPlugin, + PtyInstruction::ReportPluginCwd(..) => PtyContext::ReportPluginCwd, PtyInstruction::Exit => PtyContext::Exit, } } @@ -213,6 +215,7 @@ pub(crate) struct Pty { task_handles: HashMap>, // terminal_id to join-handle default_editor: Option, post_command_discovery_hook: Option, + plugin_cwds: HashMap, // plugin_id -> cwd } pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { @@ -676,6 +679,9 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { .with_context(err_context) .non_fatal(); }, + PtyInstruction::ReportPluginCwd(plugin_id, cwd) => { + pty.plugin_cwds.insert(plugin_id, cwd); + }, PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => { let err_context = || format!("Failed to dump layout"); pty.populate_session_layout_metadata(&mut session_layout_metadata); @@ -755,6 +761,7 @@ impl Pty { default_editor, originating_plugins: HashMap::new(), post_command_discovery_hook, + plugin_cwds: HashMap::new(), } } pub fn get_default_terminal( @@ -803,27 +810,31 @@ impl Pty { .active_panes .get(&client_id) .and_then(|pane| match pane { - PaneId::Plugin(..) => None, - PaneId::Terminal(id) => self.id_to_child_pid.get(id), + PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(), + PaneId::Terminal(id) => self.id_to_child_pid.get(id).and_then(|&id| { + self.bus + .os_input + .as_ref() + .and_then(|input| input.get_cwd(Pid::from_raw(id))) + }), }) - .and_then(|&id| { - self.bus - .os_input - .as_ref() - .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 run_command.cwd.is_none() { - run_command.cwd = self.id_to_child_pid.get(pane_id).and_then(|&id| { - self.bus - .os_input - .as_ref() - .and_then(|input| input.get_cwd(Pid::from_raw(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 + .os_input + .as_ref() + .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) => { let mut terminal_action = 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, &terminal_pane_id); - } + self.fill_cwd_from_pane_id(&mut terminal_action, &pane_id); terminal_action }, }; @@ -1482,18 +1491,24 @@ impl Pty { self.active_panes .get(&client_id) .and_then(|pane| match pane { - PaneId::Plugin(..) => None, - PaneId::Terminal(id) => self.id_to_child_pid.get(id), - }) - .and_then(|&id| { - self.bus - .os_input - .as_ref() - .and_then(|input| input.get_cwd(Pid::from_raw(id))) + PaneId::Plugin(plugin_id) => self.plugin_cwds.get(plugin_id).cloned(), + PaneId::Terminal(id) => self.id_to_child_pid.get(id).and_then(|&id| { + self.bus + .os_input + .as_ref() + .and_then(|input| input.get_cwd(Pid::from_raw(id))) + }), }) }; 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 { let cwd = get_focused_cwd(); @@ -1509,6 +1524,7 @@ impl Pty { client_id, size, cwd, + focused_plugin_id, skip_cache, should_focus_plugin, floating_pane_coordinates, diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 854410b6..836b5100 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -412,6 +412,7 @@ pub enum PtyContext { ListClientsMetadata, Reconfigure, ListClientsToPlugin, + ReportPluginCwd, Exit, }