summaryrefslogtreecommitdiffstats
path: root/zellij-utils
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2022-10-14 17:44:23 +0200
committerGitHub <noreply@github.com>2022-10-14 17:44:23 +0200
commitefceb562dec562babd90c711b30a5471e026fd3d (patch)
tree0d98a00319023c1f9724fc39cff018513413c6ee /zellij-utils
parent8c2b576b670a98d891186c1cf469ca438dfd8a45 (diff)
feat(layouts): edit panes (#1799)
* feat(layouts): edit panes * style(fmt): rustfmt
Diffstat (limited to 'zellij-utils')
-rw-r--r--zellij-utils/src/input/layout.rs14
-rw-r--r--zellij-utils/src/input/unit/layout_test.rs32
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap37
-rw-r--r--zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap37
-rw-r--r--zellij-utils/src/kdl/kdl_layout_parser.rs40
5 files changed, 147 insertions, 13 deletions
diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs
index 8299c0bc2..8e317a8e0 100644
--- a/zellij-utils/src/input/layout.rs
+++ b/zellij-utils/src/input/layout.rs
@@ -62,11 +62,15 @@ pub enum Run {
Plugin(RunPlugin),
#[serde(rename = "command")]
Command(RunCommand),
+ EditFile(PathBuf, Option<usize>), // TODO: merge this with TerminalAction::OpenFile
Cwd(PathBuf),
}
impl Run {
pub fn merge(base: &Option<Run>, other: &Option<Run>) -> Option<Run> {
+ // This method is necessary to merge between pane_templates and their consumers
+ // TODO: reconsider the way we parse command/edit/plugin pane_templates from layouts to prevent this
+ // madness
// TODO: handle Plugin variants once there's a need
match (base, other) {
(Some(Run::Command(base_run_command)), Some(Run::Command(other_run_command))) => {
@@ -91,6 +95,16 @@ impl Run {
}
Some(Run::Command(merged))
},
+ (
+ Some(Run::Command(base_run_command)),
+ Some(Run::EditFile(file_to_edit, line_number)),
+ ) => match &base_run_command.cwd {
+ Some(cwd) => Some(Run::EditFile(cwd.join(&file_to_edit), *line_number)),
+ None => Some(Run::EditFile(file_to_edit.clone(), *line_number)),
+ },
+ (Some(Run::Cwd(cwd)), Some(Run::EditFile(file_to_edit, line_number))) => {
+ Some(Run::EditFile(cwd.join(&file_to_edit), *line_number))
+ },
(Some(_base), Some(other)) => Some(other.clone()),
(Some(base), _) => Some(base.clone()),
(None, Some(other)) => Some(other.clone()),
diff --git a/zellij-utils/src/input/unit/layout_test.rs b/zellij-utils/src/input/unit/layout_test.rs
index 82a221e2e..6155024b2 100644
--- a/zellij-utils/src/input/unit/layout_test.rs
+++ b/zellij-utils/src/input/unit/layout_test.rs
@@ -1283,6 +1283,38 @@ fn pane_template_with_bare_propagated_to_its_consumer_command_with_cwd() {
}
#[test]
+fn pane_template_with_bare_propagated_to_its_consumer_edit() {
+ let kdl_layout = r#"
+ layout {
+ cwd "/tmp"
+ pane_template name="tail" {
+ cwd "foo"
+ }
+ tail edit="bar"
+ // pane should have /tmp/foo/bar with the edit file variant
+ }
+ "#;
+ let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
+ assert_snapshot!(format!("{:#?}", layout));
+}
+
+#[test]
+fn pane_template_with_command_propagated_to_its_consumer_edit() {
+ let kdl_layout = r#"
+ layout {
+ cwd "/tmp"
+ pane_template name="tail" command="not-vim" {
+ cwd "foo"
+ }
+ tail edit="bar"
+ // pane should have /tmp/foo/bar with the edit file variant
+ }
+ "#;
+ let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
+ assert_snapshot!(format!("{:#?}", layout));
+}
+
+#[test]
fn global_cwd_given_to_panes_without_cwd() {
let kdl_layout = r#"
layout {
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap
new file mode 100644
index 000000000..32bc6880c
--- /dev/null
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_bare_propagated_to_its_consumer_edit.snap
@@ -0,0 +1,37 @@
+---
+source: zellij-utils/src/input/./unit/layout_test.rs
+assertion_line: 1298
+expression: "format!(\"{:#?}\", layout)"
+---
+Layout {
+ tabs: [],
+ focused_tab_index: None,
+ template: Some(
+ PaneLayout {
+ children_split_direction: Horizontal,
+ name: None,
+ children: [
+ PaneLayout {
+ children_split_direction: Horizontal,
+ name: None,
+ children: [],
+ split_size: None,
+ run: Some(
+ EditFile(
+ "/tmp/foo/bar",
+ None,
+ ),
+ ),
+ borderless: false,
+ focus: None,
+ external_children_index: None,
+ },
+ ],
+ split_size: None,
+ run: None,
+ borderless: false,
+ focus: None,
+ external_children_index: None,
+ },
+ ),
+}
diff --git a/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap
new file mode 100644
index 000000000..f5f50be11
--- /dev/null
+++ b/zellij-utils/src/input/unit/snapshots/zellij_utils__input__layout__layout_test__pane_template_with_command_propagated_to_its_consumer_edit.snap
@@ -0,0 +1,37 @@
+---
+source: zellij-utils/src/input/./unit/layout_test.rs
+assertion_line: 1314
+expression: "format!(\"{:#?}\", layout)"
+---
+Layout {
+ tabs: [],
+ focused_tab_index: None,
+ template: Some(
+ PaneLayout {
+ children_split_direction: Horizontal,
+ name: None,
+ children: [
+ PaneLayout {
+ children_split_direction: Horizontal,
+ name: None,
+ children: [],
+ split_size: None,
+ run: Some(
+ EditFile(
+ "/tmp/foo/bar",
+ None,
+ ),
+ ),
+ borderless: false,
+ focus: None,
+ external_children_index: None,
+ },
+ ],
+ split_size: None,
+ run: None,
+ borderless: false,
+ focus: None,
+ external_children_index: None,
+ },
+ ),
+}
diff --git a/zellij-utils/src/kdl/kdl_layout_parser.rs b/zellij-utils/src/kdl/kdl_layout_parser.rs
index d7df58890..514a80e42 100644
--- a/zellij-utils/src/kdl/kdl_layout_parser.rs
+++ b/zellij-utils/src/kdl/kdl_layout_parser.rs
@@ -48,6 +48,7 @@ impl<'a> KdlLayoutParser<'a> {
|| word == "tab_template"
|| word == "default_tab_template"
|| word == "command"
+ || word == "edit"
|| word == "plugin"
|| word == "children"
|| word == "tab"
@@ -66,6 +67,7 @@ impl<'a> KdlLayoutParser<'a> {
|| property_name == "size"
|| property_name == "plugin"
|| property_name == "command"
+ || property_name == "edit"
|| property_name == "cwd"
|| property_name == "args"
|| property_name == "split_direction"
@@ -192,6 +194,8 @@ impl<'a> KdlLayoutParser<'a> {
) -> Result<Option<Run>, ConfigError> {
let command = kdl_get_string_property_or_child_value_with_error!(pane_node, "command")
.map(|c| PathBuf::from(c));
+ let edit = kdl_get_string_property_or_child_value_with_error!(pane_node, "edit")
+ .map(|c| PathBuf::from(c));
let cwd = if is_template {
// we fill the global_cwd for templates later
kdl_get_string_property_or_child_value_with_error!(pane_node, "cwd")
@@ -200,23 +204,30 @@ impl<'a> KdlLayoutParser<'a> {
self.parse_cwd(pane_node)?
};
let args = self.parse_args(pane_node)?;
- match (command, cwd, args, is_template) {
- (None, Some(cwd), _, _) => Ok(Some(Run::Cwd(cwd))),
- (None, _, Some(_args), false) => Err(ConfigError::new_kdl_error(
+ match (command, edit, cwd, args, is_template) {
+ (None, None, Some(cwd), _, _) => Ok(Some(Run::Cwd(cwd))),
+ (None, _, _, Some(_args), false) => Err(ConfigError::new_kdl_error(
"args can only be set if a command was specified".into(),
pane_node.span().offset(),
pane_node.span().len(),
)),
- (Some(command), cwd, args, _) => Ok(Some(Run::Command(RunCommand {
+ (Some(command), None, cwd, args, _) => Ok(Some(Run::Command(RunCommand {
command,
args: args.unwrap_or_else(|| vec![]),
cwd,
hold_on_close: true,
}))),
+ (None, Some(edit), Some(cwd), _, _) => Ok(Some(Run::EditFile(cwd.join(edit), None))),
+ (None, Some(edit), None, _, _) => Ok(Some(Run::EditFile(edit, None))),
+ (Some(_command), Some(_edit), _, _, _) => Err(ConfigError::new_kdl_error(
+ "cannot have both a command and an edit instruction for the same pane".into(),
+ pane_node.span().offset(),
+ pane_node.span().len(),
+ )),
_ => Ok(None),
}
}
- fn parse_command_or_plugin_block(
+ fn parse_command_plugin_or_edit_block(
&self,
kdl_node: &KdlNode,
) -> Result<Option<Run>, ConfigError> {
@@ -224,7 +235,7 @@ impl<'a> KdlLayoutParser<'a> {
if let Some(plugin_block) = kdl_get_child!(kdl_node, "plugin") {
if run.is_some() {
return Err(ConfigError::new_kdl_error(
- "Cannot have both a command and a plugin block for a single pane".into(),
+ "Cannot have both a command/edit and a plugin block for a single pane".into(),
plugin_block.span().offset(),
plugin_block.span().len(),
));
@@ -233,7 +244,7 @@ impl<'a> KdlLayoutParser<'a> {
}
Ok(run)
}
- fn parse_command_or_plugin_block_for_template(
+ fn parse_command_plugin_or_edit_block_for_template(
&self,
kdl_node: &KdlNode,
) -> Result<Option<Run>, ConfigError> {
@@ -241,7 +252,7 @@ impl<'a> KdlLayoutParser<'a> {
if let Some(plugin_block) = kdl_get_child!(kdl_node, "plugin") {
if run.is_some() {
return Err(ConfigError::new_kdl_error(
- "Cannot have both a command and a plugin block for a single pane".into(),
+ "Cannot have both a command/edit and a plugin block for a single pane".into(),
plugin_block.span().offset(),
plugin_block.span().len(),
));
@@ -257,7 +268,7 @@ impl<'a> KdlLayoutParser<'a> {
let name = kdl_get_string_property_or_child_value_with_error!(kdl_node, "name")
.map(|name| name.to_string());
let split_size = self.parse_split_size(kdl_node)?;
- let run = self.parse_command_or_plugin_block(kdl_node)?;
+ let run = self.parse_command_plugin_or_edit_block(kdl_node)?;
let children_split_direction = self.parse_split_direction(kdl_node)?;
let (external_children_index, children) = match kdl_children_nodes!(kdl_node) {
Some(children) => self.parse_child_pane_nodes_for_pane(&children)?,
@@ -315,7 +326,7 @@ impl<'a> KdlLayoutParser<'a> {
.map(|name| name.to_string());
let args = self.parse_args(kdl_node)?;
let split_size = self.parse_split_size(kdl_node)?;
- let run = self.parse_command_or_plugin_block_for_template(kdl_node)?;
+ let run = self.parse_command_plugin_or_edit_block_for_template(kdl_node)?;
self.assert_no_bare_args_in_pane_node_with_template(
&run,
&pane_template.run,
@@ -370,6 +381,9 @@ impl<'a> KdlLayoutParser<'a> {
run_command.cwd = Some(global_cwd.clone());
},
},
+ Some(Run::EditFile(path_to_file, _line_number)) => {
+ *path_to_file = global_cwd.join(&path_to_file);
+ },
Some(Run::Cwd(pane_template_cwd)) => {
*pane_template_cwd = global_cwd.join(&pane_template_cwd);
},
@@ -406,7 +420,7 @@ impl<'a> KdlLayoutParser<'a> {
let borderless = kdl_get_bool_property_or_child_value_with_error!(kdl_node, "borderless");
let focus = kdl_get_bool_property_or_child_value_with_error!(kdl_node, "focus");
let split_size = self.parse_split_size(kdl_node)?;
- let run = self.parse_command_or_plugin_block(kdl_node)?;
+ let run = self.parse_command_plugin_or_edit_block(kdl_node)?;
let children_split_direction = self.parse_split_direction(kdl_node)?;
let (external_children_index, pane_parts) = match kdl_children_nodes!(kdl_node) {
Some(children) => self.parse_child_pane_nodes_for_pane(&children)?,
@@ -625,7 +639,7 @@ impl<'a> KdlLayoutParser<'a> {
let has_cwd_prop =
kdl_get_string_property_or_child_value_with_error!(kdl_node, "cwd").is_some();
let has_non_cwd_run_prop = self
- .parse_command_or_plugin_block(kdl_node)?
+ .parse_command_plugin_or_edit_block(kdl_node)?
.map(|r| match r {
Run::Cwd(_) => false,
_ => true,
@@ -643,7 +657,7 @@ impl<'a> KdlLayoutParser<'a> {
offending_nodes.push("focus");
}
if has_non_cwd_run_prop {
- offending_nodes.push("command/plugin");
+ offending_nodes.push("command/edit/plugin");
}
if has_cwd_prop {
offending_nodes.push("cwd");