From 21273ac95a2fed6b07d8550fe2d4f65993be7037 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Mon, 26 Feb 2024 15:30:15 +0100 Subject: [PATCH] feat(plugins): introduce plugin aliases (#3157) * working prototype with passing tests * new tests and passing plugin tests as well * style(code): cleanups * cleanup strider from unused search feature * prototype of removing old plugin block from the config * aliases working from config file and all tests passing * fixups and cleanups * use aliases in layouts * update test snapshot * style(fmt): rustfmt --- default-plugins/strider/src/main.rs | 138 ------ .../strider/src/search/controls_line.rs | 353 --------------- default-plugins/strider/src/search/mod.rs | 317 ------------- .../strider/src/search/search_results.rs | 308 ------------- .../strider/src/search/search_state.rs | 264 ----------- .../src/search/selection_controls_area.rs | 61 --- default-plugins/strider/src/search/ui.rs | 120 ----- default-plugins/strider/src/state.rs | 22 - zellij-client/src/lib.rs | 2 +- zellij-server/src/lib.rs | 13 +- zellij-server/src/panes/floating_panes/mod.rs | 7 +- zellij-server/src/panes/tiled_panes/mod.rs | 7 +- zellij-server/src/plugins/mod.rs | 216 +++++---- .../src/plugins/unit/plugin_tests.rs | 415 +++++++++++------- ...ts__load_new_plugin_with_plugin_alias.snap | 12 + ..._plugin_tests__start_or_reload_plugin.snap | 22 +- zellij-server/src/plugins/wasm_bridge.rs | 287 ++++++------ zellij-server/src/plugins/zellij_exports.rs | 14 +- zellij-server/src/pty.rs | 14 +- zellij-server/src/route.rs | 4 +- zellij-server/src/screen.rs | 92 ++-- zellij-server/src/session_layout_metadata.rs | 5 +- zellij-server/src/tab/layout_applier.rs | 18 +- zellij-server/src/tab/mod.rs | 17 +- ...ng_layout_is_included_in_swap_layouts.snap | 4 +- ..._plugins_and_commands_swaped_properly.snap | 4 +- ...and_panes_absent_from_existing_layout.snap | 4 +- ...mand_panes_present_in_existing_layout.snap | 6 +- ...ugin_panes_present_in_existing_layout.snap | 6 +- ...ugin_panes_present_in_existing_layout.snap | 6 +- .../src/tab/unit/tab_integration_tests.rs | 106 +---- zellij-server/src/unit/screen_tests.rs | 194 +++++++- ...k_floating_plugin_pane_to_a_new_tab-2.snap | 6 +- ...k_floating_plugin_pane_to_a_new_tab-3.snap | 6 +- ...k_floating_plugin_pane_to_a_new_tab-4.snap | 6 +- ...k_floating_plugin_pane_to_a_new_tab-6.snap | 6 +- ...k_floating_plugin_pane_to_a_new_tab-7.snap | 6 +- ...eak_floating_plugin_pane_to_a_new_tab.snap | 6 +- ..._can_break_plugin_pane_to_a_new_tab-3.snap | 4 +- ..._can_break_plugin_pane_to_a_new_tab-4.snap | 4 +- ...en_can_break_plugin_pane_to_a_new_tab.snap | 4 +- ...end_cli_launch_or_focus_plugin_action.snap | 22 +- zellij-utils/assets/config/default.kdl | 14 +- zellij-utils/assets/layouts/compact.kdl | 2 +- zellij-utils/assets/layouts/compact.swap.kdl | 2 +- zellij-utils/assets/layouts/default.kdl | 4 +- zellij-utils/assets/layouts/default.swap.kdl | 4 +- .../assets/layouts/disable-status-bar.kdl | 2 +- zellij-utils/assets/layouts/strider.kdl | 6 +- zellij-utils/assets/layouts/strider.swap.kdl | 6 +- zellij-utils/assets/layouts/welcome.kdl | 4 +- zellij-utils/src/cli.rs | 2 +- zellij-utils/src/input/actions.rs | 82 ++-- zellij-utils/src/input/config.rs | 86 ++-- zellij-utils/src/input/layout.rs | 196 ++++++++- zellij-utils/src/input/plugins.rs | 113 ++--- zellij-utils/src/input/unit/layout_test.rs | 47 +- ...ad_swap_layouts_from_a_different_file.snap | 134 +++--- zellij-utils/src/ipc.rs | 4 +- zellij-utils/src/kdl/kdl_layout_parser.rs | 31 +- zellij-utils/src/kdl/mod.rs | 99 +++-- zellij-utils/src/plugin_api/action.rs | 104 +++-- zellij-utils/src/session_serialization.rs | 31 +- zellij-utils/src/setup.rs | 14 - ...efault_config_with_no_cli_arguments-2.snap | 322 +++++++------- ..._default_config_with_no_cli_arguments.snap | 180 ++++---- ...out_env_vars_override_config_env_vars.snap | 180 ++++---- ...out_keybinds_override_config_keybinds.snap | 158 ++++--- ...ayout_plugins_override_config_plugins.snap | 24 +- ..._layout_themes_override_config_themes.snap | 180 ++++---- ..._ui_config_overrides_config_ui_config.snap | 180 ++++---- 71 files changed, 2097 insertions(+), 3242 deletions(-) delete mode 100644 default-plugins/strider/src/search/controls_line.rs delete mode 100644 default-plugins/strider/src/search/mod.rs delete mode 100644 default-plugins/strider/src/search/search_results.rs delete mode 100644 default-plugins/strider/src/search/search_state.rs delete mode 100644 default-plugins/strider/src/search/selection_controls_area.rs delete mode 100644 default-plugins/strider/src/search/ui.rs create mode 100644 zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__load_new_plugin_with_plugin_alias.snap diff --git a/default-plugins/strider/src/main.rs b/default-plugins/strider/src/main.rs index 598bf61d..2e06240a 100644 --- a/default-plugins/strider/src/main.rs +++ b/default-plugins/strider/src/main.rs @@ -1,49 +1,22 @@ -mod search; mod state; use colored::*; -use search::{FileContentsWorker, FileNameWorker, MessageToSearch, ResultsOfSearch}; -use serde::{Deserialize, Serialize}; -use serde_json; use state::{refresh_directory, FsEntry, State}; use std::collections::BTreeMap; use std::{cmp::min, time::Instant}; use zellij_tile::prelude::*; register_plugin!(State); -register_worker!(FileNameWorker, file_name_search_worker, FILE_NAME_WORKER); -register_worker!( - FileContentsWorker, - file_contents_search_worker, - FILE_CONTENTS_WORKER -); impl ZellijPlugin for State { fn load(&mut self, _configuration: BTreeMap) { refresh_directory(self); - self.search_state.loading = true; subscribe(&[ EventType::Key, EventType::Mouse, EventType::CustomMessage, EventType::Timer, - EventType::FileSystemCreate, - EventType::FileSystemUpdate, - EventType::FileSystemDelete, - EventType::PermissionRequestResult, ]); - post_message_to(PluginMessage { - worker_name: Some("file_name_search".into()), - name: serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(), - payload: "".into(), - }); - post_message_to(PluginMessage { - worker_name: Some("file_contents_search".into()), - name: serde_json::to_string(&MessageToSearch::ScanFolder).unwrap(), - payload: "".into(), - }); - self.search_state.loading = true; - set_timeout(0.5); // for displaying loading animation } fn update(&mut self, event: Event) -> bool { @@ -55,58 +28,8 @@ impl ZellijPlugin for State { }; self.ev_history.push_back((event.clone(), Instant::now())); match event { - Event::PermissionRequestResult(_) => { - should_render = true; - }, - Event::Timer(_elapsed) => { - if self.search_state.loading { - set_timeout(0.5); - self.search_state.progress_animation(); - should_render = true; - } - }, - Event::CustomMessage(message, payload) => match serde_json::from_str(&message) { - Ok(MessageToPlugin::UpdateFileNameSearchResults) => { - if let Ok(results_of_search) = serde_json::from_str::(&payload) - { - self.search_state - .update_file_name_search_results(results_of_search); - should_render = true; - } - }, - Ok(MessageToPlugin::UpdateFileContentsSearchResults) => { - if let Ok(results_of_search) = serde_json::from_str::(&payload) - { - self.search_state - .update_file_contents_search_results(results_of_search); - should_render = true; - } - }, - Ok(MessageToPlugin::DoneScanningFolder) => { - self.search_state.loading = false; - should_render = true; - }, - Err(e) => eprintln!("Failed to deserialize custom message: {:?}", e), - }, Event::Key(key) => match key { - Key::Esc if self.typing_search_term() => { - if self.search_state.search_term.is_empty() { - self.stop_typing_search_term(); - } else { - self.search_state.handle_key(key); - } - should_render = true; - }, - _ if self.typing_search_term() => { - self.search_state.handle_key(key); - should_render = true; - }, - Key::Char('/') => { - self.start_typing_search_term(); - should_render = true; - }, Key::Esc => { - self.stop_typing_search_term(); hide_self(); should_render = true; }, @@ -190,54 +113,6 @@ impl ZellijPlugin for State { }, _ => {}, }, - Event::FileSystemCreate(paths) => { - let paths: Vec = paths - .iter() - .map(|p| p.to_string_lossy().to_string()) - .collect(); - post_message_to(PluginMessage { - worker_name: Some("file_name_search".into()), - name: serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(), - payload: serde_json::to_string(&paths).unwrap(), - }); - post_message_to(PluginMessage { - worker_name: Some("file_contents_search".into()), - name: serde_json::to_string(&MessageToSearch::FileSystemCreate).unwrap(), - payload: serde_json::to_string(&paths).unwrap(), - }); - }, - Event::FileSystemUpdate(paths) => { - let paths: Vec = paths - .iter() - .map(|p| p.to_string_lossy().to_string()) - .collect(); - post_message_to(PluginMessage { - worker_name: Some("file_name_search".into()), - name: serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(), - payload: serde_json::to_string(&paths).unwrap(), - }); - post_message_to(PluginMessage { - worker_name: Some("file_contents_search".into()), - name: serde_json::to_string(&MessageToSearch::FileSystemUpdate).unwrap(), - payload: serde_json::to_string(&paths).unwrap(), - }); - }, - Event::FileSystemDelete(paths) => { - let paths: Vec = paths - .iter() - .map(|p| p.to_string_lossy().to_string()) - .collect(); - post_message_to(PluginMessage { - worker_name: Some("file_name_search".into()), - name: serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(), - payload: serde_json::to_string(&paths).unwrap(), - }); - post_message_to(PluginMessage { - worker_name: Some("file_contents_search".into()), - name: serde_json::to_string(&MessageToSearch::FileSystemDelete).unwrap(), - payload: serde_json::to_string(&paths).unwrap(), - }); - }, _ => { dbg!("Unknown event {:?}", event); }, @@ -246,12 +121,6 @@ impl ZellijPlugin for State { } fn render(&mut self, rows: usize, cols: usize) { - if self.typing_search_term() { - self.search_state.change_size(rows, cols); - print!("{}", self.search_state); - return; - } - for i in 0..rows { if self.selected() < self.scroll() { *self.scroll_mut() = self.selected(); @@ -288,10 +157,3 @@ impl ZellijPlugin for State { } } } - -#[derive(Serialize, Deserialize)] -pub enum MessageToPlugin { - UpdateFileNameSearchResults, - UpdateFileContentsSearchResults, - DoneScanningFolder, -} diff --git a/default-plugins/strider/src/search/controls_line.rs b/default-plugins/strider/src/search/controls_line.rs deleted file mode 100644 index a75715ef..00000000 --- a/default-plugins/strider/src/search/controls_line.rs +++ /dev/null @@ -1,353 +0,0 @@ -use crate::search::search_state::SearchType; -use crate::search::ui::{ - arrow, bold, color_line_to_end, dot, styled_text, BLACK, GRAY_DARK, GRAY_LIGHT, RED, WHITE, -}; - -#[derive(Default)] -pub struct ControlsLine { - controls: Vec, - scanning_indication: Option>, - animation_offset: u8, -} - -impl ControlsLine { - pub fn new(controls: Vec, scanning_indication: Option>) -> Self { - ControlsLine { - controls, - scanning_indication, - ..Default::default() - } - } - pub fn with_animation_offset(mut self, animation_offset: u8) -> Self { - self.animation_offset = animation_offset; - self - } - pub fn render(&self, max_width: usize, show_controls: bool) -> String { - if show_controls { - self.render_controls(max_width) - } else { - self.render_empty_line(max_width) - } - } - pub fn render_controls(&self, max_width: usize) -> String { - let loading_animation = - LoadingAnimation::new(&self.scanning_indication, self.animation_offset); - let full_length = loading_animation.full_len() - + self.controls.iter().map(|c| c.full_len()).sum::(); - let mid_length = - loading_animation.mid_len() + self.controls.iter().map(|c| c.mid_len()).sum::(); - let short_length = loading_animation.short_len() - + self.controls.iter().map(|c| c.short_len()).sum::(); - if max_width >= full_length { - let mut to_render = String::new(); - for control in &self.controls { - to_render.push_str(&control.render_full_length()); - } - to_render.push_str(&self.render_padding(max_width.saturating_sub(full_length))); - to_render.push_str(&loading_animation.render_full_length()); - to_render - } else if max_width >= mid_length { - let mut to_render = String::new(); - for control in &self.controls { - to_render.push_str(&control.render_mid_length()); - } - to_render.push_str(&self.render_padding(max_width.saturating_sub(mid_length))); - to_render.push_str(&loading_animation.render_mid_length()); - to_render - } else if max_width >= short_length { - let mut to_render = String::new(); - for control in &self.controls { - to_render.push_str(&control.render_short_length()); - } - to_render.push_str(&self.render_padding(max_width.saturating_sub(short_length))); - to_render.push_str(&loading_animation.render_short_length()); - to_render - } else { - format!("") - } - } - pub fn render_empty_line(&self, max_width: usize) -> String { - let loading_animation = - LoadingAnimation::new(&self.scanning_indication, self.animation_offset); - let mut to_render = String::new(); - if max_width >= loading_animation.full_len() { - to_render.push_str( - &self.render_padding(max_width.saturating_sub(loading_animation.full_len())), - ); - to_render.push_str(&loading_animation.render_full_length()); - } else if max_width >= loading_animation.mid_len() { - to_render.push_str( - &self.render_padding(max_width.saturating_sub(loading_animation.mid_len())), - ); - to_render.push_str(&loading_animation.render_mid_length()); - } else if max_width >= loading_animation.short_len() { - to_render.push_str( - &self.render_padding(max_width.saturating_sub(loading_animation.short_len())), - ); - to_render.push_str(&loading_animation.render_short_length()); - } - to_render - } - fn render_padding(&self, padding: usize) -> String { - // TODO: color whole line - format!("{}\u{1b}[{}C", color_line_to_end(GRAY_LIGHT), padding) - } -} - -pub struct Control { - key: &'static str, - options: Vec<&'static str>, - option_index: (usize, usize), // eg. 1 out of 2 (1, 2) - keycode_background_color: u8, - keycode_foreground_color: u8, - control_text_background_color: u8, - control_text_foreground_color: u8, - active_dot_color: u8, -} - -impl Default for Control { - fn default() -> Self { - Control { - key: "", - options: vec![], - option_index: (0, 0), - keycode_background_color: GRAY_LIGHT, - keycode_foreground_color: WHITE, - control_text_background_color: GRAY_DARK, - control_text_foreground_color: BLACK, - active_dot_color: RED, - } - } -} - -impl Control { - pub fn new( - key: &'static str, - options: Vec<&'static str>, - option_index: (usize, usize), - ) -> Self { - Control { - key, - options, - option_index, - ..Default::default() - } - } - pub fn new_floating_control(key: &'static str, should_open_floating: bool) -> Self { - if should_open_floating { - Control::new(key, vec!["OPEN FLOATING", "FLOATING", "F"], (2, 2)) - } else { - Control::new(key, vec!["OPEN TILED", "TILED", "T"], (1, 2)) - } - } - pub fn new_filter_control(key: &'static str, search_filter: &SearchType) -> Self { - match search_filter { - SearchType::NamesAndContents => Control::new( - key, - vec!["FILE NAMES AND CONTENTS", "NAMES + CONTENTS", "N+C"], - (1, 3), - ), - SearchType::Names => Control::new(key, vec!["FILE NAMES", "NAMES", "N"], (2, 3)), - SearchType::Contents => { - Control::new(key, vec!["FILE CONTENTS", "CONTENTS", "C"], (3, 3)) - }, - } - } - pub fn short_len(&self) -> usize { - let short_text = self - .options - .get(2) - .or_else(|| self.options.get(1)) - .or_else(|| self.options.get(0)) - .unwrap_or(&""); - short_text.chars().count() + self.key.chars().count() + self.option_index.1 + 7 - // 7 for all the spaces and decorations - } - pub fn mid_len(&self) -> usize { - let mid_text = self - .options - .get(1) - .or_else(|| self.options.get(0)) - .unwrap_or(&""); - mid_text.chars().count() + self.key.chars().count() + self.option_index.1 + 7 - // 7 for all the spaces and decorations - } - pub fn full_len(&self) -> usize { - let full_text = self.options.get(0).unwrap_or(&""); - full_text.chars().count() + self.key.chars().count() + self.option_index.1 + 7 - // 7 for all the spaces and decorations - } - pub fn render_short_length(&self) -> String { - let short_text = self - .options - .get(2) - .or_else(|| self.options.get(1)) - .or_else(|| self.options.get(0)) - .unwrap_or(&""); - self.render(short_text) - } - pub fn render_mid_length(&self) -> String { - let mid_text = self - .options - .get(1) - .or_else(|| self.options.get(0)) - .unwrap_or(&""); - self.render(mid_text) - } - pub fn render_full_length(&self) -> String { - let full_text = self.options.get(0).unwrap_or(&""); - self.render(full_text) - } - fn render(&self, text: &str) -> String { - format!( - "{}{}{}{}{}{}", - self.render_keycode(&format!(" {} ", self.key)), - arrow( - self.keycode_background_color, - self.control_text_background_color - ), - self.render_selection_dots(), - self.render_control_text(&format!("{} ", text)), - arrow( - self.control_text_background_color, - self.keycode_background_color - ), - color_line_to_end(self.keycode_background_color), - ) - } - fn render_keycode(&self, text: &str) -> String { - styled_text( - self.keycode_foreground_color, - self.keycode_background_color, - &bold(text), - ) - } - fn render_control_text(&self, text: &str) -> String { - styled_text( - self.control_text_foreground_color, - self.control_text_background_color, - &bold(text), - ) - } - fn render_selection_dots(&self) -> String { - let mut selection_dots = String::from(" "); - for i in 1..=self.option_index.1 { - if i == self.option_index.0 { - selection_dots.push_str(&dot( - self.active_dot_color, - self.control_text_background_color, - )); - } else { - selection_dots.push_str(&dot( - self.control_text_foreground_color, - self.control_text_background_color, - )); - } - } - selection_dots.push_str(" "); - selection_dots - } -} - -struct LoadingAnimation { - scanning_indication: Option>, - animation_offset: u8, - background_color: u8, - foreground_color: u8, -} -impl LoadingAnimation { - pub fn new(scanning_indication: &Option>, animation_offset: u8) -> Self { - LoadingAnimation { - scanning_indication: scanning_indication.clone(), - animation_offset, - background_color: GRAY_LIGHT, - foreground_color: WHITE, - } - } - pub fn full_len(&self) -> usize { - self.scanning_indication - .as_ref() - .and_then(|scanning_indication| scanning_indication.get(0)) - .map(|s| s.chars().count() + 3) // 3 for animation dots - .unwrap_or(0) - } - pub fn mid_len(&self) -> usize { - self.scanning_indication - .as_ref() - .and_then(|scanning_indication| { - scanning_indication - .get(1) - .or_else(|| scanning_indication.get(0)) - }) - .map(|s| s.chars().count() + 3) // 3 for animation dots - .unwrap_or(0) - } - pub fn short_len(&self) -> usize { - self.scanning_indication - .as_ref() - .and_then(|scanning_indication| { - scanning_indication - .get(2) - .or_else(|| scanning_indication.get(1)) - .or_else(|| scanning_indication.get(0)) - }) - .map(|s| s.chars().count() + 3) // 3 for animation dots - .unwrap_or(0) - } - pub fn render_full_length(&self) -> String { - self.scanning_indication - .as_ref() - .and_then(|scanning_indication| scanning_indication.get(0)) - .map(|s| { - styled_text( - self.foreground_color, - self.background_color, - &bold(&(s.to_string() + &self.animation_dots())), - ) - }) - .unwrap_or_else(String::new) - } - pub fn render_mid_length(&self) -> String { - self.scanning_indication - .as_ref() - .and_then(|scanning_indication| { - scanning_indication - .get(1) - .or_else(|| scanning_indication.get(0)) - }) - .map(|s| { - styled_text( - self.background_color, - self.foreground_color, - &bold(&(s.to_string() + &self.animation_dots())), - ) - }) - .unwrap_or_else(String::new) - } - pub fn render_short_length(&self) -> String { - self.scanning_indication - .as_ref() - .and_then(|scanning_indication| { - scanning_indication - .get(2) - .or_else(|| scanning_indication.get(1)) - .or_else(|| scanning_indication.get(0)) - }) - .map(|s| { - styled_text( - self.background_color, - self.foreground_color, - &bold(&(s.to_string() + &self.animation_dots())), - ) - }) - .unwrap_or_else(String::new) - } - fn animation_dots(&self) -> String { - let mut to_render = String::from(""); - let dot_count = self.animation_offset % 4; - for _ in 0..dot_count { - to_render.push('.'); - } - to_render - } -} diff --git a/default-plugins/strider/src/search/mod.rs b/default-plugins/strider/src/search/mod.rs deleted file mode 100644 index 6ffa60cb..00000000 --- a/default-plugins/strider/src/search/mod.rs +++ /dev/null @@ -1,317 +0,0 @@ -pub mod controls_line; -pub mod search_results; -pub mod search_state; -pub mod selection_controls_area; -pub mod ui; - -use crate::state::{CURRENT_SEARCH_TERM, ROOT}; -use crate::MessageToPlugin; -use search_state::SearchType; -use std::collections::{BTreeMap, BTreeSet, HashMap}; -use std::path::{Path, PathBuf}; - -use unicode_width::UnicodeWidthStr; -use zellij_tile::prelude::*; - -use fuzzy_matcher::skim::SkimMatcherV2; -use fuzzy_matcher::FuzzyMatcher; -use ignore::Walk; -use search_results::SearchResult; -use serde::{Deserialize, Serialize}; - -use std::io::{self, BufRead}; - -#[derive(Default, Serialize, Deserialize)] -pub struct Search { - search_type: SearchType, - file_names: BTreeSet, - file_contents: BTreeMap<(String, usize), String>, // file_name, line_number, line - cached_file_name_results: HashMap>, - cached_file_contents_results: HashMap>, -} - -impl Search { - pub fn new(search_type: SearchType) -> Self { - Search { - search_type, - ..Default::default() - } - } - fn on_message(&mut self, message: String, payload: String) { - match serde_json::from_str::(&message) { - Ok(MessageToSearch::ScanFolder) => { - self.scan_hd(); - post_message_to_plugin(PluginMessage { - worker_name: None, - name: serde_json::to_string(&MessageToPlugin::DoneScanningFolder).unwrap(), - payload: "".to_owned(), - }); - }, - Ok(MessageToSearch::Search) => { - if let Some(current_search_term) = self.read_search_term_from_hd_cache() { - self.search(current_search_term); - } - }, - Ok(MessageToSearch::FileSystemCreate) => { - self.rescan_files(payload); - }, - Ok(MessageToSearch::FileSystemUpdate) => { - self.rescan_files(payload); - }, - Ok(MessageToSearch::FileSystemDelete) => { - self.delete_files(payload); - }, - Err(e) => eprintln!("Failed to deserialize worker message {:?}", e), - } - } - pub fn scan_hd(&mut self) { - for result in Walk::new(ROOT) { - if let Ok(entry) = result { - self.add_file_entry(entry.path(), entry.metadata().ok()); - } - } - } - pub fn search(&mut self, search_term: String) { - let search_results_limit = 100; // artificial limit to prevent probably unwanted chaos - // let mut matcher = SkimMatcherV2::default().use_cache(true).element_limit(search_results_limit); - let mut file_names_search_results = None; - let mut file_contents_search_results = None; - if let SearchType::Names | SearchType::NamesAndContents = self.search_type { - let file_names_matches = match self.cached_file_name_results.get(&search_term) { - Some(cached_results) => cached_results.clone(), - None => { - let mut matcher = SkimMatcherV2::default().use_cache(true); - let results = self.search_file_names(&search_term, &mut matcher); - self.cached_file_name_results - .insert(search_term.clone(), results.clone()); - results - }, - }; - file_names_search_results = Some( - ResultsOfSearch::new(search_term.clone(), file_names_matches) - .limit_search_results(search_results_limit), - ); - }; - if let SearchType::Contents | SearchType::NamesAndContents = self.search_type { - let file_contents_matches = match self.cached_file_contents_results.get(&search_term) { - Some(cached_results) => cached_results.clone(), - None => { - let mut matcher = SkimMatcherV2::default().use_cache(true); - let results = self.search_file_contents(&search_term, &mut matcher); - self.cached_file_contents_results - .insert(search_term.clone(), results.clone()); - results - }, - }; - file_contents_search_results = Some( - ResultsOfSearch::new(search_term.clone(), file_contents_matches) - .limit_search_results(search_results_limit), - ); - }; - - // if the search term changed before we finished, let's search again! - if let Some(current_search_term) = self.read_search_term_from_hd_cache() { - if current_search_term != search_term { - return self.search(current_search_term.into()); - } - } - if let Some(file_names_search_results) = file_names_search_results { - post_message_to_plugin(PluginMessage { - name: serde_json::to_string(&MessageToPlugin::UpdateFileNameSearchResults).unwrap(), - payload: serde_json::to_string(&file_names_search_results).unwrap(), - ..Default::default() - }); - } - if let Some(file_contents_search_results) = file_contents_search_results { - post_message_to_plugin(PluginMessage { - name: serde_json::to_string(&MessageToPlugin::UpdateFileContentsSearchResults) - .unwrap(), - payload: serde_json::to_string(&file_contents_search_results).unwrap(), - ..Default::default() - }); - } - } - pub fn rescan_files(&mut self, paths: String) { - match serde_json::from_str::>(&paths) { - Ok(paths) => { - for path in paths { - self.add_file_entry(&path, path.metadata().ok()); - } - self.cached_file_name_results.clear(); - self.cached_file_contents_results.clear(); - }, - Err(e) => eprintln!("Failed to deserialize paths: {:?}", e), - } - } - pub fn delete_files(&mut self, paths: String) { - match serde_json::from_str::>(&paths) { - Ok(paths) => { - self.remove_existing_entries(&paths); - self.cached_file_name_results.clear(); - self.cached_file_contents_results.clear(); - }, - Err(e) => eprintln!("Failed to deserialize paths: {:?}", e), - } - } - fn add_file_entry(&mut self, file_name: &Path, file_metadata: Option) { - let file_path = file_name.display().to_string(); - let file_path_stripped_prefix = self.strip_file_prefix(&file_name); - - self.file_names.insert(file_path_stripped_prefix.clone()); - if let SearchType::NamesAndContents | SearchType::Contents = self.search_type { - if file_metadata.map(|f| f.is_file()).unwrap_or(false) { - if let Ok(file) = std::fs::File::open(&file_path) { - let lines = io::BufReader::new(file).lines(); - for (index, line) in lines.enumerate() { - match line { - Ok(line) => { - self.file_contents.insert( - (file_path_stripped_prefix.clone(), index + 1), - String::from_utf8_lossy( - &strip_ansi_escapes::strip(line).unwrap(), - ) - .to_string(), - ); - }, - Err(_) => { - break; // probably a binary file, skip it - }, - } - } - } - } - } - } - fn search_file_names( - &self, - search_term: &str, - matcher: &mut SkimMatcherV2, - ) -> Vec { - let mut matches = vec![]; - for entry in &self.file_names { - if let Some((score, indices)) = matcher.fuzzy_indices(&entry, &search_term) { - matches.push(SearchResult::new_file_name( - score, - indices, - entry.to_owned(), - )); - } - } - matches - } - fn search_file_contents( - &self, - search_term: &str, - matcher: &mut SkimMatcherV2, - ) -> Vec { - let mut matches = vec![]; - for ((file_name, line_number), line_entry) in &self.file_contents { - if let Some((score, indices)) = matcher.fuzzy_indices(&line_entry, &search_term) { - matches.push(SearchResult::new_file_line( - score, - indices, - file_name.clone(), - line_entry.clone(), - *line_number, - )); - } - } - matches - } - fn strip_file_prefix(&self, file_name: &Path) -> String { - let mut file_path_stripped_prefix = file_name.display().to_string().split_off(ROOT.width()); - if file_path_stripped_prefix.starts_with('/') { - file_path_stripped_prefix.remove(0); - } - file_path_stripped_prefix - } - fn read_search_term_from_hd_cache(&self) -> Option { - match std::fs::read(CURRENT_SEARCH_TERM) { - Ok(current_search_term) => { - Some(String::from_utf8_lossy(¤t_search_term).to_string()) - }, - _ => None, - } - } - fn remove_existing_entries(&mut self, paths: &Vec) { - let file_path_stripped_prefixes: Vec = - paths.iter().map(|p| self.strip_file_prefix(&p)).collect(); - self.file_names - .retain(|file_name| !file_path_stripped_prefixes.contains(file_name)); - self.file_contents.retain(|(file_name, _line_in_file), _| { - !file_path_stripped_prefixes.contains(file_name) - }); - } -} - -#[derive(Serialize, Deserialize)] -pub enum MessageToSearch { - ScanFolder, - Search, - FileSystemCreate, - FileSystemUpdate, - FileSystemDelete, -} - -#[derive(Serialize, Deserialize)] -pub struct FileNameWorker { - search: Search, -} - -impl Default for FileNameWorker { - fn default() -> Self { - FileNameWorker { - search: Search::new(SearchType::Names), - } - } -} - -#[derive(Serialize, Deserialize)] -pub struct FileContentsWorker { - search: Search, -} - -impl Default for FileContentsWorker { - fn default() -> Self { - FileContentsWorker { - search: Search::new(SearchType::Contents), - } - } -} - -impl<'de> ZellijWorker<'de> for FileNameWorker { - fn on_message(&mut self, message: String, payload: String) { - self.search.on_message(message, payload); - } -} - -impl<'de> ZellijWorker<'de> for FileContentsWorker { - fn on_message(&mut self, message: String, payload: String) { - self.search.on_message(message, payload); - } -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ResultsOfSearch { - pub search_term: String, - pub search_results: Vec, -} - -impl ResultsOfSearch { - pub fn new(search_term: String, search_results: Vec) -> Self { - ResultsOfSearch { - search_term, - search_results, - } - } - pub fn limit_search_results(mut self, max_results: usize) -> Self { - self.search_results - .sort_by(|a, b| b.score().cmp(&a.score())); - self.search_results = if self.search_results.len() > max_results { - self.search_results.drain(..max_results).collect() - } else { - self.search_results.drain(..).collect() - }; - self - } -} diff --git a/default-plugins/strider/src/search/search_results.rs b/default-plugins/strider/src/search/search_results.rs deleted file mode 100644 index b76200ae..00000000 --- a/default-plugins/strider/src/search/search_results.rs +++ /dev/null @@ -1,308 +0,0 @@ -use crate::search::ui::{ - bold, styled_text, styled_text_background, styled_text_foreground, underline, GRAY_LIGHT, - GREEN, ORANGE, -}; -use serde::{Deserialize, Serialize}; -use unicode_width::UnicodeWidthStr; - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum SearchResult { - File { - path: String, - score: i64, - indices: Vec, - }, - LineInFile { - path: String, - line: String, - line_number: usize, - score: i64, - indices: Vec, - }, -} - -impl SearchResult { - pub fn new_file_name(score: i64, indices: Vec, path: String) -> Self { - SearchResult::File { - path, - score, - indices, - } - } - pub fn new_file_line( - score: i64, - indices: Vec, - path: String, - line: String, - line_number: usize, - ) -> Self { - SearchResult::LineInFile { - path, - score, - indices, - line, - line_number, - } - } - pub fn score(&self) -> i64 { - match self { - SearchResult::File { score, .. } => *score, - SearchResult::LineInFile { score, .. } => *score, - } - } - pub fn rendered_height(&self) -> usize { - match self { - SearchResult::File { .. } => 1, - SearchResult::LineInFile { .. } => 2, - } - } - pub fn is_same_entry(&self, other: &Self) -> bool { - match (&self, other) { - ( - SearchResult::File { path: my_path, .. }, - SearchResult::File { - path: other_path, .. - }, - ) => my_path == other_path, - ( - SearchResult::LineInFile { - path: my_path, - line_number: my_line_number, - .. - }, - SearchResult::LineInFile { - path: other_path, - line_number: other_line_number, - .. - }, - ) => my_path == other_path && my_line_number == other_line_number, - _ => false, - } - } - pub fn render( - &self, - max_width: usize, - is_selected: bool, - is_below_search_result: bool, - ) -> String { - let max_width = max_width.saturating_sub(4); // for the UI left line separator - match self { - SearchResult::File { path, indices, .. } => self.render_file_result( - path, - indices, - is_selected, - is_below_search_result, - max_width, - ), - SearchResult::LineInFile { - path, - line, - line_number, - indices, - .. - } => self.render_line_in_file_result( - path, - line, - *line_number, - indices, - is_selected, - is_below_search_result, - max_width, - ), - } - } - fn render_file_result( - &self, - path: &String, - indices: &Vec, - is_selected: bool, - is_below_search_result: bool, - max_width: usize, - ) -> String { - if is_selected { - let line = self.render_line_with_indices( - path, - indices, - max_width.saturating_sub(3), - Some(GREEN), - ); - let selection_arrow = styled_text_foreground(ORANGE, "┌>"); - format!("{} {}", selection_arrow, line) - } else { - let line_prefix = if is_below_search_result { "│ " } else { " " }; - let line = - self.render_line_with_indices(path, indices, max_width.saturating_sub(3), None); - format!("{} {}", line_prefix, line) - } - } - fn render_line_in_file_result( - &self, - path: &String, - line: &String, - line_number: usize, - indices: &Vec, - is_selected: bool, - is_below_search_result: bool, - max_width: usize, - ) -> String { - let line_number_prefix_text = format!("└ {} ", line_number); - let max_width_of_line_in_file = max_width - .saturating_sub(3) - .saturating_sub(line_number_prefix_text.width()); - if is_selected { - let file_name_line = self.render_line_with_indices( - path, - &vec![], - max_width.saturating_sub(3), - Some(GREEN), - ); - let line_in_file = self.render_line_with_indices( - line, - indices, - max_width_of_line_in_file, - Some(GREEN), - ); - let line_number_prefix = styled_text_foreground(GREEN, &bold(&line_number_prefix_text)); - format!( - "{} {}\n│ {}{}", - styled_text_foreground(ORANGE, "┌>"), - file_name_line, - line_number_prefix, - line_in_file - ) - } else { - let file_name_line = - self.render_line_with_indices(path, &vec![], max_width.saturating_sub(3), None); - let line_in_file = - self.render_line_with_indices(line, indices, max_width_of_line_in_file, None); - let line_number_prefix = bold(&line_number_prefix_text); - let line_prefix = if is_below_search_result { "│ " } else { " " }; - format!( - "{} {}\n{} {}{}", - line_prefix, file_name_line, line_prefix, line_number_prefix, line_in_file - ) - } - } - fn render_line_with_indices( - &self, - line_to_render: &String, - indices: &Vec, - max_width: usize, - foreground_color: Option, - ) -> String { - let non_index_character_style = |c: &str| match foreground_color { - Some(foreground_color) => styled_text_foreground(foreground_color, &bold(c)), - None => bold(c), - }; - let index_character_style = |c: &str| match foreground_color { - Some(foreground_color) => { - styled_text(foreground_color, GRAY_LIGHT, &bold(&underline(c))) - }, - None => styled_text_background(GRAY_LIGHT, &bold(&underline(c))), - }; - - let truncate_positions = - self.truncate_line_with_indices(line_to_render, indices, max_width); - let truncate_start_position = truncate_positions.map(|p| p.0).unwrap_or(0); - let truncate_end_position = truncate_positions - .map(|p| p.1) - .unwrap_or(line_to_render.chars().count()); - let mut visible_portion = String::new(); - for (i, character) in line_to_render.chars().enumerate() { - if i >= truncate_start_position && i <= truncate_end_position { - if indices.contains(&i) { - visible_portion.push_str(&index_character_style(&character.to_string())); - } else { - visible_portion.push_str(&non_index_character_style(&character.to_string())); - } - } - } - if truncate_positions.is_some() { - let left_truncate_sign = if truncate_start_position == 0 { - "" - } else { - ".." - }; - let right_truncate_sign = if truncate_end_position == line_to_render.chars().count() { - "" - } else { - ".." - }; - format!( - "{}{}{}", - non_index_character_style(left_truncate_sign), - visible_portion, - non_index_character_style(right_truncate_sign) - ) - } else { - visible_portion - } - } - fn truncate_line_with_indices( - &self, - line_to_render: &String, - indices: &Vec, - max_width: usize, - ) -> Option<(usize, usize)> { - let first_index = indices.get(0).copied().unwrap_or(0); - let last_index = indices - .last() - .copied() - .unwrap_or_else(|| std::cmp::min(line_to_render.chars().count(), max_width)); - if line_to_render.width() <= max_width { - // there's enough room, no need to truncate - None - } else if last_index.saturating_sub(first_index) < max_width { - // truncate around the indices - let mut width_remaining = max_width - .saturating_sub(1) - .saturating_sub(last_index.saturating_sub(first_index)); - - let mut string_start_position = first_index; - let mut string_end_position = last_index; - - let mut i = 0; - loop { - if i >= width_remaining { - break; - } - if string_start_position > 0 && string_end_position < line_to_render.chars().count() - { - let take_from_start = i % 2 == 0; - if take_from_start { - string_start_position -= 1; - if string_start_position == 0 { - width_remaining += 2; // no need for truncating dots - } - } else { - string_end_position += 1; - if string_end_position == line_to_render.chars().count() { - width_remaining += 2; // no need for truncating dots - } - } - } else if string_end_position < line_to_render.chars().count() { - string_end_position += 1; - if string_end_position == line_to_render.chars().count() { - width_remaining += 2; // no need for truncating dots - } - } else if string_start_position > 0 { - string_start_position -= 1; - if string_start_position == 0 { - width_remaining += 2; // no need for truncating dots - } - } else { - break; - } - i += 1; - } - Some((string_start_position, string_end_position)) - } else if !indices.is_empty() { - // no room for all indices, remove the last one and try again - let mut new_indices = indices.clone(); - new_indices.pop(); - self.truncate_line_with_indices(line_to_render, &new_indices, max_width) - } else { - Some((first_index, last_index)) - } - } -} diff --git a/default-plugins/strider/src/search/search_state.rs b/default-plugins/strider/src/search/search_state.rs deleted file mode 100644 index 60d03941..00000000 --- a/default-plugins/strider/src/search/search_state.rs +++ /dev/null @@ -1,264 +0,0 @@ -use crate::search::search_results::SearchResult; -use crate::search::{MessageToSearch, ResultsOfSearch}; -use serde::{Deserialize, Serialize}; -use std::path::PathBuf; -use zellij_tile::prelude::{ - hide_self, open_file, open_file_floating, open_terminal, open_terminal_floating, - post_message_to, FileToOpen, Key, PluginMessage, -}; - -pub const CURRENT_SEARCH_TERM: &str = "/data/current_search_term"; - -#[derive(Default)] -pub struct SearchState { - pub search_term: String, - pub file_name_search_results: Vec, - pub file_contents_search_results: Vec, - pub loading: bool, - pub loading_animation_offset: u8, - pub selected_search_result: usize, - pub should_open_floating: bool, - pub search_filter: SearchType, - pub display_rows: usize, - pub display_columns: usize, - pub displayed_search_results: (usize, Vec), // usize is selected index -} - -impl SearchState { - pub fn handle_key(&mut self, key: Key) { - match key { - Key::Down => self.move_search_selection_down(), - Key::Up => self.move_search_selection_up(), - Key::Char('\n') => self.open_search_result_in_editor(), - Key::BackTab => self.open_search_result_in_terminal(), - Key::Ctrl('f') => { - self.should_open_floating = !self.should_open_floating; - }, - Key::Ctrl('r') => self.toggle_search_filter(), - Key::Esc => { - if !self.search_term.is_empty() { - self.clear_state(); - } else { - hide_self(); - } - }, - _ => self.append_to_search_term(key), - } - } - pub fn update_file_name_search_results(&mut self, mut results_of_search: ResultsOfSearch) { - if self.search_term == results_of_search.search_term { - self.file_name_search_results = results_of_search.search_results.drain(..).collect(); - self.update_displayed_search_results(); - } - } - pub fn update_file_contents_search_results(&mut self, mut results_of_search: ResultsOfSearch) { - if self.search_term == results_of_search.search_term { - self.file_contents_search_results = - results_of_search.search_results.drain(..).collect(); - self.update_displayed_search_results(); - } - } - pub fn change_size(&mut self, rows: usize, cols: usize) { - self.display_rows = rows; - self.display_columns = cols; - } - pub fn progress_animation(&mut self) { - if self.loading_animation_offset == u8::MAX { - self.loading_animation_offset = 0; - } else { - self.loading_animation_offset = self.loading_animation_offset.saturating_add(1); - } - } - pub fn number_of_lines_in_displayed_search_results(&self) -> usize { - self.displayed_search_results - .1 - .iter() - .map(|l| l.rendered_height()) - .sum() - } - fn move_search_selection_down(&mut self) { - if self.displayed_search_results.0 < self.max_search_selection_index() { - self.displayed_search_results.0 += 1; - } - } - fn move_search_selection_up(&mut self) { - self.displayed_search_results.0 = self.displayed_search_results.0.saturating_sub(1); - } - fn open_search_result_in_editor(&mut self) { - match self.selected_search_result_entry() { - Some(SearchResult::File { path, .. }) => { - if self.should_open_floating { - open_file_floating( - FileToOpen { - path: PathBuf::from(path), - ..Default::default() - }, - None, - ); - } else { - open_file(FileToOpen { - path: PathBuf::from(path), - ..Default::default() - }); - } - }, - Some(SearchResult::LineInFile { - path, line_number, .. - }) => { - if self.should_open_floating { - open_file_floating( - FileToOpen { - path: PathBuf::from(path), - line_number: Some(line_number), - ..Default::default() - }, - None, - ); - } else { - open_file(FileToOpen { - path: PathBuf::from(path), - line_number: Some(line_number), - ..Default::default() - }); - } - }, - None => eprintln!("Search results not found"), - } - } - fn open_search_result_in_terminal(&mut self) { - let dir_path_of_result = |path: &str| -> PathBuf { - let file_path = PathBuf::from(path); - let mut dir_path = file_path.components(); - dir_path.next_back(); // remove file name to stay with just the folder - dir_path.as_path().into() - }; - let selected_search_result_entry = self.selected_search_result_entry(); - if let Some(SearchResult::File { path, .. }) | Some(SearchResult::LineInFile { path, .. }) = - selected_search_result_entry - { - let dir_path = dir_path_of_result(&path); - if self.should_open_floating { - open_terminal_floating(&dir_path, None); - } else { - open_terminal(&dir_path); - } - } - } - fn toggle_search_filter(&mut self) { - self.search_filter.progress(); - self.send_search_query(); - } - fn clear_state(&mut self) { - self.file_name_search_results.clear(); - self.file_contents_search_results.clear(); - self.displayed_search_results = (0, vec![]); - self.search_term.clear(); - } - fn append_to_search_term(&mut self, key: Key) { - match key { - Key::Char(character) => { - self.search_term.push(character); - }, - Key::Backspace => { - self.search_term.pop(); - if self.search_term.len() == 0 { - self.clear_state(); - } - }, - _ => {}, - } - self.send_search_query(); - } - fn send_search_query(&mut self) { - match std::fs::write(CURRENT_SEARCH_TERM, &self.search_term) { - Ok(_) => { - if !self.search_term.is_empty() { - post_message_to(PluginMessage { - worker_name: Some("file_name_search".into()), - name: serde_json::to_string(&MessageToSearch::Search).unwrap(), - payload: "".into(), - }); - post_message_to(PluginMessage { - worker_name: Some("file_contents_search".into()), - name: serde_json::to_string(&MessageToSearch::Search).unwrap(), - payload: "".into(), - }); - self.file_name_search_results.clear(); - self.file_contents_search_results.clear(); - } - }, - Err(e) => eprintln!("Failed to write search term to HD, aborting search: {}", e), - } - } - fn max_search_selection_index(&self) -> usize { - self.displayed_search_results.1.len().saturating_sub(1) - } - fn update_displayed_search_results(&mut self) { - if self.search_term.is_empty() { - self.clear_state(); - return; - } - let mut search_results_of_interest = match self.search_filter { - SearchType::NamesAndContents => { - let mut all_search_results = self.file_name_search_results.clone(); - all_search_results.append(&mut self.file_contents_search_results.clone()); - all_search_results.sort_by(|a, b| b.score().cmp(&a.score())); - all_search_results - }, - SearchType::Names => self.file_name_search_results.clone(), - SearchType::Contents => self.file_contents_search_results.clone(), - }; - let mut height_taken_up_by_results = 0; - let mut displayed_search_results = vec![]; - for search_result in search_results_of_interest.drain(..) { - if height_taken_up_by_results + search_result.rendered_height() - > self.rows_for_results() - { - break; - } - height_taken_up_by_results += search_result.rendered_height(); - displayed_search_results.push(search_result); - } - let new_index = self - .selected_search_result_entry() - .and_then(|currently_selected_search_result| { - displayed_search_results - .iter() - .position(|r| r.is_same_entry(¤tly_selected_search_result)) - }) - .unwrap_or(0); - self.displayed_search_results = (new_index, displayed_search_results); - } - fn selected_search_result_entry(&self) -> Option { - self.displayed_search_results - .1 - .get(self.displayed_search_results.0) - .cloned() - } - pub fn rows_for_results(&self) -> usize { - self.display_rows.saturating_sub(3) // search line and 2 controls lines - } -} - -#[derive(Serialize, Deserialize)] -pub enum SearchType { - NamesAndContents, - Names, - Contents, -} - -impl SearchType { - pub fn progress(&mut self) { - match &self { - &SearchType::NamesAndContents => *self = SearchType::Names, - &SearchType::Names => *self = SearchType::Contents, - &SearchType::Contents => *self = SearchType::NamesAndContents, - } - } -} - -impl Default for SearchType { - fn default() -> Self { - SearchType::NamesAndContents - } -} diff --git a/default-plugins/strider/src/search/selection_controls_area.rs b/default-plugins/strider/src/search/selection_controls_area.rs deleted file mode 100644 index 0805e1e4..00000000 --- a/default-plugins/strider/src/search/selection_controls_area.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::search::ui::{bold, styled_text_foreground, ORANGE}; - -pub struct SelectionControlsArea { - display_lines: usize, - display_columns: usize, -} - -impl SelectionControlsArea { - pub fn new(display_lines: usize, display_columns: usize) -> Self { - SelectionControlsArea { - display_lines, - display_columns, - } - } - pub fn render(&self, result_count: usize) -> String { - let mut to_render = String::new(); - let padding = self.display_lines.saturating_sub(result_count); - for _ in 0..padding { - to_render.push_str(&self.render_padding_line()); - } - let selection_controls = self.render_selection_controls(); - to_render.push_str(&selection_controls); - to_render - } - pub fn render_empty_lines(&self) -> String { - let mut to_render = String::new(); - for _ in 0..self.display_lines { - to_render.push_str("\n"); - } - to_render - } - fn render_padding_line(&self) -> String { - format!("│\n") - } - fn render_selection_controls(&self) -> String { - if self.display_columns >= self.full_selection_controls_len() { - self.render_full_selection_controls() - } else { - self.render_truncated_selection_controls() - } - } - fn full_selection_controls_len(&self) -> usize { - 62 - } - fn render_full_selection_controls(&self) -> String { - let arrow_tail = "└ "; - let enter = styled_text_foreground(ORANGE, &bold("")); - let enter_tip = bold(" - open in editor. "); - let tab = styled_text_foreground(ORANGE, &bold("")); - let tab_tip = bold(" - open terminal at location."); - format!("{}{}{}{}{}", arrow_tail, enter, enter_tip, tab, tab_tip) - } - fn render_truncated_selection_controls(&self) -> String { - let arrow_tail = "└ "; - let enter = styled_text_foreground(ORANGE, &bold("")); - let enter_tip = bold(" - edit. "); - let tab = styled_text_foreground(ORANGE, &bold("")); - let tab_tip = bold(" - terminal."); - format!("{}{}{}{}{}", arrow_tail, enter, enter_tip, tab, tab_tip) - } -} diff --git a/default-plugins/strider/src/search/ui.rs b/default-plugins/strider/src/search/ui.rs deleted file mode 100644 index 5ee5a3e8..00000000 --- a/default-plugins/strider/src/search/ui.rs +++ /dev/null @@ -1,120 +0,0 @@ -use crate::search::controls_line::{Control, ControlsLine}; -use crate::search::search_state::SearchState; -use crate::search::selection_controls_area::SelectionControlsArea; -use std::fmt::{Display, Formatter, Result}; - -pub const CYAN: u8 = 51; -pub const GRAY_LIGHT: u8 = 238; -pub const GRAY_DARK: u8 = 245; -pub const WHITE: u8 = 15; -pub const BLACK: u8 = 16; -pub const RED: u8 = 124; -pub const GREEN: u8 = 154; -pub const ORANGE: u8 = 166; - -impl Display for SearchState { - fn fmt(&self, f: &mut Formatter) -> Result { - write!(f, "{}", self.render_search_line())?; - write!(f, "{}", self.render_search_results())?; - write!(f, "{}", self.render_selection_control_area())?; - write!(f, "{}", self.render_controls_line())?; - Ok(()) - } -} - -impl SearchState { - pub fn render_search_line(&self) -> String { - format!( - "{}{}\n", - styled_text_foreground(CYAN, &bold("SEARCH: ")), - self.search_term - ) - } - pub fn render_search_results(&self) -> String { - let mut space_for_results = self.display_rows.saturating_sub(3); // title and both controls lines - let mut to_render = String::new(); - for (i, search_result) in self.displayed_search_results.1.iter().enumerate() { - let result_height = search_result.rendered_height(); - if space_for_results < result_height { - break; - } - space_for_results -= result_height; - let index_of_selected_result = self.displayed_search_results.0; - let is_selected = i == index_of_selected_result; - let is_below_search_result = i > index_of_selected_result; - let rendered_result = - search_result.render(self.display_columns, is_selected, is_below_search_result); - to_render.push_str(&format!("{}", rendered_result)); - to_render.push('\n') - } - to_render - } - pub fn render_selection_control_area(&self) -> String { - let rows_for_results = self.rows_for_results(); - if !self.displayed_search_results.1.is_empty() { - format!( - "{}\n", - SelectionControlsArea::new(rows_for_results, self.display_columns) - .render(self.number_of_lines_in_displayed_search_results()) - ) - } else { - format!( - "{}\n", - SelectionControlsArea::new(rows_for_results, self.display_columns) - .render_empty_lines() - ) - } - } - pub fn render_controls_line(&self) -> String { - let has_results = !self.displayed_search_results.1.is_empty(); - let tiled_floating_control = - Control::new_floating_control("Ctrl f", self.should_open_floating); - let names_contents_control = Control::new_filter_control("Ctrl r", &self.search_filter); - if self.loading { - ControlsLine::new( - vec![tiled_floating_control, names_contents_control], - Some(vec!["Scanning folder", "Scanning", "S"]), - ) - .with_animation_offset(self.loading_animation_offset) - .render(self.display_columns, has_results) - } else { - ControlsLine::new(vec![tiled_floating_control, names_contents_control], None) - .render(self.display_columns, has_results) - } - } -} - -pub fn bold(text: &str) -> String { - format!("\u{1b}[1m{}\u{1b}[m", text) -} - -pub fn underline(text: &str) -> String { - format!("\u{1b}[4m{}\u{1b}[m", text) -} - -pub fn styled_text(foreground_color: u8, background_color: u8, text: &str) -> String { - format!( - "\u{1b}[38;5;{};48;5;{}m{}\u{1b}[m", - foreground_color, background_color, text - ) -} - -pub fn styled_text_foreground(foreground_color: u8, text: &str) -> String { - format!("\u{1b}[38;5;{}m{}\u{1b}[m", foreground_color, text) -} - -pub fn styled_text_background(background_color: u8, text: &str) -> String { - format!("\u{1b}[48;5;{}m{}\u{1b}[m", background_color, text) -} - -pub fn color_line_to_end(background_color: u8) -> String { - format!("\u{1b}[48;5;{}m\u{1b}[0K", background_color) -} - -pub fn arrow(foreground: u8, background: u8) -> String { - format!("\u{1b}[38;5;{}m\u{1b}[48;5;{}m", foreground, background) -} - -pub fn dot(foreground: u8, background: u8) -> String { - format!("\u{1b}[38;5;{};48;5;{}m•", foreground, background) -} diff --git a/default-plugins/strider/src/state.rs b/default-plugins/strider/src/state.rs index 67e9b891..be4ede4b 100644 --- a/default-plugins/strider/src/state.rs +++ b/default-plugins/strider/src/state.rs @@ -1,6 +1,3 @@ -use crate::search::search_results::SearchResult; -use crate::search::search_state::SearchState; -use crate::search::search_state::SearchType; use pretty_bytes::converter as pb; use std::{ collections::{HashMap, VecDeque}, @@ -11,7 +8,6 @@ use std::{ use zellij_tile::prelude::*; pub const ROOT: &str = "/host"; -pub const CURRENT_SEARCH_TERM: &str = "/data/current_search_term"; #[derive(Default)] pub struct State { @@ -20,30 +16,12 @@ pub struct State { pub cursor_hist: HashMap, pub hide_hidden_files: bool, pub ev_history: VecDeque<(Event, Instant)>, // stores last event, can be expanded in future - pub search_state: SearchState, - pub search_paths: Vec, - pub search_term: Option, - pub file_name_search_results: Vec, - pub file_contents_search_results: Vec, pub loading: bool, pub loading_animation_offset: u8, - pub typing_search_term: bool, - pub selected_search_result: usize, - pub processed_search_index: usize, pub should_open_floating: bool, - pub search_filter: SearchType, } impl State { - pub fn typing_search_term(&self) -> bool { - self.typing_search_term - } - pub fn start_typing_search_term(&mut self) { - self.typing_search_term = true; - } - pub fn stop_typing_search_term(&mut self) { - self.typing_search_term = false; - } pub fn selected_mut(&mut self) -> &mut usize { &mut self.cursor_hist.entry(self.path.clone()).or_default().0 } diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs index 640cbcd8..06c2477a 100644 --- a/zellij-client/src/lib.rs +++ b/zellij-client/src/lib.rs @@ -242,7 +242,7 @@ pub fn start_client( Box::new(opts), Box::new(config_options.clone()), Box::new(layout.unwrap()), - Some(config.plugins.clone()), + Box::new(config.plugins.clone()), ), ipc_pipe, ) diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 00895570..acab5c27 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -50,7 +50,7 @@ use zellij_utils::{ get_mode_info, layout::Layout, options::Options, - plugins::PluginsConfig, + plugins::PluginAliases, }, ipc::{ClientAttributes, ExitReason, ServerToClientMsg}, }; @@ -65,8 +65,8 @@ pub enum ServerInstruction { Box, Box, Box, + Box, ClientId, - Option, ), Render(Option>), UnblockInputThread, @@ -365,8 +365,8 @@ pub fn start_server(mut os_input: Box, socket_path: PathBuf) { opts, config_options, layout, + plugin_aliases, client_id, - plugins, ) => { let session = init_session( os_input.clone(), @@ -375,9 +375,9 @@ pub fn start_server(mut os_input: Box, socket_path: PathBuf) { SessionOptions { opts, layout: layout.clone(), - plugins, config_options: config_options.clone(), }, + plugin_aliases, ); *session_data.write().unwrap() = Some(session); session_state @@ -832,7 +832,6 @@ pub struct SessionOptions { pub opts: Box, pub config_options: Box, pub layout: Box, - pub plugins: Option, } fn init_session( @@ -840,12 +839,12 @@ fn init_session( to_server: SenderWithContext, client_attributes: ClientAttributes, options: SessionOptions, + plugin_aliases: Box, ) -> SessionMetaData { let SessionOptions { opts, config_options, layout, - plugins, } = options; let _ = SCROLL_BUFFER_SIZE.set( @@ -975,13 +974,13 @@ fn init_session( plugin_bus, store, data_dir, - plugins.unwrap_or_default(), layout, path_to_default_shell, zellij_cwd, capabilities, client_attributes, default_shell, + plugin_aliases, ) .fatal() } diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs index ad1a03fd..07ed6173 100644 --- a/zellij-server/src/panes/floating_panes/mod.rs +++ b/zellij-server/src/panes/floating_panes/mod.rs @@ -25,7 +25,7 @@ use zellij_utils::{ data::{ModeInfo, Style}, errors::prelude::*, input::command::RunCommand, - input::layout::{FloatingPaneLayout, Run, RunPlugin}, + input::layout::{FloatingPaneLayout, Run, RunPlugin, RunPluginOrAlias}, pane_size::{Dimension, Offset, PaneGeom, Size, SizeInPixels, Viewport}, }; @@ -872,11 +872,10 @@ impl FloatingPanes { self.focus_pane_for_all_clients(active_pane_id); } } - pub fn get_plugin_pane_id(&self, run_plugin: &RunPlugin) -> Option { - let run = Some(Run::Plugin(run_plugin.clone())); + pub fn get_plugin_pane_id(&self, run_plugin_or_alias: &RunPluginOrAlias) -> Option { self.panes .iter() - .find(|(_id, s_p)| s_p.invoked_with() == &run) + .find(|(_id, pane)| run_plugin_or_alias.is_equivalent_to_run(pane.invoked_with())) .map(|(id, _)| *id) } pub fn focus_pane_if_exists(&mut self, pane_id: PaneId, client_id: ClientId) -> Result<()> { diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs index 6477a8af..8e594b27 100644 --- a/zellij-server/src/panes/tiled_panes/mod.rs +++ b/zellij-server/src/panes/tiled_panes/mod.rs @@ -22,7 +22,7 @@ use zellij_utils::{ errors::prelude::*, input::{ command::RunCommand, - layout::{Run, RunPlugin, SplitDirection}, + layout::{Run, RunPlugin, RunPluginOrAlias, SplitDirection}, }, pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport}, }; @@ -1744,11 +1744,10 @@ impl TiledPanes { fn reset_boundaries(&mut self) { self.client_id_to_boundaries.clear(); } - pub fn get_plugin_pane_id(&self, run_plugin: &RunPlugin) -> Option { - let run = Some(Run::Plugin(run_plugin.clone())); + pub fn get_plugin_pane_id(&self, run_plugin_or_alias: &RunPluginOrAlias) -> Option { self.panes .iter() - .find(|(_id, s_p)| s_p.invoked_with() == &run) + .find(|(_id, pane)| run_plugin_or_alias.is_equivalent_to_run(pane.invoked_with())) .map(|(id, _)| *id) } pub fn pane_info(&self) -> Vec { diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs index ebae02a3..80a59045 100644 --- a/zellij-server/src/plugins/mod.rs +++ b/zellij-server/src/plugins/mod.rs @@ -32,11 +32,8 @@ use zellij_utils::{ errors::{prelude::*, ContextType, PluginContext}, input::{ command::TerminalAction, - layout::{ - FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation, - TiledPaneLayout, - }, - plugins::PluginsConfig, + layout::{FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginOrAlias, TiledPaneLayout}, + plugins::PluginAliases, }, ipc::ClientAttributes, pane_size::Size, @@ -50,7 +47,7 @@ pub enum PluginInstruction { Option, // should float bool, // should be opened in place Option, // pane title - RunPlugin, + RunPluginOrAlias, usize, // tab index Option, // pane id to replace if this is to be opened "in-place" ClientId, @@ -63,7 +60,7 @@ pub enum PluginInstruction { Reload( Option, // should float Option, // pane title - RunPlugin, + RunPluginOrAlias, usize, // tab index Size, ), @@ -173,19 +170,18 @@ pub(crate) fn plugin_thread_main( bus: Bus, store: Store, data_dir: PathBuf, - plugins: PluginsConfig, - layout: Box, + mut layout: Box, path_to_default_shell: PathBuf, zellij_cwd: PathBuf, capabilities: PluginCapabilities, client_attributes: ClientAttributes, default_shell: Option, + plugin_aliases: Box, ) -> Result<()> { info!("Wasm main thread starts"); - let plugin_dir = data_dir.join("plugins/"); let plugin_global_data_dir = plugin_dir.join("data"); - + layout.populate_plugin_aliases_in_layout(&plugin_aliases); let store = Arc::new(Mutex::new(store)); // use this channel to ensure that tasks spawned from this thread terminate before exiting @@ -193,7 +189,6 @@ pub(crate) fn plugin_thread_main( let (shutdown_send, shutdown_receive) = channel::bounded::<()>(1); let mut wasm_bridge = WasmBridge::new( - plugins, bus.senders.clone(), store, plugin_dir, @@ -213,38 +208,42 @@ pub(crate) fn plugin_thread_main( should_float, should_be_open_in_place, pane_title, - run, + mut run_plugin_or_alias, tab_index, pane_id_to_replace, client_id, size, cwd, skip_cache, - ) => match wasm_bridge.load_plugin( - &run, - Some(tab_index), - size, - cwd.clone(), - skip_cache, - Some(client_id), - None, - ) { - Ok((plugin_id, client_id)) => { - drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin( - should_float, - should_be_open_in_place, - run, - pane_title, - Some(tab_index), - plugin_id, - pane_id_to_replace, - cwd, - Some(client_id), - ))); - }, - Err(e) => { - log::error!("Failed to load plugin: {e}"); - }, + ) => { + run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases); + let run_plugin = run_plugin_or_alias.get_run_plugin(); + match wasm_bridge.load_plugin( + &run_plugin, + Some(tab_index), + size, + cwd.clone(), + skip_cache, + Some(client_id), + None, + ) { + Ok((plugin_id, client_id)) => { + drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin( + should_float, + should_be_open_in_place, + run_plugin_or_alias, + pane_title, + Some(tab_index), + plugin_id, + pane_id_to_replace, + cwd, + Some(client_id), + ))); + }, + Err(e) => { + log::error!("Failed to load plugin: {e}"); + }, + } }, PluginInstruction::Update(updates) => { wasm_bridge.update_plugins(updates, shutdown_send.clone())?; @@ -252,50 +251,69 @@ pub(crate) fn plugin_thread_main( PluginInstruction::Unload(pid) => { wasm_bridge.unload_plugin(pid)?; }, - PluginInstruction::Reload(should_float, pane_title, run, tab_index, size) => { - match wasm_bridge.reload_plugin(&run) { - Ok(_) => { - let _ = bus - .senders - .send_to_server(ServerInstruction::UnblockInputThread); - }, - Err(err) => match err.downcast_ref::() { - Some(ZellijError::PluginDoesNotExist) => { - log::warn!("Plugin {} not found, starting it instead", run.location); - // we intentionally do not provide the client_id here because it belongs to - // the cli who spawned the command and is not an existing client_id - let skip_cache = true; // when reloading we always skip cache - match wasm_bridge.load_plugin( - &run, - Some(tab_index), - size, - None, - skip_cache, - None, - None, - ) { - Ok((plugin_id, _client_id)) => { - let should_be_open_in_place = false; - drop(bus.senders.send_to_screen(ScreenInstruction::AddPlugin( - should_float, - should_be_open_in_place, - run, - pane_title, + PluginInstruction::Reload( + should_float, + pane_title, + mut run_plugin_or_alias, + tab_index, + size, + ) => { + run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases); + match run_plugin_or_alias.get_run_plugin() { + Some(run_plugin) => { + match wasm_bridge.reload_plugin(&run_plugin) { + Ok(_) => { + let _ = bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread); + }, + Err(err) => match err.downcast_ref::() { + Some(ZellijError::PluginDoesNotExist) => { + log::warn!( + "Plugin {} not found, starting it instead", + run_plugin.location + ); + // we intentionally do not provide the client_id here because it belongs to + // the cli who spawned the command and is not an existing client_id + let skip_cache = true; // when reloading we always skip cache + match wasm_bridge.load_plugin( + &Some(run_plugin), Some(tab_index), - plugin_id, + size, + None, + skip_cache, None, None, - None, - ))); + ) { + Ok((plugin_id, _client_id)) => { + let should_be_open_in_place = false; + drop(bus.senders.send_to_screen( + ScreenInstruction::AddPlugin( + should_float, + should_be_open_in_place, + run_plugin_or_alias, + pane_title, + Some(tab_index), + plugin_id, + None, + None, + None, + ), + )); + }, + Err(e) => { + log::error!("Failed to load plugin: {e}"); + }, + }; }, - Err(e) => { - log::error!("Failed to load plugin: {e}"); + _ => { + return Err(err); }, - }; - }, - _ => { - return Err(err); - }, + }, + } + }, + None => { + log::error!("Failed to find plugin info for: {:?}", run_plugin_or_alias) }, } }, @@ -311,15 +329,21 @@ pub(crate) fn plugin_thread_main( PluginInstruction::NewTab( cwd, terminal_action, - tab_layout, - floating_panes_layout, + mut tab_layout, + mut floating_panes_layout, tab_index, client_id, ) => { - let mut plugin_ids: HashMap< - (RunPluginLocation, PluginUserConfiguration), - Vec, - > = HashMap::new(); + let mut plugin_ids: HashMap> = HashMap::new(); + tab_layout = tab_layout.or_else(|| Some(layout.new_tab().0)); + tab_layout + .as_mut() + .map(|t| t.populate_plugin_aliases_in_layout(&plugin_aliases)); + floating_panes_layout.iter_mut().for_each(|f| { + f.run + .as_mut() + .map(|f| f.populate_run_plugin_if_needed(&plugin_aliases)); + }); let mut extracted_run_instructions = tab_layout .clone() .unwrap_or_else(|| layout.new_tab().0) @@ -337,10 +361,11 @@ pub(crate) fn plugin_thread_main( .collect(); extracted_run_instructions.append(&mut extracted_floating_plugins); for run_instruction in extracted_run_instructions { - if let Some(Run::Plugin(run)) = run_instruction { + if let Some(Run::Plugin(run_plugin_or_alias)) = run_instruction { + let run_plugin = run_plugin_or_alias.get_run_plugin(); let skip_cache = false; let (plugin_id, _client_id) = wasm_bridge.load_plugin( - &run, + &run_plugin, Some(tab_index), size, None, @@ -349,7 +374,7 @@ pub(crate) fn plugin_thread_main( None, )?; plugin_ids - .entry((run.location, run.configuration)) + .entry(run_plugin_or_alias.clone()) .or_default() .push(plugin_id); } @@ -488,6 +513,7 @@ pub(crate) fn plugin_thread_main( &args, &bus, &mut wasm_bridge, + &plugin_aliases, ); }, None => { @@ -550,6 +576,7 @@ pub(crate) fn plugin_thread_main( &Some(message.message_args), &bus, &mut wasm_bridge, + &plugin_aliases, ); }, None => { @@ -660,16 +687,19 @@ fn pipe_to_specific_plugins( args: &Option>, bus: &Bus, wasm_bridge: &mut WasmBridge, + plugin_aliases: &PluginAliases, ) { let is_private = true; let size = Size::default(); - match RunPlugin::from_url(&plugin_url) { - Ok(mut run_plugin) => { - if let Some(configuration) = configuration { - run_plugin.configuration = PluginUserConfiguration::new(configuration.clone()); - } + match RunPluginOrAlias::from_url( + &plugin_url, + configuration, + Some(plugin_aliases), + cwd.clone(), + ) { + Ok(run_plugin_or_alias) => { let all_plugin_ids = wasm_bridge.get_or_load_plugins( - run_plugin, + run_plugin_or_alias, size, cwd.clone(), skip_cache, @@ -683,7 +713,7 @@ fn pipe_to_specific_plugins( pipe_messages.push(( Some(plugin_id), client_id, - PipeMessage::new(pipe_source.clone(), name, payload, args, is_private), // PipeMessage::new(PipeSource::Cli(pipe_id.clone()), &name, &payload, &args, is_private) + PipeMessage::new(pipe_source.clone(), name, payload, args, is_private), )); } }, diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 98fe1a07..07212c3b 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -8,9 +8,11 @@ use tempfile::tempdir; use wasmer::Store; use zellij_utils::data::{Event, Key, PermissionStatus, PermissionType, PluginCapabilities}; use zellij_utils::errors::ErrorContext; -use zellij_utils::input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}; +use zellij_utils::input::layout::{ + Layout, PluginAlias, PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias, +}; use zellij_utils::input::permission::PermissionCache; -use zellij_utils::input::plugins::PluginsConfig; +use zellij_utils::input::plugins::PluginAliases; use zellij_utils::ipc::ClientAttributes; use zellij_utils::lazy_static::lazy_static; use zellij_utils::pane_size::Size; @@ -249,6 +251,17 @@ fn create_plugin_thread( let plugin_capabilities = PluginCapabilities::default(); let client_attributes = ClientAttributes::default(); let default_shell_action = None; // TODO: change me + let mut plugin_aliases = PluginAliases::default(); + plugin_aliases.aliases.insert( + "fixture_plugin_for_tests".to_owned(), + RunPlugin::from_url(&format!( + "file:{}/../target/e2e-data/plugins/fixture-plugin-for-tests.wasm", + std::env::var_os("CARGO_MANIFEST_DIR") + .unwrap() + .to_string_lossy() + )) + .unwrap(), + ); let plugin_thread = std::thread::Builder::new() .name("plugin_thread".to_string()) .spawn(move || { @@ -257,13 +270,13 @@ fn create_plugin_thread( plugin_bus, store, data_dir, - PluginsConfig::default(), Box::new(Layout::default()), default_shell, zellij_cwd, plugin_capabilities, client_attributes, default_shell_action, + Box::new(plugin_aliases), ) .expect("TEST") }) @@ -335,13 +348,13 @@ fn create_plugin_thread_with_server_receiver( plugin_bus, store, data_dir, - PluginsConfig::default(), Box::new(Layout::default()), default_shell, zellij_cwd, plugin_capabilities, client_attributes, default_shell_action, + Box::new(PluginAliases::default()), ) .expect("TEST"); }) @@ -419,13 +432,13 @@ fn create_plugin_thread_with_pty_receiver( plugin_bus, store, data_dir, - PluginsConfig::default(), Box::new(Layout::default()), default_shell, zellij_cwd, plugin_capabilities, client_attributes, default_shell_action, + Box::new(PluginAliases::default()), ) .expect("TEST") }) @@ -498,13 +511,13 @@ fn create_plugin_thread_with_background_jobs_receiver( plugin_bus, store, data_dir, - PluginsConfig::default(), Box::new(Layout::default()), default_shell, zellij_cwd, plugin_capabilities, client_attributes, default_shell_action, + Box::new(PluginAliases::default()), ) .expect("TEST") }) @@ -554,11 +567,90 @@ pub fn load_new_plugin_from_hd() { let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(None); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: 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!( + received_screen_instructions, + ScreenInstruction::PluginBytes, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + 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::InputReceived, + )])); // will be cached and sent to the plugin once it's loaded + screen_thread.join().unwrap(); // this might take a while if the cache is cold + teardown(); + let plugin_bytes_event = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::PluginBytes(plugin_render_assets) = i { + for plugin_render_asset in plugin_render_assets { + let plugin_id = plugin_render_asset.plugin_id; + let client_id = plugin_render_asset.client_id; + let plugin_bytes = plugin_render_asset.bytes.clone(); + let plugin_bytes = String::from_utf8_lossy(plugin_bytes.as_slice()).to_string(); + if plugin_bytes.contains("InputReceived") { + return Some((plugin_id, client_id, plugin_bytes)); + } + } + } + None + }); + assert_snapshot!(format!("{:#?}", plugin_bytes_event)); +} + +#[test] +#[ignore] +pub fn load_new_plugin_with_plugin_alias() { + // here we load our fixture plugin into the plugin thread, and then send it an update message + // expecting tha thte plugin will log the received event and render it later after the update + // message (this is what the fixture plugin does) + // we then listen on our mock screen receiver to make sure we got a PluginBytes instruction + // that contains said render, and assert against it + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = create_plugin_thread(None); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::Alias(PluginAlias { + name: "fixture_plugin_for_tests".to_owned(), + configuration: Default::default(), + run_plugin: None, + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -629,11 +721,11 @@ pub fn plugin_workers() { let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -708,11 +800,11 @@ pub fn plugin_workers_persist_state() { let plugin_host_folder = PathBuf::from(temp_folder.path()); let cache_path = plugin_host_folder.join("permissions_test.kdl"); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -797,11 +889,11 @@ pub fn can_subscribe_to_hd_events() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -874,11 +966,11 @@ pub fn switch_to_mode_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -945,11 +1037,11 @@ pub fn switch_to_mode_plugin_command_permission_denied() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1016,11 +1108,11 @@ pub fn new_tabs_with_layout_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1101,11 +1193,11 @@ pub fn new_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1172,11 +1264,11 @@ pub fn go_to_next_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1242,11 +1334,11 @@ pub fn go_to_previous_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1312,11 +1404,11 @@ pub fn resize_focused_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1382,11 +1474,11 @@ pub fn resize_focused_pane_with_direction_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1452,11 +1544,11 @@ pub fn focus_next_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1522,11 +1614,11 @@ pub fn focus_previous_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1592,11 +1684,11 @@ pub fn move_focus_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1662,11 +1754,11 @@ pub fn move_focus_or_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1732,11 +1824,11 @@ pub fn edit_scrollback_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1802,11 +1894,11 @@ pub fn write_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1872,11 +1964,11 @@ pub fn write_chars_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -1942,11 +2034,11 @@ pub fn toggle_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2012,11 +2104,11 @@ pub fn move_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2082,11 +2174,11 @@ pub fn move_pane_with_direction_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2152,11 +2244,11 @@ pub fn clear_screen_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2223,11 +2315,11 @@ pub fn scroll_up_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2294,11 +2386,11 @@ pub fn scroll_down_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2364,11 +2456,11 @@ pub fn scroll_to_top_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2434,11 +2526,11 @@ pub fn scroll_to_bottom_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2504,11 +2596,11 @@ pub fn page_scroll_up_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2574,11 +2666,11 @@ pub fn page_scroll_down_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2644,11 +2736,11 @@ pub fn toggle_focus_fullscreen_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2714,11 +2806,11 @@ pub fn toggle_pane_frames_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2784,11 +2876,11 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2854,11 +2946,11 @@ pub fn undo_rename_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2924,11 +3016,11 @@ pub fn close_focus_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -2994,11 +3086,11 @@ pub fn toggle_active_tab_sync_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3064,11 +3156,11 @@ pub fn close_focused_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3134,11 +3226,11 @@ pub fn undo_rename_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3204,11 +3296,11 @@ pub fn previous_swap_layout_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3274,11 +3366,11 @@ pub fn next_swap_layout_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3344,11 +3436,11 @@ pub fn go_to_tab_name_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3414,11 +3506,11 @@ pub fn focus_or_create_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3484,11 +3576,11 @@ pub fn go_to_tab() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3554,11 +3646,11 @@ pub fn start_or_reload_plugin() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3624,11 +3716,11 @@ pub fn quit_zellij_plugin_command() { 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 = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3701,11 +3793,11 @@ pub fn detach_plugin_command() { 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 = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3778,11 +3870,11 @@ pub fn open_file_floating_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3859,11 +3951,11 @@ pub fn open_file_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -3940,11 +4032,11 @@ pub fn open_file_with_line_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4022,11 +4114,11 @@ pub fn open_file_with_line_floating_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4103,11 +4195,11 @@ pub fn open_terminal_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4180,11 +4272,11 @@ pub fn open_terminal_floating_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4257,11 +4349,11 @@ pub fn open_command_pane_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4334,11 +4426,11 @@ pub fn open_command_pane_floating_plugin_command() { create_plugin_thread_with_pty_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4411,11 +4503,11 @@ pub fn switch_to_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4481,11 +4573,11 @@ pub fn hide_self_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4551,11 +4643,11 @@ pub fn show_self_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4620,11 +4712,11 @@ pub fn close_terminal_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4690,11 +4782,11 @@ pub fn close_plugin_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4760,11 +4852,11 @@ pub fn focus_terminal_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4830,11 +4922,11 @@ pub fn focus_plugin_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4900,11 +4992,11 @@ pub fn rename_terminal_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -4970,11 +5062,11 @@ pub fn rename_plugin_pane_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5040,11 +5132,11 @@ pub fn rename_tab_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5119,11 +5211,11 @@ pub fn send_configuration_to_plugins() { "fake_config_key_2".to_owned(), "fake_config_value_2".to_owned(), ); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: PluginUserConfiguration::new(configuration), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5190,11 +5282,11 @@ pub fn request_plugin_permissions() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5256,11 +5348,11 @@ pub fn granted_permission_request_result() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5324,7 +5416,7 @@ pub fn granted_permission_request_result() { let permission_cache = PermissionCache::from_path_or_default(Some(cache_path)); let mut permissions = permission_cache - .get_permissions(run_plugin.location.to_string()) + .get_permissions(PathBuf::from(&*PLUGIN_FIXTURE).display().to_string()) .clone(); let permissions = permissions.as_mut().map(|p| { let mut permissions = p.clone(); @@ -5346,11 +5438,11 @@ pub fn denied_permission_request_result() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5413,7 +5505,8 @@ pub fn denied_permission_request_result() { teardown(); let permission_cache = PermissionCache::from_path_or_default(Some(cache_path)); - let permissions = permission_cache.get_permissions(run_plugin.location.to_string()); + let permissions = + permission_cache.get_permissions(PathBuf::from(&*PLUGIN_FIXTURE).display().to_string()); assert_snapshot!(format!("{:#?}", permissions)); } @@ -5429,11 +5522,11 @@ pub fn run_command_plugin_command() { create_plugin_thread_with_background_jobs_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5506,11 +5599,11 @@ pub fn run_command_with_env_vars_and_cwd_plugin_command() { create_plugin_thread_with_background_jobs_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5583,11 +5676,11 @@ pub fn web_request_plugin_command() { create_plugin_thread_with_background_jobs_receiver(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5660,11 +5753,11 @@ pub fn unblock_input_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5741,11 +5834,11 @@ pub fn block_input_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5823,11 +5916,11 @@ pub fn pipe_output_plugin_command() { 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 = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5912,11 +6005,11 @@ pub fn pipe_message_to_plugin_plugin_command() { create_plugin_thread(Some(plugin_host_folder)); let plugin_should_float = Some(false); let plugin_title = Some("test_plugin".to_owned()); - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -5998,11 +6091,11 @@ pub fn switch_session_plugin_command() { 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 = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -6078,11 +6171,11 @@ pub fn switch_session_with_layout_plugin_command() { 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 = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { @@ -6158,11 +6251,11 @@ pub fn disconnect_other_clients_plugins_command() { 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 = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), configuration: Default::default(), - }; + }); let tab_index = 1; let client_id = 1; let size = Size { diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__load_new_plugin_with_plugin_alias.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__load_new_plugin_with_plugin_alias.snap new file mode 100644 index 00000000..b5b7ef4a --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__load_new_plugin_with_plugin_alias.snap @@ -0,0 +1,12 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +assertion_line: 706 +expression: "format!(\"{:#?}\", plugin_bytes_event)" +--- +Some( + ( + 0, + 1, + "Rows: 20, Cols: 121, Received events: [InputReceived]\n\r", + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap index 05002124..a55b17ec 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__start_or_reload_plugin.snap @@ -1,19 +1,21 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 2931 +assertion_line: 3700 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( StartOrReloadPluginPane( - RunPlugin { - _allow_exec_host_cmd: false, - location: File( - "/path/to/my/plugin.wasm", - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: File( + "/path/to/my/plugin.wasm", + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + ), None, ), ) diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index f4679b5e..10a1f51a 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -37,8 +37,8 @@ use zellij_utils::{ errors::prelude::*, input::{ command::TerminalAction, - layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}, - plugins::PluginsConfig, + layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias}, + plugins::PluginConfig, }, ipc::ClientAttributes, pane_size::Size, @@ -76,7 +76,6 @@ impl PluginRenderAsset { pub struct WasmBridge { connected_clients: Arc>>, - plugins: PluginsConfig, senders: ThreadSenders, store: Arc>, plugin_dir: PathBuf, @@ -106,7 +105,6 @@ pub struct WasmBridge { impl WasmBridge { pub fn new( - plugins: PluginsConfig, senders: ThreadSenders, store: Arc>, plugin_dir: PathBuf, @@ -124,7 +122,6 @@ impl WasmBridge { let watcher = None; WasmBridge { connected_clients, - plugins, senders, store, plugin_dir, @@ -150,7 +147,7 @@ impl WasmBridge { } pub fn load_plugin( &mut self, - run: &RunPlugin, + run: &Option, tab_index: Option, size: Size, cwd: Option, @@ -176,95 +173,109 @@ impl WasmBridge { let plugin_id = self.next_plugin_id; - let mut plugin = self - .plugins - .get(run) - .with_context(|| format!("failed to resolve plugin {run:?}")) - .with_context(err_context)?; - let plugin_name = run.location.to_string(); + match run { + Some(run) => { + let mut plugin = PluginConfig::from_run_plugin(run) + .with_context(|| format!("failed to resolve plugin {run:?}")) + .with_context(err_context)?; + let plugin_name = run.location.to_string(); - self.cached_events_for_pending_plugins - .insert(plugin_id, vec![]); - self.cached_resizes_for_pending_plugins - .insert(plugin_id, (size.rows, size.cols)); + self.cached_events_for_pending_plugins + .insert(plugin_id, vec![]); + self.cached_resizes_for_pending_plugins + .insert(plugin_id, (size.rows, size.cols)); - let load_plugin_task = task::spawn({ - let plugin_dir = self.plugin_dir.clone(); - let plugin_cache = self.plugin_cache.clone(); - let senders = self.senders.clone(); - let store = self.store.clone(); - let plugin_map = self.plugin_map.clone(); - let connected_clients = self.connected_clients.clone(); - let path_to_default_shell = self.path_to_default_shell.clone(); - let zellij_cwd = cwd.unwrap_or_else(|| self.zellij_cwd.clone()); - let capabilities = self.capabilities.clone(); - let client_attributes = self.client_attributes.clone(); - let default_shell = self.default_shell.clone(); - let default_layout = self.default_layout.clone(); - async move { - let _ = - senders.send_to_background_jobs(BackgroundJob::AnimatePluginLoading(plugin_id)); - let mut loading_indication = LoadingIndication::new(plugin_name.clone()); + let load_plugin_task = task::spawn({ + let plugin_dir = self.plugin_dir.clone(); + let plugin_cache = self.plugin_cache.clone(); + let senders = self.senders.clone(); + let store = self.store.clone(); + let plugin_map = self.plugin_map.clone(); + let connected_clients = self.connected_clients.clone(); + let path_to_default_shell = self.path_to_default_shell.clone(); + let zellij_cwd = cwd.unwrap_or_else(|| self.zellij_cwd.clone()); + let capabilities = self.capabilities.clone(); + let client_attributes = self.client_attributes.clone(); + let default_shell = self.default_shell.clone(); + let default_layout = self.default_layout.clone(); + async move { + let _ = senders.send_to_background_jobs( + BackgroundJob::AnimatePluginLoading(plugin_id), + ); + let mut loading_indication = LoadingIndication::new(plugin_name.clone()); - if let RunPluginLocation::Remote(url) = &plugin.location { - let file_name: String = PortableHash::default() - .hash128(url.as_bytes()) - .iter() - .map(ToString::to_string) - .collect(); + if let RunPluginLocation::Remote(url) = &plugin.location { + let file_name: String = PortableHash::default() + .hash128(url.as_bytes()) + .iter() + .map(ToString::to_string) + .collect(); - let downloader = Downloader::new(ZELLIJ_CACHE_DIR.to_path_buf()); - match downloader.download(url, Some(&file_name)).await { - Ok(_) => plugin.path = ZELLIJ_CACHE_DIR.join(&file_name), - Err(e) => handle_plugin_loading_failure( - &senders, + let downloader = Downloader::new(ZELLIJ_CACHE_DIR.to_path_buf()); + match downloader.download(url, Some(&file_name)).await { + Ok(_) => plugin.path = ZELLIJ_CACHE_DIR.join(&file_name), + Err(e) => handle_plugin_loading_failure( + &senders, + plugin_id, + &mut loading_indication, + e, + cli_client_id, + ), + } + } + + match PluginLoader::start_plugin( plugin_id, + client_id, + &plugin, + tab_index, + plugin_dir, + plugin_cache, + senders.clone(), + store, + plugin_map, + size, + connected_clients.clone(), &mut loading_indication, - e, - cli_client_id, - ), + path_to_default_shell, + zellij_cwd.clone(), + capabilities, + client_attributes, + default_shell, + default_layout, + skip_cache, + ) { + Ok(_) => handle_plugin_successful_loading(&senders, plugin_id), + Err(e) => handle_plugin_loading_failure( + &senders, + plugin_id, + &mut loading_indication, + e, + cli_client_id, + ), + } + let _ = senders.send_to_plugin(PluginInstruction::ApplyCachedEvents { + plugin_ids: vec![plugin_id], + done_receiving_permissions: false, + }); } - } - - match PluginLoader::start_plugin( - plugin_id, - client_id, - &plugin, - tab_index, - plugin_dir, - plugin_cache, - senders.clone(), - store, - plugin_map, - size, - connected_clients.clone(), - &mut loading_indication, - path_to_default_shell, - zellij_cwd.clone(), - capabilities, - client_attributes, - default_shell, - default_layout, - skip_cache, - ) { - Ok(_) => handle_plugin_successful_loading(&senders, plugin_id), - Err(e) => handle_plugin_loading_failure( - &senders, - plugin_id, - &mut loading_indication, - e, - cli_client_id, - ), - } - let _ = senders.send_to_plugin(PluginInstruction::ApplyCachedEvents { - plugin_ids: vec![plugin_id], - done_receiving_permissions: false, }); - } - }); - self.loading_plugins - .insert((plugin_id, run.clone()), load_plugin_task); - self.next_plugin_id += 1; + self.loading_plugins + .insert((plugin_id, run.clone()), load_plugin_task); + self.next_plugin_id += 1; + }, + None => { + self.next_plugin_id += 1; + let mut loading_indication = LoadingIndication::new(format!("{}", plugin_id)); + handle_plugin_loading_failure( + &self.senders, + plugin_id, + &mut loading_indication, + "Failed to resolve plugin alias", + None, + ); + }, + } Ok((plugin_id, client_id)) } pub fn unload_plugin(&mut self, pid: PluginId) -> Result<()> { @@ -1076,7 +1087,7 @@ impl WasmBridge { // returns its details pub fn get_or_load_plugins( &mut self, - run_plugin: RunPlugin, + run_plugin_or_alias: RunPluginOrAlias, size: Size, cwd: Option, skip_cache: bool, @@ -1086,52 +1097,62 @@ impl WasmBridge { pane_id_to_replace: Option, cli_client_id: Option, ) -> Vec<(PluginId, Option)> { - let all_plugin_ids = self.all_plugin_and_client_ids_for_plugin_location( - &run_plugin.location, - &run_plugin.configuration, - ); - if all_plugin_ids.is_empty() { - if let Some(loading_plugin_id) = - self.plugin_id_of_loading_plugin(&run_plugin.location, &run_plugin.configuration) - { - return vec![(loading_plugin_id, None)]; - } - match self.load_plugin( - &run_plugin, - None, - size, - cwd.clone(), - skip_cache, - None, - cli_client_id, - ) { - Ok((plugin_id, client_id)) => { - drop(self.senders.send_to_screen(ScreenInstruction::AddPlugin( - Some(should_float), - should_be_open_in_place, - run_plugin, - pane_title, - None, - plugin_id, - pane_id_to_replace, - cwd, - Some(client_id), - ))); - vec![(plugin_id, Some(client_id))] - }, - Err(e) => { - log::error!("Failed to load plugin: {e}"); - if let Some(cli_client_id) = cli_client_id { - let _ = self.senders.send_to_server(ServerInstruction::LogError( - vec![format!("Failed to log plugin: {e}")], - cli_client_id, - )); + let run_plugin = run_plugin_or_alias.get_run_plugin(); + match run_plugin { + Some(run_plugin) => { + let all_plugin_ids = self.all_plugin_and_client_ids_for_plugin_location( + &run_plugin.location, + &run_plugin.configuration, + ); + if all_plugin_ids.is_empty() { + if let Some(loading_plugin_id) = self.plugin_id_of_loading_plugin( + &run_plugin.location, + &run_plugin.configuration, + ) { + return vec![(loading_plugin_id, None)]; } - vec![] - }, - } - } else { - all_plugin_ids + match self.load_plugin( + &Some(run_plugin), + None, + size, + cwd.clone(), + skip_cache, + None, + cli_client_id, + ) { + Ok((plugin_id, client_id)) => { + drop(self.senders.send_to_screen(ScreenInstruction::AddPlugin( + Some(should_float), + should_be_open_in_place, + run_plugin_or_alias, + pane_title, + None, + plugin_id, + pane_id_to_replace, + cwd, + Some(client_id), + ))); + vec![(plugin_id, Some(client_id))] + }, + Err(e) => { + log::error!("Failed to load plugin: {e}"); + if let Some(cli_client_id) = cli_client_id { + let _ = self.senders.send_to_server(ServerInstruction::LogError( + vec![format!("Failed to log plugin: {e}")], + cli_client_id, + )); + } + vec![] + }, + } + } else { + all_plugin_ids + } + }, + None => { + log::error!("Plugin not found for alias"); + vec![] + }, } } pub fn clear_plugin_map_cache(&mut self) { diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 19bac282..533d85f2 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -27,8 +27,6 @@ use zellij_utils::{ ipc::{ClientToServerMsg, IpcSenderWithContext}, }; -use url::Url; - use crate::{panes::PaneId, screen::ScreenInstruction}; use zellij_utils::{ @@ -41,7 +39,7 @@ use zellij_utils::{ input::{ actions::Action, command::{RunCommand, RunCommandAction, TerminalAction}, - layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}, + layout::{Layout, RunPluginOrAlias}, plugins::PluginType, }, plugin_api::{ @@ -1226,15 +1224,9 @@ fn start_or_reload_plugin(env: &ForeignFunctionEnv, url: &str) -> Result<()> { ) }; let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); - let url = Url::parse(&url).map_err(|e| anyhow!("Failed to parse url: {}", e))?; - let run_plugin_location = RunPluginLocation::parse(url.as_str(), Some(cwd)) + let run_plugin_or_alias = RunPluginOrAlias::from_url(url, &None, None, Some(cwd)) .map_err(|e| anyhow!("Failed to parse plugin location: {}", e))?; - let run_plugin = RunPlugin { - location: run_plugin_location, - _allow_exec_host_cmd: false, - configuration: PluginUserConfiguration::new(BTreeMap::new()), // TODO: allow passing configuration - }; - let action = Action::StartOrReloadPlugin(run_plugin); + let action = Action::StartOrReloadPlugin(run_plugin_or_alias); apply_action!(action, error_msg, env); Ok(()) } diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index 0f9001a2..20997053 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -19,8 +19,8 @@ use zellij_utils::{ input::{ command::{RunCommand, TerminalAction}, layout::{ - FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation, - TiledPaneLayout, + FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPluginLocation, + RunPluginOrAlias, TiledPaneLayout, }, }, pane_size::Size, @@ -62,8 +62,8 @@ pub enum PtyInstruction { Option, Option, Vec, - usize, // tab_index - HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, // plugin_ids + usize, // tab_index + HashMap>, // plugin_ids ClientId, ), // the String is the tab name ClosePane(PaneId), @@ -85,7 +85,7 @@ pub enum PtyInstruction { Option, // should float bool, // should be opened in place Option, // pane title - RunPlugin, + RunPluginOrAlias, usize, // tab index Option, // pane id to replace if this is to be opened "in-place" ClientId, @@ -874,7 +874,7 @@ impl Pty { layout: TiledPaneLayout, floating_panes_layout: Vec, default_shell: Option, - plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + plugin_ids: HashMap>, tab_index: usize, client_id: ClientId, ) -> Result<()> { @@ -1337,7 +1337,7 @@ impl Pty { should_float: Option, should_open_in_place: bool, // should be opened in place pane_title: Option, // pane title - run: RunPlugin, + run: RunPluginOrAlias, tab_index: usize, // tab index pane_id_to_replace: Option, // pane id to replace if this is to be opened "in-place" client_id: ClientId, diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 120f8f50..c8a7f419 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -1023,15 +1023,15 @@ pub(crate) fn route_thread_main( cli_args, opts, layout, - plugin_config, + plugin_aliases, ) => { let new_client_instruction = ServerInstruction::NewClient( client_attributes, cli_args, opts, layout, + plugin_aliases, client_id, - plugin_config, ); to_server .send(new_client_instruction) diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index b8ebf4e3..4594fe3c 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -20,7 +20,7 @@ use zellij_utils::{ envs::set_session_name, input::command::TerminalAction, input::layout::{ - FloatingPaneLayout, Layout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation, + FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginLocation, RunPluginOrAlias, SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, }, position::Position, @@ -220,7 +220,7 @@ pub enum ScreenInstruction { Vec, Vec<(u32, HoldForCommand)>, // new pane pids Vec<(u32, HoldForCommand)>, // new floating pane pids - HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + HashMap>, usize, // tab_index ClientId, ), @@ -279,10 +279,16 @@ pub enum ScreenInstruction { PreviousSwapLayout(ClientId), NextSwapLayout(ClientId), QueryTabNames(ClientId), - NewTiledPluginPane(RunPlugin, Option, bool, Option, ClientId), // Option is + NewTiledPluginPane( + RunPluginOrAlias, + Option, + bool, + Option, + ClientId, + ), // Option is // optional pane title, bool is skip cache, Option is an optional cwd NewFloatingPluginPane( - RunPlugin, + RunPluginOrAlias, Option, bool, Option, @@ -291,13 +297,13 @@ pub enum ScreenInstruction { ), // Option is an // optional pane title, bool // is skip cache, Option is an optional cwd - NewInPlacePluginPane(RunPlugin, Option, PaneId, bool, ClientId), // Option is an + NewInPlacePluginPane(RunPluginOrAlias, Option, PaneId, bool, ClientId), // Option is an // optional pane title, bool is skip cache - StartOrReloadPluginPane(RunPlugin, Option), + StartOrReloadPluginPane(RunPluginOrAlias, Option), AddPlugin( Option, // should_float bool, // should be opened in place - RunPlugin, + RunPluginOrAlias, Option, // pane title Option, // tab index u32, // plugin id @@ -309,9 +315,17 @@ pub enum ScreenInstruction { StartPluginLoadingIndication(u32, LoadingIndication), // u32 - plugin_id ProgressPluginLoadingOffset(u32), // u32 - plugin id RequestStateUpdateForPlugins, - LaunchOrFocusPlugin(RunPlugin, bool, bool, bool, Option, bool, ClientId), // bools are: should_float, move_to_focused_tab, should_open_in_place, Option is the pane id to replace, bool following it is skip_cache + LaunchOrFocusPlugin( + RunPluginOrAlias, + bool, + bool, + bool, + Option, + bool, + ClientId, + ), // bools are: should_float, move_to_focused_tab, should_open_in_place, Option is the pane id to replace, bool following it is skip_cache LaunchPlugin( - RunPlugin, + RunPluginOrAlias, bool, bool, Option, @@ -1224,7 +1238,7 @@ impl Screen { floating_panes_layout: Vec, new_terminal_ids: Vec<(u32, HoldForCommand)>, new_floating_terminal_ids: Vec<(u32, HoldForCommand)>, - new_plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + new_plugin_ids: HashMap>, tab_index: usize, client_id: ClientId, ) -> Result<()> { @@ -1830,7 +1844,7 @@ impl Screen { pub fn focus_plugin_pane( &mut self, - run_plugin: &RunPlugin, + run_plugin: &RunPluginOrAlias, should_float: bool, move_to_focused_tab: bool, client_id: ClientId, @@ -3452,7 +3466,7 @@ pub(crate) fn screen_thread_main( ScreenInstruction::AddPlugin( should_float, should_be_in_place, - run_plugin_location, + run_plugin_or_alias, pane_title, tab_index, plugin_id, @@ -3465,10 +3479,10 @@ pub(crate) fn screen_thread_main( "({}) - {}", cwd.map(|cwd| cwd.display().to_string()) .unwrap_or(".".to_owned()), - run_plugin_location.location + run_plugin_or_alias.location_string() ) }); - let run_plugin = Run::Plugin(run_plugin_location); + let run_plugin = Run::Plugin(run_plugin_or_alias); if should_be_in_place { if let Some(pane_id_to_replace) = pane_id_to_replace { @@ -3571,33 +3585,35 @@ pub(crate) fn screen_thread_main( skip_cache, client_id, ) => match pane_id_to_replace { - Some(pane_id_to_replace) => match screen.active_tab_indices.values().next() { - Some(tab_index) => { - let size = Size::default(); - screen - .bus - .senders - .send_to_pty(PtyInstruction::FillPluginCwd( - Some(should_float), - should_open_in_place, - None, - run_plugin, - *tab_index, - Some(pane_id_to_replace), - client_id, - size, - skip_cache, - None, - None, - ))?; - }, - None => { - log::error!( + Some(pane_id_to_replace) if should_open_in_place => { + match screen.active_tab_indices.values().next() { + Some(tab_index) => { + let size = Size::default(); + screen + .bus + .senders + .send_to_pty(PtyInstruction::FillPluginCwd( + Some(should_float), + should_open_in_place, + None, + run_plugin, + *tab_index, + Some(pane_id_to_replace), + client_id, + size, + skip_cache, + None, + None, + ))?; + }, + None => { + log::error!( "Could not find an active tab - is there at least 1 connected user?" ); - }, + }, + } }, - None => { + _ => { let client_id = if screen.active_tab_indices.contains_key(&client_id) { Some(client_id) } else { diff --git a/zellij-server/src/session_layout_metadata.rs b/zellij-server/src/session_layout_metadata.rs index f746d14b..da19bc90 100644 --- a/zellij-server/src/session_layout_metadata.rs +++ b/zellij-server/src/session_layout_metadata.rs @@ -5,7 +5,7 @@ use zellij_utils::common_path::common_path_all; use zellij_utils::pane_size::PaneGeom; use zellij_utils::{ input::command::RunCommand, - input::layout::{Layout, Run, RunPlugin}, + input::layout::{Layout, Run, RunPlugin, RunPluginOrAlias}, session_serialization::{GlobalLayoutManifest, PaneLayoutManifest, TabLayoutManifest}, }; @@ -178,7 +178,8 @@ impl SessionLayoutMetadata { let mut update_cmd_in_pane_metadata = |pane_layout_metadata: &mut PaneLayoutMetadata| { if let PaneId::Plugin(id) = pane_layout_metadata.id { if let Some(run_plugin) = plugin_ids_to_run_plugins.remove(&id) { - pane_layout_metadata.run = Some(Run::Plugin(run_plugin)); + pane_layout_metadata.run = + Some(Run::Plugin(RunPluginOrAlias::RunPlugin(run_plugin))); } } }; diff --git a/zellij-server/src/tab/layout_applier.rs b/zellij-server/src/tab/layout_applier.rs index 9fcb0360..c66fac17 100644 --- a/zellij-server/src/tab/layout_applier.rs +++ b/zellij-server/src/tab/layout_applier.rs @@ -18,9 +18,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::rc::Rc; use zellij_utils::{ data::{Palette, Style}, - input::layout::{ - FloatingPaneLayout, PluginUserConfiguration, Run, RunPluginLocation, TiledPaneLayout, - }, + input::layout::{FloatingPaneLayout, Run, RunPluginOrAlias, TiledPaneLayout}, pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport}, }; @@ -104,7 +102,7 @@ impl<'a> LayoutApplier<'a> { floating_panes_layout: Vec, new_terminal_ids: Vec<(u32, HoldForCommand)>, new_floating_terminal_ids: Vec<(u32, HoldForCommand)>, - mut new_plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + mut new_plugin_ids: HashMap>, client_id: ClientId, ) -> Result { // true => should_show_floating_panes @@ -208,7 +206,7 @@ impl<'a> LayoutApplier<'a> { &mut self, layout: TiledPaneLayout, new_terminal_ids: Vec<(u32, HoldForCommand)>, - new_plugin_ids: &mut HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + new_plugin_ids: &mut HashMap>, client_id: ClientId, ) -> Result<()> { let err_context = || format!("failed to apply tiled panes layout"); @@ -263,9 +261,9 @@ impl<'a> LayoutApplier<'a> { let positions_and_size = positions_in_layout.iter(); for (layout, position_and_size) in positions_and_size { if let Some(Run::Plugin(run)) = layout.run.clone() { - let pane_title = run.location.to_string(); + let pane_title = run.location_string(); let pid = new_plugin_ids - .get_mut(&(run.location, run.configuration)) + .get_mut(&run) .and_then(|ids| ids.pop()) .with_context(err_context)?; let mut new_plugin = PluginPane::new( @@ -372,7 +370,7 @@ impl<'a> LayoutApplier<'a> { &mut self, floating_panes_layout: Vec, new_floating_terminal_ids: Vec<(u32, HoldForCommand)>, - new_plugin_ids: &mut HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + new_plugin_ids: &mut HashMap>, layout_name: Option, ) -> Result { // true => has floating panes @@ -392,9 +390,9 @@ impl<'a> LayoutApplier<'a> { position_and_size, ); } else if let Some(Run::Plugin(run)) = floating_pane_layout.run.clone() { - let pane_title = run.location.to_string(); + let pane_title = run.location_string(); let pid = new_plugin_ids - .get_mut(&(run.location, run.configuration)) + .get_mut(&run) .and_then(|ids| ids.pop()) .with_context(err_context)?; let mut new_pane = PluginPane::new( diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index de1beccc..8c135b7d 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -51,7 +51,7 @@ use zellij_utils::{ command::TerminalAction, layout::{ FloatingPaneLayout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation, - SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, + RunPluginOrAlias, SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, }, parse_keys, }, @@ -636,7 +636,7 @@ impl Tab { floating_panes_layout: Vec, new_terminal_ids: Vec<(u32, HoldForCommand)>, new_floating_terminal_ids: Vec<(u32, HoldForCommand)>, - new_plugin_ids: HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + new_plugin_ids: HashMap>, client_id: ClientId, ) -> Result<()> { self.swap_layouts @@ -3587,15 +3587,16 @@ impl Tab { self.set_force_render(); } - pub fn find_plugin(&self, run_plugin: &RunPlugin) -> Option { + pub fn find_plugin(&self, run_plugin_or_alias: &RunPluginOrAlias) -> Option { self.tiled_panes - .get_plugin_pane_id(run_plugin) - .or_else(|| self.floating_panes.get_plugin_pane_id(run_plugin)) + .get_plugin_pane_id(run_plugin_or_alias) + .or_else(|| self.floating_panes.get_plugin_pane_id(run_plugin_or_alias)) .or_else(|| { - let run = Some(Run::Plugin(run_plugin.clone())); self.suppressed_panes .iter() - .find(|(_id, s_p)| s_p.1.invoked_with() == &run) + .find(|(_id, (_, pane))| { + run_plugin_or_alias.is_equivalent_to_run(pane.invoked_with()) + }) .map(|(id, _)| *id) }) } @@ -3769,7 +3770,7 @@ pub fn pane_info_for_pane(pane_id: &PaneId, pane: &Box) -> PaneInfo { pane_info.id = *plugin_id; pane_info.is_plugin = true; pane_info.plugin_url = pane.invoked_with().as_ref().and_then(|c| match c { - Run::Plugin(run_plugin) => Some(run_plugin.location.to_string()), + Run::Plugin(run_plugin_or_alias) => Some(run_plugin_or_alias.location_string()), _ => None, }); }, diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__base_floating_layout_is_included_in_swap_layouts.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__base_floating_layout_is_included_in_swap_layouts.snap index cd3f576f..e60c5fd3 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__base_floating_layout_is_included_in_swap_layouts.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__base_floating_layout_is_included_in_swap_layouts.snap @@ -1,9 +1,9 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 6071 +assertion_line: 6089 expression: snapshot --- -00 (C): ┌ tab-bar ────────────────────────────────────────┌ status-bar ──────────────────────────────────────────────┐──────────┐ +00 (C): ┌ zellij:tab-bar ─────────────────────────────────┌ zellij:status-bar ───────────────────────────────────────┐──────────┐ 01 (C): │I am a tab bar │I am a │ │ 02 (C): │ │status bar │ │ 03 (C): │ │ │ │ diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__floating_layout_with_plugins_and_commands_swaped_properly.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__floating_layout_with_plugins_and_commands_swaped_properly.snap index 10982475..1d8dfe04 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__floating_layout_with_plugins_and_commands_swaped_properly.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__floating_layout_with_plugins_and_commands_swaped_properly.snap @@ -1,9 +1,9 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 5971 +assertion_line: 5995 expression: snapshot --- -00 (C): ┌ status-bar ──────────────────────────────────────────────┐─────────────────────────────────────────────────┐──────────┐ +00 (C): ┌ zellij:status-bar ───────────────────────────────────────┐ab-bar ──────────────────────────────────────────┐──────────┐ 01 (C): │I am a │b bar │ │ 02 (C): │status bar │ │ │ 03 (C): │ │ │ │ diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_including_command_panes_absent_from_existing_layout.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_including_command_panes_absent_from_existing_layout.snap index 6bdd963e..fb7d9176 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_including_command_panes_absent_from_existing_layout.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_including_command_panes_absent_from_existing_layout.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 5541 +assertion_line: 6180 expression: snapshot --- 00 (C): ┌ Pane #2 ─────────────────────────────────────────────────┐────────────────────────────────────────────────────────────┐ @@ -8,7 +8,7 @@ expression: snapshot 02 (C): │ │ │ 03 (C): │ │ │ 04 (C): │ │ │ -05 (C): │ ┌ status-bar ──────────────────────────────────────────────┐ │ +05 (C): │ ┌ zellij:status-bar ───────────────────────────────────────┐ │ 06 (C): │ │I am a │ │ 07 (C): │ │status bar │─┐ │ 08 (C): │ │ │ │ │ diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_command_panes_present_in_existing_layout.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_command_panes_present_in_existing_layout.snap index 8db6a06a..01d107cd 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_command_panes_present_in_existing_layout.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_command_panes_present_in_existing_layout.snap @@ -1,14 +1,14 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 6269 +assertion_line: 6275 expression: snapshot --- 00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 01 (C): │ │ 02 (C): │ ┌ command2 ────────────── SCROLL: 0/1 ┐ │ 03 (C): │ │ Waiting to run: command2 │ │ -04 (C): │ │ ┌ tab-bar ─────────────────────────────┐ │ -05 (C): │ │<│I am a tab bar ┌ status-bar ──────────────────────────────────────────────┐ │ +04 (C): │ │ ┌ zellij:tab-bar ──────────────────────┐ │ +05 (C): │ │<│I am a tab bar ┌ zellij:status-bar ───────────────────────────────────────┐ │ 06 (C): │ │l│ │I am a │ │ 07 (C): │ └─│ │status bar │─┐ │ 08 (C): │ │ │ │ │ │ diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_plugin_panes_present_in_existing_layout.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_plugin_panes_present_in_existing_layout.snap index 278676fa..bb542c19 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_plugin_panes_present_in_existing_layout.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_floating_layouts_not_including_plugin_panes_present_in_existing_layout.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 6363 +assertion_line: 6432 expression: snapshot --- 00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ @@ -8,11 +8,11 @@ expression: snapshot 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ -05 (C): │ ┌ tab-bar ─────────────────────────────────────────────────┐ │ +05 (C): │ ┌ zellij:tab-bar ──────────────────────────────────────────┐ │ 06 (C): │ │I am a tab bar │ │ 07 (C): │ │ ┌ Pane #2 ─────────────────────────────────────────────────┐ │ 08 (C): │ │ │ │ │ -09 (C): │ │ │ ┌ status-bar ──────────────────────────────────────────────┐ │ +09 (C): │ │ │ ┌ zellij:status-bar ───────────────────────────────────────┐ │ 10 (C): │ │ │ │I am a │ │ 11 (C): │ │ │ │status bar │ │ 12 (C): │ │ │ │ │ │ diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_layouts_not_including_plugin_panes_present_in_existing_layout.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_layouts_not_including_plugin_panes_present_in_existing_layout.snap index 1c8c7f77..9a5f4867 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_layouts_not_including_plugin_panes_present_in_existing_layout.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_layouts_not_including_plugin_panes_present_in_existing_layout.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 5481 +assertion_line: 5510 expression: snapshot --- 00 (C): ┌ Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ @@ -17,10 +17,10 @@ expression: snapshot 11 (C): │ │ 12 (C): │ run, drop to shell, exit │ 13 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -14 (C): ┌ status-bar ───────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +14 (C): ┌ zellij:status-bar ────────────────────────────────────────────────────────────────────────────────────────────────────┐ 15 (C): │I am a │ 16 (C): │status bar │ 17 (C): │ │ 18 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -19 (C): ┌ tab-bar ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +19 (C): ┌ zellij:tab-bar ───────────────────────────────────────────────────────────────────────────────────────────────────────┐ diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs index ef5cc1bf..f8953235 100644 --- a/zellij-server/src/tab/unit/tab_integration_tests.rs +++ b/zellij-server/src/tab/unit/tab_integration_tests.rs @@ -20,8 +20,8 @@ use zellij_utils::data::ResizeStrategy; use zellij_utils::envs::set_session_name; use zellij_utils::errors::{prelude::*, ErrorContext}; use zellij_utils::input::layout::{ - FloatingPaneLayout, Layout, PluginUserConfiguration, RunPluginLocation, SwapFloatingLayout, - SwapTiledLayout, TiledPaneLayout, + FloatingPaneLayout, Layout, PluginUserConfiguration, RunPluginLocation, RunPluginOrAlias, + SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, }; use zellij_utils::input::plugins::PluginTag; use zellij_utils::ipc::IpcReceiverWithContext; @@ -273,7 +273,7 @@ fn create_new_tab_with_swap_layouts( Vec, Vec<(u32, Option)>, Vec<(u32, Option)>, - HashMap<(RunPluginLocation, PluginUserConfiguration), Vec>, + HashMap>, )>, draw_pane_frames: bool, ) -> Tab { @@ -5022,17 +5022,11 @@ fn layout_with_plugins_and_commands_swaped_properly() { let new_floating_terminal_ids = vec![]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -5123,17 +5117,11 @@ fn base_layout_is_included_in_swap_layouts() { let new_floating_terminal_ids = vec![]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -5221,17 +5209,11 @@ fn swap_layouts_including_command_panes_absent_from_existing_layout() { let new_floating_terminal_ids = vec![]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -5322,17 +5304,11 @@ fn swap_layouts_not_including_command_panes_present_in_existing_layout() { let new_floating_terminal_ids = vec![]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -5496,17 +5472,11 @@ fn swap_layouts_not_including_plugin_panes_present_in_existing_layout() { let new_floating_terminal_ids = vec![]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -5987,17 +5957,11 @@ fn floating_layout_with_plugins_and_commands_swaped_properly() { let new_terminal_ids = vec![(4, None)]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -6086,17 +6050,11 @@ fn base_floating_layout_is_included_in_swap_layouts() { let new_terminal_ids = vec![(4, None)]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -6184,17 +6142,11 @@ fn swap_floating_layouts_including_command_panes_absent_from_existing_layout() { let new_terminal_ids = vec![(4, None)]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -6285,17 +6237,11 @@ fn swap_floating_layouts_not_including_command_panes_present_in_existing_layout( let new_terminal_ids = vec![(4, None)]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); @@ -6448,17 +6394,11 @@ fn swap_floating_layouts_not_including_plugin_panes_present_in_existing_layout() let new_terminal_ids = vec![(4, None)]; let mut new_plugin_ids = HashMap::new(); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:tab-bar", &None, None, None).unwrap(), vec![1], ); new_plugin_ids.insert( - ( - RunPluginLocation::Zellij(PluginTag::new("status-bar")), - Default::default(), - ), + RunPluginOrAlias::from_url("zellij:status-bar", &None, None, None).unwrap(), vec![2], ); diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index dc8939e6..64b1e188 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -15,8 +15,8 @@ use zellij_utils::errors::{prelude::*, ErrorContext}; use zellij_utils::input::actions::Action; use zellij_utils::input::command::{RunCommand, TerminalAction}; use zellij_utils::input::layout::{ - FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginLocation, SplitDirection, SplitSize, - TiledPaneLayout, + FloatingPaneLayout, Layout, PluginAlias, PluginUserConfiguration, Run, RunPlugin, + RunPluginLocation, RunPluginOrAlias, SplitDirection, SplitSize, TiledPaneLayout, }; use zellij_utils::input::options::Options; use zellij_utils::ipc::IpcReceiverWithContext; @@ -338,10 +338,91 @@ impl MockScreen { let mut floating_pane_ids = vec![]; let mut plugin_ids = HashMap::new(); plugin_ids.insert( - ( - RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")), - Default::default(), - ), + RunPluginOrAlias::from_url("file:/path/to/fake/plugin", &None, None, None).unwrap(), + vec![1], + ); + for i in 0..pane_count { + pane_ids.push((i as u32, None)); + } + for i in 0..floating_pane_count { + floating_pane_ids.push((i as u32, None)); + } + let default_shell = None; + let tab_name = None; + let tab_index = self.last_opened_tab_index.map(|l| l + 1).unwrap_or(0); + let _ = self.to_screen.send(ScreenInstruction::NewTab( + None, + default_shell, + Some(pane_layout.clone()), + initial_floating_panes_layout.clone(), + tab_name, + (vec![], vec![]), // swap layouts + self.main_client_id, + )); + let _ = self.to_screen.send(ScreenInstruction::ApplyLayout( + pane_layout, + initial_floating_panes_layout, + pane_ids, + floating_pane_ids, + plugin_ids, + tab_index, + self.main_client_id, + )); + self.last_opened_tab_index = Some(tab_index); + screen_thread + } + // same as the above function, but starts a plugin with a plugin alias + pub fn run_with_alias( + &mut self, + initial_layout: Option, + initial_floating_panes_layout: Vec, + ) -> std::thread::JoinHandle<()> { + let config_options = self.config_options.clone(); + let client_attributes = self.client_attributes.clone(); + let screen_bus = Bus::new( + vec![self.screen_receiver.take().unwrap()], + None, + Some(&self.to_pty.clone()), + Some(&self.to_plugin.clone()), + Some(&self.to_server.clone()), + Some(&self.to_pty_writer.clone()), + Some(&self.to_background_jobs.clone()), + Some(Box::new(self.os_input.clone())), + ) + .should_silently_fail(); + let debug = false; + let screen_thread = std::thread::Builder::new() + .name("screen_thread".to_string()) + .spawn(move || { + set_var("ZELLIJ_SESSION_NAME", "zellij-test"); + screen_thread_main( + screen_bus, + None, + client_attributes, + Box::new(config_options), + debug, + Box::new(Layout::default()), + ) + .expect("TEST") + }) + .unwrap(); + let pane_layout = initial_layout.unwrap_or_default(); + let pane_count = pane_layout.extract_run_instructions().len(); + let floating_pane_count = initial_floating_panes_layout.len(); + let mut pane_ids = vec![]; + let mut floating_pane_ids = vec![]; + let mut plugin_ids = HashMap::new(); + plugin_ids.insert( + RunPluginOrAlias::Alias(PluginAlias { + name: "fixture_plugin_for_tests".to_owned(), + configuration: Some(Default::default()), + run_plugin: Some(RunPlugin { + location: RunPluginLocation::parse("file:/path/to/fake/plugin", None).unwrap(), + configuration: PluginUserConfiguration::default(), + ..Default::default() + }), + ..Default::default() + }), vec![1], ); for i in 0..pane_count { @@ -358,7 +439,6 @@ impl MockScreen { default_shell, Some(pane_layout.clone()), initial_floating_panes_layout.clone(), - // vec![], // floating_panes_layout tab_name, (vec![], vec![]), // swap layouts self.main_client_id, @@ -366,10 +446,8 @@ impl MockScreen { let _ = self.to_screen.send(ScreenInstruction::ApplyLayout( pane_layout, initial_floating_panes_layout, - // vec![], // floating panes layout pane_ids, floating_pane_ids, - // vec![], // floating pane ids plugin_ids, tab_index, self.main_client_id, @@ -2884,7 +2962,7 @@ pub fn send_cli_launch_or_focus_plugin_action() { floating: true, in_place: false, move_to_focused_tab: true, - url: url::Url::parse("file:/path/to/fake/plugin").unwrap(), + url: "file:/path/to/fake/plugin".to_owned(), configuration: Default::default(), skip_plugin_cache: false, }; @@ -2917,11 +2995,11 @@ pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded() { let session_metadata = mock_screen.clone_session_metadata(); let mut initial_layout = TiledPaneLayout::default(); let existing_plugin_pane = TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")), configuration: Default::default(), - })), + }))), ..Default::default() }; initial_layout.children_split_direction = SplitDirection::Vertical; @@ -2944,7 +3022,89 @@ pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded() { floating: true, in_place: false, move_to_focused_tab: true, - url: url::Url::parse("file:/path/to/fake/plugin").unwrap(), + url: "file:/path/to/fake/plugin".to_owned(), + configuration: Default::default(), + skip_plugin_cache: false, + }; + send_cli_action_to_server(&session_metadata, cli_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be + mock_screen.teardown(vec![plugin_thread, server_thread, screen_thread]); + + let plugin_load_instruction_sent = received_plugin_instructions + .lock() + .unwrap() + .iter() + .find(|instruction| match instruction { + PluginInstruction::Load(..) => true, + _ => false, + }) + .is_some(); + assert!( + !plugin_load_instruction_sent, + "Plugin Load instruction should not be sent for an already loaded plugin" + ); + let snapshots = take_snapshots_and_cursor_coordinates_from_render_events( + received_server_instructions.lock().unwrap().iter(), + size, + ); + let snapshot_count = snapshots.len(); + assert_eq!( + snapshot_count, 2, + "Another render was sent for focusing the already loaded plugin" + ); + for (cursor_coordinates, _snapshot) in snapshots.iter().skip(1) { + assert!( + cursor_coordinates.is_none(), + "Cursor moved to existing plugin in final snapshot indicating focus changed" + ); + } +} + +#[test] +pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded_for_plugin_alias() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; // fake client id should not appear in the screen's state + let mut mock_screen = MockScreen::new(size); + let plugin_receiver = mock_screen.plugin_receiver.take().unwrap(); + let session_metadata = mock_screen.clone_session_metadata(); + let mut initial_layout = TiledPaneLayout::default(); + let existing_plugin_pane = TiledPaneLayout { + run: Some(Run::Plugin(RunPluginOrAlias::Alias(PluginAlias { + name: "fixture_plugin_for_tests".to_owned(), + configuration: Some(Default::default()), + run_plugin: Some(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")), + configuration: Default::default(), + }), + ..Default::default() + }))), + ..Default::default() + }; + initial_layout.children_split_direction = SplitDirection::Vertical; + initial_layout.children = vec![TiledPaneLayout::default(), existing_plugin_pane]; + let screen_thread = mock_screen.run_with_alias(Some(initial_layout), vec![]); + let received_plugin_instructions = Arc::new(Mutex::new(vec![])); + let plugin_thread = log_actions_in_thread!( + received_plugin_instructions, + PluginInstruction::Exit, + plugin_receiver + ); + let received_server_instructions = Arc::new(Mutex::new(vec![])); + let server_receiver = mock_screen.server_receiver.take().unwrap(); + let server_thread = log_actions_in_thread!( + received_server_instructions, + ServerInstruction::KillSession, + server_receiver + ); + let cli_action = CliAction::LaunchOrFocusPlugin { + floating: true, + in_place: false, + move_to_focused_tab: true, + url: "fixture_plugin_for_tests".to_owned(), configuration: Default::default(), skip_plugin_cache: false, }; @@ -3184,11 +3344,11 @@ pub fn screen_can_break_plugin_pane_to_a_new_tab() { let mut initial_layout = TiledPaneLayout::default(); let mut pane_to_break_free = TiledPaneLayout::default(); pane_to_break_free.name = Some("plugin_pane_to_break_free".to_owned()); - pane_to_break_free.run = Some(Run::Plugin(RunPlugin { + pane_to_break_free.run = Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")), configuration: Default::default(), - })); + }))); let mut pane_to_stay = TiledPaneLayout::default(); pane_to_stay.name = Some("pane_to_stay".to_owned()); initial_layout.children_split_direction = SplitDirection::Vertical; @@ -3254,11 +3414,11 @@ pub fn screen_can_break_floating_plugin_pane_to_a_new_tab() { pane_to_break_free.name = Some("tiled_pane".to_owned()); let mut floating_pane = FloatingPaneLayout::default(); floating_pane.name = Some("floating_plugin_pane_to_eject".to_owned()); - floating_pane.run = Some(Run::Plugin(RunPlugin { + floating_pane.run = Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")), configuration: Default::default(), - })); + }))); let mut floating_panes_layout = vec![floating_pane]; initial_layout.children_split_direction = SplitDirection::Vertical; initial_layout.children = vec![pane_to_break_free]; diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap index 85285fcf..9ca5b2aa 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-2.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2986 +assertion_line: 3171 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ @@ -8,8 +8,8 @@ expression: "format!(\"{}\", snapshot)" 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ -05 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │ -06 (C): │ │Loading /path/to/fake/plugin │ │ +05 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +06 (C): │ │Loading file:/path/to/fake/plugin │ │ 07 (C): │ │ │ │ 08 (C): │ │ │ │ 09 (C): │ │ │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap index bf91ddbd..1305aa26 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-3.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2986 +assertion_line: 3171 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)" 04 (C): │ │ 05 (C): │ │ 06 (C): │ │ -07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │ -08 (C): │ │Loading /path/to/fake/plugin │ │ +07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +08 (C): │ │Loading file:/path/to/fake/plugin │ │ 09 (C): │ │ │ │ 10 (C): │ │ │ │ 11 (C): │ │ │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-4.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-4.snap index bf91ddbd..1305aa26 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-4.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-4.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2986 +assertion_line: 3171 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)" 04 (C): │ │ 05 (C): │ │ 06 (C): │ │ -07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │ -08 (C): │ │Loading /path/to/fake/plugin │ │ +07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +08 (C): │ │Loading file:/path/to/fake/plugin │ │ 09 (C): │ │ │ │ 10 (C): │ │ │ │ 11 (C): │ │ │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-6.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-6.snap index bf91ddbd..1305aa26 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-6.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-6.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2986 +assertion_line: 3171 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)" 04 (C): │ │ 05 (C): │ │ 06 (C): │ │ -07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │ -08 (C): │ │Loading /path/to/fake/plugin │ │ +07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +08 (C): │ │Loading file:/path/to/fake/plugin │ │ 09 (C): │ │ │ │ 10 (C): │ │ │ │ 11 (C): │ │ │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-7.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-7.snap index bf91ddbd..1305aa26 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-7.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-7.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2986 +assertion_line: 3171 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -10,8 +10,8 @@ expression: "format!(\"{}\", snapshot)" 04 (C): │ │ 05 (C): │ │ 06 (C): │ │ -07 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │ -08 (C): │ │Loading /path/to/fake/plugin │ │ +07 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +08 (C): │ │Loading file:/path/to/fake/plugin │ │ 09 (C): │ │ │ │ 10 (C): │ │ │ │ 11 (C): │ │ │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab.snap index 85285fcf..9ca5b2aa 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2986 +assertion_line: 3171 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ @@ -8,8 +8,8 @@ expression: "format!(\"{}\", snapshot)" 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ -05 (C): │ ┌ /path/to/fake/plugin ────────────────┐ │ -06 (C): │ │Loading /path/to/fake/plugin │ │ +05 (C): │ ┌ file:/path/to/fake/plugin ───────────┐ │ +06 (C): │ │Loading file:/path/to/fake/plugin │ │ 07 (C): │ │ │ │ 08 (C): │ │ │ │ 09 (C): │ │ │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-3.snap index e0a620f3..b938c7bc 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-3.snap @@ -1,10 +1,10 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2914 +assertion_line: 3097 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐ -01 (C): │Loading /path/to/fake/plugin │ +01 (C): │Loading file:/path/to/fake/plugin │ 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap index e0a620f3..b938c7bc 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-4.snap @@ -1,10 +1,10 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2914 +assertion_line: 3097 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ plugin_pane_to_break_free ───────────────────────────────────────────────────┐ -01 (C): │Loading /path/to/fake/plugin │ +01 (C): │Loading file:/path/to/fake/plugin │ 02 (C): │ │ 03 (C): │ │ 04 (C): │ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab.snap index 4d4ae3f9..a2011a8f 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab.snap @@ -1,10 +1,10 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2914 +assertion_line: 3097 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ plugin_pane_to_break_free ───────────┐┌ pane_to_stay ────────────────────────┐ -01 (C): │Loading /path/to/fake/plugin ││ │ +01 (C): │Loading file:/path/to/fake/plugin ││ │ 02 (C): │ ││ │ 03 (C): │ ││ │ 04 (C): │ ││ │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap index 28a3f4bb..56b466ed 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2639 +assertion_line: 2758 expression: "format!(\"{:#?}\", pty_fill_plugin_cwd_instruction)" --- Some( @@ -10,15 +10,17 @@ Some( ), false, None, - RunPlugin { - _allow_exec_host_cmd: false, - location: File( - "/path/to/fake/plugin", - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: File( + "/path/to/fake/plugin", + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + ), 0, None, 1, diff --git a/zellij-utils/assets/config/default.kdl b/zellij-utils/assets/config/default.kdl index f8dc9a75..c8e61bf4 100644 --- a/zellij-utils/assets/config/default.kdl +++ b/zellij-utils/assets/config/default.kdl @@ -186,11 +186,15 @@ keybinds { } plugins { - tab-bar { path "tab-bar"; } - status-bar { path "status-bar"; } - strider { path "strider"; } - compact-bar { path "compact-bar"; } - session-manager { path "session-manager"; } + tab-bar location="zellij:tab-bar" + status-bar location="zellij:status-bar" + strider location="zellij:strider" + compact-bar location="zellij:compact-bar" + session-manager location="zellij:session-manager" + welcome-screen location="zellij:session-manager" { + welcome_screen true + } + filepicker location="zellij:strider" } // Choose what to do when zellij receives SIGTERM, SIGINT, SIGQUIT or SIGHUP diff --git a/zellij-utils/assets/layouts/compact.kdl b/zellij-utils/assets/layouts/compact.kdl index 7871ad40..0ac57ee3 100644 --- a/zellij-utils/assets/layouts/compact.kdl +++ b/zellij-utils/assets/layouts/compact.kdl @@ -1,6 +1,6 @@ layout { pane pane size=1 borderless=true { - plugin location="zellij:compact-bar" + plugin location="compact-bar" } } diff --git a/zellij-utils/assets/layouts/compact.swap.kdl b/zellij-utils/assets/layouts/compact.swap.kdl index 923a117c..300b4bdf 100644 --- a/zellij-utils/assets/layouts/compact.swap.kdl +++ b/zellij-utils/assets/layouts/compact.swap.kdl @@ -1,7 +1,7 @@ tab_template name="ui" { children pane size=1 borderless=true { - plugin location="zellij:compact-bar" + plugin location="compact-bar" } } diff --git a/zellij-utils/assets/layouts/default.kdl b/zellij-utils/assets/layouts/default.kdl index 4434b29b..460aee8a 100644 --- a/zellij-utils/assets/layouts/default.kdl +++ b/zellij-utils/assets/layouts/default.kdl @@ -1,9 +1,9 @@ layout { pane size=1 borderless=true { - plugin location="zellij:tab-bar" + plugin location="tab-bar" } pane pane size=2 borderless=true { - plugin location="zellij:status-bar" + plugin location="status-bar" } } diff --git a/zellij-utils/assets/layouts/default.swap.kdl b/zellij-utils/assets/layouts/default.swap.kdl index 6d5cdb55..71a6dfe9 100644 --- a/zellij-utils/assets/layouts/default.swap.kdl +++ b/zellij-utils/assets/layouts/default.swap.kdl @@ -1,10 +1,10 @@ tab_template name="ui" { pane size=1 borderless=true { - plugin location="zellij:tab-bar" + plugin location="tab-bar" } children pane size=2 borderless=true { - plugin location="zellij:status-bar" + plugin location="status-bar" } } diff --git a/zellij-utils/assets/layouts/disable-status-bar.kdl b/zellij-utils/assets/layouts/disable-status-bar.kdl index 5eca5b0c..36a194e7 100644 --- a/zellij-utils/assets/layouts/disable-status-bar.kdl +++ b/zellij-utils/assets/layouts/disable-status-bar.kdl @@ -1,6 +1,6 @@ layout { pane size=1 borderless=true { - plugin location="zellij:tab-bar" + plugin location="tab-bar" } pane } diff --git a/zellij-utils/assets/layouts/strider.kdl b/zellij-utils/assets/layouts/strider.kdl index 57ec01a7..96600061 100644 --- a/zellij-utils/assets/layouts/strider.kdl +++ b/zellij-utils/assets/layouts/strider.kdl @@ -1,14 +1,14 @@ layout { pane size=1 borderless=true { - plugin location="zellij:tab-bar" + plugin location="tab-bar" } pane split_direction="Vertical" { pane size="20%" { - plugin location="zellij:strider" + plugin location="strider" } pane } pane size=2 borderless=true { - plugin location="zellij:status-bar" + plugin location="status-bar" } } diff --git a/zellij-utils/assets/layouts/strider.swap.kdl b/zellij-utils/assets/layouts/strider.swap.kdl index 579fcc8e..b53444ff 100644 --- a/zellij-utils/assets/layouts/strider.swap.kdl +++ b/zellij-utils/assets/layouts/strider.swap.kdl @@ -1,10 +1,10 @@ tab_template name="ui" { pane size=1 borderless=true { - plugin location="zellij:tab-bar" + plugin location="tab-bar" } pane split_direction="Vertical" { pane size="20%" { - plugin location="zellij:strider" + plugin location="strider" } pane { children @@ -12,7 +12,7 @@ tab_template name="ui" { } pane size=2 borderless=true { - plugin location="zellij:status-bar" + plugin location="status-bar" } } diff --git a/zellij-utils/assets/layouts/welcome.kdl b/zellij-utils/assets/layouts/welcome.kdl index 1884fe1f..0ee72ce0 100644 --- a/zellij-utils/assets/layouts/welcome.kdl +++ b/zellij-utils/assets/layouts/welcome.kdl @@ -1,8 +1,6 @@ layout { pane borderless=true { - plugin location="zellij:session-manager" { - welcome_screen true - } + plugin location="welcome-screen" } } session_serialization false // this will apply only to the initial welcome screen layout, and is intended to prevent lots of garbage sessions left around diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 595293f4..e5b65d39 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -627,7 +627,7 @@ pub enum CliAction { in_place: bool, #[clap(short, long, value_parser)] move_to_focused_tab: bool, - url: Url, + url: String, #[clap(short, long, value_parser)] configuration: Option, #[clap(short, long, value_parser)] diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index b19529e4..18ed0a8d 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -2,8 +2,8 @@ use super::command::RunCommandAction; use super::layout::{ - FloatingPaneLayout, Layout, RunPlugin, RunPluginLocation, SwapFloatingLayout, SwapTiledLayout, - TiledPaneLayout, + FloatingPaneLayout, Layout, PluginAlias, RunPlugin, RunPluginLocation, RunPluginOrAlias, + SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, }; use crate::cli::CliAction; use crate::data::{Direction, Resize}; @@ -217,9 +217,9 @@ pub enum Action { LeftClick(Position), RightClick(Position), MiddleClick(Position), - LaunchOrFocusPlugin(RunPlugin, bool, bool, bool, bool), // bools => should float, + LaunchOrFocusPlugin(RunPluginOrAlias, bool, bool, bool, bool), // bools => should float, // move_to_focused_tab, should_open_in_place, skip_cache - LaunchPlugin(RunPlugin, bool, bool, bool, Option), // bools => should float, + LaunchPlugin(RunPluginOrAlias, bool, bool, bool, Option), // bools => should float, // should_open_in_place, skip_cache, Option is cwd LeftMouseRelease(Position), RightMouseRelease(Position), @@ -246,19 +246,19 @@ pub enum Action { /// Query all tab names QueryTabNames, /// Open a new tiled (embedded, non-floating) plugin pane - NewTiledPluginPane(RunPlugin, Option, bool, Option), // String is an optional name, bool is + NewTiledPluginPane(RunPluginOrAlias, Option, bool, Option), // String is an optional name, bool is // skip_cache, Option is cwd NewFloatingPluginPane( - RunPlugin, + RunPluginOrAlias, Option, bool, Option, Option, ), // String is an optional name, bool is // skip_cache, Option is cwd - NewInPlacePluginPane(RunPlugin, Option, bool), // String is an optional name, bool is + NewInPlacePluginPane(RunPluginOrAlias, Option, bool), // String is an optional name, bool is // skip_cache - StartOrReloadPlugin(RunPlugin), + StartOrReloadPlugin(RunPluginOrAlias), CloseTerminalPane(u32), ClosePluginPane(u32), FocusTerminalPaneWithId(u32, bool), // bool is should_float_if_hidden @@ -351,14 +351,20 @@ impl Action { let cwd = cwd .map(|cwd| current_dir.join(cwd)) .or_else(|| Some(current_dir)); - let user_configuration = configuration.unwrap_or_default(); if let Some(plugin) = plugin { - let location = RunPluginLocation::parse(&plugin, cwd.clone()) - .map_err(|e| format!("Failed to parse plugin loction {plugin}: {}", e))?; - let plugin = RunPlugin { - _allow_exec_host_cmd: false, - location, - configuration: user_configuration, + let plugin = match RunPluginLocation::parse(&plugin, cwd.clone()) { + Ok(location) => { + let user_configuration = configuration.unwrap_or_default(); + RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location, + configuration: user_configuration, + }) + }, + Err(_) => RunPluginOrAlias::Alias(PluginAlias::new( + &plugin, + &configuration.map(|c| c.inner().clone()), + )), }; if floating { Ok(vec![Action::NewFloatingPluginPane( @@ -571,14 +577,13 @@ impl Action { CliAction::QueryTabNames => Ok(vec![Action::QueryTabNames]), CliAction::StartOrReloadPlugin { url, configuration } => { let current_dir = get_current_dir(); - let run_plugin_location = RunPluginLocation::parse(&url, Some(current_dir)) - .map_err(|e| format!("Failed to parse plugin location: {}", e))?; - let run_plugin = RunPlugin { - location: run_plugin_location, - _allow_exec_host_cmd: false, - configuration: configuration.unwrap_or_default(), - }; - Ok(vec![Action::StartOrReloadPlugin(run_plugin)]) + let run_plugin_or_alias = RunPluginOrAlias::from_url( + &url, + &configuration.map(|c| c.inner().clone()), + None, + Some(current_dir), + )?; + Ok(vec![Action::StartOrReloadPlugin(run_plugin_or_alias)]) }, CliAction::LaunchOrFocusPlugin { url, @@ -589,15 +594,14 @@ impl Action { skip_plugin_cache, } => { let current_dir = get_current_dir(); - let run_plugin_location = RunPluginLocation::parse(url.as_str(), Some(current_dir)) - .map_err(|e| format!("Failed to parse plugin location: {}", e))?; - let run_plugin = RunPlugin { - location: run_plugin_location, - _allow_exec_host_cmd: false, - configuration: configuration.unwrap_or_default(), - }; + let run_plugin_or_alias = RunPluginOrAlias::from_url( + url.as_str(), + &configuration.map(|c| c.inner().clone()), + None, + Some(current_dir), + )?; Ok(vec![Action::LaunchOrFocusPlugin( - run_plugin, + run_plugin_or_alias, floating, move_to_focused_tab, in_place, @@ -612,16 +616,14 @@ impl Action { skip_plugin_cache, } => { let current_dir = get_current_dir(); - let run_plugin_location = - RunPluginLocation::parse(url.as_str(), Some(current_dir.clone())) - .map_err(|e| format!("Failed to parse plugin location: {}", e))?; - let run_plugin = RunPlugin { - location: run_plugin_location, - _allow_exec_host_cmd: false, - configuration: configuration.unwrap_or_default(), - }; + let run_plugin_or_alias = RunPluginOrAlias::from_url( + &url.as_str(), + &configuration.map(|c| c.inner().clone()), + None, + Some(current_dir.clone()), + )?; Ok(vec![Action::LaunchPlugin( - run_plugin, + run_plugin_or_alias, floating, in_place, skip_plugin_cache, diff --git a/zellij-utils/src/input/config.rs b/zellij-utils/src/input/config.rs index eb8fe521..cf6620a9 100644 --- a/zellij-utils/src/input/config.rs +++ b/zellij-utils/src/input/config.rs @@ -9,7 +9,7 @@ use std::convert::TryFrom; use super::keybinds::Keybinds; use super::options::Options; -use super::plugins::{PluginsConfig, PluginsConfigError}; +use super::plugins::{PluginAliases, PluginsConfigError}; use super::theme::{Themes, UiConfig}; use crate::cli::{CliArgs, Command}; use crate::envs::EnvironmentVariables; @@ -25,7 +25,7 @@ pub struct Config { pub keybinds: Keybinds, pub options: Options, pub themes: Themes, - pub plugins: PluginsConfig, + pub plugins: PluginAliases, pub ui: UiConfig, pub env: EnvironmentVariables, } @@ -226,7 +226,7 @@ impl Config { self.options = self.options.merge(other.options); self.keybinds.merge(other.keybinds.clone()); self.themes = self.themes.merge(other.themes); - self.plugins = self.plugins.merge(other.plugins); + self.plugins.merge(other.plugins); self.ui = self.ui.merge(other.ui); self.env = self.env.merge(other.env); Ok(()) @@ -237,11 +237,11 @@ impl Config { mod config_test { use super::*; use crate::data::{InputMode, Palette, PaletteColor, PluginTag}; - use crate::input::layout::RunPluginLocation; + use crate::input::layout::{RunPlugin, RunPluginLocation}; use crate::input::options::{Clipboard, OnForceClose}; - use crate::input::plugins::{PluginConfig, PluginType, PluginsConfig}; + use crate::input::plugins::{PluginConfig, PluginType}; use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig}; - use std::collections::HashMap; + use std::collections::{BTreeMap, HashMap}; use std::io::Write; use tempfile::tempdir; @@ -591,60 +591,54 @@ mod config_test { fn can_define_plugin_configuration_in_configfile() { let config_contents = r#" plugins { - tab-bar { path "tab-bar"; } - status-bar { path "status-bar"; } - strider { - path "strider" - _allow_exec_host_cmd true + tab-bar location="zellij:tab-bar" + status-bar location="zellij:status-bar" + strider location="zellij:strider" + compact-bar location="zellij:compact-bar" + session-manager location="zellij:session-manager" + welcome-screen location="zellij:session-manager" { + welcome_screen true } - compact-bar { path "compact-bar"; } + filepicker location="zellij:strider" } "#; let config = Config::from_kdl(config_contents, None).unwrap(); - let mut expected_plugin_configuration = HashMap::new(); + let mut expected_plugin_configuration = BTreeMap::new(); expected_plugin_configuration.insert( - PluginTag::new("tab-bar"), - PluginConfig { - path: PathBuf::from("tab-bar"), - run: PluginType::Pane(None), - location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")), - _allow_exec_host_cmd: false, - userspace_configuration: Default::default(), - }, + "tab-bar".to_owned(), + RunPlugin::from_url("zellij:tab-bar").unwrap(), ); expected_plugin_configuration.insert( - PluginTag::new("status-bar"), - PluginConfig { - path: PathBuf::from("status-bar"), - run: PluginType::Pane(None), - location: RunPluginLocation::Zellij(PluginTag::new("status-bar")), - _allow_exec_host_cmd: false, - userspace_configuration: Default::default(), - }, + "status-bar".to_owned(), + RunPlugin::from_url("zellij:status-bar").unwrap(), ); expected_plugin_configuration.insert( - PluginTag::new("strider"), - PluginConfig { - path: PathBuf::from("strider"), - run: PluginType::Pane(None), - location: RunPluginLocation::Zellij(PluginTag::new("strider")), - _allow_exec_host_cmd: true, - userspace_configuration: Default::default(), - }, + "strider".to_owned(), + RunPlugin::from_url("zellij:strider").unwrap(), ); expected_plugin_configuration.insert( - PluginTag::new("compact-bar"), - PluginConfig { - path: PathBuf::from("compact-bar"), - run: PluginType::Pane(None), - location: RunPluginLocation::Zellij(PluginTag::new("compact-bar")), - _allow_exec_host_cmd: false, - userspace_configuration: Default::default(), - }, + "compact-bar".to_owned(), + RunPlugin::from_url("zellij:compact-bar").unwrap(), + ); + expected_plugin_configuration.insert( + "session-manager".to_owned(), + RunPlugin::from_url("zellij:session-manager").unwrap(), + ); + let mut welcome_screen_configuration = BTreeMap::new(); + welcome_screen_configuration.insert("welcome_screen".to_owned(), "true".to_owned()); + expected_plugin_configuration.insert( + "welcome-screen".to_owned(), + RunPlugin::from_url("zellij:session-manager") + .unwrap() + .with_configuration(welcome_screen_configuration), + ); + expected_plugin_configuration.insert( + "filepicker".to_owned(), + RunPlugin::from_url("zellij:strider").unwrap(), ); assert_eq!( config.plugins, - PluginsConfig::from_data(expected_plugin_configuration), + PluginAliases::from_data(expected_plugin_configuration), "Plugins defined in config" ); } diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index 3dfadb40..ad2fca89 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -23,7 +23,7 @@ use std::cmp::Ordering; use std::fmt::{Display, Formatter}; use std::str::FromStr; -use super::plugins::{PluginTag, PluginsConfigError}; +use super::plugins::{PluginAliases, PluginTag, PluginsConfigError}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::vec::Vec; @@ -80,10 +80,122 @@ impl SplitSize { } } +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)] +pub enum RunPluginOrAlias { + RunPlugin(RunPlugin), + Alias(PluginAlias), +} + +impl Default for RunPluginOrAlias { + fn default() -> Self { + RunPluginOrAlias::RunPlugin(Default::default()) + } +} + +impl RunPluginOrAlias { + pub fn location_string(&self) -> String { + match self { + RunPluginOrAlias::RunPlugin(run_plugin) => run_plugin.location.display(), + RunPluginOrAlias::Alias(plugin_alias) => plugin_alias.name.clone(), + } + } + pub fn populate_run_plugin_if_needed(&mut self, plugin_aliases: &PluginAliases) { + if let RunPluginOrAlias::Alias(run_plugin_alias) = self { + if run_plugin_alias.run_plugin.is_some() { + log::warn!("Overriding plugin alias"); + } + let merged_run_plugin = plugin_aliases + .aliases + .get(run_plugin_alias.name.as_str()) + .map(|r| { + r.clone().merge_configuration( + &run_plugin_alias + .configuration + .as_ref() + .map(|c| c.inner().clone()), + ) + }); + run_plugin_alias.run_plugin = merged_run_plugin; + } + } + pub fn get_run_plugin(&self) -> Option { + match self { + RunPluginOrAlias::RunPlugin(run_plugin) => Some(run_plugin.clone()), + RunPluginOrAlias::Alias(plugin_alias) => plugin_alias.run_plugin.clone(), + } + } + pub fn get_configuration(&self) -> Option { + self.get_run_plugin().map(|r| r.configuration.clone()) + } + pub fn from_url( + url: &str, + configuration: &Option>, + alias_dict: Option<&PluginAliases>, + cwd: Option, + ) -> Result { + match RunPluginLocation::parse(&url, cwd) { + Ok(location) => Ok(RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location, + configuration: configuration + .as_ref() + .map(|c| PluginUserConfiguration::new(c.clone())) + .unwrap_or_default(), + })), + Err(PluginsConfigError::InvalidUrlScheme(_)) + | Err(PluginsConfigError::InvalidUrl(..)) => { + let mut plugin_alias = PluginAlias::new(&url, configuration); + if let Some(alias_dict) = alias_dict { + plugin_alias.run_plugin = alias_dict + .aliases + .get(url) + .map(|r| r.clone().merge_configuration(configuration)); + } + Ok(RunPluginOrAlias::Alias(plugin_alias)) + }, + Err(e) => { + return Err(format!("Failed to parse plugin location {url}: {}", e)); + }, + } + } + pub fn is_equivalent_to_run(&self, run: &Option) -> bool { + match (self, run) { + ( + RunPluginOrAlias::Alias(self_alias), + Some(Run::Plugin(RunPluginOrAlias::Alias(run_alias))), + ) => { + self_alias.name == run_alias.name + && self_alias + .configuration + .as_ref() + // we do the is_empty() checks because an empty configuration is the same as no + // configuration (i.e. None) + .and_then(|c| if c.inner().is_empty() { None } else { Some(c) }) + == run_alias.configuration.as_ref().and_then(|c| { + if c.inner().is_empty() { + None + } else { + Some(c) + } + }) + }, + ( + RunPluginOrAlias::Alias(self_alias), + Some(Run::Plugin(RunPluginOrAlias::RunPlugin(other_run_plugin))), + ) => self_alias.run_plugin.as_ref() == Some(other_run_plugin), + ( + RunPluginOrAlias::RunPlugin(self_run_plugin), + Some(Run::Plugin(RunPluginOrAlias::RunPlugin(other_run_plugin))), + ) => self_run_plugin == other_run_plugin, + _ => false, + } + } +} + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub enum Run { #[serde(rename = "plugin")] - Plugin(RunPlugin), + Plugin(RunPluginOrAlias), #[serde(rename = "command")] Command(RunCommand), EditFile(PathBuf, Option, Option), // TODO: merge this with TerminalAction::OpenFile @@ -227,6 +339,23 @@ impl Run { Run::Cwd(cwd) => Some(cwd.clone()), } } + pub fn get_run_plugin(&self) -> Option { + match self { + Run::Plugin(RunPluginOrAlias::RunPlugin(run_plugin)) => Some(run_plugin.clone()), + Run::Plugin(RunPluginOrAlias::Alias(plugin_alias)) => { + plugin_alias.run_plugin.as_ref().map(|r| r.clone()) + }, + _ => None, + } + } + pub fn populate_run_plugin_if_needed(&mut self, alias_dict: &PluginAliases) { + match self { + Run::Plugin(run_plugin_alias) => { + run_plugin_alias.populate_run_plugin_if_needed(alias_dict) + }, + _ => {}, + } + } } #[allow(clippy::derive_hash_xor_eq)] @@ -246,6 +375,35 @@ impl RunPlugin { ..Default::default() }) } + pub fn with_configuration(mut self, configuration: BTreeMap) -> Self { + self.configuration = PluginUserConfiguration::new(configuration); + self + } + pub fn merge_configuration(mut self, configuration: &Option>) -> Self { + if let Some(configuration) = configuration { + self.configuration.merge(configuration); + } + self + } +} + +#[derive(Debug, Serialize, Deserialize, Clone, Hash, Default, PartialEq, Eq)] +pub struct PluginAlias { + pub name: String, + pub configuration: Option, + pub run_plugin: Option, +} + +impl PluginAlias { + pub fn new(name: &str, configuration: &Option>) -> Self { + PluginAlias { + name: name.to_owned(), + configuration: configuration + .as_ref() + .map(|c| PluginUserConfiguration::new(c.clone())), + ..Default::default() + } + } } #[allow(clippy::derive_hash_xor_eq)] @@ -280,6 +438,11 @@ impl PluginUserConfiguration { pub fn insert(&mut self, config_key: impl Into, config_value: impl Into) { self.0.insert(config_key.into(), config_value.into()); } + pub fn merge(&mut self, other_config: &BTreeMap) { + for (key, value) in other_config { + self.0.insert(key.to_owned(), value.clone()); + } + } } impl FromStr for PluginUserConfiguration { @@ -706,6 +869,15 @@ impl TiledPaneLayout { child.add_cwd_to_layout(cwd); } } + pub fn populate_plugin_aliases_in_layout(&mut self, plugin_aliases: &PluginAliases) { + match self.run.as_mut() { + Some(run) => run.populate_run_plugin_if_needed(plugin_aliases), + _ => {}, + } + for child in self.children.iter_mut() { + child.populate_plugin_aliases_in_layout(plugin_aliases); + } + } pub fn deepest_depth(&self) -> usize { let mut deepest_child_depth = 0; for child in self.children.iter() { @@ -1141,6 +1313,26 @@ impl Layout { Err(_e) => None, } } + pub fn populate_plugin_aliases_in_layout(&mut self, plugin_aliases: &PluginAliases) { + for tab in self.tabs.iter_mut() { + tab.1.populate_plugin_aliases_in_layout(plugin_aliases); + for floating_pane_layout in tab.2.iter_mut() { + floating_pane_layout + .run + .as_mut() + .map(|f| f.populate_run_plugin_if_needed(&plugin_aliases)); + } + } + if let Some(template) = self.template.as_mut() { + template.0.populate_plugin_aliases_in_layout(plugin_aliases); + for floating_pane_layout in template.1.iter_mut() { + floating_pane_layout + .run + .as_mut() + .map(|f| f.populate_run_plugin_if_needed(&plugin_aliases)); + } + } + } } fn split_space( diff --git a/zellij-utils/src/input/plugins.rs b/zellij-utils/src/input/plugins.rs index 2a262222..cb3d6891 100644 --- a/zellij-utils/src/input/plugins.rs +++ b/zellij-utils/src/input/plugins.rs @@ -1,6 +1,5 @@ //! Plugins configuration metadata -use std::borrow::Borrow; -use std::collections::HashMap; +use std::collections::BTreeMap; use std::fs; use std::path::{Path, PathBuf}; use thiserror::Error; @@ -14,73 +13,17 @@ use crate::consts::ASSET_MAP; pub use crate::data::PluginTag; use crate::errors::prelude::*; -use std::collections::BTreeMap; -use std::fmt; - -/// Used in the config struct for plugin metadata -#[derive(Clone, PartialEq, Deserialize, Serialize)] -pub struct PluginsConfig(pub HashMap); - -impl fmt::Debug for PluginsConfig { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut stable_sorted = BTreeMap::new(); - for (plugin_tag, plugin_config) in self.0.iter() { - stable_sorted.insert(plugin_tag, plugin_config); - } - write!(f, "{:#?}", stable_sorted) - } +#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct PluginAliases { + pub aliases: BTreeMap, } -impl PluginsConfig { - pub fn new() -> Self { - Self(HashMap::new()) +impl PluginAliases { + pub fn merge(&mut self, other: Self) { + self.aliases.extend(other.aliases); } - pub fn from_data(data: HashMap) -> Self { - PluginsConfig(data) - } - - /// Get plugin config from run configuration specified in layout files. - pub fn get(&self, run: impl Borrow) -> Option { - let run = run.borrow(); - match &run.location { - RunPluginLocation::File(path) => Some(PluginConfig { - path: path.clone(), - run: PluginType::Pane(None), - _allow_exec_host_cmd: run._allow_exec_host_cmd, - location: run.location.clone(), - userspace_configuration: run.configuration.clone(), - }), - RunPluginLocation::Zellij(tag) => self.0.get(tag).cloned().map(|plugin| PluginConfig { - _allow_exec_host_cmd: run._allow_exec_host_cmd, - userspace_configuration: run.configuration.clone(), - ..plugin - }), - RunPluginLocation::Remote(_) => Some(PluginConfig { - path: PathBuf::new(), - run: PluginType::Pane(None), - _allow_exec_host_cmd: run._allow_exec_host_cmd, - location: run.location.clone(), - userspace_configuration: run.configuration.clone(), - }), - } - } - - pub fn iter(&self) -> impl Iterator { - self.0.values() - } - - /// Merges two PluginConfig structs into one PluginConfig struct - /// `other` overrides the PluginConfig of `self`. - pub fn merge(&self, other: Self) -> Self { - let mut plugin_config = self.0.clone(); - plugin_config.extend(other.0); - Self(plugin_config) - } -} - -impl Default for PluginsConfig { - fn default() -> Self { - PluginsConfig(HashMap::new()) + pub fn from_data(aliases: BTreeMap) -> Self { + PluginAliases { aliases } } } @@ -100,6 +43,44 @@ pub struct PluginConfig { } impl PluginConfig { + pub fn from_run_plugin(run_plugin: &RunPlugin) -> Option { + match &run_plugin.location { + RunPluginLocation::File(path) => Some(PluginConfig { + path: path.clone(), + run: PluginType::Pane(None), + _allow_exec_host_cmd: run_plugin._allow_exec_host_cmd, + location: run_plugin.location.clone(), + userspace_configuration: run_plugin.configuration.clone(), + }), + RunPluginLocation::Zellij(tag) => { + let tag = tag.to_string(); + if tag == "status-bar" + || tag == "tab-bar" + || tag == "compact-bar" + || tag == "strider" + || tag == "session-manager" + { + Some(PluginConfig { + path: PathBuf::from(&tag), + run: PluginType::Pane(None), + _allow_exec_host_cmd: run_plugin._allow_exec_host_cmd, + location: RunPluginLocation::parse(&format!("zellij:{}", tag), None) + .ok()?, + userspace_configuration: run_plugin.configuration.clone(), + }) + } else { + None + } + }, + RunPluginLocation::Remote(_) => Some(PluginConfig { + path: PathBuf::new(), + run: PluginType::Pane(None), + _allow_exec_host_cmd: run_plugin._allow_exec_host_cmd, + location: run_plugin.location.clone(), + userspace_configuration: run_plugin.configuration.clone(), + }), + } + } /// Resolve wasm plugin bytes for the plugin path and given plugin directory. /// /// If zellij was built without the 'disable_automatic_asset_installation' feature, builtin diff --git a/zellij-utils/src/input/unit/layout_test.rs b/zellij-utils/src/input/unit/layout_test.rs index 424a5b22..b2070ce1 100644 --- a/zellij-utils/src/input/unit/layout_test.rs +++ b/zellij-utils/src/input/unit/layout_test.rs @@ -551,29 +551,29 @@ fn layout_with_plugin_panes() { TiledPaneLayout { children: vec![ TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")), _allow_exec_host_cmd: false, configuration: Default::default(), - })), + }))), ..Default::default() }, TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { location: RunPluginLocation::File(PathBuf::from( "/path/to/my/plugin.wasm", )), _allow_exec_host_cmd: false, configuration: Default::default(), - })), + }))), ..Default::default() }, TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { location: RunPluginLocation::Zellij(PluginTag::new("status-bar")), _allow_exec_host_cmd: false, configuration: PluginUserConfiguration(expected_plugin_configuration), - })), + }))), ..Default::default() }, ], @@ -2079,6 +2079,9 @@ fn run_plugin_location_parsing() { pane { plugin location="file:c:/absolute/windows/plugin.wasm" } + pane { + plugin location="filepicker" + } } "#; let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None).unwrap(); @@ -2087,59 +2090,67 @@ fn run_plugin_location_parsing() { TiledPaneLayout { children: vec![ TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")), configuration: Default::default(), - })), + }))), ..Default::default() }, TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from( "/path/to/my/plugin.wasm", )), configuration: Default::default(), - })), + }))), ..Default::default() }, TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from("plugin.wasm")), configuration: Default::default(), - })), + }))), ..Default::default() }, TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from( "relative/with space/plugin.wasm", )), configuration: Default::default(), - })), + }))), ..Default::default() }, TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from( "/absolute/with space/plugin.wasm", )), configuration: Default::default(), - })), + }))), ..Default::default() }, TiledPaneLayout { - run: Some(Run::Plugin(RunPlugin { + run: Some(Run::Plugin(RunPluginOrAlias::RunPlugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from( "c:/absolute/windows/plugin.wasm", )), configuration: Default::default(), - })), + }))), + ..Default::default() + }, + TiledPaneLayout { + run: Some(Run::Plugin(RunPluginOrAlias::Alias(PluginAlias { + name: "filepicker".to_owned(), + configuration: Some(PluginUserConfiguration::default()), + ..Default::default() + }))), ..Default::default() }, ], diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap index 0ebdf2ca..abfd8801 100644 --- a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap +++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__can_load_swap_layouts_from_a_different_file.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/input/./unit/layout_test.rs -assertion_line: 1880 +assertion_line: 1935 expression: "format!(\"{:#?}\", layout)" --- Layout { @@ -65,17 +65,19 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), ), ), borderless: true, @@ -167,17 +169,19 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), ), ), borderless: true, @@ -220,17 +224,19 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), ), ), borderless: true, @@ -387,17 +393,19 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), ), ), borderless: true, @@ -440,17 +448,19 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), ), ), borderless: true, @@ -688,17 +698,19 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), ), ), borderless: true, diff --git a/zellij-utils/src/ipc.rs b/zellij-utils/src/ipc.rs index 902d0235..b91ff697 100644 --- a/zellij-utils/src/ipc.rs +++ b/zellij-utils/src/ipc.rs @@ -4,7 +4,7 @@ use crate::{ data::{ClientId, ConnectToSession, InputMode, Style}, errors::{get_current_ctx, prelude::*, ErrorContext}, input::keybinds::Keybinds, - input::{actions::Action, layout::Layout, options::Options, plugins::PluginsConfig}, + input::{actions::Action, layout::Layout, options::Options, plugins::PluginAliases}, pane_size::{Size, SizeInPixels}, }; use interprocess::local_socket::LocalSocketStream; @@ -76,7 +76,7 @@ pub enum ClientToServerMsg { Box, Box, Box, - Option, + Box, ), AttachClient( ClientAttributes, diff --git a/zellij-utils/src/kdl/kdl_layout_parser.rs b/zellij-utils/src/kdl/kdl_layout_parser.rs index 16be5fca..2aa3ba57 100644 --- a/zellij-utils/src/kdl/kdl_layout_parser.rs +++ b/zellij-utils/src/kdl/kdl_layout_parser.rs @@ -3,8 +3,8 @@ use crate::input::{ config::ConfigError, layout::{ FloatingPaneLayout, Layout, LayoutConstraint, PercentOrFixed, PluginUserConfiguration, Run, - RunPlugin, RunPluginLocation, SplitDirection, SplitSize, SwapFloatingLayout, - SwapTiledLayout, TiledPaneLayout, + RunPluginOrAlias, SplitDirection, SplitSize, SwapFloatingLayout, SwapTiledLayout, + TiledPaneLayout, }, }; @@ -313,20 +313,21 @@ impl<'a> KdlLayoutParser<'a> { plugin_block.span().len(), ), )?; - let location = - RunPluginLocation::parse(&string_url, self.cwd_prefix(None)?).map_err(|e| { - ConfigError::new_layout_kdl_error( - e.to_string(), - url_node.span().offset(), - url_node.span().len(), - ) - })?; let configuration = KdlLayoutParser::parse_plugin_user_configuration(&plugin_block)?; - Ok(Some(Run::Plugin(RunPlugin { - _allow_exec_host_cmd, - location, - configuration, - }))) + let run_plugin_or_alias = RunPluginOrAlias::from_url( + &string_url, + &Some(configuration.inner().clone()), + None, + self.cwd_prefix(None)?, + ) + .map_err(|e| { + ConfigError::new_kdl_error( + format!("Failed to parse plugin: {}", e), + url_node.span().offset(), + url_node.span().len(), + ) + })?; + Ok(Some(Run::Plugin(run_plugin_or_alias))) } pub fn parse_plugin_user_configuration( plugin_block: &KdlNode, diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index 1d721090..23d7e69e 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -7,10 +7,10 @@ use crate::envs::EnvironmentVariables; use crate::home::{find_default_config_dir, get_layout_dir}; use crate::input::config::{Config, ConfigError, KdlError}; use crate::input::keybinds::Keybinds; -use crate::input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}; +use crate::input::layout::{Layout, RunPlugin, RunPluginOrAlias}; use crate::input::options::{Clipboard, OnForceClose, Options}; use crate::input::permission::{GrantedPermission, PermissionCache}; -use crate::input::plugins::{PluginConfig, PluginTag, PluginType, PluginsConfig}; +use crate::input::plugins::PluginAliases; use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig}; use kdl_layout_parser::KdlLayoutParser; use std::collections::{BTreeMap, HashMap, HashSet}; @@ -981,15 +981,22 @@ impl TryFrom<(&KdlNode, &Options)> for Action { .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "skip_plugin_cache")) .unwrap_or(false); let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); - let location = RunPluginLocation::parse(&plugin_path, Some(current_dir))?; let configuration = KdlLayoutParser::parse_plugin_user_configuration(&kdl_action)?; - let run_plugin = RunPlugin { - location, - _allow_exec_host_cmd: false, - configuration, - }; + let run_plugin_or_alias = RunPluginOrAlias::from_url( + &plugin_path, + &Some(configuration.inner().clone()), + None, + Some(current_dir), + ) + .map_err(|e| { + ConfigError::new_kdl_error( + format!("Failed to parse plugin: {}", e), + kdl_action.span().offset(), + kdl_action.span().len(), + ) + })?; Ok(Action::LaunchOrFocusPlugin( - run_plugin, + run_plugin_or_alias, should_float, move_to_focused_tab, should_open_in_place, @@ -1019,15 +1026,22 @@ impl TryFrom<(&KdlNode, &Options)> for Action { .and_then(|c_m| kdl_child_bool_value_for_entry(c_m, "skip_plugin_cache")) .unwrap_or(false); let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); - let location = RunPluginLocation::parse(&plugin_path, Some(current_dir))?; let configuration = KdlLayoutParser::parse_plugin_user_configuration(&kdl_action)?; - let run_plugin = RunPlugin { - location, - _allow_exec_host_cmd: false, - configuration, - }; + let run_plugin_or_alias = RunPluginOrAlias::from_url( + &plugin_path, + &Some(configuration.inner().clone()), + None, + Some(current_dir), + ) + .map_err(|e| { + ConfigError::new_kdl_error( + format!("Failed to parse plugin: {}", e), + kdl_action.span().offset(), + kdl_action.span().len(), + ) + })?; Ok(Action::LaunchPlugin( - run_plugin, + run_plugin_or_alias, should_float, should_open_in_place, skip_plugin_cache, @@ -1810,9 +1824,9 @@ impl Config { let config_themes = Themes::from_kdl(kdl_themes)?; config.themes = config.themes.merge(config_themes); } - if let Some(kdl_plugin_config) = kdl_config.get("plugins") { - let config_plugins = PluginsConfig::from_kdl(kdl_plugin_config)?; - config.plugins = config.plugins.merge(config_plugins); + if let Some(kdl_plugin_aliases) = kdl_config.get("plugins") { + let config_plugins = PluginAliases::from_kdl(kdl_plugin_aliases)?; + config.plugins.merge(config_plugins); } if let Some(kdl_ui_config) = kdl_config.get("ui") { let config_ui = UiConfig::from_kdl(&kdl_ui_config)?; @@ -1826,38 +1840,27 @@ impl Config { } } -impl PluginsConfig { - pub fn from_kdl(kdl_plugin_config: &KdlNode) -> Result { - let mut plugins: HashMap = HashMap::new(); - for plugin_config in - kdl_children_nodes_or_error!(kdl_plugin_config, "no plugin config found") - { - let plugin_name = kdl_name!(plugin_config); - let plugin_tag = PluginTag::new(plugin_name); - let path = kdl_children_property_first_arg_as_string!(plugin_config, "path") - .map(|path| PathBuf::from(path)) - .ok_or(ConfigError::new_kdl_error( - "Plugin path not found or invalid".into(), - plugin_config.span().offset(), - plugin_config.span().len(), - ))?; - let allow_exec_host_cmd = - kdl_children_property_first_arg_as_bool!(plugin_config, "_allow_exec_host_cmd") - .unwrap_or(false); - let plugin_config = PluginConfig { - path, - run: PluginType::Pane(None), - location: RunPluginLocation::Zellij(plugin_tag.clone()), - _allow_exec_host_cmd: allow_exec_host_cmd, - userspace_configuration: PluginUserConfiguration::new(BTreeMap::new()), // TODO: consider removing the whole - // "plugins" section in the config - // because it's not used??? - }; - plugins.insert(plugin_tag, plugin_config); +impl PluginAliases { + pub fn from_kdl(kdl_plugin_aliases: &KdlNode) -> Result { + let mut aliases: BTreeMap = BTreeMap::new(); + if let Some(kdl_plugin_aliases) = kdl_children_nodes!(kdl_plugin_aliases) { + for alias_definition in kdl_plugin_aliases { + let alias_name = kdl_name!(alias_definition); + if let Some(string_url) = + kdl_get_string_property_or_child_value!(alias_definition, "location") + { + let configuration = + KdlLayoutParser::parse_plugin_user_configuration(&alias_definition)?; + let run_plugin = RunPlugin::from_url(string_url)? + .with_configuration(configuration.inner().clone()); + aliases.insert(alias_name.to_owned(), run_plugin); + } + } } - Ok(PluginsConfig(plugins)) + Ok(PluginAliases { aliases }) } } + impl UiConfig { pub fn from_kdl(kdl_ui_config: &KdlNode) -> Result { let mut ui_config = UiConfig::default(); diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index ed657897..5673d1f9 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -18,9 +18,10 @@ use crate::errors::prelude::*; use crate::input::actions::Action; use crate::input::actions::{SearchDirection, SearchOption}; use crate::input::command::RunCommandAction; -use crate::input::layout::{PluginUserConfiguration, RunPlugin, RunPluginLocation}; +use crate::input::layout::{ + PluginUserConfiguration, RunPlugin, RunPluginLocation, RunPluginOrAlias, +}; use crate::position::Position; -use url::Url; use std::collections::BTreeMap; use std::convert::TryFrom; @@ -403,24 +404,23 @@ impl TryFrom for Action { Some(ProtobufActionName::LaunchOrFocusPlugin) => { match protobuf_action.optional_payload { Some(OptionalPayload::LaunchOrFocusPluginPayload(payload)) => { - let run_plugin_location = - RunPluginLocation::parse(&payload.plugin_url, None) - .map_err(|_| "Malformed LaunchOrFocusPlugin payload")?; let configuration: PluginUserConfiguration = payload .plugin_configuration .and_then(|p| PluginUserConfiguration::try_from(p).ok()) .unwrap_or_default(); - let run_plugin = RunPlugin { - _allow_exec_host_cmd: false, - location: run_plugin_location, - configuration, - }; + let run_plugin_or_alias = RunPluginOrAlias::from_url( + &payload.plugin_url.as_str(), + &Some(configuration.inner().clone()), + None, + None, + ) + .map_err(|_| "Malformed LaunchOrFocusPlugin payload")?; let should_float = payload.should_float; let move_to_focused_tab = payload.move_to_focused_tab; let should_open_in_place = payload.should_open_in_place; let skip_plugin_cache = payload.skip_plugin_cache; Ok(Action::LaunchOrFocusPlugin( - run_plugin, + run_plugin_or_alias, should_float, move_to_focused_tab, should_open_in_place, @@ -432,25 +432,24 @@ impl TryFrom for Action { }, Some(ProtobufActionName::LaunchPlugin) => match protobuf_action.optional_payload { Some(OptionalPayload::LaunchOrFocusPluginPayload(payload)) => { - let run_plugin_location = - RunPluginLocation::parse(&payload.plugin_url, None) - .map_err(|_| "Malformed LaunchOrFocusPlugin payload")?; let configuration: PluginUserConfiguration = payload .plugin_configuration .and_then(|p| PluginUserConfiguration::try_from(p).ok()) .unwrap_or_default(); - let run_plugin = RunPlugin { - _allow_exec_host_cmd: false, - location: run_plugin_location, - configuration, - }; + let run_plugin_or_alias = RunPluginOrAlias::from_url( + &payload.plugin_url.as_str(), + &Some(configuration.inner().clone()), + None, + None, + ) + .map_err(|_| "Malformed LaunchOrFocusPlugin payload")?; let should_float = payload.should_float; let _move_to_focused_tab = payload.move_to_focused_tab; // not actually used in // this action let should_open_in_place = payload.should_open_in_place; let skip_plugin_cache = payload.skip_plugin_cache; Ok(Action::LaunchPlugin( - run_plugin, + run_plugin_or_alias, should_float, should_open_in_place, skip_plugin_cache, @@ -553,11 +552,11 @@ impl TryFrom for Action { let run_plugin_location = RunPluginLocation::parse(&payload.plugin_url, None) .map_err(|_| "Malformed NewTiledPluginPane payload")?; - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { location: run_plugin_location, _allow_exec_host_cmd: false, configuration: PluginUserConfiguration::default(), - }; + }); let pane_name = payload.pane_name; let skip_plugin_cache = payload.skip_plugin_cache; Ok(Action::NewTiledPluginPane( @@ -576,11 +575,11 @@ impl TryFrom for Action { let run_plugin_location = RunPluginLocation::parse(&payload.plugin_url, None) .map_err(|_| "Malformed NewTiledPluginPane payload")?; - let run_plugin = RunPlugin { + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { location: run_plugin_location, _allow_exec_host_cmd: false, configuration: PluginUserConfiguration::default(), - }; + }); let pane_name = payload.pane_name; let skip_plugin_cache = payload.skip_plugin_cache; Ok(Action::NewFloatingPluginPane( @@ -597,14 +596,11 @@ impl TryFrom for Action { Some(ProtobufActionName::StartOrReloadPlugin) => { match protobuf_action.optional_payload { Some(OptionalPayload::StartOrReloadPluginPayload(payload)) => { - let run_plugin_location = RunPluginLocation::parse(&payload, None) - .map_err(|_| "Malformed StartOrReloadPluginPayload payload")?; - let run_plugin = RunPlugin { - _allow_exec_host_cmd: false, - location: run_plugin_location, - configuration: PluginUserConfiguration::default(), - }; - Ok(Action::StartOrReloadPlugin(run_plugin)) + let run_plugin_or_alias = + RunPluginOrAlias::from_url(&payload.as_str(), &None, None, None) + .map_err(|_| "Malformed LaunchOrFocusPlugin payload")?; + + Ok(Action::StartOrReloadPlugin(run_plugin_or_alias)) }, _ => Err("Wrong payload for Action::StartOrReloadPlugin"), } @@ -1044,44 +1040,44 @@ impl TryFrom for ProtobufAction { }) }, Action::LaunchOrFocusPlugin( - run_plugin, + run_plugin_or_alias, should_float, move_to_focused_tab, should_open_in_place, skip_plugin_cache, ) => { - let url: Url = Url::from(&run_plugin.location); + let configuration = run_plugin_or_alias.get_configuration().unwrap_or_default(); Ok(ProtobufAction { name: ProtobufActionName::LaunchOrFocusPlugin as i32, optional_payload: Some(OptionalPayload::LaunchOrFocusPluginPayload( LaunchOrFocusPluginPayload { - plugin_url: url.into(), + plugin_url: run_plugin_or_alias.location_string(), should_float, move_to_focused_tab, should_open_in_place, - plugin_configuration: Some(run_plugin.configuration.try_into()?), + plugin_configuration: Some(configuration.try_into()?), skip_plugin_cache, }, )), }) }, Action::LaunchPlugin( - run_plugin, + run_plugin_or_alias, should_float, should_open_in_place, skip_plugin_cache, _cwd, ) => { - let url: Url = Url::from(&run_plugin.location); + let configuration = run_plugin_or_alias.get_configuration().unwrap_or_default(); Ok(ProtobufAction { name: ProtobufActionName::LaunchPlugin as i32, optional_payload: Some(OptionalPayload::LaunchOrFocusPluginPayload( LaunchOrFocusPluginPayload { - plugin_url: url.into(), + plugin_url: run_plugin_or_alias.location_string(), should_float, move_to_focused_tab: false, should_open_in_place, - plugin_configuration: Some(run_plugin.configuration.try_into()?), + plugin_configuration: Some(configuration.try_into()?), skip_plugin_cache, }, )), @@ -1166,12 +1162,11 @@ impl TryFrom for ProtobufAction { optional_payload: None, }), Action::NewTiledPluginPane(run_plugin, pane_name, skip_plugin_cache, _cwd) => { - let plugin_url: Url = Url::from(&run_plugin.location); Ok(ProtobufAction { name: ProtobufActionName::NewTiledPluginPane as i32, optional_payload: Some(OptionalPayload::NewTiledPluginPanePayload( NewPluginPanePayload { - plugin_url: plugin_url.into(), + plugin_url: run_plugin.location_string(), pane_name, skip_plugin_cache, }, @@ -1185,27 +1180,30 @@ impl TryFrom for ProtobufAction { _cwd, _coordinates, ) => { - let plugin_url: Url = Url::from(&run_plugin.location); + // let plugin_url: Url = match run_plugin { + // RunPluginOrAlias::RunPlugin(run_plugin) => Url::from(&run_plugin.location), + // RunPluginOrAlias::Alias(plugin_alias) => { + // // TODO: support plugin alias + // unimplemented!() + // } + // }; Ok(ProtobufAction { name: ProtobufActionName::NewFloatingPluginPane as i32, optional_payload: Some(OptionalPayload::NewFloatingPluginPanePayload( NewPluginPanePayload { - plugin_url: plugin_url.into(), + plugin_url: run_plugin.location_string(), pane_name, skip_plugin_cache, }, )), }) }, - Action::StartOrReloadPlugin(run_plugin) => { - let plugin_url: Url = Url::from(&run_plugin.location); - Ok(ProtobufAction { - name: ProtobufActionName::StartOrReloadPlugin as i32, - optional_payload: Some(OptionalPayload::StartOrReloadPluginPayload( - plugin_url.into(), - )), - }) - }, + Action::StartOrReloadPlugin(run_plugin) => Ok(ProtobufAction { + name: ProtobufActionName::StartOrReloadPlugin as i32, + optional_payload: Some(OptionalPayload::StartOrReloadPluginPayload( + run_plugin.location_string(), + )), + }), Action::CloseTerminalPane(terminal_pane_id) => Ok(ProtobufAction { name: ProtobufActionName::CloseTerminalPane as i32, optional_payload: Some(OptionalPayload::CloseTerminalPanePayload(terminal_pane_id)), diff --git a/zellij-utils/src/session_serialization.rs b/zellij-utils/src/session_serialization.rs index 0cd97328..d34aeb14 100644 --- a/zellij-utils/src/session_serialization.rs +++ b/zellij-utils/src/session_serialization.rs @@ -1,20 +1,11 @@ -//! # Persistence module -//! !WIP! This module is holding the logic for all persistence sessions need -//! -//! # Examples -//! ```rust,no_run -//! fn main() { -//! } -//! ``` -//! use std::collections::BTreeMap; use std::path::PathBuf; use crate::{ input::layout::PluginUserConfiguration, input::layout::{ - FloatingPaneLayout, Layout, PercentOrFixed, Run, SplitDirection, SplitSize, - SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, + FloatingPaneLayout, Layout, PercentOrFixed, Run, RunPluginOrAlias, SplitDirection, + SplitSize, SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, }, pane_size::{Constraint, PaneGeom}, }; @@ -238,10 +229,20 @@ fn extract_plugin_and_config( layout_run: &Option, ) -> (Option, Option) { match &layout_run { - Some(Run::Plugin(run_plugin)) => ( - Some(run_plugin.location.display()), - Some(run_plugin.configuration.clone()), - ), + Some(Run::Plugin(run_plugin_or_alias)) => match run_plugin_or_alias { + RunPluginOrAlias::RunPlugin(run_plugin) => ( + Some(run_plugin.location.display()), + Some(run_plugin.configuration.clone()), + ), + RunPluginOrAlias::Alias(plugin_alias) => { + let name = plugin_alias.name.clone(); + let configuration = plugin_alias + .run_plugin + .as_ref() + .map(|run_plugin| run_plugin.configuration.clone()); + (Some(name), configuration) + }, + }, _ => (None, None), } } diff --git a/zellij-utils/src/setup.rs b/zellij-utils/src/setup.rs index bf34a894..d4146587 100644 --- a/zellij-utils/src/setup.rs +++ b/zellij-utils/src/setup.rs @@ -770,20 +770,6 @@ mod setup_test { assert_snapshot!(format!("{:#?}", config)); } #[test] - fn layout_plugins_override_config_plugins() { - let mut cli_args = CliArgs::default(); - cli_args.config = Some(PathBuf::from(format!( - "{}/src/test-fixtures/config-with-plugins-config.kdl", - env!("CARGO_MANIFEST_DIR") - ))); - cli_args.layout = Some(PathBuf::from(format!( - "{}/src/test-fixtures/layout-with-plugins-config.kdl", - env!("CARGO_MANIFEST_DIR") - ))); - let (config, _layout, _options, _, _) = Setup::from_cli_args(&cli_args).unwrap(); - assert_snapshot!(format!("{:#?}", config)); - } - #[test] fn layout_themes_override_config_themes() { let mut cli_args = CliArgs::default(); cli_args.config = Some(PathBuf::from(format!( diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-2.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-2.snap index e98379dd..ade6b116 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-2.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-2.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/setup.rs -assertion_line: 672 +assertion_line: 699 expression: "format!(\"{:#?}\", layout)" --- Layout { @@ -23,17 +23,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -73,17 +73,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -133,17 +133,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -235,17 +235,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -288,17 +288,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -455,17 +455,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -508,17 +508,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -756,17 +756,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -816,17 +816,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -899,17 +899,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -952,17 +952,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -1119,17 +1119,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -1172,17 +1172,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -1420,17 +1420,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -1480,17 +1480,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + Alias( + PluginAlias { + name: "tab-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, @@ -1582,17 +1582,17 @@ Layout { ), run: Some( Plugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + Alias( + PluginAlias { + name: "status-bar", + configuration: Some( + PluginUserConfiguration( + {}, + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + run_plugin: None, + }, + ), ), ), borderless: true, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap index f73b753e..18eaddce 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/setup.rs -assertion_line: 671 +assertion_line: 698 expression: "format!(\"{:#?}\", config)" --- Config { @@ -2655,17 +2655,19 @@ Config { 'w', ): [ LaunchOrFocusPlugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), true, true, false, @@ -3831,91 +3833,87 @@ Config { serialization_interval: None, }, themes: {}, - plugins: { - PluginTag( - "compact-bar", - ): PluginConfig { - path: "compact-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "compact-bar", + plugins: PluginAliases { + aliases: { + "compact-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "compact-bar", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "session-manager", - ): PluginConfig { - path: "session-manager", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "status-bar", - ): PluginConfig { - path: "status-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + }, + "filepicker": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "strider", - ): PluginConfig { - path: "strider", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "strider", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "tab-bar", - ): PluginConfig { - path: "tab-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + }, + "session-manager": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "status-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "strider": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "tab-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "welcome-screen": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), + ), + configuration: PluginUserConfiguration( + { + "welcome_screen": "true", + }, + ), + }, }, }, ui: UiConfig { diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap index b5c185c8..89f544ff 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/setup.rs -assertion_line: 729 +assertion_line: 756 expression: "format!(\"{:#?}\", config)" --- Config { @@ -2655,17 +2655,19 @@ Config { 'w', ): [ LaunchOrFocusPlugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), true, true, false, @@ -3831,91 +3833,87 @@ Config { serialization_interval: None, }, themes: {}, - plugins: { - PluginTag( - "compact-bar", - ): PluginConfig { - path: "compact-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "compact-bar", + plugins: PluginAliases { + aliases: { + "compact-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "compact-bar", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "session-manager", - ): PluginConfig { - path: "session-manager", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "status-bar", - ): PluginConfig { - path: "status-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + }, + "filepicker": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "strider", - ): PluginConfig { - path: "strider", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "strider", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "tab-bar", - ): PluginConfig { - path: "tab-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + }, + "session-manager": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "status-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "strider": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "tab-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "welcome-screen": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), + ), + configuration: PluginUserConfiguration( + { + "welcome_screen": "true", + }, + ), + }, }, }, ui: UiConfig { diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap index a6df2f5e..23fddc93 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/setup.rs -assertion_line: 785 +assertion_line: 813 expression: "format!(\"{:#?}\", config)" --- Config { @@ -89,91 +89,87 @@ Config { serialization_interval: None, }, themes: {}, - plugins: { - PluginTag( - "compact-bar", - ): PluginConfig { - path: "compact-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "compact-bar", + plugins: PluginAliases { + aliases: { + "compact-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "compact-bar", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "session-manager", - ): PluginConfig { - path: "session-manager", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "status-bar", - ): PluginConfig { - path: "status-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + }, + "filepicker": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "strider", - ): PluginConfig { - path: "strider", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "strider", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "tab-bar", - ): PluginConfig { - path: "tab-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + }, + "session-manager": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "status-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "strider": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "tab-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "welcome-screen": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), + ), + configuration: PluginUserConfiguration( + { + "welcome_screen": "true", + }, + ), + }, }, }, ui: UiConfig { diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap index e055135e..6e891732 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/setup.rs -assertion_line: 757 +assertion_line: 784 expression: "format!(\"{:#?}\", config)" --- Config { @@ -2655,17 +2655,19 @@ Config { 'w', ): [ LaunchOrFocusPlugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), true, true, false, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap index ba5df24d..1d682130 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/setup.rs -assertion_line: 771 +assertion_line: 799 expression: "format!(\"{:#?}\", config)" --- Config { @@ -2655,17 +2655,19 @@ Config { 'w', ): [ LaunchOrFocusPlugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), true, true, false, @@ -4135,91 +4137,87 @@ Config { }, }, }, - plugins: { - PluginTag( - "compact-bar", - ): PluginConfig { - path: "compact-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "compact-bar", + plugins: PluginAliases { + aliases: { + "compact-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "compact-bar", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "session-manager", - ): PluginConfig { - path: "session-manager", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "status-bar", - ): PluginConfig { - path: "status-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + }, + "filepicker": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "strider", - ): PluginConfig { - path: "strider", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "strider", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "tab-bar", - ): PluginConfig { - path: "tab-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + }, + "session-manager": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "status-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "strider": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "tab-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "welcome-screen": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), + ), + configuration: PluginUserConfiguration( + { + "welcome_screen": "true", + }, + ), + }, }, }, ui: UiConfig { diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap index a6e7350e..de44f0f1 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap @@ -1,6 +1,6 @@ --- source: zellij-utils/src/setup.rs -assertion_line: 743 +assertion_line: 770 expression: "format!(\"{:#?}\", config)" --- Config { @@ -2655,17 +2655,19 @@ Config { 'w', ): [ LaunchOrFocusPlugin( - RunPlugin { - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + RunPlugin( + RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - configuration: PluginUserConfiguration( - {}, - ), - }, + configuration: PluginUserConfiguration( + {}, + ), + }, + ), true, true, false, @@ -3831,91 +3833,87 @@ Config { serialization_interval: None, }, themes: {}, - plugins: { - PluginTag( - "compact-bar", - ): PluginConfig { - path: "compact-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "compact-bar", + plugins: PluginAliases { + aliases: { + "compact-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "compact-bar", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "session-manager", - ): PluginConfig { - path: "session-manager", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "session-manager", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "status-bar", - ): PluginConfig { - path: "status-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "status-bar", + }, + "filepicker": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "strider", - ): PluginConfig { - path: "strider", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "strider", + configuration: PluginUserConfiguration( + {}, ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), - }, - PluginTag( - "tab-bar", - ): PluginConfig { - path: "tab-bar", - run: Pane( - None, - ), - _allow_exec_host_cmd: false, - location: Zellij( - PluginTag( - "tab-bar", + }, + "session-manager": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), ), - ), - userspace_configuration: PluginUserConfiguration( - {}, - ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "status-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "status-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "strider": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "strider", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "tab-bar": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "tab-bar", + ), + ), + configuration: PluginUserConfiguration( + {}, + ), + }, + "welcome-screen": RunPlugin { + _allow_exec_host_cmd: false, + location: Zellij( + PluginTag( + "session-manager", + ), + ), + configuration: PluginUserConfiguration( + { + "welcome_screen": "true", + }, + ), + }, }, }, ui: UiConfig {