summaryrefslogtreecommitdiffstats
path: root/zellij-server
diff options
context:
space:
mode:
authorBrooks J Rady <b.j.rady@gmail.com>2021-06-03 13:05:52 +0100
committerBrooks J Rady <b.j.rady@gmail.com>2021-06-03 13:05:52 +0100
commita9ce13c1d2ff02981ccb552bf3da9355ec63273b (patch)
tree7dfd80d080d4cd56dea21306a9ea5d40ad7d3819 /zellij-server
parent5164bd99b7750122b36fd1fa54a90047e483067c (diff)
feat(ui): added feature for an experimental resize
The `parametric_resize_beta` feature has been added that enables the new resize system. This change also introduces some background tweaks that start laying the groundwork for future resize work without breaking functionality.
Diffstat (limited to 'zellij-server')
-rw-r--r--zellij-server/src/lib.rs2
-rw-r--r--zellij-server/src/tab.rs6
-rw-r--r--zellij-server/src/ui/mod.rs1
-rw-r--r--zellij-server/src/ui/pane_resizer.rs678
-rw-r--r--zellij-server/src/ui/pane_resizer_beta.rs248
5 files changed, 735 insertions, 200 deletions
diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs
index 4dff7838c..9b859d064 100644
--- a/zellij-server/src/lib.rs
+++ b/zellij-server/src/lib.rs
@@ -114,7 +114,7 @@ pub fn start_server(os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
.working_directory(std::env::current_dir().unwrap())
.umask(0o077)
// FIXME: My cherished `dbg!` was broken, so this is a hack to bring it back
- .stderr(std::fs::File::create("dbg.log").unwrap())
+ //.stderr(std::fs::File::create("dbg.log").unwrap())
.start()
.expect("could not daemonize the server process");
diff --git a/zellij-server/src/tab.rs b/zellij-server/src/tab.rs
index e90984ca4..f07e4a411 100644
--- a/zellij-server/src/tab.rs
+++ b/zellij-server/src/tab.rs
@@ -3,12 +3,16 @@
use zellij_utils::{serde, zellij_tile};
+#[cfg(not(feature = "parametric_resize_beta"))]
+use crate::ui::pane_resizer::PaneResizer;
+#[cfg(feature = "parametric_resize_beta")]
+use crate::ui::pane_resizer_beta::PaneResizer;
use crate::{
os_input_output::ServerOsApi,
panes::{PaneId, PluginPane, TerminalPane},
pty::{PtyInstruction, VteBytes},
thread_bus::ThreadSenders,
- ui::{boundaries::Boundaries, layout::Layout, pane_resizer::PaneResizer},
+ ui::{boundaries::Boundaries, layout::Layout},
wasm_vm::PluginInstruction,
ServerInstruction, SessionState,
};
diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs
index 1e4c85fd3..6d6a43753 100644
--- a/zellij-server/src/ui/mod.rs
+++ b/zellij-server/src/ui/mod.rs
@@ -1,3 +1,4 @@
pub mod boundaries;
pub mod layout;
pub mod pane_resizer;
+pub mod pane_resizer_beta;
diff --git a/zellij-server/src/ui/pane_resizer.rs b/zellij-server/src/ui/pane_resizer.rs
index ced0193ec..5ab065481 100644
--- a/zellij-server/src/ui/pane_resizer.rs
+++ b/zellij-server/src/ui/pane_resizer.rs
@@ -1,247 +1,529 @@
use crate::{os_input_output::ServerOsApi, panes::PaneId, tab::Pane};
-use cassowary::{
- strength::{REQUIRED, STRONG},
- Constraint, Solver, Variable,
- WeightedRelation::*,
-};
use std::{
+ cmp::Ordering,
collections::{BTreeMap, HashSet},
- ops::Not,
};
use zellij_utils::pane_size::PositionAndSize;
-const GAP_SIZE: usize = 1; // Panes are separated by this number of rows / columns
-
-pub struct PaneResizer<'a> {
+pub(crate) struct PaneResizer<'a> {
panes: &'a mut BTreeMap<PaneId, Box<dyn Pane>>,
- vars: BTreeMap<PaneId, (Variable, Variable)>,
- solver: Solver,
os_api: &'a mut Box<dyn ServerOsApi>,
}
-#[derive(Debug, Clone, Copy)]
-enum Direction {
- Horizontal,
- Vertical,
-}
-
-impl Not for Direction {
- type Output = Self;
-
- fn not(self) -> Self::Output {
- match self {
- Direction::Horizontal => Direction::Vertical,
- Direction::Vertical => Direction::Horizontal,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-struct Span {
- pid: PaneId,
- direction: Direction,
- fixed: bool,
- pos: usize,
- size: usize,
- pos_var: Variable,
- size_var: Variable,
-}
-
// TODO: currently there are some functions here duplicated with Tab
// all resizing functions should move here
-// FIXME:
-// 1. Rounding causes a loss of ratios, I need to store an internal f64 for
-// each pane as well as the displayed usize and add custom rounding logic.
-// 2. Vertical resizing doesn't seem to respect the space consumed by the tab
-// and status bars?
-// 3. A 2x2 layout and simultaneous vertical + horizontal resizing sometimes
-// leads to unsolvable constraints? Maybe related to 2 (and possibly 1).
-// I should sanity-check the `spans_in_boundary()` here!
-
impl<'a> PaneResizer<'a> {
pub fn new(
panes: &'a mut BTreeMap<PaneId, Box<dyn Pane>>,
os_api: &'a mut Box<dyn ServerOsApi>,
) -> Self {
- let mut vars = BTreeMap::new();
- for &k in panes.keys() {
- vars.insert(k, (Variable::new(), Variable::new()));
- }
- PaneResizer {
- panes,
- vars,
- solver: Solver::new(),
- os_api,
- }
+ PaneResizer { panes, os_api }
}
-
pub fn resize(
&mut self,
- current_size: PositionAndSize,
+ mut current_size: PositionAndSize,
new_size: PositionAndSize,
) -> Option<(isize, isize)> {
- let col_delta = new_size.cols as isize - current_size.cols as isize;
- let row_delta = new_size.rows as isize - current_size.rows as isize;
- if col_delta != 0 {
- let spans = self.solve_direction(Direction::Horizontal, new_size.cols)?;
- self.collapse_spans(&spans);
- }
- self.solver.reset();
- if row_delta != 0 {
- let spans = self.solve_direction(Direction::Vertical, new_size.rows)?;
- self.collapse_spans(&spans);
- }
- Some((col_delta, row_delta))
+ // (column_difference, row_difference)
+ let mut successfully_resized = false;
+ let mut column_difference: isize = 0;
+ let mut row_difference: isize = 0;
+ match new_size.cols.cmp(&current_size.cols) {
+ Ordering::Greater => {
+ let increase_by = new_size.cols - current_size.cols;
+ if let Some(panes_to_resize) = find_increasable_vertical_chain(
+ &self.panes,
+ increase_by,
+ current_size.cols,
+ current_size.rows,
+ ) {
+ self.increase_panes_right_and_push_adjacents_right(
+ panes_to_resize,
+ increase_by,
+ );
+ column_difference = new_size.cols as isize - current_size.cols as isize;
+ current_size.cols = (current_size.cols as isize + column_difference) as usize;
+ successfully_resized = true;
+ };
+ }
+ Ordering::Less => {
+ let reduce_by = current_size.cols - new_size.cols;
+ if let Some(panes_to_resize) = find_reducible_vertical_chain(
+ &self.panes,
+ reduce_by,
+ current_size.cols,
+ current_size.rows,
+ ) {
+ self.reduce_panes_left_and_pull_adjacents_left(panes_to_resize, reduce_by);
+ column_difference = new_size.cols as isize - current_size.cols as isize;
+ current_size.cols = (current_size.cols as isize + column_difference) as usize;
+ successfully_resized = true;
+ };
+ }
+ Ordering::Equal => (),
+ }
+ match new_size.rows.cmp(&current_size.rows) {
+ Ordering::Greater => {
+ let increase_by = new_size.rows - current_size.rows;
+ if let Some(panes_to_resize) = find_increasable_horizontal_chain(
+ &self.panes,
+ increase_by,
+ current_size.cols,
+ current_size.rows,
+ ) {
+ self.increase_panes_down_and_push_down_adjacents(panes_to_resize, increase_by);
+ row_difference = new_size.rows as isize - current_size.rows as isize;
+ current_size.rows = (current_size.rows as isize + row_difference) as usize;
+ successfully_resized = true;
+ };
+ }
+ Ordering::Less => {
+ let reduce_by = current_size.rows - new_size.rows;
+ if let Some(panes_to_resize) = find_reducible_horizontal_chain(
+ &self.panes,
+ reduce_by,
+ current_size.cols,
+ current_size.rows,
+ ) {
+ self.reduce_panes_up_and_pull_adjacents_up(panes_to_resize, reduce_by);
+ row_difference = new_size.rows as isize - current_size.rows as isize;
+ current_size.rows = (current_size.rows as isize + row_difference) as usize;
+ successfully_resized = true;
+ };
+ }
+ Ordering::Equal => (),
+ }
+ if successfully_resized {
+ Some((column_difference, row_difference))
+ } else {
+ None
+ }
}
-
- fn solve_direction(&mut self, direction: Direction, space: usize) -> Option<Vec<Span>> {
- let mut grid = Vec::new();
- for boundary in self.grid_boundaries(direction) {
- grid.push(self.spans_in_boundary(direction, boundary));
+ fn reduce_panes_left_and_pull_adjacents_left(
+ &mut self,
+ panes_to_reduce: Vec<PaneId>,
+ reduce_by: usize,
+ ) {
+ let mut pulled_panes: HashSet<PaneId> = HashSet::new();
+ for pane_id in panes_to_reduce {
+ let (pane_x, pane_y, pane_columns, pane_rows) = {
+ let pane = self.panes.get(&pane_id).unwrap();
+ (pane.x(), pane.y(), pane.columns(), pane.rows())
+ };
+ let panes_to_pull = self.panes.values_mut().filter(|p| {
+ p.x() > pane_x + pane_columns
+ && (p.y() <= pane_y && p.y() + p.rows() >= pane_y
+ || p.y() >= pane_y && p.y() + p.rows() <= pane_y + pane_rows)
+ });
+ for pane in panes_to_pull {
+ if !pulled_panes.contains(&pane.pid()) {
+ pane.pull_left(reduce_by);
+ pulled_panes.insert(pane.pid());
+ }
+ }
+ self.reduce_pane_width_left(&pane_id, reduce_by);
+ }
+ }
+ fn reduce_panes_up_and_pull_adjacents_up(
+ &mut self,
+ panes_to_reduce: Vec<PaneId>,
+ reduce_by: usize,
+ ) {
+ let mut pulled_panes: HashSet<PaneId> = HashSet::new();
+ for pane_id in panes_to_reduce {
+ let (pane_x, pane_y, pane_columns, pane_rows) = {
+ let pane = self.panes.get(&pane_id).unwrap();
+ (pane.x(), pane.y(), pane.columns(), pane.rows())
+ };
+ let panes_to_pull = self.panes.values_mut().filter(|p| {
+ p.y() > pane_y + pane_rows
+ && (p.x() <= pane_x && p.x() + p.columns() >= pane_x
+ || p.x() >= pane_x && p.x() + p.columns() <= pane_x + pane_columns)
+ });
+ for pane in panes_to_pull {
+ if !pulled_panes.contains(&pane.pid()) {
+ pane.pull_up(reduce_by);
+ pulled_panes.insert(pane.pid());
+ }
+ }
+ self.reduce_pane_height_up(&pane_id, reduce_by);
}
+ }
+ fn increase_panes_down_and_push_down_adjacents(
+ &mut self,
+ panes_to_increase: Vec<PaneId>,
+ increase_by: usize,
+ ) {
+ let mut pushed_panes: HashSet<PaneId> = HashSet::new();
+ for pane_id in panes_to_increase {
+ let (pane_x, pane_y, pane_columns, pane_rows) = {
+ let pane = self.panes.get(&pane_id).unwrap();
+ (pane.x(), pane.y(), pane.columns(), pane.rows())
+ };
+ let panes_to_push = self.panes.values_mut().filter(|p| {
+ p.y() > pane_y + pane_rows
+ && (p.x() <= pane_x && p.x() + p.columns() >= pane_x
+ || p.x() >= pane_x && p.x() + p.columns() <= pane_x + pane_columns)
+ });
+ for pane in panes_to_push {
+ if !pushed_panes.contains(&pane.pid()) {
+ pane.push_down(increase_by);
+ pushed_panes.insert(pane.pid());
+ }
+ }
+ self.increase_pane_height_down(&pane_id, increase_by);
+ }
+ }
+ fn increase_panes_right_and_push_adjacents_right(
+ &mut self,
+ panes_to_increase: Vec<PaneId>,
+ increase_by: usize,
+ ) {
+ let mut pushed_panes: HashSet<PaneId> = HashSet::new();
+ for pane_id in panes_to_increase {
+ let (pane_x, pane_y, pane_columns, pane_rows) = {
+ let pane = self.panes.get(&pane_id).unwrap();
+ (pane.x(), pane.y(), pane.columns(), pane.rows())
+ };
+ let panes_to_push = self.panes.values_mut().filter(|p| {
+ p.x() > pane_x + pane_columns
+ && (p.y() <= pane_y && p.y() + p.rows() >= pane_y
+ || p.y() >= pane_y && p.y() + p.rows() <= pane_y + pane_rows)
+ });
+ for pane in panes_to_push {
+ if !pushed_panes.contains(&pane.pid()) {
+ pane.push_right(increase_by);
+ pushed_panes.insert(pane.pid());
+ }
+ }
+ self.increase_pane_width_right(&pane_id, increase_by);
+ }
+ }
+ fn reduce_pane_height_up(&mut self, id: &PaneId, count: usize) {
+ let pane = self.panes.get_mut(id).unwrap();
+ pane.reduce_height_up(count);
+ if let PaneId::Terminal(pid) = id {
+ self.os_api
+ .set_terminal_size_using_fd(*pid, pane.columns() as u16, pane.rows() as u16);
+ }
+ }
+ fn increase_pane_height_down(&mut self, id: &PaneId, count: usize) {
+ let pane = self.panes.get_mut(id).unwrap();
+ pane.increase_height_down(count);
+ if let PaneId::Terminal(pid) = pane.pid() {
+ self.os_api
+ .set_terminal_size_using_fd(pid, pane.columns() as u16, pane.rows() as u16);
+ }
+ }
+ fn increase_pane_width_right(&mut self, id: &PaneId, count: usize) {
+ let pane = self.panes.get_mut(id).unwrap();
+ pane.increase_width_right(count);
+ if let PaneId::Terminal(pid) = pane.pid() {
+ self.os_api
+ .set_terminal_size_using_fd(pid, pane.columns() as u16, pane.rows() as u16);
+ }
+ }
+ fn reduce_pane_width_left(&mut self, id: &PaneId, count: usize) {
+ let pane = self.panes.get_mut(id).unwrap();
+ pane.reduce_width_left(count);
+ if let PaneId::Terminal(pid) = pane.pid() {
+ self.os_api
+ .set_terminal_size_using_fd(pid, pane.columns() as u16, pane.rows() as u16);
+ }
+ }
+}
- let constraints: Vec<_> = grid
- .iter()
- .flat_map(|s| constrain_spans(space, s))
- .collect();
+fn find_next_increasable_horizontal_pane(
+ panes: &BTreeMap<PaneId, Box<dyn Pane>>,
+ right_of: &dyn Pane,
+ increase_by: usize,
+) -> Option<PaneId> {
+ let next_pane_candidates = panes.values().filter(
+ |p| {
+ p.x() == right_of.x() + right_of.columns() + 1 && p.horizontally_overlaps_with(right_of)
+ }, // TODO: the name here is wrong, it should be vertically_overlaps_with
+ );
+ let resizable_candidates =
+ next_pane_candidates.filter(|p| p.can_increase_height_by(increase_by));
+ resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id {
+ Some(next_pane) => {
+ let next_pane = panes.get(&next_pane).unwrap();
+ if next_pane.y() < p.y() {
+ next_pane_id
+ } else {
+ Some(p.pid())
+ }
+ }
+ None => Some(p.pid()),
+ })
+}
- // FIXME: This line needs to be restored before merging!
- //self.solver.add_constraints(&constraints).ok()?;
- self.solver.add_constraints(&constraints).unwrap();
- Some(grid.into_iter().flatten().collect())
- }
+fn find_next_increasable_vertical_pane(
+ panes: &BTreeMap<PaneId, Box<dyn Pane>>,
+ below: &dyn Pane,
+ increase_by: usize,
+) -> Option<PaneId> {
+ let next_pane_candidates = panes.values().filter(
+ |p| p.y() == below.y() + below.rows() + 1 && p.vertically_overlaps_with(below), // TODO: the name here is wrong, it should be horizontally_overlaps_with
+ );
+ let resizable_candidates =
+ next_pane_candidates.filter(|p| p.can_increase_width_by(increase_by));
+ resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id {
+ Some(next_pane) => {
+ let next_pane = panes.get(&next_pane).unwrap();
+ if next_pane.x() < p.x() {
+ next_pane_id
+ } else {
+ Some(p.pid())
+ }
+ }
+ None => Some(p.pid()),
+ })
+}
- fn grid_boundaries(&self, direction: Direction) -> Vec<(usize, usize)> {
- // Select the spans running *perpendicular* to the direction of resize
- let spans: Vec<Span> = self
- .panes
- .values()
- .map(|p| self.get_span(!direction, p.as_ref()))
- .collect();
+fn find_next_reducible_vertical_pane(
+ panes: &BTreeMap<PaneId, Box<dyn Pane>>,
+ below: &dyn Pane,
+ reduce_by: usize,
+) -> Option<PaneId> {
+ let next_pane_candidates = panes.values().filter(
+ |p| p.y() == below.y() + below.rows() + 1 && p.vertically_overlaps_with(below), // TODO: the name here is wrong, it should be horizontally_overlaps_with
+ );
+ let resizable_candidates = next_pane_candidates.filter(|p| p.can_reduce_width_by(reduce_by));
+ resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id {
+ Some(next_pane) => {
+ let next_pane = panes.get(&next_pane).unwrap();
+ if next_pane.x() < p.x() {
+ next_pane_id
+ } else {
+ Some(p.pid())
+ }
+ }
+ None => Some(p.pid()),
+ })
+}
- let mut last_edge = 0;
- let mut bounds = Vec::new();
- loop {
- let mut spans_on_edge: Vec<&Span> =
- spans.iter().filter(|p| p.pos == last_edge).collect();
- spans_on_edge.sort_unstable_by_key(|s| s.size);
- if let Some(next) = spans_on_edge.first() {
- let next_edge = last_edge + next.size;
- bounds.push((last_edge, next_edge));
- last_edge = next_edge + GAP_SIZE;
+fn find_next_reducible_horizontal_pane(
+ panes: &BTreeMap<PaneId, Box<dyn Pane>>,
+ right_of: &dyn Pane,
+ reduce_by: usize,
+) -> Option<PaneId> {
+ let next_pane_candidates = panes.values().filter(
+ |p| {
+ p.x() == right_of.x() + right_of.columns() + 1 && p.horizontally_overlaps_with(right_of)
+ }, // TODO: the name here is wrong, it should be vertically_overlaps_with
+ );
+ let resizable_candidates = next_pane_candidates.filter(|p| p.can_reduce_height_by(reduce_by));
+ resizable_candidates.fold(None, |next_pane_id, p| match next_pane_id {
+ Some(next_pane) => {
+ let next_pane = panes.get(&next_pane).unwrap();
+ if next_pane.y() < p.y() {
+ next_pane_id
} else {
- break;
+ Some(p.pid())
}
}
- bounds
- }
+ None => Some(p.pid()),
+ })
+}
- fn spans_in_boundary(&self, direction: Direction, boundary: (usize, usize)) -> Vec<Span> {
- let (start, end) = boundary;
- let bwn = |v| start <= v && v < end;
- let mut spans: Vec<_> = self
- .panes
+fn find_increasable_horizontal_chain(
+ panes: &BTreeMap<PaneId, Box<dyn Pane>>,
+ increase_by: usize,
+ screen_width: usize,
+ screen_height: usize, // TODO: this is the previous size (make this clearer)
+) -> Option<Vec<PaneId>> {
+ let mut horizontal_coordinate = 0;
+ loop {
+ if horizontal_coordinate == screen_height {
+ return None;
+ }
+
+ match panes
.values()
- .filter(|p| {
- let s = self.get_span(!direction, p.as_ref());
- bwn(s.pos) || bwn(s.pos + s.size)
- })
- .map(|p| self.get_span(direction, p.as_ref()))
- .collect();
- spans.sort_unstable_by_key(|s| s.pos);
- spans
+ .find(|p| p.x() == 0 && p.y() == horizontal_coordinate)
+ {
+ Some(leftmost_pane) => {
+ if !leftmost_pane.can_increase_height_by(increase_by) {
+ horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows() + 1;
+ continue;
+ }
+ let mut panes_to_resize = vec![];
+ let mut current_pane = leftmost_pane;
+ loop {
+ panes_to_resize.push(current_pane.pid());
+ if current_pane.x() + current_pane.columns() == screen_width {
+ return Some(panes_to_resize);
+ }
+ match find_next_increasable_horizontal_pane(
+ panes,
+ current_pane.as_ref(),
+ increase_by,
+ ) {
+ Some(next_pane_id) => {
+ current_pane = panes.get(&next_pane_id).unwrap();
+ }
+ None => {
+ horizontal_coordinate = leftmost_pane.y() + leftmost_pane.rows() + 1;
+ break;
+ }
+ };
+ }
+ }
+ None => {
+ return None;
+ }
+ }
}
+}
- fn get_span(&self, direction: Direction, pane: &dyn Pane) -> Span {
- let pas = pane.position_and_size();
- let (pos_var, size_var) = self.vars[&pane.pid()];
- match direction {
- Direction::Horizontal => Span {
- pid: pane.pid(),
- direction,
- fixed: pas.cols_fixed,
- pos: pas.x,
- size: pas.cols,
- pos_var,
- size_var,
- },
- Direction::Vertical => Span {
- pid: pane.pid(),
- direction,
- fixed: pas.rows_fixed,
- pos: pas.y,
- size: pas.rows,
- pos_var,
- size_var,
- },
+fn find_increasable_vertical_chain(
+ panes: &BTreeMap<PaneId, Box<dyn Pane>>,
+ increase_by: usize,
+ screen_width: usize,
+ screen_height: usize, // TODO: this is the previous size (make this clearer)
+) -> Option<Vec<PaneId>> {
+ let mut vertical_coordinate = 0;
+ loop {
+ if vertical_coordinate == screen_width {
+ return None;
}
- }
- fn collapse_spans(&mut self, spans: &[Span]) {
- for span in spans {
- let solver = &self.solver; // Hand-holding the borrow-checker
- let pane = self.panes.get_mut(&span.pid).unwrap();
- let fetch_usize = |v| solver.get_value(v).round() as usize;
- match span.direction {
- Direction::Horizontal => pane.change_pos_and_size(&PositionAndSize {
- x: fetch_usize(span.pos_var),
- cols: fetch_usize(span.size_var),
- ..pane.position_and_size()
- }),
- Direction::Vertical => pane.change_pos_and_size(&PositionAndSize {
- y: fetch_usize(span.pos_var),
- rows: fetch_usize(span.size_var),
- ..pane.position_and_size()
- }),
- }
- if let PaneId::Terminal(pid) = pane.pid() {
- self.os_api.set_terminal_size_using_fd(
- pid,
- pane.columns() as u16,
- pane.rows() as u16,
- );
+ match panes
+ .values()
+ .find(|p| p.y() == 0 && p.x() == vertical_coordinate)
+ {
+ Some(topmost_pane) => {
+ if !topmost_pane.can_increase_width_by(increase_by) {
+ vertical_coordinate = topmost_pane.x() + topmost_pane.columns() + 1;
+ continue;
+ }
+ let mut panes_to_resize = vec![];
+ let mut current_pane = topmost_pane;
+ loop {
+ panes_to_resize.push(current_pane.pid());
+ if current_pane.y() + current_pane.rows() == screen_height {
+ return Some(panes_to_resize);
+ }
+ match find_next_increasable_vertical_pane(
+ panes,
+ current_pane.as_ref(),
+ increase_by,
+ ) {
+ Some(next_pane_id) => {
+ current_pane = panes.get(&next_pane_id).unwrap();
+ }
+ None => {
+ vertical_coordinate = topmost_pane.x() + topmost_pane.columns() + 1;
+ break;
+ }
+ };
+ }
+ }
+ None => {
+ return None;
}
}
}
}
-fn constrain_spans(space: usize, spans: &[Span]) -> HashSet<Constraint> {
- let mut constraints = HashSet::new();