Skip to content

Commit

Permalink
feat(layouts): exact panes constraint (zellij-org#2206)
Browse files Browse the repository at this point in the history
* style(fmt): remove warnings

* fix(swap-layouts): introduce exact panes constraint

* fix(swap-layouts): improve floating pane swap layout ux

* style(fmt): rustfmt
  • Loading branch information
imsnif authored and joshheyse committed Mar 11, 2023
1 parent 7c659e7 commit 9d21607
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 80 deletions.
2 changes: 1 addition & 1 deletion zellij-server/src/pty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ impl Pty {
TerminalAction::RunCommand(ref mut command) => {
command.cwd = Some(cwd);
},
TerminalAction::OpenFile(ref file, line_number, ref mut edit_cwd) => {
TerminalAction::OpenFile(ref _file, _line_number, ref mut edit_cwd) => {
match edit_cwd.as_mut() {
Some(edit_cwd) => {
*edit_cwd = cwd.join(&edit_cwd);
Expand Down
14 changes: 11 additions & 3 deletions zellij-server/src/tab/swap_layouts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ impl SwapLayouts {
let mut base_swap_floating_layout = BTreeMap::new();
let tiled_panes_count = layout.0.pane_count();
let floating_panes_count = layout.1.len();
// we set MaxPanes to the current panes in the layout, because the base layout is not
// we set ExactPanes to the current panes in the layout, because the base layout is not
// intended to be progressive - i.e. to have additional panes added to it
// we also don't want it to be applied for less than the expected amount of panes, because
// then unintended things can happen
// we still want to keep it around in case we'd like to swap layouts without adding panes
base_swap_tiled_layout.insert(LayoutConstraint::MaxPanes(tiled_panes_count), layout.0);
base_swap_tiled_layout.insert(LayoutConstraint::ExactPanes(tiled_panes_count), layout.0);
base_swap_floating_layout
.insert(LayoutConstraint::MaxPanes(floating_panes_count), layout.1);
.insert(LayoutConstraint::ExactPanes(floating_panes_count), layout.1);
self.swap_tiled_layouts
.insert(0, (base_swap_tiled_layout, Some("BASE".into())));
self.swap_floating_layouts
Expand Down Expand Up @@ -174,6 +176,9 @@ impl SwapLayouts {
LayoutConstraint::MinPanes(min_panes) => {
tiled_panes.visible_panes_count() >= *min_panes
},
LayoutConstraint::ExactPanes(pane_count) => {
tiled_panes.visible_panes_count() == *pane_count
},
LayoutConstraint::NoConstraint => true,
}
}
Expand All @@ -189,6 +194,9 @@ impl SwapLayouts {
LayoutConstraint::MinPanes(min_panes) => {
floating_panes.visible_panes_count() >= *min_panes
},
LayoutConstraint::ExactPanes(pane_count) => {
floating_panes.visible_panes_count() == *pane_count
},
LayoutConstraint::NoConstraint => true,
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
---
source: zellij-server/src/tab/./unit/tab_integration_tests.rs
assertion_line: 5333
assertion_line: 5700
expression: snapshot
---
00 (C): ┌ Pane #1 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
01 (C): │
02 (C): │
03 (C): │
04 (C): │
05 (C): │
06 (C): │
07 (C): │
08 (C): │
09 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
10 (C): Pane #2 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
11 (C): │
12 (C): │
13 (C): │
14 (C): │
15 (C): │
16 (C): │
17 (C): │
18 (C): │
19 (C): └───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
00 (C): ┌ Pane #1 ──────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐
01 (C): │ ││
02 (C): │ ││
03 (C): │ ││
04 (C): │ ││
05 (C): │ ││
06 (C): │ ││
07 (C): │ ││
08 (C): │ ││
09 (C): │ ││ │
10 (C): │ ││ │
11 (C): │ ││
12 (C): │ ││
13 (C): │ ││
14 (C): │ ││
15 (C): │ ││
16 (C): │ ││
17 (C): │ ││
18 (C): │ ││
19 (C): └───────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘

6 changes: 3 additions & 3 deletions zellij-server/src/tab/unit/tab_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5681,8 +5681,8 @@ fn when_closing_a_pane_in_auto_layout_the_focus_goes_to_last_focused_pane() {
)),
true,
);
tab.move_focus_down(client_id);
tab.move_focus_down(client_id);
let _ = tab.move_focus_down(client_id);
let _ = tab.move_focus_down(client_id);
tab.close_pane(PaneId::Terminal(3), false, Some(client_id));
tab.render(&mut output, None).unwrap();

Expand All @@ -5694,7 +5694,7 @@ fn when_closing_a_pane_in_auto_layout_the_focus_goes_to_last_focused_pane() {
);
assert_eq!(
cursor_coordinates,
Some((1, 11)),
Some((62, 1)),
"cursor coordinates moved to the new pane",
);
assert_snapshot!(snapshot);
Expand Down
24 changes: 15 additions & 9 deletions zellij-utils/assets/layouts/compact.swap.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ swap_floating_layout name="staggered" {

swap_floating_layout name="enlarged" {
floating_panes max_panes=10 {
pane { x 1; y 1; width "90%"; height "90%"; }
pane { x 2; y 2; width "90%"; height "90%"; }
pane { x 3; y 3; width "90%"; height "90%"; }
pane { x 4; y 4; width "90%"; height "90%"; }
pane { x 5; y 5; width "90%"; height "90%"; }
pane { x 6; y 6; width "90%"; height "90%"; }
pane { x 7; y 7; width "90%"; height "90%"; }
pane { x 8; y 8; width "90%"; height "90%"; }
pane { x 9; y 9; width "90%"; height "90%"; }
pane { x "5%"; y 1; width "90%"; height "90%"; }
pane { x "5%"; y 2; width "90%"; height "90%"; }
pane { x "5%"; y 3; width "90%"; height "90%"; }
pane { x "5%"; y 4; width "90%"; height "90%"; }
pane { x "5%"; y 5; width "90%"; height "90%"; }
pane { x "5%"; y 6; width "90%"; height "90%"; }
pane { x "5%"; y 7; width "90%"; height "90%"; }
pane { x "5%"; y 8; width "90%"; height "90%"; }
pane { x "5%"; y 9; width "90%"; height "90%"; }
pane focus=true { x 10; y 10; width "90%"; height "90%"; }
}
}
Expand All @@ -88,4 +88,10 @@ swap_floating_layout name="spread" {
pane { x "1%"; y "1%"; width "45%"; }
pane { x "50%"; y "1%"; width "45%"; }
}
floating_panes max_panes=4 {
pane { x "1%"; y "55%"; width "45%"; height "45%"; }
pane focus=true { x "50%"; y "55%"; width "45%"; height "45%"; }
pane { x "1%"; y "1%"; width "45%"; height "45%"; }
pane { x "50%"; y "1%"; width "45%"; height "45%"; }
}
}
24 changes: 15 additions & 9 deletions zellij-utils/assets/layouts/default.swap.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ swap_floating_layout name="staggered" {

swap_floating_layout name="enlarged" {
floating_panes max_panes=10 {
pane { x 1; y 1; width "90%"; height "90%"; }
pane { x 2; y 2; width "90%"; height "90%"; }
pane { x 3; y 3; width "90%"; height "90%"; }
pane { x 4; y 4; width "90%"; height "90%"; }
pane { x 5; y 5; width "90%"; height "90%"; }
pane { x 6; y 6; width "90%"; height "90%"; }
pane { x 7; y 7; width "90%"; height "90%"; }
pane { x 8; y 8; width "90%"; height "90%"; }
pane { x 9; y 9; width "90%"; height "90%"; }
pane { x "5%"; y 1; width "90%"; height "90%"; }
pane { x "5%"; y 2; width "90%"; height "90%"; }
pane { x "5%"; y 3; width "90%"; height "90%"; }
pane { x "5%"; y 4; width "90%"; height "90%"; }
pane { x "5%"; y 5; width "90%"; height "90%"; }
pane { x "5%"; y 6; width "90%"; height "90%"; }
pane { x "5%"; y 7; width "90%"; height "90%"; }
pane { x "5%"; y 8; width "90%"; height "90%"; }
pane { x "5%"; y 9; width "90%"; height "90%"; }
pane focus=true { x 10; y 10; width "90%"; height "90%"; }
}
}
Expand All @@ -91,4 +91,10 @@ swap_floating_layout name="spread" {
pane { x "1%"; y "1%"; width "45%"; }
pane { x "50%"; y "1%"; width "45%"; }
}
floating_panes max_panes=4 {
pane { x "1%"; y "55%"; width "45%"; height "45%"; }
pane focus=true { x "50%"; y "55%"; width "45%"; height "45%"; }
pane { x "1%"; y "1%"; width "45%"; height "45%"; }
pane { x "50%"; y "1%"; width "45%"; height "45%"; }
}
}
26 changes: 16 additions & 10 deletions zellij-utils/assets/layouts/strider.swap.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ swap_tiled_layout name="horizontal" {
swap_tiled_layout name="stacked" {
ui min_panes=6 {
pane split_direction="vertical" {
pane focus=true
pane
pane stacked=true { children; }
}
}
Expand All @@ -73,15 +73,15 @@ swap_floating_layout name="staggered" {

swap_floating_layout name="enlarged" {
floating_panes max_panes=10 {
pane { x 1; y 1; width "90%"; height "90%"; }
pane { x 2; y 2; width "90%"; height "90%"; }
pane { x 3; y 3; width "90%"; height "90%"; }
pane { x 4; y 4; width "90%"; height "90%"; }
pane { x 5; y 5; width "90%"; height "90%"; }
pane { x 6; y 6; width "90%"; height "90%"; }
pane { x 7; y 7; width "90%"; height "90%"; }
pane { x 8; y 8; width "90%"; height "90%"; }
pane { x 9; y 9; width "90%"; height "90%"; }
pane { x "5%"; y 1; width "90%"; height "90%"; }
pane { x "5%"; y 2; width "90%"; height "90%"; }
pane { x "5%"; y 3; width "90%"; height "90%"; }
pane { x "5%"; y 4; width "90%"; height "90%"; }
pane { x "5%"; y 5; width "90%"; height "90%"; }
pane { x "5%"; y 6; width "90%"; height "90%"; }
pane { x "5%"; y 7; width "90%"; height "90%"; }
pane { x "5%"; y 8; width "90%"; height "90%"; }
pane { x "5%"; y 9; width "90%"; height "90%"; }
pane focus=true { x 10; y 10; width "90%"; height "90%"; }
}
}
Expand All @@ -99,4 +99,10 @@ swap_floating_layout name="spread" {
pane { x "1%"; y "1%"; width "45%"; }
pane { x "50%"; y "1%"; width "45%"; }
}
floating_panes max_panes=4 {
pane { x "1%"; y "55%"; width "45%"; height "45%"; }
pane focus=true { x "50%"; y "55%"; width "45%"; height "45%"; }
pane { x "1%"; y "1%"; width "45%"; height "45%"; }
pane { x "50%"; y "1%"; width "45%"; height "45%"; }
}
}
1 change: 1 addition & 0 deletions zellij-utils/src/input/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ impl fmt::Display for RunPluginLocation {
pub enum LayoutConstraint {
MaxPanes(usize),
MinPanes(usize),
ExactPanes(usize),
NoConstraint,
}

Expand Down
49 changes: 43 additions & 6 deletions zellij-utils/src/kdl/kdl_layout_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ impl<'a> KdlLayoutParser<'a> {
|| property_name == "children"
|| property_name == "max_panes"
|| property_name == "min_panes"
|| property_name == "exact_panes"
}
fn assert_legal_node_name(&self, name: &str, kdl_node: &KdlNode) -> Result<(), ConfigError> {
if name.contains(char::is_whitespace) {
Expand Down Expand Up @@ -1747,6 +1748,12 @@ impl<'a> KdlLayoutParser<'a> {
tab_template_kdl_node,
)?;
swap_tiled_layout.insert(layout_constraint, layout);
} else {
return Err(ConfigError::new_layout_kdl_error(
format!("Unknown layout node: '{}'", layout_node_name),
layout.span().offset(),
layout.span().len(),
));
}
}
swap_tiled_layouts.push((swap_tiled_layout, swap_layout_name));
Expand Down Expand Up @@ -1787,6 +1794,12 @@ impl<'a> KdlLayoutParser<'a> {
tab_template_kdl_node,
)?;
swap_floating_layout.insert(layout_constraint, layout);
} else {
return Err(ConfigError::new_layout_kdl_error(
format!("Unknown layout node: '{}'", layout_node_name),
layout.span().offset(),
layout.span().len(),
));
}
}
swap_floating_layouts.push((swap_floating_layout, swap_layout_name));
Expand Down Expand Up @@ -1814,17 +1827,41 @@ impl<'a> KdlLayoutParser<'a> {
layout_node
));
};
if let Some(exact_panes) =
kdl_get_string_property_or_child_value!(layout_node, "exact_panes")
{
return Err(kdl_parsing_error!(
format!(
"exact_panes should be a fixed number (eg. 1) and not a quoted string (\"{}\")",
exact_panes,
),
layout_node
));
};
let max_panes = kdl_get_int_property_or_child_value!(layout_node, "max_panes");
let min_panes = kdl_get_int_property_or_child_value!(layout_node, "min_panes");
match (min_panes, max_panes) {
(Some(_min_panes), Some(_max_panes)) => Err(kdl_parsing_error!(
let exact_panes = kdl_get_int_property_or_child_value!(layout_node, "exact_panes");
let mut constraint_count = 0;
let mut constraint = None;
if let Some(max_panes) = max_panes {
constraint_count += 1;
constraint = Some(LayoutConstraint::MaxPanes(max_panes as usize));
}
if let Some(min_panes) = min_panes {
constraint_count += 1;
constraint = Some(LayoutConstraint::MinPanes(min_panes as usize));
}
if let Some(exact_panes) = exact_panes {
constraint_count += 1;
constraint = Some(LayoutConstraint::ExactPanes(exact_panes as usize));
}
if constraint_count > 1 {
return Err(kdl_parsing_error!(
format!("cannot have more than one constraint (eg. max_panes + min_panes)'"),
layout_node
)),
(Some(min_panes), None) => Ok(LayoutConstraint::MinPanes(min_panes as usize)),
(None, Some(max_panes)) => Ok(LayoutConstraint::MaxPanes(max_panes as usize)),
_ => Ok(LayoutConstraint::NoConstraint),
));
}
Ok(constraint.unwrap_or(LayoutConstraint::NoConstraint))
}
fn populate_one_swap_tiled_layout(
&self,
Expand Down
Loading

0 comments on commit 9d21607

Please sign in to comment.