From 00cd33637bd43e1c0980254a04ce18f0dedb2b57 Mon Sep 17 00:00:00 2001 From: Jae-Heon Ji <32578710+jaeheonji@users.noreply.github.com> Date: Thu, 16 Feb 2023 22:32:27 +0900 Subject: feat: add args to new-tab action (#2072) * fix(themes): missing tokyo-night-dark theme * feat: add args to new-tab action * fix: name can be set without layout * feat: pass config options to action parser * chore: remove unnecessary default values * chore: update snapshots * fix(status-bar): add exception for NewTab * fix: update code review * feat: add shallow_eq for action --- zellij-utils/assets/plugins/compact-bar.wasm | Bin 387952 -> 397489 bytes zellij-utils/assets/plugins/status-bar.wasm | Bin 476653 -> 485616 bytes zellij-utils/assets/plugins/strider.wasm | Bin 404184 -> 413509 bytes zellij-utils/assets/plugins/tab-bar.wasm | Bin 364104 -> 373679 bytes zellij-utils/src/input/actions.rs | 8 +++ zellij-utils/src/kdl/mod.rs | 93 +++++++++++++++++++++++---- 6 files changed, 87 insertions(+), 14 deletions(-) (limited to 'zellij-utils') diff --git a/zellij-utils/assets/plugins/compact-bar.wasm b/zellij-utils/assets/plugins/compact-bar.wasm index f9bd5d630..46267f5e7 100644 Binary files a/zellij-utils/assets/plugins/compact-bar.wasm and b/zellij-utils/assets/plugins/compact-bar.wasm differ diff --git a/zellij-utils/assets/plugins/status-bar.wasm b/zellij-utils/assets/plugins/status-bar.wasm index 99fcb027c..5b4f6eb06 100644 Binary files a/zellij-utils/assets/plugins/status-bar.wasm and b/zellij-utils/assets/plugins/status-bar.wasm differ diff --git a/zellij-utils/assets/plugins/strider.wasm b/zellij-utils/assets/plugins/strider.wasm index 1df8a13d8..0af68b2f2 100644 Binary files a/zellij-utils/assets/plugins/strider.wasm and b/zellij-utils/assets/plugins/strider.wasm differ diff --git a/zellij-utils/assets/plugins/tab-bar.wasm b/zellij-utils/assets/plugins/tab-bar.wasm index 51f215d13..1166de83c 100644 Binary files a/zellij-utils/assets/plugins/tab-bar.wasm and b/zellij-utils/assets/plugins/tab-bar.wasm differ diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index b5d6acb13..7db0e4f3f 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -208,6 +208,14 @@ pub enum Action { } impl Action { + /// Checks that two Action are match except their mutable attributes. + pub fn shallow_eq(&self, other_action: &Action) -> bool { + match (self, other_action) { + (Action::NewTab(_, _, _), Action::NewTab(_, _, _)) => true, + _ => self == other_action, + } + } + pub fn actions_from_cli( cli_action: CliAction, get_current_dir: Box PathBuf>, diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index 2a81300ca..f7a6ac4db 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -301,10 +301,10 @@ macro_rules! keys_from_kdl { #[macro_export] macro_rules! actions_from_kdl { - ( $kdl_node:expr ) => { + ( $kdl_node:expr, $config_options:expr ) => { kdl_children_nodes_or_error!($kdl_node, "no actions found for key_block") .iter() - .map(|kdl_action| Action::try_from(kdl_action)) + .map(|kdl_action| Action::try_from((kdl_action, $config_options))) .collect::>()? }; } @@ -614,9 +614,9 @@ impl TryFrom<(&str, &KdlDocument)> for PaletteColor { } } -impl TryFrom<&KdlNode> for Action { +impl TryFrom<(&KdlNode, &Options)> for Action { type Error = ConfigError; - fn try_from(kdl_action: &KdlNode) -> Result { + fn try_from((kdl_action, config_options): (&KdlNode, &Options)) -> Result { let action_name = kdl_name!(kdl_action); let action_arguments: Vec<&KdlEntry> = kdl_argument_values!(kdl_action); let action_children: Vec<&KdlDocument> = kdl_children!(kdl_action); @@ -742,7 +742,64 @@ impl TryFrom<&KdlNode> for Action { "PaneNameInput" => { parse_kdl_action_u8_arguments!(action_name, action_arguments, kdl_action) }, - "NewTab" => Ok(Action::NewTab(None, vec![], None)), + "NewTab" => { + let command_metadata = action_children.iter().next(); + if command_metadata.is_none() { + return Ok(Action::NewTab(None, vec![], None)); + } + + let current_dir = std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")); + + let layout = command_metadata + .and_then(|c_m| kdl_child_string_value_for_entry(c_m, "layout")) + .map(|layout_string| PathBuf::from(layout_string)) + .or_else(|| config_options.default_layout.clone()); + let cwd = command_metadata + .and_then(|c_m| kdl_child_string_value_for_entry(c_m, "cwd")) + .map(|cwd_string| PathBuf::from(cwd_string)) + .map(|cwd| current_dir.join(cwd)); + let name = command_metadata + .and_then(|c_m| kdl_child_string_value_for_entry(c_m, "name")) + .map(|name_string| name_string.to_string()); + + let (path_to_raw_layout, raw_layout) = + Layout::stringified_from_path_or_default(layout.as_ref(), None).map_err( + |e| { + ConfigError::new_kdl_error( + format!("Failed to load layout: {}", e), + kdl_action.span().offset(), + kdl_action.span().len(), + ) + }, + )?; + + let layout = + Layout::from_str(&raw_layout, path_to_raw_layout, cwd).map_err(|e| { + ConfigError::new_kdl_error( + format!("Failed to load layout: {}", e), + kdl_action.span().offset(), + kdl_action.span().len(), + ) + })?; + + let mut tabs = layout.tabs(); + if tabs.len() > 1 { + return Err(ConfigError::new_kdl_error( + "Tab layout cannot itself have tabs".to_string(), + kdl_action.span().offset(), + kdl_action.span().len(), + )); + } else if !tabs.is_empty() { + let (tab_name, layout, floating_panes_layout) = tabs.drain(..).next().unwrap(); + let name = tab_name.or(name); + + Ok(Action::NewTab(Some(layout), floating_panes_layout, name)) + } else { + let (layout, floating_panes_layout) = layout.new_tab(); + + Ok(Action::NewTab(Some(layout), floating_panes_layout, name)) + } + }, "GoToTab" => parse_kdl_action_u8_arguments!(action_name, action_arguments, kdl_action), "TabNameInput" => { parse_kdl_action_u8_arguments!(action_name, action_arguments, kdl_action) @@ -1370,12 +1427,13 @@ impl Keybinds { fn bind_keys_in_block( block: &KdlNode, input_mode_keybinds: &mut HashMap>, + config_options: &Options, ) -> Result<(), ConfigError> { let all_nodes = kdl_children_nodes_or_error!(block, "no keybinding block for mode"); let bind_nodes = all_nodes.iter().filter(|n| kdl_name!(n) == "bind"); let unbind_nodes = all_nodes.iter().filter(|n| kdl_name!(n) == "unbind"); for key_block in bind_nodes { - Keybinds::bind_actions_for_each_key(key_block, input_mode_keybinds)?; + Keybinds::bind_actions_for_each_key(key_block, input_mode_keybinds, config_options)?; } // we loop a second time so that the unbinds always happen after the binds for key_block in unbind_nodes { @@ -1392,7 +1450,11 @@ impl Keybinds { } Ok(()) } - pub fn from_kdl(kdl_keybinds: &KdlNode, base_keybinds: Keybinds) -> Result { + pub fn from_kdl( + kdl_keybinds: &KdlNode, + base_keybinds: Keybinds, + config_options: &Options, + ) -> Result { let clear_defaults = kdl_arg_is_truthy!(kdl_keybinds, "clear-defaults"); let mut keybinds_from_config = if clear_defaults { Keybinds::default() @@ -1416,7 +1478,7 @@ impl Keybinds { continue; } let mut input_mode_keybinds = keybinds_from_config.get_input_mode_mut(&mode); - Keybinds::bind_keys_in_block(block, &mut input_mode_keybinds)?; + Keybinds::bind_keys_in_block(block, &mut input_mode_keybinds, config_options)?; } } if kdl_name!(block) == "shared_among" { @@ -1429,7 +1491,7 @@ impl Keybinds { continue; } let mut input_mode_keybinds = keybinds_from_config.get_input_mode_mut(&mode); - Keybinds::bind_keys_in_block(block, &mut input_mode_keybinds)?; + Keybinds::bind_keys_in_block(block, &mut input_mode_keybinds, config_options)?; } } } @@ -1443,7 +1505,7 @@ impl Keybinds { } let mut input_mode_keybinds = Keybinds::input_mode_keybindings(mode, &mut keybinds_from_config)?; - Keybinds::bind_keys_in_block(mode, &mut input_mode_keybinds)?; + Keybinds::bind_keys_in_block(mode, &mut input_mode_keybinds, config_options)?; } if let Some(global_unbind) = kdl_keybinds.children().and_then(|c| c.get("unbind")) { Keybinds::unbind_keys_in_all_modes(global_unbind, &mut keybinds_from_config)?; @@ -1453,9 +1515,10 @@ impl Keybinds { fn bind_actions_for_each_key( key_block: &KdlNode, input_mode_keybinds: &mut HashMap>, + config_options: &Options, ) -> Result<(), ConfigError> { let keys: Vec = keys_from_kdl!(key_block); - let actions: Vec = actions_from_kdl!(key_block); + let actions: Vec = actions_from_kdl!(key_block, config_options); for key in keys { input_mode_keybinds.insert(key, actions.clone()); } @@ -1508,13 +1571,15 @@ impl Config { pub fn from_kdl(kdl_config: &str, base_config: Option) -> Result { let mut config = base_config.unwrap_or_else(|| Config::default()); let kdl_config: KdlDocument = kdl_config.parse()?; + + let config_options = Options::from_kdl(&kdl_config)?; + config.options = config.options.merge(config_options); + // TODO: handle cases where we have more than one of these blocks (eg. two "keybinds") // this should give an informative parsing error if let Some(kdl_keybinds) = kdl_config.get("keybinds") { - config.keybinds = Keybinds::from_kdl(&kdl_keybinds, config.keybinds)?; + config.keybinds = Keybinds::from_kdl(&kdl_keybinds, config.keybinds, &config.options)?; } - let config_options = Options::from_kdl(&kdl_config)?; - config.options = config.options.merge(config_options); if let Some(kdl_themes) = kdl_config.get("themes") { let config_themes = Themes::from_kdl(kdl_themes)?; config.themes = config.themes.merge(config_themes); -- cgit v1.2.3