diff options
author | Aram Drevekenin <aram@poor.dev> | 2022-10-14 15:08:32 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-14 15:08:32 +0200 |
commit | d074bb1cda819bd660b76b3be54b4db10d0eeed4 (patch) | |
tree | fa85e65655909167cbd998b564e0a91353c3f5a3 /zellij-utils | |
parent | 5c43a59e00eb84bbba84b25cc2750c84359cd8a5 (diff) |
feat(layouts): global cwd (#1798)
* feat(layouts): allow defining a global cwd
* feat(layouts): allow passing global cwd from cli
* style(fmt): rustfmt
* fix(layouts): error on mixed cwd and pane children
Diffstat (limited to 'zellij-utils')
18 files changed, 1010 insertions, 131 deletions
diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index bef1afb33..ae0c2141c 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -253,5 +253,7 @@ pub enum CliAction { layout: Option<PathBuf>, #[clap(short, long, value_parser)] name: Option<String>, + #[clap(short, long, value_parser, requires("layout"))] + cwd: Option<PathBuf>, }, } diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index de1350ddd..d337a75a9 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -344,12 +344,12 @@ impl Action { Action::TabNameInput(name.as_bytes().to_vec()), ]), CliAction::UndoRenameTab => Ok(vec![Action::UndoRenameTab]), - CliAction::NewTab { name, layout } => { + CliAction::NewTab { name, layout, cwd } => { if let Some(layout_path) = layout { let (path_to_raw_layout, raw_layout) = Layout::stringified_from_path_or_default(Some(&layout_path), None) .map_err(|e| format!("Failed to load layout: {}", e))?; - let layout = Layout::from_str(&raw_layout, path_to_raw_layout).map_err(|e| { + let layout = Layout::from_str(&raw_layout, path_to_raw_layout, cwd).map_err(|e| { let stringified_error = match e { ConfigError::KdlError(kdl_error) => { let error = kdl_error.add_src(layout_path.as_path().as_os_str().to_string_lossy().to_string(), String::from(raw_layout)); diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index f823ed401..8299c0bc2 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -62,6 +62,41 @@ pub enum Run { Plugin(RunPlugin), #[serde(rename = "command")] Command(RunCommand), + Cwd(PathBuf), +} + +impl Run { + pub fn merge(base: &Option<Run>, other: &Option<Run>) -> Option<Run> { + // TODO: handle Plugin variants once there's a need + match (base, other) { + (Some(Run::Command(base_run_command)), Some(Run::Command(other_run_command))) => { + let mut merged = other_run_command.clone(); + if merged.cwd.is_none() && base_run_command.cwd.is_some() { + merged.cwd = base_run_command.cwd.clone(); + } + if merged.args.is_empty() && !base_run_command.args.is_empty() { + merged.args = base_run_command.args.clone(); + } + Some(Run::Command(merged)) + }, + (Some(Run::Command(base_run_command)), Some(Run::Cwd(other_cwd))) => { + let mut merged = base_run_command.clone(); + merged.cwd = Some(other_cwd.clone()); + Some(Run::Command(merged)) + }, + (Some(Run::Cwd(base_cwd)), Some(Run::Command(other_command))) => { + let mut merged = other_command.clone(); + if merged.cwd.is_none() { + merged.cwd = Some(base_cwd.clone()); + } + Some(Run::Command(merged)) + }, + (Some(_base), Some(other)) => Some(other.clone()), + (Some(base), _) => Some(base.clone()), + (None, Some(other)) => Some(other.clone()), + (None, None) => None, + } + } } #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -252,12 +287,16 @@ impl Layout { ) -> Result<(Layout, Config), ConfigError> { let (path_to_raw_layout, raw_layout) = Layout::stringified_from_path_or_default(layout_path, layout_dir)?; - let layout = Layout::from_kdl(&raw_layout, path_to_raw_layout)?; + let layout = Layout::from_kdl(&raw_layout, path_to_raw_layout, None)?; let config = Config::from_kdl(&raw_layout, Some(config))?; // this merges the two config, with Ok((layout, config)) } - pub fn from_str(raw: &str, path_to_raw_layout: String) -> Result<Layout, ConfigError> { - Layout::from_kdl(raw, path_to_raw_layout) + pub fn from_str( + raw: &str, + path_to_raw_layout: String, + cwd: Option<PathBuf>, + ) -> Result<Layout, ConfigError> { + Layout::from_kdl(raw, path_to_raw_layout, cwd) } pub fn stringified_from_dir( layout: &PathBuf, diff --git a/zellij-utils/src/input/unit/layout_test.rs b/zellij-utils/src/input/unit/layout_test.rs index ce077a42e..82a221e2e 100644 --- a/zellij-utils/src/input/unit/layout_test.rs +++ b/zellij-utils/src/input/unit/layout_test.rs @@ -4,7 +4,7 @@ use insta::assert_snapshot; #[test] fn empty_layout() { let kdl_layout = "layout"; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout::default()), ..Default::default() @@ -19,7 +19,7 @@ fn layout_with_one_pane() { pane } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![PaneLayout::default()], @@ -39,7 +39,7 @@ fn layout_with_multiple_panes() { pane } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![ @@ -68,7 +68,7 @@ fn layout_with_nested_panes() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![ @@ -96,7 +96,7 @@ fn layout_with_tabs() { tab } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { tabs: vec![(None, PaneLayout::default())], template: Some(PaneLayout::default()), @@ -120,7 +120,7 @@ fn layout_with_nested_differing_tabs() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { tabs: vec![ ( @@ -160,7 +160,7 @@ fn layout_with_panes_in_different_mixed_split_sizes() { pane size=2; } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![ @@ -195,7 +195,7 @@ fn layout_with_command_panes() { pane command="htop" } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![PaneLayout { @@ -220,7 +220,7 @@ fn layout_with_command_panes_and_cwd() { pane command="htop" cwd="/path/to/my/cwd" } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![PaneLayout { @@ -248,7 +248,7 @@ fn layout_with_command_panes_and_cwd_and_args() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![PaneLayout { @@ -280,7 +280,7 @@ fn layout_with_plugin_panes() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![ @@ -313,7 +313,7 @@ fn layout_with_borderless_panes() { pane borderless=true } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![PaneLayout { @@ -334,7 +334,7 @@ fn layout_with_focused_panes() { pane focus=true } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![PaneLayout { @@ -355,7 +355,7 @@ fn layout_with_pane_names() { pane name="my awesome pane" } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { template: Some(PaneLayout { children: vec![PaneLayout { @@ -377,7 +377,7 @@ fn layout_with_tab_names() { tab name="my cool tab name 2" } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { tabs: vec![ ( @@ -410,7 +410,7 @@ fn layout_with_focused_tab() { tab } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { tabs: vec![ (None, PaneLayout::default()), @@ -444,7 +444,7 @@ fn layout_with_tab_templates() { one-above-one-below } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); let expected_layout = Layout { tabs: vec![ ( @@ -518,7 +518,7 @@ fn layout_with_default_tab_template() { tab } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -545,7 +545,7 @@ fn layout_with_pane_templates() { left-and-right } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -566,7 +566,7 @@ fn layout_with_tab_and_pane_templates() { left-right-and-htop } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -587,7 +587,7 @@ fn layout_with_nested_pane_templates() { left-and-right } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -613,7 +613,7 @@ fn layout_with_nested_branched_pane_templates() { left-and-right } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -637,7 +637,7 @@ fn circular_dependency_pane_templates_error() { one } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None); assert!(layout.is_err(), "circular dependency detected"); } @@ -659,7 +659,7 @@ fn children_not_as_first_child_of_tab_template() { horizontal-with-vertical-top } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -682,7 +682,7 @@ fn error_on_more_than_one_children_block_in_tab_template() { horizontal-with-vertical-top } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None); assert!( layout.is_err(), "error provided for more than one children block" @@ -707,7 +707,7 @@ fn children_not_as_first_child_of_pane_template() { horizontal-with-vertical-top } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -730,7 +730,7 @@ fn error_on_more_than_one_children_block_in_pane_template() { horizontal-with-vertical-top } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None); assert!( layout.is_err(), "error provided for more than one children block" @@ -759,7 +759,7 @@ fn combined_tab_and_pane_template_both_with_children() { horizontal-with-vertical-top } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -775,7 +775,7 @@ fn cannot_define_tab_template_name_with_space() { pane } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None); assert!(layout.is_err(), "error provided for tab name with space"); } @@ -791,7 +791,7 @@ fn cannot_define_pane_template_name_with_space() { pane } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None); assert!(layout.is_err(), "error provided for tab name with space"); } @@ -805,7 +805,7 @@ fn cannot_define_panes_and_tabs_on_same_level() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None); assert!( layout.is_err(), "error provided for tab and pane on the same level" @@ -839,7 +839,7 @@ fn cannot_define_tab_template_names_as_keywords() { ", keyword ); - let layout = Layout::from_kdl(&kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None); assert!( layout.is_err(), "{}", @@ -877,7 +877,7 @@ fn cannot_define_pane_template_names_as_keywords() { ", keyword ); - let layout = Layout::from_kdl(&kdl_layout, "layout_file_name".into()); + let layout = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None); assert!( layout.is_err(), "{}", @@ -897,7 +897,7 @@ fn error_on_multiple_layout_nodes_in_file() { layout " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -912,7 +912,7 @@ fn error_on_unknown_layout_node() { }} " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -925,7 +925,7 @@ fn error_on_unknown_layout_pane_property() { }} " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -938,7 +938,7 @@ fn error_on_unknown_layout_pane_template_property() { }} " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -951,7 +951,7 @@ fn error_on_unknown_layout_tab_property() { }} " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -964,7 +964,7 @@ fn error_on_unknown_layout_tab_template_property() { }} " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -981,7 +981,7 @@ fn error_on_pane_templates_without_a_name() { }} " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -998,7 +998,7 @@ fn error_on_tab_templates_without_a_name() { }} " ); - let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -1011,7 +1011,7 @@ fn error_on_more_than_one_focused_tab() { tab } "#; - let layout_error = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap_err(); + let layout_error = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap_err(); assert_snapshot!(format!("{:?}", layout_error)); } @@ -1029,7 +1029,7 @@ fn args_override_args_in_template() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -1046,7 +1046,7 @@ fn args_added_to_args_in_template() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{:#?}", layout)); } @@ -1064,7 +1064,7 @@ fn cwd_override_cwd_in_template() { } } "#; - let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into()).unwrap(); + let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap(); assert_snapshot!(format!("{: |