fix(layout): various parser and ui fixes (#2191)
* fix(layout): error on nodes outside layout node * fix(layout): move stacked property to pane * fix(layout): various stack exceptions * fix(ui): non-flexible stacked pane titles now take up their full length * fix(ui): stack titles with no-pane-frames take up their proper length * style(fmt): rustfmt
This commit is contained in:
parent
d65e8220b6
commit
5bcc1bb382
11 changed files with 391 additions and 99 deletions
|
|
@ -358,13 +358,7 @@ impl Pane for TerminalPane {
|
|||
self.pane_name.clone()
|
||||
};
|
||||
|
||||
let mut frame_geom = self.current_geom();
|
||||
if !frame_params.should_draw_pane_frames {
|
||||
// in this case the width of the frame needs not include the pane corners
|
||||
frame_geom
|
||||
.cols
|
||||
.set_inner(frame_geom.cols.as_usize().saturating_sub(1));
|
||||
}
|
||||
let frame_geom = self.current_geom();
|
||||
let mut frame = PaneFrame::new(
|
||||
frame_geom.into(),
|
||||
self.grid.scrollback_position_and_length(),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
---
|
||||
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
|
||||
assertion_line: 3204
|
||||
assertion_line: 3249
|
||||
expression: snapshot
|
||||
---
|
||||
00 (C): ├─ Pane #2 ─────────────────────────────────────────────────
|
||||
01 (C): ├─ Pane #3 ─────────────────────────────────────────────────
|
||||
02 (C): ├─ Pane #4 ─────────────────────────────────────────────────
|
||||
00 (C): ├─ Pane #2 ──────────────────────────────────────────────────
|
||||
01 (C): ├─ Pane #3 ──────────────────────────────────────────────────
|
||||
02 (C): ├─ Pane #4 ──────────────────────────────────────────────────
|
||||
03 (C): │
|
||||
04 (C): │
|
||||
05 (C): │
|
||||
|
|
|
|||
|
|
@ -3163,7 +3163,7 @@ fn swap_tiled_layout_with_stacked_children() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3213,7 +3213,7 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3263,7 +3263,7 @@ fn move_focus_up_with_stacked_panes() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3315,7 +3315,7 @@ fn move_focus_down_with_stacked_panes() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3371,7 +3371,7 @@ fn move_focus_right_into_stacked_panes() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3431,7 +3431,7 @@ fn move_focus_left_into_stacked_panes() {
|
|||
swap_tiled_layout {
|
||||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
pane focus=true
|
||||
}
|
||||
}
|
||||
|
|
@ -3494,7 +3494,7 @@ fn move_focus_up_into_stacked_panes() {
|
|||
pane
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -3558,7 +3558,7 @@ fn move_focus_down_into_stacked_panes() {
|
|||
pane
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -3617,7 +3617,7 @@ fn close_main_stacked_pane() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3668,7 +3668,7 @@ fn close_main_stacked_pane_in_mid_stack() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3728,7 +3728,7 @@ fn close_one_liner_stacked_pane_below_main_pane() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3789,7 +3789,7 @@ fn close_one_liner_stacked_pane_above_main_pane() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3849,7 +3849,7 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3912,7 +3912,7 @@ fn can_increase_size_of_main_pane_in_stack_vertically() {
|
|||
pane
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -3976,7 +3976,7 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() {
|
|||
pane
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4044,7 +4044,7 @@ fn increasing_size_of_main_pane_in_stack_horizontally_does_not_break_stack() {
|
|||
pane focus=true
|
||||
pane
|
||||
}
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4125,7 +4125,7 @@ fn can_increase_size_into_pane_stack_horizontally() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4187,7 +4187,7 @@ fn can_increase_size_into_pane_stack_vertically() {
|
|||
pane
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4252,7 +4252,7 @@ fn can_increase_size_into_pane_stack_non_directionally() {
|
|||
pane
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4320,7 +4320,7 @@ fn increasing_size_into_main_pane_in_stack_horizontally_does_not_break_stack() {
|
|||
pane focus=true
|
||||
pane
|
||||
}
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4397,7 +4397,7 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4457,7 +4457,7 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4521,7 +4521,7 @@ fn cannot_decrease_stack_size_beyond_minimum_height() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4586,7 +4586,7 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4645,7 +4645,7 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4706,7 +4706,7 @@ fn close_stacked_pane_with_previously_focused_other_pane() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4774,7 +4774,7 @@ fn close_pane_near_stacked_panes() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4837,7 +4837,7 @@ fn focus_next_pane_expands_stacked_panes() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
@ -4897,7 +4897,7 @@ fn stacked_panes_can_become_fullscreen() {
|
|||
tab {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
pane
|
||||
}
|
||||
|
|
|
|||
|
|
@ -343,7 +343,9 @@ impl PaneFrame {
|
|||
self.render_my_and_others_focus(max_length)
|
||||
} else if !self.other_focused_clients.is_empty() {
|
||||
self.render_other_focused_users(max_length)
|
||||
} else if self.pane_is_stacked_under || self.pane_is_stacked_over {
|
||||
} else if (self.pane_is_stacked_under || self.pane_is_stacked_over)
|
||||
&& self.exit_status.is_some()
|
||||
{
|
||||
let (first_part, first_part_len) = self.first_exited_held_title_part_full();
|
||||
if first_part_len <= max_length {
|
||||
Some((first_part, first_part_len))
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ swap_tiled_layout name="stacked" {
|
|||
ui min_panes=4 {
|
||||
pane split_direction="vertical" {
|
||||
pane
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ swap_tiled_layout name="stacked" {
|
|||
ui min_panes=5 {
|
||||
pane split_direction="vertical" {
|
||||
pane
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ swap_tiled_layout name="stacked" {
|
|||
ui min_panes=6 {
|
||||
pane split_direction="vertical" {
|
||||
pane focus=true
|
||||
pane { children stacked=true; }
|
||||
pane stacked=true { children; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1849,3 +1849,96 @@ fn can_load_swap_layouts_from_a_different_file() {
|
|||
.unwrap();
|
||||
assert_snapshot!(format!("{:#?}", layout));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_define_stacked_children_for_pane_node() {
|
||||
let kdl_layout = r#"
|
||||
layout {
|
||||
pane stacked=true {
|
||||
pane
|
||||
pane
|
||||
}
|
||||
}
|
||||
"#;
|
||||
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None).unwrap();
|
||||
assert_snapshot!(format!("{:#?}", layout));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_define_stacked_children_for_pane_template() {
|
||||
let kdl_layout = r#"
|
||||
layout {
|
||||
pane_template name="stack" stacked=true {
|
||||
children
|
||||
}
|
||||
stack {
|
||||
pane
|
||||
pane
|
||||
}
|
||||
}
|
||||
"#;
|
||||
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None).unwrap();
|
||||
assert_snapshot!(format!("{:#?}", layout));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cannot_define_stacked_panes_for_bare_node() {
|
||||
let kdl_layout = r#"
|
||||
layout {
|
||||
pane stacked=true
|
||||
}
|
||||
"#;
|
||||
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None);
|
||||
assert!(layout.is_err(), "error provided for tab name with space");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cannot_define_stacked_panes_with_vertical_split_direction() {
|
||||
let kdl_layout = r#"
|
||||
layout {
|
||||
pane stacked=true split_direction="vertical" {
|
||||
pane
|
||||
pane
|
||||
}
|
||||
}
|
||||
"#;
|
||||
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None);
|
||||
assert!(layout.is_err(), "error provided for tab name with space");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cannot_define_stacked_panes_with_grandchildren() {
|
||||
let kdl_layout = r#"
|
||||
layout {
|
||||
pane stacked=true {
|
||||
pane {
|
||||
pane
|
||||
pane
|
||||
}
|
||||
pane
|
||||
}
|
||||
}
|
||||
"#;
|
||||
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None);
|
||||
assert!(layout.is_err(), "error provided for tab name with space");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cannot_define_stacked_panes_with_grandchildren_in_pane_template() {
|
||||
let kdl_layout = r#"
|
||||
layout {
|
||||
pane_template name="stack" stacked=true {
|
||||
children
|
||||
}
|
||||
stack {
|
||||
pane
|
||||
pane {
|
||||
pane
|
||||
pane
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None, None);
|
||||
assert!(layout.is_err(), "error provided for tab name with space");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||
assertion_line: 1870
|
||||
expression: "format!(\"{:#?}\", layout)"
|
||||
---
|
||||
Layout {
|
||||
tabs: [],
|
||||
focused_tab_index: None,
|
||||
template: Some(
|
||||
(
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: false,
|
||||
},
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: false,
|
||||
},
|
||||
],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: true,
|
||||
},
|
||||
],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: false,
|
||||
},
|
||||
[],
|
||||
),
|
||||
),
|
||||
swap_layouts: [],
|
||||
swap_tiled_layouts: [],
|
||||
swap_floating_layouts: [],
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
source: zellij-utils/src/input/./unit/layout_test.rs
|
||||
assertion_line: 1893
|
||||
expression: "format!(\"{:#?}\", layout)"
|
||||
---
|
||||
Layout {
|
||||
tabs: [],
|
||||
focused_tab_index: None,
|
||||
template: Some(
|
||||
(
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: false,
|
||||
},
|
||||
TiledPaneLayout {
|
||||
children_split_direction: Horizontal,
|
||||
name: None,
|
||||
children: [],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: false,
|
||||
},
|
||||
],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: true,
|
||||
},
|
||||
],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: true,
|
||||
},
|
||||
],
|
||||
split_size: None,
|
||||
run: None,
|
||||
borderless: false,
|
||||
focus: None,
|
||||
external_children_index: None,
|
||||
children_are_stacked: false,
|
||||
},
|
||||
[],
|
||||
),
|
||||
),
|
||||
swap_layouts: [],
|
||||
swap_tiled_layouts: [],
|
||||
swap_floating_layouts: [],
|
||||
}
|
||||
|
|
@ -53,6 +53,8 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
}
|
||||
}
|
||||
fn is_a_reserved_word(&self, word: &str) -> bool {
|
||||
// note that it's important that none of these words happens to also be a config property,
|
||||
// otherwise they might collide
|
||||
word == "pane"
|
||||
|| word == "layout"
|
||||
|| word == "pane_template"
|
||||
|
|
@ -90,6 +92,7 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
|| property_name == "split_direction"
|
||||
|| property_name == "pane"
|
||||
|| property_name == "children"
|
||||
|| property_name == "stacked"
|
||||
}
|
||||
fn is_a_valid_floating_pane_property(&self, property_name: &str) -> bool {
|
||||
property_name == "borderless"
|
||||
|
|
@ -166,6 +169,25 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
fn assert_no_grandchildren_in_stack(
|
||||
&self,
|
||||
children: &[KdlNode],
|
||||
is_part_of_stack: bool,
|
||||
) -> Result<(), ConfigError> {
|
||||
if is_part_of_stack {
|
||||
for child in children {
|
||||
if kdl_name!(child) == "pane" || self.pane_templates.get(kdl_name!(child)).is_some()
|
||||
{
|
||||
return Err(ConfigError::new_layout_kdl_error(
|
||||
format!("Stacked panes cannot have children"),
|
||||
child.span().offset(),
|
||||
child.span().len(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn parse_split_size(&self, kdl_node: &KdlNode) -> Result<Option<SplitSize>, ConfigError> {
|
||||
if let Some(size) = kdl_get_string_property_or_child_value!(kdl_node, "size") {
|
||||
match SplitSize::from_str(size) {
|
||||
|
|
@ -408,8 +430,14 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
}
|
||||
Ok(run)
|
||||
}
|
||||
fn parse_pane_node(&self, kdl_node: &KdlNode) -> Result<TiledPaneLayout, ConfigError> {
|
||||
fn parse_pane_node(
|
||||
&self,
|
||||
kdl_node: &KdlNode,
|
||||
is_part_of_stack: bool,
|
||||
) -> Result<TiledPaneLayout, ConfigError> {
|
||||
self.assert_valid_pane_properties(kdl_node)?;
|
||||
let children_are_stacked =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "stacked").unwrap_or(false);
|
||||
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 name = kdl_get_string_property_or_child_value_with_error!(kdl_node, "name")
|
||||
|
|
@ -417,11 +445,26 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
let split_size = self.parse_split_size(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_are_stacked, children) =
|
||||
match kdl_children_nodes!(kdl_node) {
|
||||
Some(children) => self.parse_child_pane_nodes_for_pane(&children)?,
|
||||
None => (None, false, vec![]),
|
||||
};
|
||||
let (external_children_index, children) = match kdl_children_nodes!(kdl_node) {
|
||||
Some(children) => {
|
||||
self.assert_no_grandchildren_in_stack(&children, is_part_of_stack)?;
|
||||
self.parse_child_pane_nodes_for_pane(&children, children_are_stacked)?
|
||||
},
|
||||
None => (None, vec![]),
|
||||
};
|
||||
if children_are_stacked && external_children_index.is_none() && children.is_empty() {
|
||||
return Err(ConfigError::new_layout_kdl_error(
|
||||
format!("A stacked pane must have children nodes or possibly a \"children\" node if in a swap_layout"),
|
||||
kdl_node.span().offset(),
|
||||
kdl_node.span().len(),
|
||||
));
|
||||
} else if children_are_stacked && children_split_direction == SplitDirection::Vertical {
|
||||
return Err(ConfigError::new_layout_kdl_error(
|
||||
format!("Stacked panes cannot be vertical"),
|
||||
kdl_node.span().offset(),
|
||||
kdl_node.span().len(),
|
||||
));
|
||||
}
|
||||
self.assert_no_mixed_children_and_properties(kdl_node)?;
|
||||
Ok(TiledPaneLayout {
|
||||
borderless: borderless.unwrap_or_default(),
|
||||
|
|
@ -467,12 +510,16 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
pane_template: &mut TiledPaneLayout,
|
||||
pane_template_kdl_node: &KdlNode,
|
||||
) -> Result<(), ConfigError> {
|
||||
let children_are_stacked =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "stacked")
|
||||
.unwrap_or(pane_template.children_are_stacked);
|
||||
let children_split_direction = self.parse_split_direction(kdl_node)?;
|
||||
let (external_children_index, children_are_stacked, pane_parts) =
|
||||
match kdl_children_nodes!(kdl_node) {
|
||||
Some(children) => self.parse_child_pane_nodes_for_pane(&children)?,
|
||||
None => (None, false, vec![]),
|
||||
};
|
||||
let (external_children_index, pane_parts) = match kdl_children_nodes!(kdl_node) {
|
||||
Some(children) => {
|
||||
self.parse_child_pane_nodes_for_pane(&children, children_are_stacked)?
|
||||
},
|
||||
None => (None, vec![]),
|
||||
};
|
||||
if pane_parts.len() > 0 {
|
||||
let child_panes_layout = TiledPaneLayout {
|
||||
children_split_direction,
|
||||
|
|
@ -493,20 +540,14 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
fn populate_external_children_index(
|
||||
&self,
|
||||
kdl_node: &KdlNode,
|
||||
) -> Result<Option<(usize, bool)>, ConfigError> {
|
||||
// Option<(external_children_index, is_stacked)>
|
||||
) -> Result<Option<usize>, ConfigError> {
|
||||
// Option<external_children_index>
|
||||
if let Some(pane_child_nodes) = kdl_children_nodes!(kdl_node) {
|
||||
for (i, child) in pane_child_nodes.iter().enumerate() {
|
||||
if kdl_name!(child) == "children" {
|
||||
let stacked =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "stacked")
|
||||
.unwrap_or(false);
|
||||
if let Some(grand_children) = kdl_children_nodes!(child) {
|
||||
let grand_children: Vec<&str> = grand_children
|
||||
.iter()
|
||||
.map(|g| kdl_name!(g))
|
||||
.filter(|g| g != &"stacked")
|
||||
.collect();
|
||||
let grand_children: Vec<&str> =
|
||||
grand_children.iter().map(|g| kdl_name!(g)).collect();
|
||||
if !grand_children.is_empty() {
|
||||
return Err(ConfigError::new_layout_kdl_error(
|
||||
format!(
|
||||
|
|
@ -518,7 +559,7 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
));
|
||||
}
|
||||
}
|
||||
return Ok(Some((i, stacked)));
|
||||
return Ok(Some(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -539,6 +580,8 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
let focus = kdl_get_bool_property_or_child_value_with_error!(kdl_node, "focus");
|
||||
let name = kdl_get_string_property_or_child_value_with_error!(kdl_node, "name")
|
||||
.map(|name| name.to_string());
|
||||
let children_are_stacked =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "stacked");
|
||||
let args = self.parse_args(kdl_node)?;
|
||||
let close_on_exit =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "close_on_exit");
|
||||
|
|
@ -547,10 +590,7 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
let split_size = self.parse_split_size(kdl_node)?;
|
||||
let run = self.parse_command_plugin_or_edit_block_for_template(kdl_node)?;
|
||||
|
||||
// TODO: change should_insert_children to should_keep_pane_external_children_index
|
||||
// or smth
|
||||
let external_children_index_and_is_stacked = if should_mark_external_children_index
|
||||
{
|
||||
let external_children_index = if should_mark_external_children_index {
|
||||
self.populate_external_children_index(kdl_node)?
|
||||
} else {
|
||||
None
|
||||
|
|
@ -589,15 +629,18 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
pane_template.split_size = Some(split_size);
|
||||
}
|
||||
if let Some(index_of_children) = pane_template.external_children_index {
|
||||
pane_template
|
||||
.children
|
||||
.insert(index_of_children, TiledPaneLayout::default());
|
||||
pane_template.children.insert(
|
||||
index_of_children,
|
||||
TiledPaneLayout {
|
||||
children_are_stacked: children_are_stacked.unwrap_or_default(),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
pane_template.external_children_index =
|
||||
external_children_index_and_is_stacked.map(|(index, _is_stacked)| index);
|
||||
pane_template.children_are_stacked = external_children_index_and_is_stacked
|
||||
.map(|(_index, is_stacked)| is_stacked)
|
||||
.unwrap_or(false);
|
||||
if let Some(children_are_stacked) = children_are_stacked {
|
||||
pane_template.children_are_stacked = children_are_stacked;
|
||||
}
|
||||
pane_template.external_children_index = external_children_index;
|
||||
Ok(pane_template)
|
||||
},
|
||||
PaneOrFloatingPane::FloatingPane(_) => {
|
||||
|
|
@ -758,6 +801,8 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
) -> Result<bool, ConfigError> {
|
||||
// pane properties
|
||||
let borderless = kdl_get_bool_property_or_child_value_with_error!(kdl_node, "borderless");
|
||||
let children_are_stacked =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "stacked");
|
||||
let split_size = self.parse_split_size(kdl_node)?;
|
||||
let split_direction =
|
||||
kdl_get_string_property_or_child_value_with_error!(kdl_node, "split_direction");
|
||||
|
|
@ -772,6 +817,7 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
let has_pane_properties = borderless.is_some()
|
||||
|| split_size.is_some()
|
||||
|| split_direction.is_some()
|
||||
|| children_are_stacked.is_some()
|
||||
|| has_children_nodes;
|
||||
let has_floating_pane_properties =
|
||||
height.is_some() || width.is_some() || x.is_some() || y.is_some();
|
||||
|
|
@ -789,6 +835,8 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
|
||||
// pane properties
|
||||
let borderless = kdl_get_bool_property_or_child_value_with_error!(kdl_node, "borderless");
|
||||
let children_are_stacked =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "stacked");
|
||||
let split_size = self.parse_split_size(kdl_node)?;
|
||||
let split_direction =
|
||||
kdl_get_string_property_or_child_value_with_error!(kdl_node, "split_direction");
|
||||
|
|
@ -803,6 +851,7 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
let has_pane_properties = borderless.is_some()
|
||||
|| split_size.is_some()
|
||||
|| split_direction.is_some()
|
||||
|| children_are_stacked.is_some()
|
||||
|| has_children_nodes;
|
||||
let has_floating_pane_properties =
|
||||
height.is_some() || width.is_some() || x.is_some() || y.is_some();
|
||||
|
|
@ -812,6 +861,9 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
if borderless.is_some() {
|
||||
pane_properties.push("borderless");
|
||||
}
|
||||
if children_are_stacked.is_some() {
|
||||
pane_properties.push("stacked");
|
||||
}
|
||||
if split_size.is_some() {
|
||||
pane_properties.push("split_size");
|
||||
}
|
||||
|
|
@ -905,13 +957,18 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
// pane properties
|
||||
let borderless =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "borderless");
|
||||
let children_are_stacked =
|
||||
kdl_get_bool_property_or_child_value_with_error!(kdl_node, "stacked")
|
||||
.unwrap_or(false);
|
||||
let split_size = self.parse_split_size(kdl_node)?;
|
||||
let children_split_direction = self.parse_split_direction(kdl_node)?;
|
||||
let (external_children_index, children_are_stacked, pane_parts) =
|
||||
match kdl_children_nodes!(kdl_node) {
|
||||
Some(children) => self.parse_child_pane_nodes_for_pane(&children)?,
|
||||
None => (None, false, vec![]),
|
||||
};
|
||||
let is_part_of_stack = false;
|
||||
let (external_children_index, pane_parts) = match kdl_children_nodes!(kdl_node) {
|
||||
Some(children) => {
|
||||
self.parse_child_pane_nodes_for_pane(&children, children_are_stacked)?
|
||||
},
|
||||
None => (None, vec![]),
|
||||
};
|
||||
self.assert_no_mixed_children_and_properties(kdl_node)?;
|
||||
self.pane_templates.insert(
|
||||
template_name,
|
||||
|
|
@ -983,9 +1040,10 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
child_floating_panes: &mut Vec<FloatingPaneLayout>,
|
||||
) -> Result<Vec<TiledPaneLayout>, ConfigError> {
|
||||
let mut nodes = vec![];
|
||||
let is_part_of_stack = false;
|
||||
for child in children {
|
||||
if kdl_name!(child) == "pane" {
|
||||
nodes.push(self.parse_pane_node(child)?);
|
||||
nodes.push(self.parse_pane_node(child, is_part_of_stack)?);
|
||||
} else if let Some((pane_template, pane_template_kdl_node)) =
|
||||
self.pane_templates.get(kdl_name!(child)).cloned()
|
||||
{
|
||||
|
|
@ -1019,23 +1077,18 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
fn parse_child_pane_nodes_for_pane(
|
||||
&self,
|
||||
children: &[KdlNode],
|
||||
) -> Result<(Option<usize>, bool, Vec<TiledPaneLayout>), ConfigError> {
|
||||
// usize is external_children_index, bool is "children_are_stacked"
|
||||
is_part_of_stack: bool,
|
||||
) -> Result<(Option<usize>, Vec<TiledPaneLayout>), ConfigError> {
|
||||
// usize is external_children_index
|
||||
let mut external_children_index = None;
|
||||
let mut children_are_stacked = false;
|
||||
let mut nodes = vec![];
|
||||
for (i, child) in children.iter().enumerate() {
|
||||
if kdl_name!(child) == "pane" {
|
||||
nodes.push(self.parse_pane_node(child)?);
|
||||
nodes.push(self.parse_pane_node(child, is_part_of_stack)?);
|
||||
} else if kdl_name!(child) == "children" {
|
||||
let stacked = kdl_get_bool_property_or_child_value_with_error!(child, "stacked")
|
||||
.unwrap_or(false);
|
||||
if let Some(grand_children) = kdl_children_nodes!(child) {
|
||||
let grand_children: Vec<&str> = grand_children
|
||||
.iter()
|
||||
.map(|g| kdl_name!(g))
|
||||
.filter(|g| g != &"stacked")
|
||||
.collect();
|
||||
let grand_children: Vec<&str> =
|
||||
grand_children.iter().map(|g| kdl_name!(g)).collect();
|
||||
if !grand_children.is_empty() {
|
||||
return Err(ConfigError::new_layout_kdl_error(
|
||||
format!(
|
||||
|
|
@ -1048,7 +1101,6 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
}
|
||||
}
|
||||
external_children_index = Some(i);
|
||||
children_are_stacked = stacked;
|
||||
} else if let Some((pane_template, pane_template_kdl_node)) =
|
||||
self.pane_templates.get(kdl_name!(child)).cloned()
|
||||
{
|
||||
|
|
@ -1067,7 +1119,7 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
));
|
||||
}
|
||||
}
|
||||
Ok((external_children_index, children_are_stacked, nodes))
|
||||
Ok((external_children_index, nodes))
|
||||
}
|
||||
fn has_child_nodes(&self, kdl_node: &KdlNode) -> bool {
|
||||
if let Some(children) = kdl_children_nodes!(kdl_node) {
|
||||
|
|
@ -1445,10 +1497,11 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
let mut tab_floating_children = vec![];
|
||||
let mut external_children_index = None;
|
||||
let mut children_index_offset = 0;
|
||||
let is_part_of_stack = false;
|
||||
if let Some(children) = kdl_children_nodes!(kdl_node) {
|
||||
for (i, child) in children.iter().enumerate() {
|
||||
if kdl_name!(child) == "pane" {
|
||||
tab_children.push(self.parse_pane_node(child)?);
|
||||
tab_children.push(self.parse_pane_node(child, is_part_of_stack)?);
|
||||
} else if kdl_name!(child) == "children" {
|
||||
let node_has_child_nodes =
|
||||
child.children().map(|c| !c.is_empty()).unwrap_or(false);
|
||||
|
|
@ -1925,7 +1978,8 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
));
|
||||
}
|
||||
if child_name == "pane" {
|
||||
let mut pane_node = self.parse_pane_node(child)?;
|
||||
let is_part_of_stack = false;
|
||||
let mut pane_node = self.parse_pane_node(child, is_part_of_stack)?;
|
||||
if let Some(global_cwd) = &self.global_cwd {
|
||||
pane_node.add_cwd_to_layout(&global_cwd);
|
||||
}
|
||||
|
|
@ -2109,6 +2163,17 @@ impl<'a> KdlLayoutParser<'a> {
|
|||
.filter(|n| kdl_name!(n) == "layout")
|
||||
.count()
|
||||
> 1;
|
||||
let mut non_layout_nodes_in_root = kdl_layout
|
||||
.nodes()
|
||||
.iter()
|
||||
.filter(|n| kdl_name!(n) != "layout" && self.is_a_reserved_word(kdl_name!(n)));
|
||||
if let Some(first_non_layout_node) = non_layout_nodes_in_root.next() {
|
||||
return Err(ConfigError::new_layout_kdl_error(
|
||||
"This node should be inside the main \"layout\" node".into(),
|
||||
first_non_layout_node.span().offset(),
|
||||
first_non_layout_node.span().len(),
|
||||
));
|
||||
}
|
||||
if has_multiple_layout_nodes {
|
||||
return Err(ConfigError::new_layout_kdl_error(
|
||||
"Only one layout node per file allowed".into(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue