feat(layouts): allow defining a tab cwd (#1828)
This commit is contained in:
parent
ebf61f6ff2
commit
e59b09a1b6
9 changed files with 709 additions and 56 deletions
|
|
@ -111,6 +111,25 @@ impl Run {
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn add_cwd(&mut self, cwd: &PathBuf) {
|
||||||
|
match self {
|
||||||
|
Run::Command(run_command) => match run_command.cwd.as_mut() {
|
||||||
|
Some(run_cwd) => {
|
||||||
|
*run_cwd = cwd.join(&run_cwd);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
run_command.cwd = Some(cwd.clone());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Run::EditFile(path_to_file, _line_number) => {
|
||||||
|
*path_to_file = cwd.join(&path_to_file);
|
||||||
|
},
|
||||||
|
Run::Cwd(path) => {
|
||||||
|
*path = cwd.join(&path);
|
||||||
|
},
|
||||||
|
_ => {}, // plugins aren't yet supported
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
|
|
@ -233,6 +252,17 @@ impl PaneLayout {
|
||||||
default_layout.children = vec![PaneLayout::default()];
|
default_layout.children = vec![PaneLayout::default()];
|
||||||
default_layout
|
default_layout
|
||||||
}
|
}
|
||||||
|
pub fn add_cwd_to_layout(&mut self, cwd: &PathBuf) {
|
||||||
|
match self.run.as_mut() {
|
||||||
|
Some(run) => run.add_cwd(cwd),
|
||||||
|
None => {
|
||||||
|
self.run = Some(Run::Cwd(cwd.clone()));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for child in self.children.iter_mut() {
|
||||||
|
child.add_cwd_to_layout(cwd);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
|
|
|
||||||
|
|
@ -1379,3 +1379,104 @@ fn global_cwd_passed_from_layout_constructor_overrides_global_cwd_in_layout_file
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_snapshot!(format!("{:#?}", layout));
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn global_cwd_with_tab_cwd_given_to_panes_without_cwd() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
cwd "/tmp"
|
||||||
|
tab cwd="./foo" {
|
||||||
|
pane
|
||||||
|
pane command="tail"
|
||||||
|
}
|
||||||
|
// both should have the /tmp/foo cwd
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tab_cwd_given_to_panes_without_cwd() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
tab cwd="/tmp" {
|
||||||
|
pane
|
||||||
|
pane command="tail"
|
||||||
|
}
|
||||||
|
// both should have the /tmp cwd
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tab_cwd_prepended_to_panes_with_cwd() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
tab cwd="/tmp" {
|
||||||
|
pane cwd="./foo"
|
||||||
|
pane command="tail" cwd="./foo"
|
||||||
|
}
|
||||||
|
// both should have the /tmp/foo cwd
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
cwd "/tmp"
|
||||||
|
tab cwd="./foo" {
|
||||||
|
pane // should have /tmp/foo
|
||||||
|
pane command="tail" cwd="./bar" // should have /tmp/foo/bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_pane_templates() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
cwd "/tmp"
|
||||||
|
pane_template name="my_pane_template" {
|
||||||
|
pane // should have /tmp/foo
|
||||||
|
pane command="tail" cwd="./bar" // should have /tmp/foo/bar
|
||||||
|
children
|
||||||
|
}
|
||||||
|
tab cwd="./foo" {
|
||||||
|
my_pane_template {
|
||||||
|
pane // should have /tmp/foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_tab_templates() {
|
||||||
|
let kdl_layout = r#"
|
||||||
|
layout {
|
||||||
|
cwd "/tmp"
|
||||||
|
tab_template name="my_tab_template" {
|
||||||
|
pane // should have /tmp/foo
|
||||||
|
pane command="tail" cwd="./bar" // should have /tmp/foo/bar
|
||||||
|
children
|
||||||
|
}
|
||||||
|
my_tab_template cwd="./foo" {
|
||||||
|
pane // should have /tmp/foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
|
||||||
|
assert_snapshot!(format!("{:#?}", layout));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1441
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: Some(
|
||||||
|
"/tmp/./foo/./bar",
|
||||||
|
),
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,119 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1462
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: Some(
|
||||||
|
"/tmp/./foo/./bar",
|
||||||
|
),
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1481
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: Some(
|
||||||
|
"/tmp/./foo/./bar",
|
||||||
|
),
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1396
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: Some(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1411
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: Some(
|
||||||
|
"/tmp",
|
||||||
|
),
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||||
|
assertion_line: 1426
|
||||||
|
expression: "format!(\"{:#?}\", layout)"
|
||||||
|
---
|
||||||
|
Layout {
|
||||||
|
tabs: [
|
||||||
|
(
|
||||||
|
None,
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Command(
|
||||||
|
RunCommand {
|
||||||
|
command: "tail",
|
||||||
|
args: [],
|
||||||
|
cwd: Some(
|
||||||
|
"/tmp/./foo",
|
||||||
|
),
|
||||||
|
hold_on_close: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
split_size: None,
|
||||||
|
run: Some(
|
||||||
|
Cwd(
|
||||||
|
"/tmp",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
focused_tab_index: None,
|
||||||
|
template: Some(
|
||||||
|
PaneLayout {
|
||||||
|
children_split_direction: Horizontal,
|
||||||
|
name: None,
|
||||||
|
children: [],
|
||||||
|
split_size: None,
|
||||||
|
run: None,
|
||||||
|
borderless: false,
|
||||||
|
focus: None,
|
||||||
|
external_children_index: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
@ -75,7 +75,10 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
|| property_name == "children"
|
|| property_name == "children"
|
||||||
}
|
}
|
||||||
fn is_a_valid_tab_property(&self, property_name: &str) -> bool {
|
fn is_a_valid_tab_property(&self, property_name: &str) -> bool {
|
||||||
property_name == "focus" || property_name == "name" || property_name == "split_direction"
|
property_name == "focus"
|
||||||
|
|| property_name == "name"
|
||||||
|
|| property_name == "split_direction"
|
||||||
|
|| property_name == "cwd"
|
||||||
}
|
}
|
||||||
fn assert_legal_node_name(&self, name: &str, kdl_node: &KdlNode) -> Result<(), ConfigError> {
|
fn assert_legal_node_name(&self, name: &str, kdl_node: &KdlNode) -> Result<(), ConfigError> {
|
||||||
if name.contains(char::is_whitespace) {
|
if name.contains(char::is_whitespace) {
|
||||||
|
|
@ -177,14 +180,18 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn cwd_prefix(&self, tab_cwd: Option<&PathBuf>) -> Result<Option<PathBuf>, ConfigError> {
|
||||||
|
Ok(match (&self.global_cwd, tab_cwd) {
|
||||||
|
(Some(global_cwd), Some(tab_cwd)) => Some(global_cwd.join(tab_cwd)),
|
||||||
|
(None, Some(tab_cwd)) => Some(tab_cwd.clone()),
|
||||||
|
(Some(global_cwd), None) => Some(global_cwd.clone()),
|
||||||
|
(None, None) => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
fn parse_cwd(&self, kdl_node: &KdlNode) -> Result<Option<PathBuf>, ConfigError> {
|
fn parse_cwd(&self, kdl_node: &KdlNode) -> Result<Option<PathBuf>, ConfigError> {
|
||||||
Ok(
|
Ok(
|
||||||
kdl_get_string_property_or_child_value_with_error!(kdl_node, "cwd")
|
kdl_get_string_property_or_child_value_with_error!(kdl_node, "cwd")
|
||||||
.and_then(|c| match &self.global_cwd {
|
.map(|cwd| PathBuf::from(cwd)),
|
||||||
Some(global_cwd) => Some(global_cwd.join(c)),
|
|
||||||
None => Some(PathBuf::from(c)),
|
|
||||||
})
|
|
||||||
.or_else(|| self.global_cwd.as_ref().map(|g| g.clone())),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn parse_pane_command(
|
fn parse_pane_command(
|
||||||
|
|
@ -196,13 +203,7 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
.map(|c| PathBuf::from(c));
|
.map(|c| PathBuf::from(c));
|
||||||
let edit = kdl_get_string_property_or_child_value_with_error!(pane_node, "edit")
|
let edit = kdl_get_string_property_or_child_value_with_error!(pane_node, "edit")
|
||||||
.map(|c| PathBuf::from(c));
|
.map(|c| PathBuf::from(c));
|
||||||
let cwd = if is_template {
|
let cwd = self.parse_cwd(pane_node)?;
|
||||||
// we fill the global_cwd for templates later
|
|
||||||
kdl_get_string_property_or_child_value_with_error!(pane_node, "cwd")
|
|
||||||
.map(|c| PathBuf::from(c))
|
|
||||||
} else {
|
|
||||||
self.parse_cwd(pane_node)?
|
|
||||||
};
|
|
||||||
let args = self.parse_args(pane_node)?;
|
let args = self.parse_args(pane_node)?;
|
||||||
match (command, edit, cwd, args, is_template) {
|
match (command, edit, cwd, args, is_template) {
|
||||||
(None, None, Some(cwd), _, _) => Ok(Some(Run::Cwd(cwd))),
|
(None, None, Some(cwd), _, _) => Ok(Some(Run::Cwd(cwd))),
|
||||||
|
|
@ -233,7 +234,13 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
) -> Result<Option<Run>, ConfigError> {
|
) -> Result<Option<Run>, ConfigError> {
|
||||||
let mut run = self.parse_pane_command(kdl_node, false)?;
|
let mut run = self.parse_pane_command(kdl_node, false)?;
|
||||||
if let Some(plugin_block) = kdl_get_child!(kdl_node, "plugin") {
|
if let Some(plugin_block) = kdl_get_child!(kdl_node, "plugin") {
|
||||||
if run.is_some() {
|
let has_non_cwd_run_prop = run
|
||||||
|
.map(|r| match r {
|
||||||
|
Run::Cwd(_) => false,
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
if has_non_cwd_run_prop {
|
||||||
return Err(ConfigError::new_kdl_error(
|
return Err(ConfigError::new_kdl_error(
|
||||||
"Cannot have both a command/edit 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().offset(),
|
||||||
|
|
@ -250,7 +257,13 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
) -> Result<Option<Run>, ConfigError> {
|
) -> Result<Option<Run>, ConfigError> {
|
||||||
let mut run = self.parse_pane_command(kdl_node, true)?;
|
let mut run = self.parse_pane_command(kdl_node, true)?;
|
||||||
if let Some(plugin_block) = kdl_get_child!(kdl_node, "plugin") {
|
if let Some(plugin_block) = kdl_get_child!(kdl_node, "plugin") {
|
||||||
if run.is_some() {
|
let has_non_cwd_run_prop = run
|
||||||
|
.map(|r| match r {
|
||||||
|
Run::Cwd(_) => false,
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
if has_non_cwd_run_prop {
|
||||||
return Err(ConfigError::new_kdl_error(
|
return Err(ConfigError::new_kdl_error(
|
||||||
"Cannot have both a command/edit 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().offset(),
|
||||||
|
|
@ -339,7 +352,6 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
pane_template_kdl_node,
|
pane_template_kdl_node,
|
||||||
)?;
|
)?;
|
||||||
pane_template.run = Run::merge(&pane_template.run, &run);
|
pane_template.run = Run::merge(&pane_template.run, &run);
|
||||||
self.populate_global_cwd_for_pane_run(&mut pane_template.run)?;
|
|
||||||
if let (Some(Run::Command(pane_template_run_command)), Some(args)) =
|
if let (Some(Run::Command(pane_template_run_command)), Some(args)) =
|
||||||
(pane_template.run.as_mut(), args)
|
(pane_template.run.as_mut(), args)
|
||||||
{
|
{
|
||||||
|
|
@ -367,31 +379,6 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
pane_template.external_children_index = None;
|
pane_template.external_children_index = None;
|
||||||
Ok(pane_template)
|
Ok(pane_template)
|
||||||
}
|
}
|
||||||
fn populate_global_cwd_for_pane_run(
|
|
||||||
&self,
|
|
||||||
pane_run: &mut Option<Run>,
|
|
||||||
) -> Result<(), ConfigError> {
|
|
||||||
if let Some(global_cwd) = &self.global_cwd {
|
|
||||||
match pane_run.as_mut() {
|
|
||||||
Some(Run::Command(run_command)) => match run_command.cwd.as_mut() {
|
|
||||||
Some(run_command_cwd) => {
|
|
||||||
*run_command_cwd = global_cwd.join(&run_command_cwd);
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
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);
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
fn parse_split_direction(&self, kdl_node: &KdlNode) -> Result<SplitDirection, ConfigError> {
|
fn parse_split_direction(&self, kdl_node: &KdlNode) -> Result<SplitDirection, ConfigError> {
|
||||||
match kdl_get_string_property_or_child_value_with_error!(kdl_node, "split_direction") {
|
match kdl_get_string_property_or_child_value_with_error!(kdl_node, "split_direction") {
|
||||||
Some(direction) => match SplitDirection::from_str(direction) {
|
Some(direction) => match SplitDirection::from_str(direction) {
|
||||||
|
|
@ -453,21 +440,23 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
self.assert_valid_tab_properties(kdl_node)?;
|
self.assert_valid_tab_properties(kdl_node)?;
|
||||||
let tab_name =
|
let tab_name =
|
||||||
kdl_get_string_property_or_child_value!(kdl_node, "name").map(|s| s.to_string());
|
kdl_get_string_property_or_child_value!(kdl_node, "name").map(|s| s.to_string());
|
||||||
|
let tab_cwd =
|
||||||
|
kdl_get_string_property_or_child_value!(kdl_node, "cwd").map(|c| PathBuf::from(c));
|
||||||
let is_focused = kdl_get_bool_property_or_child_value!(kdl_node, "focus").unwrap_or(false);
|
let is_focused = kdl_get_bool_property_or_child_value!(kdl_node, "focus").unwrap_or(false);
|
||||||
let children_split_direction = self.parse_split_direction(kdl_node)?;
|
let children_split_direction = self.parse_split_direction(kdl_node)?;
|
||||||
let children = match kdl_children_nodes!(kdl_node) {
|
let children = match kdl_children_nodes!(kdl_node) {
|
||||||
Some(children) => self.parse_child_pane_nodes_for_tab(children)?,
|
Some(children) => self.parse_child_pane_nodes_for_tab(children)?,
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
Ok((
|
let mut pane_layout = PaneLayout {
|
||||||
is_focused,
|
children_split_direction,
|
||||||
tab_name,
|
children,
|
||||||
PaneLayout {
|
..Default::default()
|
||||||
children_split_direction,
|
};
|
||||||
children,
|
if let Some(cwd_prefix) = &self.cwd_prefix(tab_cwd.as_ref())? {
|
||||||
..Default::default()
|
pane_layout.add_cwd_to_layout(&cwd_prefix);
|
||||||
},
|
}
|
||||||
))
|
Ok((is_focused, tab_name, pane_layout))
|
||||||
}
|
}
|
||||||
fn parse_child_pane_nodes_for_tab(
|
fn parse_child_pane_nodes_for_tab(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -700,6 +689,8 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
// (is_focused, Option<tab_name>, PaneLayout)
|
// (is_focused, Option<tab_name>, PaneLayout)
|
||||||
let tab_name =
|
let tab_name =
|
||||||
kdl_get_string_property_or_child_value!(kdl_node, "name").map(|s| s.to_string());
|
kdl_get_string_property_or_child_value!(kdl_node, "name").map(|s| s.to_string());
|
||||||
|
let tab_cwd =
|
||||||
|
kdl_get_string_property_or_child_value!(kdl_node, "cwd").map(|c| PathBuf::from(c));
|
||||||
let is_focused = kdl_get_bool_property_or_child_value!(kdl_node, "focus").unwrap_or(false);
|
let is_focused = kdl_get_bool_property_or_child_value!(kdl_node, "focus").unwrap_or(false);
|
||||||
let children_split_direction = self.parse_split_direction(kdl_node)?;
|
let children_split_direction = self.parse_split_direction(kdl_node)?;
|
||||||
match kdl_children_nodes!(kdl_node) {
|
match kdl_children_nodes!(kdl_node) {
|
||||||
|
|
@ -725,6 +716,9 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if let Some(cwd_prefix) = self.cwd_prefix(tab_cwd.as_ref())? {
|
||||||
|
tab_layout.add_cwd_to_layout(&cwd_prefix);
|
||||||
|
}
|
||||||
tab_layout.external_children_index = None;
|
tab_layout.external_children_index = None;
|
||||||
Ok((is_focused, tab_name, tab_layout))
|
Ok((is_focused, tab_name, tab_layout))
|
||||||
}
|
}
|
||||||
|
|
@ -1017,7 +1011,11 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
child.span().len(),
|
child.span().len(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
child_panes.push(self.parse_pane_node(child)?);
|
let mut pane_node = self.parse_pane_node(child)?;
|
||||||
|
if let Some(global_cwd) = &self.global_cwd {
|
||||||
|
pane_node.add_cwd_to_layout(&global_cwd);
|
||||||
|
}
|
||||||
|
child_panes.push(pane_node);
|
||||||
} else if child_name == "tab" {
|
} else if child_name == "tab" {
|
||||||
if !child_panes.is_empty() {
|
if !child_panes.is_empty() {
|
||||||
return Err(ConfigError::new_kdl_error(
|
return Err(ConfigError::new_kdl_error(
|
||||||
|
|
@ -1064,11 +1062,12 @@ impl<'a> KdlLayoutParser<'a> {
|
||||||
child.span().len(),
|
child.span().len(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
child_panes.push(self.parse_pane_node_with_template(
|
let mut pane_template =
|
||||||
child,
|
self.parse_pane_node_with_template(child, pane_template, &pane_template_kdl_node)?;
|
||||||
pane_template,
|
if let Some(cwd_prefix) = &self.cwd_prefix(None)? {
|
||||||
&pane_template_kdl_node,
|
pane_template.add_cwd_to_layout(&cwd_prefix);
|
||||||
)?);
|
}
|
||||||
|
child_panes.push(pane_template);
|
||||||
} else if !self.is_a_reserved_word(child_name) {
|
} else if !self.is_a_reserved_word(child_name) {
|
||||||
return Err(ConfigError::new_kdl_error(
|
return Err(ConfigError::new_kdl_error(
|
||||||
format!("Unknown layout node: '{}'", child_name),
|
format!("Unknown layout node: '{}'", child_name),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue