diff --git a/default-plugins/compact-bar/src/main.rs b/default-plugins/compact-bar/src/main.rs index 40fa65f52a..18c9f12b4d 100644 --- a/default-plugins/compact-bar/src/main.rs +++ b/default-plugins/compact-bar/src/main.rs @@ -2,6 +2,7 @@ mod line; mod tab; use std::cmp::{max, min}; +use std::collections::BTreeMap; use std::convert::TryInto; use tab::get_tab_to_focus; @@ -30,7 +31,7 @@ static ARROW_SEPARATOR: &str = ""; register_plugin!(State); impl ZellijPlugin for State { - fn load(&mut self) { + fn load(&mut self, configuration: BTreeMap) { set_selectable(false); subscribe(&[ EventType::TabUpdate, diff --git a/default-plugins/fixture-plugin-for-tests/src/main.rs b/default-plugins/fixture-plugin-for-tests/src/main.rs index 20457f13fd..074aa1a4d0 100644 --- a/default-plugins/fixture-plugin-for-tests/src/main.rs +++ b/default-plugins/fixture-plugin-for-tests/src/main.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; use zellij_tile::prelude::*; // This is a fixture plugin used only for tests in Zellij @@ -9,6 +10,7 @@ use zellij_tile::prelude::*; struct State { received_events: Vec, received_payload: Option, + configuration: BTreeMap, } #[derive(Default, Serialize, Deserialize)] @@ -35,7 +37,8 @@ register_plugin!(State); register_worker!(TestWorker, test_worker, TEST_WORKER); impl ZellijPlugin for State { - fn load(&mut self) { + fn load(&mut self, configuration: BTreeMap) { + self.configuration = configuration; subscribe(&[ EventType::InputReceived, EventType::Key, @@ -210,6 +213,9 @@ impl ZellijPlugin for State { Key::Ctrl('x') => { rename_tab(1, "new tab name"); }, + Key::Ctrl('z') => { + go_to_tab_name(&format!("{:?}", self.configuration)); + }, _ => {}, }, Event::CustomMessage(message, payload) => { diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs index ee14e45d54..d768b35ed8 100644 --- a/default-plugins/status-bar/src/main.rs +++ b/default-plugins/status-bar/src/main.rs @@ -8,6 +8,7 @@ use ansi_term::{ Style, }; +use std::collections::BTreeMap; use std::fmt::{Display, Error, Formatter}; use zellij_tile::prelude::actions::Action; use zellij_tile::prelude::*; @@ -196,7 +197,7 @@ fn color_elements(palette: Palette, different_color_alternates: bool) -> Colored } impl ZellijPlugin for State { - fn load(&mut self) { + fn load(&mut self, configuration: BTreeMap) { // TODO: Should be able to choose whether to use the cache through config. self.tip_name = get_cached_tip_name(); set_selectable(false); @@ -207,7 +208,10 @@ impl ZellijPlugin for State { EventType::InputReceived, EventType::SystemClipboardFailure, ]); - self.supermode = false; // TODO: from config + self.supermode = configuration + .get("supermode") + .and_then(|s| s.trim().parse().ok()) + .unwrap_or(false); self.standby_mode = InputMode::Pane; if self.supermode { switch_to_input_mode(&InputMode::Locked); // supermode should start locked (TODO: only diff --git a/default-plugins/strider/src/main.rs b/default-plugins/strider/src/main.rs index 3a4ab08667..9e05f06066 100644 --- a/default-plugins/strider/src/main.rs +++ b/default-plugins/strider/src/main.rs @@ -6,6 +6,7 @@ use search::{FileContentsWorker, FileNameWorker, MessageToSearch, ResultsOfSearc 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::*; @@ -18,10 +19,8 @@ register_worker!( ); impl ZellijPlugin for State { - fn load(&mut self) { - // Example + fn load(&mut self, configuration: BTreeMap) { request_permission(&[PermissionType::KeyboardInput]); - refresh_directory(self); self.search_state.loading = true; subscribe(&[ diff --git a/default-plugins/tab-bar/src/main.rs b/default-plugins/tab-bar/src/main.rs index 05fdd5608d..fc67ef918e 100644 --- a/default-plugins/tab-bar/src/main.rs +++ b/default-plugins/tab-bar/src/main.rs @@ -2,6 +2,7 @@ mod line; mod tab; use std::cmp::{max, min}; +use std::collections::BTreeMap; use std::convert::TryInto; use tab::get_tab_to_focus; @@ -30,7 +31,7 @@ static ARROW_SEPARATOR: &str = ""; register_plugin!(State); impl ZellijPlugin for State { - fn load(&mut self) { + fn load(&mut self, configuration: BTreeMap) { set_selectable(false); subscribe(&[ EventType::TabUpdate, diff --git a/src/main.rs b/src/main.rs index e3737b19ef..f32d76cd85 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,7 @@ fn main() { name, close_on_exit, start_suspended, + configuration: None, }; commands::send_action_to_session(command_cli_action, opts.session, config); std::process::exit(0); diff --git a/zellij-server/src/plugins/plugin_loader.rs b/zellij-server/src/plugins/plugin_loader.rs index 84e822bcfe..1ad8333043 100644 --- a/zellij-server/src/plugins/plugin_loader.rs +++ b/zellij-server/src/plugins/plugin_loader.rs @@ -1,6 +1,6 @@ use crate::plugins::plugin_map::{PluginEnv, PluginMap, RunningPlugin, Subscriptions}; use crate::plugins::plugin_worker::{plugin_worker, RunningWorker}; -use crate::plugins::zellij_exports::{wasi_read_string, zellij_exports}; +use crate::plugins::zellij_exports::{wasi_read_string, wasi_write_object, zellij_exports}; use crate::plugins::PluginId; use highway::{HighwayHash, PortableHash}; use log::info; @@ -745,7 +745,14 @@ impl<'a> PluginLoader<'a> { } } start_function.call(&[]).with_context(err_context)?; + + wasi_write_object( + &plugin_env.wasi_env, + &self.plugin.userspace_configuration.inner(), + ) + .with_context(err_context)?; load_function.call(&[]).with_context(err_context)?; + display_loading_stage!( indicate_starting_plugin_success, self.loading_indication, diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 3ec8485b03..663ca94eec 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -2,12 +2,13 @@ use super::plugin_thread_main; use crate::screen::ScreenInstruction; use crate::{channels::SenderWithContext, thread_bus::Bus, ServerInstruction}; use insta::assert_snapshot; +use std::collections::BTreeMap; use std::path::PathBuf; use tempfile::tempdir; use wasmer::Store; use zellij_utils::data::{Event, Key, PluginCapabilities}; use zellij_utils::errors::ErrorContext; -use zellij_utils::input::layout::{Layout, RunPlugin, RunPluginLocation}; +use zellij_utils::input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}; use zellij_utils::input::plugins::PluginsConfig; use zellij_utils::ipc::ClientAttributes; use zellij_utils::lazy_static::lazy_static; @@ -349,6 +350,7 @@ pub fn load_new_plugin_from_hd() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -407,6 +409,7 @@ pub fn plugin_workers() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -468,6 +471,7 @@ pub fn plugin_workers_persist_state() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -541,6 +545,7 @@ pub fn can_subscribe_to_hd_events() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -605,6 +610,7 @@ pub fn switch_to_mode_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -666,6 +672,7 @@ pub fn new_tabs_with_layout_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -741,6 +748,7 @@ pub fn new_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -802,6 +810,7 @@ pub fn go_to_next_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -862,6 +871,7 @@ pub fn go_to_previous_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -922,6 +932,7 @@ pub fn resize_focused_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -982,6 +993,7 @@ pub fn resize_focused_pane_with_direction_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1042,6 +1054,7 @@ pub fn focus_next_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1102,6 +1115,7 @@ pub fn focus_previous_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1162,6 +1176,7 @@ pub fn move_focus_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1222,6 +1237,7 @@ pub fn move_focus_or_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1282,6 +1298,7 @@ pub fn edit_scrollback_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1342,6 +1359,7 @@ pub fn write_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1402,6 +1420,7 @@ pub fn write_chars_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1462,6 +1481,7 @@ pub fn toggle_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1522,6 +1542,7 @@ pub fn move_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1582,6 +1603,7 @@ pub fn move_pane_with_direction_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1642,6 +1664,7 @@ pub fn clear_screen_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1702,6 +1725,7 @@ pub fn scroll_up_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1762,6 +1786,7 @@ pub fn scroll_down_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1822,6 +1847,7 @@ pub fn scroll_to_top_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1882,6 +1908,7 @@ pub fn scroll_to_bottom_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -1942,6 +1969,7 @@ pub fn page_scroll_up_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2002,6 +2030,7 @@ pub fn page_scroll_down_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2062,6 +2091,7 @@ pub fn toggle_focus_fullscreen_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2122,6 +2152,7 @@ pub fn toggle_pane_frames_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2182,6 +2213,7 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2242,6 +2274,7 @@ pub fn undo_rename_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2302,6 +2335,7 @@ pub fn close_focus_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2362,6 +2396,7 @@ pub fn toggle_active_tab_sync_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2422,6 +2457,7 @@ pub fn close_focused_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2482,6 +2518,7 @@ pub fn undo_rename_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2542,6 +2579,7 @@ pub fn previous_swap_layout_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2602,6 +2640,7 @@ pub fn next_swap_layout_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2662,6 +2701,7 @@ pub fn go_to_tab_name_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2722,6 +2762,7 @@ pub fn focus_or_create_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2782,6 +2823,7 @@ pub fn go_to_tab() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2842,6 +2884,7 @@ pub fn start_or_reload_plugin() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2902,6 +2945,7 @@ pub fn quit_zellij_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -2962,6 +3006,7 @@ pub fn detach_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3022,6 +3067,7 @@ pub fn open_file_floating_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3082,6 +3128,7 @@ pub fn open_file_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3142,6 +3189,7 @@ pub fn open_file_with_line_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3202,6 +3250,7 @@ pub fn open_file_with_line_floating_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3262,6 +3311,7 @@ pub fn open_terminal_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3322,6 +3372,7 @@ pub fn open_terminal_floating_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3382,6 +3433,7 @@ pub fn open_command_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3442,6 +3494,7 @@ pub fn open_command_pane_floating_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3502,6 +3555,7 @@ pub fn switch_to_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3562,6 +3616,7 @@ pub fn hide_self_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3622,6 +3677,7 @@ pub fn show_self_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3682,6 +3738,7 @@ pub fn close_terminal_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3742,6 +3799,7 @@ pub fn close_plugin_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3802,6 +3860,7 @@ pub fn focus_terminal_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3862,6 +3921,7 @@ pub fn focus_plugin_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3922,6 +3982,7 @@ pub fn rename_terminal_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -3982,6 +4043,7 @@ pub fn rename_plugin_pane_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -4042,6 +4104,7 @@ pub fn rename_tab_plugin_command() { let run_plugin = RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), }; let tab_index = 1; let client_id = 1; @@ -4088,3 +4151,76 @@ pub fn rename_tab_plugin_command() { .clone(); assert_snapshot!(format!("{:#?}", new_tab_event)); } + +#[test] +#[ignore] +pub fn send_configuration_to_plugins() { + let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its + // destructor removes the directory + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let (plugin_thread_sender, screen_receiver, mut teardown) = + create_plugin_thread(Some(plugin_host_folder)); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let mut configuration = BTreeMap::new(); + configuration.insert( + "fake_config_key_1".to_owned(), + "fake_config_value_1".to_owned(), + ); + configuration.insert( + "fake_config_key_2".to_owned(), + "fake_config_value_2".to_owned(), + ); + let run_plugin = 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 { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::GoToTabName, + screen_receiver, + 1 + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + plugin_title, + run_plugin, + tab_index, + client_id, + size, + )); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(Key::Ctrl('z')), // this triggers the enent in the fixture plugin + )])); + std::thread::sleep(std::time::Duration::from_millis(100)); + screen_thread.join().unwrap(); // this might take a while if the cache is cold + teardown(); + // here we make sure we received a rename_tab event with the title being the stringified + // (Debug) configuration we sent to the fixture plugin to make sure it got there properly + + let go_to_tab_event = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::GoToTabName(..) = i { + Some(i.clone()) + } else { + None + } + }) + .clone(); + assert_snapshot!(format!("{:#?}", go_to_tab_event)); +} diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap new file mode 100644 index 0000000000..01cb4b6b4d --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__send_configuration_to_plugins.snap @@ -0,0 +1,19 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +assertion_line: 4220 +expression: "format!(\"{:#?}\", go_to_tab_event)" +--- +Some( + GoToTabName( + "{\"fake_config_key_1\": \"fake_config_value_1\", \"fake_config_key_2\": \"fake_config_value_2\"}\n\r", + ( + [], + [], + ), + None, + false, + Some( + 1, + ), + ), +) 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 72364a88e0..05002124ab 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,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 2889 +assertion_line: 2931 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -10,6 +10,9 @@ Some( location: File( "/path/to/my/plugin.wasm", ), + configuration: PluginUserConfiguration( + {}, + ), }, None, ), diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 12c2b40247..ddc7906f6c 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -5,7 +5,7 @@ use crate::route::route_action; use log::{debug, warn}; use serde::{de::DeserializeOwned, Serialize}; use std::{ - collections::HashSet, + collections::{BTreeMap, HashSet}, path::PathBuf, process, sync::{Arc, Mutex}, @@ -27,7 +27,7 @@ use zellij_utils::{ input::{ actions::Action, command::{RunCommand, RunCommandAction, TerminalAction}, - layout::{Layout, RunPlugin, RunPluginLocation}, + layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}, plugins::PluginType, }, serde, @@ -1006,6 +1006,7 @@ fn host_start_or_reload_plugin(env: &ForeignFunctionEnv) { 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); apply_action!(action, error_msg, env); diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 61d2b391fa..6dd597aadf 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -14,8 +14,8 @@ use zellij_utils::pane_size::{Size, SizeInPixels}; use zellij_utils::{ input::command::TerminalAction, input::layout::{ - FloatingPaneLayout, Run, RunPlugin, RunPluginLocation, SwapFloatingLayout, SwapTiledLayout, - TiledPaneLayout, + FloatingPaneLayout, PluginUserConfiguration, Run, RunPlugin, RunPluginLocation, + SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, }, position::Position, }; @@ -258,11 +258,11 @@ pub enum ScreenInstruction { PreviousSwapLayout(ClientId), NextSwapLayout(ClientId), QueryTabNames(ClientId), - NewTiledPluginPane(RunPluginLocation, Option, ClientId), // Option is + NewTiledPluginPane(RunPlugin, Option, ClientId), // Option is // optional pane title - NewFloatingPluginPane(RunPluginLocation, Option, ClientId), // Option is an - StartOrReloadPluginPane(RunPlugin, Option), + NewFloatingPluginPane(RunPlugin, Option, ClientId), // Option is an // optional pane title + StartOrReloadPluginPane(RunPlugin, Option), AddPlugin( Option, // should_float RunPlugin, @@ -2639,14 +2639,10 @@ pub(crate) fn screen_thread_main( .senders .send_to_server(ServerInstruction::Log(tab_names, client_id))?; }, - ScreenInstruction::NewTiledPluginPane(run_plugin_location, pane_title, client_id) => { + ScreenInstruction::NewTiledPluginPane(run_plugin, pane_title, client_id) => { let tab_index = screen.active_tab_indices.values().next().unwrap_or(&1); let size = Size::default(); let should_float = Some(false); - let run_plugin = RunPlugin { - _allow_exec_host_cmd: false, - location: run_plugin_location, - }; screen.bus.senders.send_to_plugin(PluginInstruction::Load( should_float, pane_title, @@ -2656,28 +2652,26 @@ pub(crate) fn screen_thread_main( size, ))?; }, - ScreenInstruction::NewFloatingPluginPane( - run_plugin_location, - pane_title, - client_id, - ) => { - let tab_index = screen.active_tab_indices.values().next().unwrap(); // TODO: no - // unwrap and - // better - let size = Size::default(); // TODO: ??? - let should_float = Some(true); - let run_plugin = RunPlugin { - _allow_exec_host_cmd: false, - location: run_plugin_location, - }; - screen.bus.senders.send_to_plugin(PluginInstruction::Load( - should_float, - pane_title, - run_plugin, - *tab_index, - client_id, - size, - ))?; + ScreenInstruction::NewFloatingPluginPane(run_plugin, pane_title, client_id) => { + match screen.active_tab_indices.values().next() { + Some(tab_index) => { + let size = Size::default(); + let should_float = Some(true); + screen.bus.senders.send_to_plugin(PluginInstruction::Load( + should_float, + pane_title, + run_plugin, + *tab_index, + client_id, + size, + ))?; + }, + None => { + log::error!( + "Could not find an active tab - is there at least 1 connected user?" + ); + }, + } }, ScreenInstruction::StartOrReloadPluginPane(run_plugin, pane_title) => { let tab_index = screen.active_tab_indices.values().next().unwrap_or(&1); diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 1040062b15..8a683edc0f 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -1854,6 +1854,7 @@ pub fn send_cli_new_pane_action_with_default_parameters() { name: None, close_on_exit: false, start_suspended: false, + configuration: None, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -1890,6 +1891,7 @@ pub fn send_cli_new_pane_action_with_split_direction() { name: None, close_on_exit: false, start_suspended: false, + configuration: None, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -1926,6 +1928,7 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() { name: None, close_on_exit: false, start_suspended: false, + configuration: None, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2550,6 +2553,7 @@ pub fn send_cli_launch_or_focus_plugin_action() { let cli_action = CliAction::LaunchOrFocusPlugin { floating: true, url: url::Url::parse("file:/path/to/fake/plugin").unwrap(), + configuration: Default::default(), }; 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 @@ -2583,6 +2587,7 @@ pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded() { run: Some(Run::Plugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from("/path/to/fake/plugin")), + configuration: Default::default(), })), ..Default::default() }; @@ -2605,6 +2610,7 @@ pub fn send_cli_launch_or_focus_plugin_action_when_plugin_is_already_loaded() { let cli_action = CliAction::LaunchOrFocusPlugin { floating: true, url: url::Url::parse("file:/path/to/fake/plugin").unwrap(), + configuration: Default::default(), }; 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 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 0751fa5f1c..d6420c3fcf 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: 2758 +assertion_line: 2572 expression: "format!(\"{:#?}\", plugin_load_instruction)" --- Some( @@ -14,6 +14,9 @@ Some( location: File( "/path/to/fake/plugin", ), + configuration: PluginUserConfiguration( + {}, + ), }, 0, 1, diff --git a/zellij-tile/src/lib.rs b/zellij-tile/src/lib.rs index 98f141942c..7bcaf47383 100644 --- a/zellij-tile/src/lib.rs +++ b/zellij-tile/src/lib.rs @@ -19,6 +19,7 @@ pub mod prelude; pub mod shim; use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; use zellij_utils::data::Event; /// This trait should be implemented - once per plugin - on a struct (normally representing the @@ -27,7 +28,7 @@ use zellij_utils::data::Event; #[allow(unused_variables)] pub trait ZellijPlugin: Default { /// Will be called when the plugin is loaded, this is a good place to [`subscribe`](shim::subscribe) to events that are interesting for this plugin. - fn load(&mut self) {} + fn load(&mut self, configuration: BTreeMap) {} /// Will be called with an [`Event`](prelude::Event) if the plugin is subscribed to said event. /// If the plugin returns `true` from this function, Zellij will know it should be rendered and call its `render` function. fn update(&mut self, event: Event) -> bool { @@ -103,7 +104,11 @@ macro_rules! register_plugin { #[no_mangle] fn load() { STATE.with(|state| { - state.borrow_mut().load(); + let configuration = $crate::shim::object_from_stdin() + .context($crate::PLUGIN_MISMATCH) + .to_stdout() + .unwrap(); + state.borrow_mut().load(configuration); }); } diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index 6639f810b6..fd2bdcda75 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -2,7 +2,7 @@ use crate::data::{Direction, InputMode, Resize}; use crate::setup::Setup; use crate::{ consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV}, - input::options::CliOptions, + input::{layout::PluginUserConfiguration, options::CliOptions}, }; use clap::{Parser, Subcommand}; use serde::{Deserialize, Serialize}; @@ -292,6 +292,8 @@ pub enum CliAction { requires("command") )] start_suspended: bool, + #[clap(short, long, value_parser)] + configuration: Option, }, /// Open the specified file in a new zellij pane with your default EDITOR Edit { @@ -376,10 +378,14 @@ pub enum CliAction { QueryTabNames, StartOrReloadPlugin { url: String, + #[clap(short, long, value_parser)] + configuration: Option, }, LaunchOrFocusPlugin { #[clap(short, long, value_parser)] floating: bool, url: Url, + #[clap(short, long, value_parser)] + configuration: Option, }, } diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index c2071846e6..568c0a2c2c 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -230,8 +230,8 @@ pub enum Action { /// Query all tab names QueryTabNames, /// Open a new tiled (embedded, non-floating) plugin pane - NewTiledPluginPane(RunPluginLocation, Option), // String is an optional name - NewFloatingPluginPane(RunPluginLocation, Option), // String is an optional name + NewTiledPluginPane(RunPlugin, Option), // String is an optional name + NewFloatingPluginPane(RunPlugin, Option), // String is an optional name StartOrReloadPlugin(RunPlugin), CloseTerminalPane(u32), ClosePluginPane(u32), @@ -292,21 +292,24 @@ impl Action { name, close_on_exit, start_suspended, + configuration, } => { let current_dir = get_current_dir(); 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) + .map_err(|e| format!("Failed to parse plugin loction {plugin}: {}", e))?; + let plugin = RunPlugin { + _allow_exec_host_cmd: false, + location, + configuration: user_configuration, + }; if floating { - let plugin = RunPluginLocation::parse(&plugin, cwd).map_err(|e| { - format!("Failed to parse plugin loction {plugin}: {}", e) - })?; Ok(vec![Action::NewFloatingPluginPane(plugin, name)]) } else { - let plugin = RunPluginLocation::parse(&plugin, cwd).map_err(|e| { - format!("Failed to parse plugin location {plugin}: {}", e) - })?; // it is intentional that a new tiled plugin pane cannot include a // direction // this is because the cli client opening a tiled plugin pane is a @@ -480,23 +483,29 @@ impl Action { CliAction::PreviousSwapLayout => Ok(vec![Action::PreviousSwapLayout]), CliAction::NextSwapLayout => Ok(vec![Action::NextSwapLayout]), CliAction::QueryTabNames => Ok(vec![Action::QueryTabNames]), - CliAction::StartOrReloadPlugin { url } => { + 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)]) }, - CliAction::LaunchOrFocusPlugin { url, floating } => { + CliAction::LaunchOrFocusPlugin { + url, + floating, + configuration, + } => { 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(), }; Ok(vec![Action::LaunchOrFocusPlugin(run_plugin, floating)]) }, diff --git a/zellij-utils/src/input/config.rs b/zellij-utils/src/input/config.rs index 4ad4ef89d6..55170aec24 100644 --- a/zellij-utils/src/input/config.rs +++ b/zellij-utils/src/input/config.rs @@ -600,6 +600,7 @@ mod config_test { run: PluginType::Pane(None), location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")), _allow_exec_host_cmd: false, + userspace_configuration: Default::default(), }, ); expected_plugin_configuration.insert( @@ -609,6 +610,7 @@ mod config_test { run: PluginType::Pane(None), location: RunPluginLocation::Zellij(PluginTag::new("status-bar")), _allow_exec_host_cmd: false, + userspace_configuration: Default::default(), }, ); expected_plugin_configuration.insert( @@ -618,6 +620,7 @@ mod config_test { run: PluginType::Pane(None), location: RunPluginLocation::Zellij(PluginTag::new("strider")), _allow_exec_host_cmd: true, + userspace_configuration: Default::default(), }, ); expected_plugin_configuration.insert( @@ -627,6 +630,7 @@ mod config_test { run: PluginType::Pane(None), location: RunPluginLocation::Zellij(PluginTag::new("compact-bar")), _allow_exec_host_cmd: false, + userspace_configuration: Default::default(), }, ); assert_eq!( diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index c1d95a125a..55e5fc69fe 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -212,6 +212,35 @@ pub struct RunPlugin { #[serde(default)] pub _allow_exec_host_cmd: bool, pub location: RunPluginLocation, + pub configuration: PluginUserConfiguration, +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub struct PluginUserConfiguration(BTreeMap); + +impl PluginUserConfiguration { + pub fn new(configuration: BTreeMap) -> Self { + PluginUserConfiguration(configuration) + } + pub fn inner(&self) -> &BTreeMap { + &self.0 + } +} + +impl FromStr for PluginUserConfiguration { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let mut ret = BTreeMap::new(); + let configs = s.split(','); + for config in configs { + let mut config = config.split('='); + let key = config.next().ok_or("invalid configuration key")?.to_owned(); + let value = config.map(|c| c.to_owned()).collect::>().join("="); + ret.insert(key, value); + } + Ok(PluginUserConfiguration(ret)) + } } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)] diff --git a/zellij-utils/src/input/plugins.rs b/zellij-utils/src/input/plugins.rs index 47cc3aa74d..f12aba2a20 100644 --- a/zellij-utils/src/input/plugins.rs +++ b/zellij-utils/src/input/plugins.rs @@ -8,7 +8,7 @@ use thiserror::Error; use serde::{Deserialize, Serialize}; use url::Url; -use super::layout::{RunPlugin, RunPluginLocation}; +use super::layout::{PluginUserConfiguration, RunPlugin, RunPluginLocation}; #[cfg(not(target_family = "wasm"))] use crate::consts::ASSET_MAP; pub use crate::data::PluginTag; @@ -48,9 +48,11 @@ impl PluginsConfig { 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 }), } @@ -86,6 +88,8 @@ pub struct PluginConfig { pub _allow_exec_host_cmd: bool, /// Original location of the pub location: RunPluginLocation, + /// Custom configuration for this plugin + pub userspace_configuration: PluginUserConfiguration, } impl PluginConfig { diff --git a/zellij-utils/src/input/unit/layout_test.rs b/zellij-utils/src/input/unit/layout_test.rs index fee88aae44..038161a49a 100644 --- a/zellij-utils/src/input/unit/layout_test.rs +++ b/zellij-utils/src/input/unit/layout_test.rs @@ -504,9 +504,18 @@ fn layout_with_plugin_panes() { pane { plugin location="file:/path/to/my/plugin.wasm" } + pane { + plugin location="zellij:status-bar" { + config_key_1 "config_value_1" + "2" true + } + } } "#; let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None).unwrap(); + let mut expected_plugin_configuration = BTreeMap::new(); + expected_plugin_configuration.insert("config_key_1".to_owned(), "config_value_1".to_owned()); + expected_plugin_configuration.insert("2".to_owned(), "true".to_owned()); let expected_layout = Layout { template: Some(( TiledPaneLayout { @@ -515,6 +524,7 @@ fn layout_with_plugin_panes() { run: Some(Run::Plugin(RunPlugin { location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")), _allow_exec_host_cmd: false, + configuration: Default::default(), })), ..Default::default() }, @@ -524,6 +534,15 @@ fn layout_with_plugin_panes() { "/path/to/my/plugin.wasm", )), _allow_exec_host_cmd: false, + configuration: Default::default(), + })), + ..Default::default() + }, + TiledPaneLayout { + run: Some(Run::Plugin(RunPlugin { + location: RunPluginLocation::Zellij(PluginTag::new("status-bar")), + _allow_exec_host_cmd: false, + configuration: PluginUserConfiguration(expected_plugin_configuration), })), ..Default::default() }, @@ -2016,6 +2035,7 @@ fn run_plugin_location_parsing() { run: Some(Run::Plugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")), + configuration: Default::default(), })), ..Default::default() }, @@ -2025,6 +2045,7 @@ fn run_plugin_location_parsing() { location: RunPluginLocation::File(PathBuf::from( "/path/to/my/plugin.wasm", )), + configuration: Default::default(), })), ..Default::default() }, @@ -2032,6 +2053,7 @@ fn run_plugin_location_parsing() { run: Some(Run::Plugin(RunPlugin { _allow_exec_host_cmd: false, location: RunPluginLocation::File(PathBuf::from("plugin.wasm")), + configuration: Default::default(), })), ..Default::default() }, @@ -2041,6 +2063,7 @@ fn run_plugin_location_parsing() { location: RunPluginLocation::File(PathBuf::from( "relative/with space/plugin.wasm", )), + configuration: Default::default(), })), ..Default::default() }, @@ -2050,6 +2073,7 @@ fn run_plugin_location_parsing() { location: RunPluginLocation::File(PathBuf::from( "/absolute/with space/plugin.wasm", )), + configuration: Default::default(), })), ..Default::default() }, @@ -2059,6 +2083,7 @@ fn run_plugin_location_parsing() { location: RunPluginLocation::File(PathBuf::from( "c:/absolute/windows/plugin.wasm", )), + configuration: 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 98d4fef5a1..e9f849b7f6 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: 1850 +assertion_line: 1863 expression: "format!(\"{:#?}\", layout)" --- Layout { @@ -66,6 +66,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -150,6 +153,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -194,6 +200,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -331,6 +340,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -375,6 +387,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -578,6 +593,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), diff --git a/zellij-utils/src/kdl/kdl_layout_parser.rs b/zellij-utils/src/kdl/kdl_layout_parser.rs index a5cab4b1bc..9cee47988e 100644 --- a/zellij-utils/src/kdl/kdl_layout_parser.rs +++ b/zellij-utils/src/kdl/kdl_layout_parser.rs @@ -2,9 +2,9 @@ use crate::input::{ command::RunCommand, config::ConfigError, layout::{ - FloatingPaneLayout, Layout, LayoutConstraint, PercentOrFixed, Run, RunPlugin, - RunPluginLocation, SplitDirection, SplitSize, SwapFloatingLayout, SwapTiledLayout, - TiledPaneLayout, + FloatingPaneLayout, Layout, LayoutConstraint, PercentOrFixed, PluginUserConfiguration, Run, + RunPlugin, RunPluginLocation, SplitDirection, SplitSize, SwapFloatingLayout, + SwapTiledLayout, TiledPaneLayout, }, }; @@ -14,7 +14,8 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::str::FromStr; use crate::{ - kdl_child_with_name, kdl_children_nodes, kdl_get_bool_property_or_child_value, + kdl_child_with_name, kdl_children_nodes, kdl_first_entry_as_bool, kdl_first_entry_as_i64, + kdl_first_entry_as_string, kdl_get_bool_property_or_child_value, kdl_get_bool_property_or_child_value_with_error, kdl_get_child, kdl_get_int_property_or_child_value, kdl_get_property_or_child, kdl_get_string_property_or_child_value, kdl_get_string_property_or_child_value_with_error, @@ -121,6 +122,11 @@ impl<'a> KdlLayoutParser<'a> { || property_name == "min_panes" || property_name == "exact_panes" } + pub fn is_a_reserved_plugin_property(property_name: &str) -> bool { + property_name == "location" + || property_name == "_allow_exec_host_cmd" + || property_name == "path" + } fn assert_legal_node_name(&self, name: &str, kdl_node: &KdlNode) -> Result<(), ConfigError> { if name.contains(char::is_whitespace) { Err(ConfigError::new_layout_kdl_error( @@ -305,11 +311,62 @@ impl<'a> KdlLayoutParser<'a> { url_node.span().len(), ) })?; + let configuration = KdlLayoutParser::parse_plugin_user_configuration(&plugin_block)?; Ok(Some(Run::Plugin(RunPlugin { _allow_exec_host_cmd, location, + configuration, }))) } + pub fn parse_plugin_user_configuration( + plugin_block: &KdlNode, + ) -> Result { + let mut configuration = BTreeMap::new(); + for user_configuration_entry in plugin_block.entries() { + let name = user_configuration_entry.name(); + let value = user_configuration_entry.value(); + if let Some(name) = name { + let name = name.to_string(); + if KdlLayoutParser::is_a_reserved_plugin_property(&name) { + continue; + } + configuration.insert(name, value.to_string()); + } + // we ignore "bare" (eg. `plugin i_am_a_bare_true_argument { arg_one 1; }`) entries + // to prevent diverging behaviour with the keybindings config + } + if let Some(user_config) = kdl_children_nodes!(plugin_block) { + for user_configuration_entry in user_config { + let config_entry_name = kdl_name!(user_configuration_entry); + if KdlLayoutParser::is_a_reserved_plugin_property(&config_entry_name) { + continue; + } + let config_entry_str_value = kdl_first_entry_as_string!(user_configuration_entry) + .map(|s| format!("{}", s.to_string())); + let config_entry_int_value = kdl_first_entry_as_i64!(user_configuration_entry) + .map(|s| format!("{}", s.to_string())); + let config_entry_bool_value = kdl_first_entry_as_bool!(user_configuration_entry) + .map(|s| format!("{}", s.to_string())); + let config_entry_children = user_configuration_entry + .children() + .map(|s| format!("{}", s.to_string().trim())); + let config_entry_value = config_entry_str_value + .or(config_entry_int_value) + .or(config_entry_bool_value) + .or(config_entry_children) + .ok_or(ConfigError::new_kdl_error( + format!( + "Failed to parse plugin block configuration: {:?}", + user_configuration_entry + ), + plugin_block.span().offset(), + plugin_block.span().len(), + ))?; + configuration.insert(config_entry_name.into(), config_entry_value); + } + } + Ok(PluginUserConfiguration::new(configuration)) + } fn parse_args(&self, pane_node: &KdlNode) -> Result>, ConfigError> { match kdl_get_child!(pane_node, "args") { Some(kdl_args) => { diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index 901f524f81..36a4472a96 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -3,14 +3,14 @@ use crate::data::{Direction, InputMode, Key, Palette, PaletteColor, PermissionTy use crate::envs::EnvironmentVariables; use crate::input::config::{Config, ConfigError, KdlError}; use crate::input::keybinds::Keybinds; -use crate::input::layout::{Layout, RunPlugin, RunPluginLocation}; +use crate::input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}; use crate::input::options::{Clipboard, OnForceClose, Options}; use crate::input::permission::GrantedPermission; use crate::input::plugins::{PluginConfig, PluginTag, PluginType, PluginsConfig}; use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig}; use crate::setup::{find_default_config_dir, get_layout_dir}; use kdl_layout_parser::KdlLayoutParser; -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet, BTreeMap}; use strum::IntoEnumIterator; use miette::NamedSource; @@ -137,6 +137,17 @@ macro_rules! kdl_first_entry_as_i64 { }; } +#[macro_export] +macro_rules! kdl_first_entry_as_bool { + ( $node:expr ) => { + $node + .entries() + .iter() + .next() + .and_then(|i| i.value().as_bool()) + }; +} + #[macro_export] macro_rules! entry_count { ( $node:expr ) => {{ @@ -895,9 +906,11 @@ impl TryFrom<(&KdlNode, &Options)> for Action { .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, }; Ok(Action::LaunchOrFocusPlugin(run_plugin, should_float)) }, @@ -1266,15 +1279,12 @@ macro_rules! kdl_get_string_property_or_child_value_with_error { #[macro_export] macro_rules! kdl_get_property_or_child { ( $kdl_node:expr, $name:expr ) => { - $kdl_node - .get($name) - // .and_then(|e| e.value().as_string()) - .or_else(|| { - $kdl_node - .children() - .and_then(|c| c.get($name)) - .and_then(|c| c.get(0)) - }) + $kdl_node.get($name).or_else(|| { + $kdl_node + .children() + .and_then(|c| c.get($name)) + .and_then(|c| c.get(0)) + }) }; } @@ -1403,30 +1413,6 @@ impl Options { } } -impl RunPlugin { - pub fn from_kdl(kdl_node: &KdlNode, cwd: Option) -> Result { - let _allow_exec_host_cmd = - kdl_get_child_entry_bool_value!(kdl_node, "_allow_exec_host_cmd").unwrap_or(false); - let string_url = kdl_get_child_entry_string_value!(kdl_node, "location").ok_or( - ConfigError::new_kdl_error( - "Plugins must have a location".into(), - kdl_node.span().offset(), - kdl_node.span().len(), - ), - )?; - let location = RunPluginLocation::parse(string_url, cwd).map_err(|e| { - ConfigError::new_layout_kdl_error( - e.to_string(), - kdl_node.span().offset(), - kdl_node.span().len(), - ) - })?; - Ok(RunPlugin { - _allow_exec_host_cmd, - location, - }) - } -} impl Layout { pub fn from_kdl( raw_layout: &str, @@ -1714,6 +1700,9 @@ impl PluginsConfig { 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); } @@ -1848,3 +1837,51 @@ impl GrantedPermission { kdl_doucment.to_string() } } + +pub fn parse_plugin_user_configuration( + plugin_block: &KdlNode, +) -> Result, ConfigError> { + let mut configuration = BTreeMap::new(); + for user_configuration_entry in plugin_block.entries() { + let name = user_configuration_entry.name(); + let value = user_configuration_entry.value(); + if let Some(name) = name { + let name = name.to_string(); + if KdlLayoutParser::is_a_reserved_plugin_property(&name) { + continue; + } + configuration.insert(name, value.to_string()); + } + } + if let Some(user_config) = kdl_children_nodes!(plugin_block) { + for user_configuration_entry in user_config { + let config_entry_name = kdl_name!(user_configuration_entry); + if KdlLayoutParser::is_a_reserved_plugin_property(&config_entry_name) { + continue; + } + let config_entry_str_value = kdl_first_entry_as_string!(user_configuration_entry) + .map(|s| format!("{}", s.to_string())); + let config_entry_int_value = kdl_first_entry_as_i64!(user_configuration_entry) + .map(|s| format!("{}", s.to_string())); + let config_entry_bool_value = kdl_first_entry_as_bool!(user_configuration_entry) + .map(|s| format!("{}", s.to_string())); + let config_entry_children = user_configuration_entry + .children() + .map(|s| format!("{}", s.to_string().trim())); + let config_entry_value = config_entry_str_value + .or(config_entry_int_value) + .or(config_entry_bool_value) + .or(config_entry_children) + .ok_or(ConfigError::new_kdl_error( + format!( + "Failed to parse plugin block configuration: {:?}", + user_configuration_entry + ), + plugin_block.span().offset(), + plugin_block.span().len(), + ))?; + configuration.insert(config_entry_name.into(), config_entry_value); + } + } + Ok(configuration) +} 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 2af2cb5672..e294f81732 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,5 +1,6 @@ --- source: zellij-utils/src/setup.rs +assertion_line: 640 expression: "format!(\"{:#?}\", layout)" --- Layout { @@ -29,6 +30,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -70,6 +74,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -121,6 +128,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -205,6 +215,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -249,6 +262,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -386,6 +402,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -430,6 +449,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -633,6 +655,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -684,6 +709,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -752,6 +780,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -796,6 +827,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -933,6 +967,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -977,6 +1014,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -1180,6 +1220,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -1231,6 +1274,9 @@ Layout { "tab-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), @@ -1315,6 +1361,9 @@ Layout { "status-bar", ), ), + configuration: PluginUserConfiguration( + {}, + ), }, ), ), 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 c9267c329f..23da443fc1 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,5 +1,6 @@ --- source: zellij-utils/src/setup.rs +assertion_line: 639 expression: "format!(\"{:#?}\", config)" --- Config { @@ -3557,6 +3558,9 @@ Config { "compact-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "status-bar", @@ -3571,6 +3575,9 @@ Config { "status-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "strider", @@ -3585,6 +3592,9 @@ Config { "strider", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "tab-bar", @@ -3599,6 +3609,9 @@ Config { "tab-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, }, 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 2c8b209561..e5f37d87a4 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,5 +1,6 @@ --- source: zellij-utils/src/setup.rs +assertion_line: 697 expression: "format!(\"{:#?}\", config)" --- Config { @@ -3557,6 +3558,9 @@ Config { "compact-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "status-bar", @@ -3571,6 +3575,9 @@ Config { "status-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "strider", @@ -3585,6 +3592,9 @@ Config { "strider", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "tab-bar", @@ -3599,6 +3609,9 @@ Config { "tab-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, }, 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 4cea161343..bb06be461b 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,5 +1,6 @@ --- source: zellij-utils/src/setup.rs +assertion_line: 753 expression: "format!(\"{:#?}\", config)" --- Config { @@ -97,6 +98,9 @@ Config { "compact-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "status-bar", @@ -111,6 +115,9 @@ Config { "status-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "strider", @@ -125,6 +132,9 @@ Config { "strider", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "tab-bar", @@ -139,6 +149,9 @@ Config { "tab-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, }, 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 5f55ff1d71..5540a57105 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,5 +1,6 @@ --- source: zellij-utils/src/setup.rs +assertion_line: 725 expression: "format!(\"{:#?}\", config)" --- Config { @@ -3557,6 +3558,9 @@ Config { "compact-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "some-other-plugin", @@ -3571,6 +3575,9 @@ Config { "some-other-plugin", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "status-bar", @@ -3585,6 +3592,9 @@ Config { "status-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "strider", @@ -3599,6 +3609,9 @@ Config { "strider", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "tab-bar", @@ -3613,6 +3626,9 @@ Config { "tab-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, }, ui: UiConfig { 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 4534d49124..b885dafffc 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,5 +1,6 @@ --- source: zellij-utils/src/setup.rs +assertion_line: 739 expression: "format!(\"{:#?}\", config)" --- Config { @@ -3861,6 +3862,9 @@ Config { "compact-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "status-bar", @@ -3875,6 +3879,9 @@ Config { "status-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "strider", @@ -3889,6 +3896,9 @@ Config { "strider", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "tab-bar", @@ -3903,6 +3913,9 @@ Config { "tab-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, }, 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 414b1d84b6..b371b61ff3 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,5 +1,6 @@ --- source: zellij-utils/src/setup.rs +assertion_line: 711 expression: "format!(\"{:#?}\", config)" --- Config { @@ -3557,6 +3558,9 @@ Config { "compact-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "status-bar", @@ -3571,6 +3575,9 @@ Config { "status-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "strider", @@ -3585,6 +3592,9 @@ Config { "strider", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, PluginTag( "tab-bar", @@ -3599,6 +3609,9 @@ Config { "tab-bar", ), ), + userspace_configuration: PluginUserConfiguration( + {}, + ), }, }, ui: UiConfig {