Reimplement resize code (#1990)

* server/floating_panes: Start removing `unwrap`s

* server/panes: Remove more `unwrap`s

in floating panes code.

* utils/data: Unify `Direction` type

which was previously present in multiple locations.
Also start working on a new Resize Method (type `ResizeStrategy`), to
remove code duplication in the resize code.

* server: Implement new resize handling

with the `ResizeStrategy` type. Add a new action with the ability to
invoke it from the CLI. Take care to maintain backwards-compatibility in
terms of configuring the new resize mode.

* utils/layout: Add conversion for SplitDirection

from `data::Direction`.

* utils/data: Add impl for `Direction`

* server/panes: Rework tiled pane resizing

but it's currently still broken in a few regards and misses ability to
perform "regular" increase/decrease.

* server/panes/tiled_panes: Add debug assertion

to catch if the total area of all panes (in percent) is different from
100.0 at some point.

* server/panes/tiled/grid: Fix resize bug

caused by the fact that neighboring plugin panes previously weren't
filtered from resize operations, even though they cannot be resized at
all.

* utils/data: Add `invert` for `Resize`

* utils/data: Add member to `ResizeStrategy`

that controls whether we invert resize behavior when increasing size
towards a bounadry. This maintains current behavior.

* server/screen: Handle new attribute

in `ResizeStrategy`

* server/panes/resizer: Return `anyhow::Error`

* server/panes/tiled: Implement resize increase/decrease

without specifying a direction (towards all possible directions).
Currently broken in some cases.

* server/pane/tiled/grid: Don't return early

to preserve resize debug assertions.

* server/pane/tiled/grid: Fix resize bug

caused by checking for the wrong alignments in some cases. Also refactor
the code for looking up aligned panes.

* server/panes/tiled/grid: Cleanup code

and remove log statements and unused functions.

* server/panes/float/grid: Invert resize

if the floating pane is hitting a boundary already.

* plugins/status-bar: Add hints for new resize

* server: Use new resize method

* server: Fix tests

with new functions and result types.

* apply rustfmt

* utils: Apply rustfmt

* server/panes/floating: Fix resize increase

behavior which would previously, upon hitting a boundary, cause the pane
to invert the resize operation, which is wrong. Instead, it now does not
resize floating panes on an undirected resize "increase" in directions
where it hits boundaries.

* server/panes/tiled: Use correct resize increments

The values for the resize increments were previously wrong, causing many
of the tests to fail.

* server/panes/tiled: Fix resize checks

to correctly consider fixed-size panes.

* utils/assets/config: Update default config

with new keybindings for resize mode.

* server/panes/tiled: Fix resize check

* server/panes/tiled: Use shortener for `Direction`

type in `change_pane_size` function.

* server/panes/tiled: Restore resize behavior

for undirected resizes, to the way it was before this PR.

* server/panes/floating: Fix resize increment

for undirected resizes

* utils/data: Fix doctest

* utils: Fix test snapshots

for tests working with the default config

* changelog: Add PR #1990
This commit is contained in:
har7an 2022-12-08 12:50:28 +00:00 committed by GitHub
parent 420c7c319b
commit 62eaea1583
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 2215 additions and 2425 deletions

View file

@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* refactor(messaging): reduce extraneous cross-thread messaging (https://github.com/zellij-org/zellij/pull/1996)
* errors: preserve caller location in `to_log` (https://github.com/zellij-org/zellij/pull/1994)
* feat: show loading screen on startup (https://github.com/zellij-org/zellij/pull/1997)
* feat: Allow "reducing" resizes, refactor resizing code (https://github.com/zellij-org/zellij/pull/1990)
## [0.33.0] - 2022-11-10

View file

@ -367,6 +367,7 @@ pub fn action_key_group(keymap: &[(Key, Vec<Action>)], actions: &[&[Action]]) ->
/// separator between them:
///
/// - "hjkl"
/// - "HJKL"
/// - "←↓↑→"
/// - "←→"
/// - "↓↑"
@ -423,6 +424,7 @@ pub fn style_key_with_modifier(keyvec: &[Key], palette: &Palette) -> Vec<ANSIStr
// Special handling of some pre-defined keygroups
let key_string = key.join("");
let key_separator = match &key_string[..] {
"HJKL" => "",
"hjkl" => "",
"←↓↑→" => "",
"←→" => "",

View file

@ -109,8 +109,7 @@ fn full_shortcut_list_nonstandard_mode(help: &ModeInfo) -> LinePart {
fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<Key>)> {
use Action as A;
use InputMode as IM;
use actions::Direction as Dir;
use actions::ResizeDirection as RDir;
use Direction as Dir;
use actions::SearchDirection as SDir;
use actions::SearchOption as SOpt;
@ -188,11 +187,23 @@ fn get_keys_and_hints(mi: &ModeInfo) -> Vec<(String, String, Vec<Key>)> {
(s("Toggle"), s("Toggle"), action_key(&km, &[A::ToggleTab])),
(s("Select pane"), s("Select"), to_normal_key),
]} else if mi.mode == IM::Resize { vec![
(s("Resize"), s("Resize"), action_key_group(&km, &[
&[A::Resize(RDir::Left)], &[A::Resize(RDir::Down)],
&[A::Resize(RDir::Up)], &[A::Resize(RDir::Right)]])),
(s("Increase to"), s("Increase"), action_key_group(&km, &[
&[A::Resize(Resize::Increase, Some(Dir::Left))],
&[A::Resize(Resize::Increase, Some(Dir::Down))],
&[A::Resize(Resize::Increase, Some(Dir::Up))],
&[A::Resize(Resize::Increase, Some(Dir::Right))]
])),
(s("Decrease from"), s("Decrease"), action_key_group(&km, &[
&[A::Resize(Resize::Decrease, Some(Dir::Left))],
&[A::Resize(Resize::Decrease, Some(Dir::Down))],
&[A::Resize(Resize::Decrease, Some(Dir::Up))],
&[A::Resize(Resize::Decrease, Some(Dir::Right))]
])),
(s("Increase/Decrease size"), s("Increase/Decrease"),
action_key_group(&km, &[&[A::Resize(RDir::Increase)], &[A::Resize(RDir::Decrease)]])),
action_key_group(&km, &[
&[A::Resize(Resize::Increase, None)],
&[A::Resize(Resize::Decrease, None)]
])),
(s("Select pane"), s("Select"), to_normal_key),
]} else if mi.mode == IM::Move { vec![
(s("Move"), s("Move"), action_key_group(&km, &[
@ -666,13 +677,10 @@ mod tests {
keybinds: vec![(
InputMode::Pane,
vec![
(Key::Left, vec![Action::MoveFocus(actions::Direction::Left)]),
(Key::Down, vec![Action::MoveFocus(actions::Direction::Down)]),
(Key::Up, vec![Action::MoveFocus(actions::Direction::Up)]),
(
Key::Right,
vec![Action::MoveFocus(actions::Direction::Right)],
),
(Key::Left, vec![Action::MoveFocus(Direction::Left)]),
(Key::Down, vec![Action::MoveFocus(Direction::Down)]),
(Key::Up, vec![Action::MoveFocus(Direction::Up)]),
(Key::Right, vec![Action::MoveFocus(Direction::Right)]),
(Key::Char('n'), vec![Action::NewPane(None, None), TO_NORMAL]),
(Key::Char('x'), vec![Action::CloseFocus, TO_NORMAL]),
(
@ -701,13 +709,10 @@ mod tests {
keybinds: vec![(
InputMode::Pane,
vec![
(Key::Left, vec![Action::MoveFocus(actions::Direction::Left)]),
(Key::Down, vec![Action::MoveFocus(actions::Direction::Down)]),
(Key::Up, vec![Action::MoveFocus(actions::Direction::Up)]),
(
Key::Right,
vec![Action::MoveFocus(actions::Direction::Right)],
),
(Key::Left, vec![Action::MoveFocus(Direction::Left)]),
(Key::Down, vec![Action::MoveFocus(Direction::Down)]),
(Key::Up, vec![Action::MoveFocus(Direction::Up)]),
(Key::Right, vec![Action::MoveFocus(Direction::Right)]),
(Key::Char('n'), vec![Action::NewPane(None, None), TO_NORMAL]),
(Key::Char('x'), vec![Action::CloseFocus, TO_NORMAL]),
(
@ -732,22 +737,10 @@ mod tests {
keybinds: vec![(
InputMode::Pane,
vec![
(
Key::Ctrl('a'),
vec![Action::MoveFocus(actions::Direction::Left)],
),
(
Key::Ctrl('\n'),
vec![Action::MoveFocus(actions::Direction::Down)],
),
(
Key::Ctrl('1'),
vec![Action::MoveFocus(actions::Direction::Up)],
),
(
Key::Ctrl(' '),
vec![Action::MoveFocus(actions::Direction::Right)],
),
(Key::Ctrl('a'), vec![Action::MoveFocus(Direction::Left)]),
(Key::Ctrl('\n'), vec![Action::MoveFocus(Direction::Down)]),
(Key::Ctrl('1'), vec![Action::MoveFocus(Direction::Up)]),
(Key::Ctrl(' '), vec![Action::MoveFocus(Direction::Right)]),
(Key::Backspace, vec![Action::NewPane(None, None), TO_NORMAL]),
(Key::Esc, vec![Action::CloseFocus, TO_NORMAL]),
(Key::End, vec![Action::ToggleFocusFullscreen, TO_NORMAL]),

View file

@ -1,10 +1,7 @@
use ansi_term::{unstyled_len, ANSIString, ANSIStrings, Style};
use crate::{action_key_group, style_key_with_modifier, LinePart};
use zellij_tile::prelude::{
actions::{Action, Direction},
*,
};
use zellij_tile::prelude::{actions::Action, *};
macro_rules! strings {
($ANSIStrings:expr) => {{

View file

@ -1,10 +1,7 @@
use ansi_term::{unstyled_len, ANSIString, ANSIStrings, Style};
use crate::{action_key, action_key_group, style_key_with_modifier, LinePart};
use zellij_tile::prelude::{
actions::{Action, Direction, ResizeDirection},
*,
};
use zellij_tile::prelude::{actions::Action, *};
macro_rules! strings {
($ANSIStrings:expr) => {{
@ -75,8 +72,8 @@ fn add_keybinds(help: &ModeInfo) -> Keygroups {
let mut resize_keys = action_key_group(
&normal_keymap,
&[
&[Action::Resize(ResizeDirection::Increase)],
&[Action::Resize(ResizeDirection::Decrease)],
&[Action::Resize(Resize::Increase, None)],
&[Action::Resize(Resize::Decrease, None)],
],
);
if resize_keys.contains(&Key::Alt(CharOrArrow::Char('=')))

View file

@ -2,8 +2,8 @@ use super::input_loop;
use crate::stdin_ansi_parser::StdinAnsiParser;
use crate::stdin_loop;
use zellij_utils::anyhow::Result;
use zellij_utils::data::{InputMode, Palette};
use zellij_utils::input::actions::{Action, Direction};
use zellij_utils::data::{Direction, InputMode, Palette};
use zellij_utils::input::actions::Action;
use zellij_utils::input::config::Config;
use zellij_utils::input::options::Options;
use zellij_utils::nix;

View file

@ -2,18 +2,23 @@ use crate::tab::{MIN_TERMINAL_HEIGHT, MIN_TERMINAL_WIDTH};
use crate::{panes::PaneId, tab::Pane};
use std::cmp::Ordering;
use std::collections::HashMap;
use zellij_utils::data::ResizeStrategy;
use zellij_utils::errors::prelude::*;
use zellij_utils::pane_size::{Dimension, PaneGeom, Size, Viewport};
use std::cell::RefCell;
use std::rc::Rc;
const RESIZE_INCREMENT_WIDTH: usize = 5;
const RESIZE_INCREMENT_HEIGHT: usize = 2;
const MOVE_INCREMENT_HORIZONTAL: usize = 10;
const MOVE_INCREMENT_VERTICAL: usize = 5;
const MAX_PANES: usize = 100;
// For error reporting
fn no_pane_id(pane_id: &PaneId) -> String {
format!("no floating pane with ID {:?} found", pane_id)
}
pub struct FloatingPaneGrid<'a> {
panes: Rc<RefCell<HashMap<PaneId, &'a mut Box<dyn Pane>>>>,
desired_pane_positions: Rc<RefCell<&'a mut HashMap<PaneId, PaneGeom>>>,
@ -36,14 +41,17 @@ impl<'a> FloatingPaneGrid<'a> {
viewport,
}
}
pub fn move_pane_by(&mut self, pane_id: PaneId, x: isize, y: isize) {
pub fn move_pane_by(&mut self, pane_id: PaneId, x: isize, y: isize) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} by ({x}, {y})");
// true => succeeded to move, false => failed to move
let new_pane_position = {
let mut panes = self.panes.borrow_mut();
let pane = panes
.iter_mut()
.find(|(p_id, _p)| **p_id == pane_id)
.unwrap()
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?
.1;
let mut new_pane_position = pane.position_and_size();
let min_x = self.viewport.x as isize;
@ -60,20 +68,39 @@ impl<'a> FloatingPaneGrid<'a> {
new_pane_position.y = new_y as usize;
new_pane_position
};
self.set_pane_geom(pane_id, new_pane_position);
self.set_pane_geom(pane_id, new_pane_position)
.with_context(err_context)
}
fn set_pane_geom(&mut self, pane_id: PaneId, new_pane_geom: PaneGeom) {
fn set_pane_geom(&mut self, pane_id: PaneId, new_pane_geom: PaneGeom) -> Result<()> {
let err_context = || {
format!(
"failed to set pane {pane_id:?} geometry to {:?}",
new_pane_geom
)
};
let mut panes = self.panes.borrow_mut();
let pane = panes
.iter_mut()
.find(|(p_id, _p)| **p_id == pane_id)
.unwrap()
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?
.1;
pane.set_geom(new_pane_geom);
let mut desired_pane_positions = self.desired_pane_positions.borrow_mut();
desired_pane_positions.insert(pane_id, new_pane_geom);
Ok(())
}
pub fn resize(&mut self, space: Size) {
pub fn resize(&mut self, space: Size) -> Result<()> {
let err_context = || {
format!(
"failed to resize from {:?} to {:?}",
self.display_area, space
)
};
let mut panes = self.panes.borrow_mut();
let desired_pane_positions = self.desired_pane_positions.borrow();
@ -89,7 +116,15 @@ impl<'a> FloatingPaneGrid<'a> {
for (pane_id, pane) in panes.iter_mut() {
let mut new_pane_geom = pane.current_geom();
let desired_pane_geom = desired_pane_positions.get(pane_id).unwrap();
let desired_pane_geom = desired_pane_positions
.get(pane_id)
.with_context(|| {
format!(
"failed to acquire desired pane geometry for pane {:?}",
pane_id
)
})
.with_context(err_context)?;
let desired_pane_geom_is_inside_viewport =
pane_geom_is_inside_viewport(&new_viewport, desired_pane_geom);
let pane_is_in_desired_position = new_pane_geom == *desired_pane_geom;
@ -230,436 +265,340 @@ impl<'a> FloatingPaneGrid<'a> {
pane.set_geom(new_pane_geom);
}
}
Ok(())
}
pub fn move_pane_left(&mut self, pane_id: &PaneId) {
if let Some(move_by) = self.can_move_pane_left(pane_id, MOVE_INCREMENT_HORIZONTAL) {
self.move_pane_position_left(pane_id, move_by);
pub fn move_pane_left(&mut self, pane_id: &PaneId) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} left");
if let Some(move_by) = self
.can_move_pane_left(pane_id, MOVE_INCREMENT_HORIZONTAL)
.with_context(err_context)?
{
self.move_pane_position_left(pane_id, move_by)
.with_context(err_context)?;
}
Ok(())
}
pub fn move_pane_right(&mut self, pane_id: &PaneId) {
if let Some(move_by) = self.can_move_pane_right(pane_id, MOVE_INCREMENT_HORIZONTAL) {
self.move_pane_position_right(pane_id, move_by);
pub fn move_pane_right(&mut self, pane_id: &PaneId) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} right");
if let Some(move_by) = self
.can_move_pane_right(pane_id, MOVE_INCREMENT_HORIZONTAL)
.with_context(err_context)?
{
self.move_pane_position_right(pane_id, move_by)
.with_context(err_context)?;
}
Ok(())
}
pub fn move_pane_down(&mut self, pane_id: &PaneId) {
if let Some(move_by) = self.can_move_pane_down(pane_id, MOVE_INCREMENT_VERTICAL) {
self.move_pane_position_down(pane_id, move_by);
pub fn move_pane_down(&mut self, pane_id: &PaneId) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} down");
if let Some(move_by) = self
.can_move_pane_down(pane_id, MOVE_INCREMENT_VERTICAL)
.with_context(err_context)?
{
self.move_pane_position_down(pane_id, move_by)
.with_context(err_context)?;
}
Ok(())
}
pub fn move_pane_up(&mut self, pane_id: &PaneId) {
if let Some(move_by) = self.can_move_pane_up(pane_id, MOVE_INCREMENT_VERTICAL) {
self.move_pane_position_up(pane_id, move_by);
pub fn move_pane_up(&mut self, pane_id: &PaneId) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} up");
if let Some(move_by) = self
.can_move_pane_up(pane_id, MOVE_INCREMENT_VERTICAL)
.with_context(err_context)?
{
self.move_pane_position_up(pane_id, move_by)
.with_context(err_context)?;
}
Ok(())
}
fn can_move_pane_left(&self, pane_id: &PaneId, move_by: usize) -> Option<usize> {
fn can_move_pane_left(&self, pane_id: &PaneId, move_by: usize) -> Result<Option<usize>> {
let err_context = || {
format!(
"failed to determine if pane {pane_id:?} can be moved left by {move_by} columns"
)
};
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let pane = panes
.get(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let space_until_left_screen_edge = pane.x().saturating_sub(self.viewport.x);
if space_until_left_screen_edge >= move_by {
Ok(if space_until_left_screen_edge >= move_by {
Some(move_by)
} else if space_until_left_screen_edge > 0 {
Some(space_until_left_screen_edge)
} else {
None
})
}
}
fn can_move_pane_right(&self, pane_id: &PaneId, move_by: usize) -> Option<usize> {
fn can_move_pane_right(&self, pane_id: &PaneId, move_by: usize) -> Result<Option<usize>> {
let err_context = || {
format!(
"failed to determine if pane {pane_id:?} can be moved right by {move_by} columns"
)
};
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let pane = panes
.get(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let space_until_right_screen_edge =
(self.viewport.x + self.viewport.cols).saturating_sub(pane.x() + pane.cols());
if space_until_right_screen_edge >= move_by {
Ok(if space_until_right_screen_edge >= move_by {
Some(move_by)
} else if space_until_right_screen_edge > 0 {
Some(space_until_right_screen_edge)
} else {
None
})
}
}
fn can_move_pane_up(&self, pane_id: &PaneId, move_by: usize) -> Option<usize> {
fn can_move_pane_up(&self, pane_id: &PaneId, move_by: usize) -> Result<Option<usize>> {
let err_context =
|| format!("failed to determine if pane {pane_id:?} can be moved up by {move_by} rows");
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let pane = panes
.get(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let space_until_top_screen_edge = pane.y().saturating_sub(self.viewport.y);
if space_until_top_screen_edge >= move_by {
Ok(if space_until_top_screen_edge >= move_by {
Some(move_by)
} else if space_until_top_screen_edge > 0 {
Some(space_until_top_screen_edge)
} else {
None
})
}
}
fn can_move_pane_down(&self, pane_id: &PaneId, move_by: usize) -> Option<usize> {
fn can_move_pane_down(&self, pane_id: &PaneId, move_by: usize) -> Result<Option<usize>> {
let err_context = || {
format!("failed to determine if pane {pane_id:?} can be moved down by {move_by} rows")
};
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let pane = panes
.get(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let space_until_bottom_screen_edge =
(self.viewport.y + self.viewport.rows).saturating_sub(pane.y() + pane.rows());
if space_until_bottom_screen_edge >= move_by {
Ok(if space_until_bottom_screen_edge >= move_by {
Some(move_by)
} else if space_until_bottom_screen_edge > 0 {
Some(space_until_bottom_screen_edge)
} else {
None
})
}
}
fn move_pane_position_left(&mut self, pane_id: &PaneId, move_by: usize) {
fn move_pane_position_left(&mut self, pane_id: &PaneId, move_by: usize) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} left by {move_by}");
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(pane_id).unwrap();
let pane = panes
.get_mut(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let mut current_geom = pane.position_and_size();
current_geom.x -= move_by;
current_geom
};
self.set_pane_geom(*pane_id, new_pane_geom);
self.set_pane_geom(*pane_id, new_pane_geom)
.with_context(err_context)
}
fn move_pane_position_right(&mut self, pane_id: &PaneId, move_by: usize) {
fn move_pane_position_right(&mut self, pane_id: &PaneId, move_by: usize) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} right by {move_by}");
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(pane_id).unwrap();
let pane = panes
.get_mut(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let mut current_geom = pane.position_and_size();
current_geom.x += move_by;
current_geom
};
self.set_pane_geom(*pane_id, new_pane_geom);
self.set_pane_geom(*pane_id, new_pane_geom)
.with_context(err_context)
}
fn move_pane_position_down(&mut self, pane_id: &PaneId, move_by: usize) {
fn move_pane_position_down(&mut self, pane_id: &PaneId, move_by: usize) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} down by {move_by}");
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(pane_id).unwrap();
let pane = panes
.get_mut(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let mut current_geom = pane.position_and_size();
current_geom.y += move_by;
current_geom
};
self.set_pane_geom(*pane_id, new_pane_geom);
self.set_pane_geom(*pane_id, new_pane_geom)
.with_context(err_context)
}
fn move_pane_position_up(&mut self, pane_id: &PaneId, move_by: usize) {
fn move_pane_position_up(&mut self, pane_id: &PaneId, move_by: usize) -> Result<()> {
let err_context = || format!("failed to move pane {pane_id:?} up by {move_by}");
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(pane_id).unwrap();
let pane = panes
.get_mut(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?;
let mut current_geom = pane.position_and_size();
current_geom.y -= move_by;
current_geom
};
self.set_pane_geom(*pane_id, new_pane_geom);
self.set_pane_geom(*pane_id, new_pane_geom)
.with_context(err_context)
}
pub fn resize_pane_left(&'a mut self, pane_id: &PaneId) {
if let Some(increase_by) = self.can_increase_pane_size_left(pane_id, RESIZE_INCREMENT_WIDTH)
{
self.increase_pane_size_left(pane_id, increase_by);
} else if let Some(decrease_by) =
self.can_decrease_pane_size_left(pane_id, RESIZE_INCREMENT_WIDTH)
{
self.decrease_pane_size_left(pane_id, decrease_by);
}
}
pub fn resize_pane_right(&mut self, pane_id: &PaneId) {
if let Some(increase_by) =
self.can_increase_pane_size_right(pane_id, RESIZE_INCREMENT_WIDTH)
{
self.increase_pane_size_right(pane_id, increase_by);
} else if let Some(decrease_by) =
self.can_decrease_pane_size_right(pane_id, RESIZE_INCREMENT_WIDTH)
{
self.decrease_pane_size_right(pane_id, decrease_by);
}
}
pub fn resize_pane_down(&mut self, pane_id: &PaneId) {
if let Some(increase_by) =
self.can_increase_pane_size_down(pane_id, RESIZE_INCREMENT_HEIGHT)
{
self.increase_pane_size_down(pane_id, increase_by);
} else if let Some(decrease_by) =
self.can_decrease_pane_size_down(pane_id, RESIZE_INCREMENT_HEIGHT)
{
self.decrease_pane_size_down(pane_id, decrease_by);
}
}
pub fn resize_pane_up(&mut self, pane_id: &PaneId) {
if let Some(increase_by) = self.can_increase_pane_size_up(pane_id, RESIZE_INCREMENT_HEIGHT)
{
self.increase_pane_size_up(pane_id, increase_by);
} else if let Some(decrease_by) =
self.can_decrease_pane_size_up(pane_id, RESIZE_INCREMENT_HEIGHT)
{
self.decrease_pane_size_up(pane_id, decrease_by);
}
}
pub fn resize_increase(&mut self, pane_id: &PaneId) {
if let Some(increase_by) =
self.can_increase_pane_size_left(pane_id, RESIZE_INCREMENT_WIDTH / 2)
{
self.increase_pane_size_left(pane_id, increase_by);
}
if let Some(increase_by) =
self.can_increase_pane_size_right(pane_id, RESIZE_INCREMENT_WIDTH / 2)
{
self.increase_pane_size_right(pane_id, increase_by);
}
if let Some(increase_by) =
self.can_increase_pane_size_down(pane_id, RESIZE_INCREMENT_HEIGHT / 2)
{
self.increase_pane_size_down(pane_id, increase_by);
}
if let Some(increase_by) =
self.can_increase_pane_size_up(pane_id, RESIZE_INCREMENT_HEIGHT / 2)
{
self.increase_pane_size_up(pane_id, increase_by);
}
}
pub fn resize_decrease(&mut self, pane_id: &PaneId) {
if let Some(decrease_by) =
self.can_decrease_pane_size_left(pane_id, RESIZE_INCREMENT_WIDTH / 2)
{
self.decrease_pane_size_left(pane_id, decrease_by);
}
if let Some(decrease_by) =
self.can_decrease_pane_size_right(pane_id, RESIZE_INCREMENT_WIDTH / 2)
{
self.decrease_pane_size_right(pane_id, decrease_by);
}
if let Some(decrease_by) =
self.can_decrease_pane_size_down(pane_id, RESIZE_INCREMENT_HEIGHT / 2)
{
self.decrease_pane_size_down(pane_id, decrease_by);
}
if let Some(decrease_by) =
self.can_decrease_pane_size_up(pane_id, RESIZE_INCREMENT_HEIGHT / 2)
{
self.decrease_pane_size_up(pane_id, decrease_by);
}
}
fn can_increase_pane_size_left(
&self,
pub fn change_pane_size(
&mut self,
pane_id: &PaneId,
max_increase_by: usize,
) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let distance_to_left_edge = pane.x().saturating_sub(self.viewport.x);
if distance_to_left_edge.saturating_sub(max_increase_by) > 0 {
Some(max_increase_by)
} else if distance_to_left_edge > 0 {
Some(distance_to_left_edge)
strategy: &ResizeStrategy,
change_by: (usize, usize), // (x, y)
) -> Result<()> {
let err_context = || format!("failed to {strategy} for pane {pane_id:?}");
let mut geometry = self
.panes
.borrow()
.get(pane_id)
.with_context(|| no_pane_id(&pane_id))
.with_context(err_context)?
.position_and_size();
let change_by = if strategy.direction.is_none() {
(change_by.0 / 2, change_by.1 / 2)
} else {
None
change_by
};
// Move left border
if strategy.move_left_border_left() || strategy.move_all_borders_out() {
let increment = std::cmp::min(geometry.x.saturating_sub(self.viewport.x), change_by.0);
// Invert if on boundary already
if increment == 0 && strategy.direction.is_some() {
return self.change_pane_size(pane_id, &strategy.invert(), change_by);
}
}
fn can_decrease_pane_size_left(
&self,
pane_id: &PaneId,
max_decrease_by: usize,
) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let space_left_to_decrease = pane.cols().saturating_sub(MIN_TERMINAL_WIDTH);
if space_left_to_decrease.saturating_sub(max_decrease_by) > 0 {
Some(max_decrease_by)
} else if space_left_to_decrease > 0 {
Some(space_left_to_decrease)
} else {
None
}
}
fn can_increase_pane_size_right(
&self,
pane_id: &PaneId,
max_increase_by: usize,
) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let distance_to_right_edge =
(self.viewport.x + self.viewport.cols).saturating_sub(pane.x() + pane.cols());
if pane.x() + pane.cols() + max_increase_by < self.viewport.cols {
Some(max_increase_by)
} else if distance_to_right_edge > 0 {
Some(distance_to_right_edge)
} else {
None
}
}
fn can_decrease_pane_size_right(
&self,
pane_id: &PaneId,
max_decrease_by: usize,
) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let space_left_to_decrease = pane.cols().saturating_sub(MIN_TERMINAL_WIDTH);
let pane_right_edge = pane.x() + pane.cols();
if space_left_to_decrease.saturating_sub(max_decrease_by) > 0
&& pane.x() + max_decrease_by <= pane_right_edge + MIN_TERMINAL_WIDTH
{
Some(max_decrease_by)
} else if space_left_to_decrease > 0
&& pane.x() + max_decrease_by <= pane_right_edge + MIN_TERMINAL_WIDTH
{
Some(space_left_to_decrease)
} else {
None
}
}
fn can_increase_pane_size_down(
&self,
pane_id: &PaneId,
max_increase_by: usize,
) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let distance_to_bottom_edge =
(self.viewport.y + self.viewport.rows).saturating_sub(pane.y() + pane.rows());
if pane.y() + pane.rows() + max_increase_by < self.viewport.rows {
Some(max_increase_by)
} else if distance_to_bottom_edge > 0 {
Some(distance_to_bottom_edge)
} else {
None
}
}
fn can_decrease_pane_size_down(
&self,
pane_id: &PaneId,
max_decrease_by: usize,
) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let space_left_to_decrease = pane.rows().saturating_sub(MIN_TERMINAL_HEIGHT);
let pane_bottom_edge = pane.y() + pane.rows();
if space_left_to_decrease.saturating_sub(max_decrease_by) > 0
&& pane.y() + max_decrease_by <= pane_bottom_edge + MIN_TERMINAL_HEIGHT
{
Some(max_decrease_by)
} else if space_left_to_decrease > 0
&& pane.y() + max_decrease_by <= pane_bottom_edge + MIN_TERMINAL_HEIGHT
{
Some(space_left_to_decrease)
} else {
None
}
}
fn can_increase_pane_size_up(&self, pane_id: &PaneId, max_increase_by: usize) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let distance_to_top_edge = pane.y().saturating_sub(self.viewport.y);
if distance_to_top_edge.saturating_sub(max_increase_by) > 0 {
Some(max_increase_by)
} else if distance_to_top_edge > 0 {
Some(distance_to_top_edge)
} else {
None
}
}
fn can_decrease_pane_size_up(&self, pane_id: &PaneId, max_decrease_by: usize) -> Option<usize> {
let panes = self.panes.borrow();
let pane = panes.get(pane_id).unwrap();
let space_left_to_decrease = pane.rows().saturating_sub(MIN_TERMINAL_HEIGHT);
if space_left_to_decrease.saturating_sub(max_decrease_by) > 0 {
Some(max_decrease_by)
} else if space_left_to_decrease > 0 {
Some(space_left_to_decrease)
} else {
None
}
}
fn increase_pane_size_left(&mut self, id: &PaneId, increase_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom.x -= increase_by;
current_geom
geometry.x -= increment;
geometry
.cols
.set_inner(current_geom.cols.as_usize() + increase_by);
current_geom
};
self.set_pane_geom(*id, new_pane_geom);
}
fn decrease_pane_size_left(&mut self, id: &PaneId, decrease_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom
.set_inner(geometry.cols.as_usize() + increment);
} else if strategy.move_left_border_right() || strategy.move_all_borders_in() {
let increment = std::cmp::min(
geometry.cols.as_usize().saturating_sub(MIN_TERMINAL_WIDTH),
change_by.0,
);
geometry.x += increment;
geometry
.cols
.set_inner(current_geom.cols.as_usize() - decrease_by);
current_geom
.set_inner(geometry.cols.as_usize() - increment);
};
self.set_pane_geom(*id, new_pane_geom);
// Move right border
if strategy.move_right_border_right() || strategy.move_all_borders_out() {
let increment = std::cmp::min(
(self.viewport.x + self.viewport.cols)
.saturating_sub(geometry.x + geometry.cols.as_usize()),
change_by.0,
);
// Invert if on boundary already
if increment == 0 && strategy.direction.is_some() {
return self.change_pane_size(pane_id, &strategy.invert(), change_by);
}
fn increase_pane_size_right(&mut self, id: &PaneId, increase_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom
geometry
.cols
.set_inner(current_geom.cols.as_usize() + increase_by);
current_geom
};
self.set_pane_geom(*id, new_pane_geom);
}
fn decrease_pane_size_right(&mut self, id: &PaneId, decrease_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom.x += decrease_by;
current_geom
.set_inner(geometry.cols.as_usize() + increment);
} else if strategy.move_right_border_left() || strategy.move_all_borders_in() {
let increment = std::cmp::min(
geometry.cols.as_usize().saturating_sub(MIN_TERMINAL_WIDTH),
change_by.0,
);
geometry
.cols
.set_inner(current_geom.cols.as_usize() - decrease_by);
current_geom
.set_inner(geometry.cols.as_usize() - increment);
};
self.set_pane_geom(*id, new_pane_geom);
// Move upper border
if strategy.move_upper_border_up() || strategy.move_all_borders_out() {
let increment = std::cmp::min(geometry.y.saturating_sub(self.viewport.y), change_by.1);
// Invert if on boundary already
if increment == 0 && strategy.direction.is_some() {
return self.change_pane_size(pane_id, &strategy.invert(), change_by);
}
fn increase_pane_size_down(&mut self, id: &PaneId, increase_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom
geometry.y -= increment;
geometry
.rows
.set_inner(current_geom.rows.as_usize() + increase_by);
current_geom
};
self.set_pane_geom(*id, new_pane_geom);
}
fn decrease_pane_size_down(&mut self, id: &PaneId, decrease_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom.y += decrease_by;
current_geom
.set_inner(geometry.rows.as_usize() + increment);
} else if strategy.move_upper_border_down() || strategy.move_all_borders_in() {
let increment = std::cmp::min(
geometry.rows.as_usize().saturating_sub(MIN_TERMINAL_HEIGHT),
change_by.1,
);
geometry.y += increment;
geometry
.rows
.set_inner(current_geom.rows.as_usize() - decrease_by);
current_geom
};
self.set_pane_geom(*id, new_pane_geom);
.set_inner(geometry.rows.as_usize() - increment);
}
fn increase_pane_size_up(&mut self, id: &PaneId, increase_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom.y -= increase_by;
current_geom
// Move lower border
if strategy.move_lower_border_down() || strategy.move_all_borders_out() {
let increment = std::cmp::min(
(self.viewport.y + self.viewport.rows)
.saturating_sub(geometry.y + geometry.rows.as_usize()),
change_by.1,
);
// Invert if on boundary already
if increment == 0 && strategy.direction.is_some() {
return self.change_pane_size(pane_id, &strategy.invert(), change_by);
}
geometry
.rows
.set_inner(current_geom.rows.as_usize() + increase_by);
pane.set_geom(current_geom);
current_geom
};
self.set_pane_geom(*id, new_pane_geom);
}
fn decrease_pane_size_up(&mut self, id: &PaneId, decrease_by: usize) {
let new_pane_geom = {
let mut panes = self.panes.borrow_mut();
let pane = panes.get_mut(id).unwrap();
let mut current_geom = pane.position_and_size();
current_geom
.set_inner(geometry.rows.as_usize() + increment);
} else if strategy.move_lower_border_up() || strategy.move_all_borders_in() {
let increment = std::cmp::min(
geometry.rows.as_usize().saturating_sub(MIN_TERMINAL_HEIGHT),
change_by.1,
);
geometry
.rows
.set_inner(current_geom.rows.as_usize() - decrease_by);
current_geom
};
self.set_pane_geom(*id, new_pane_geom);
.set_inner(geometry.rows.as_usize() - increment);
}
self.set_pane_geom(*pane_id, geometry)
.with_context(err_context)
}
pub fn next_selectable_pane_id_to_the_left(&self, current_pane_id: &PaneId) -> Option<PaneId> {
let panes = self.panes.borrow();
let current_pane = panes.get(current_pane_id)?;

View file

@ -1,5 +1,8 @@
mod floating_pane_grid;
use zellij_utils::position::Position;
use zellij_utils::{
data::{Direction, ResizeStrategy},
position::Position,
};
use crate::resize_pty;
use crate::tab::Pane;
@ -25,6 +28,9 @@ use zellij_utils::{
pane_size::{Offset, PaneGeom, Size, Viewport},
};
const RESIZE_INCREMENT_WIDTH: usize = 5;
const RESIZE_INCREMENT_HEIGHT: usize = 2;
pub struct FloatingPanes {
panes: BTreeMap<PaneId, Box<dyn Pane>>,
display_area: Rc<RefCell<Size>>,
@ -101,20 +107,28 @@ impl FloatingPanes {
&mut self,
pane: Box<dyn Pane>,
client_id: ClientId,
) -> Option<Box<dyn Pane>> {
) -> Result<Box<dyn Pane>> {
self.active_panes
.get(&client_id)
.with_context(|| format!("failed to determine active pane for client {client_id}"))
.copied()
.and_then(|active_pane_id| self.replace_pane(active_pane_id, pane))
.with_context(|| format!("failed to replace active pane for client {client_id}"))
}
pub fn replace_pane(
&mut self,
pane_id: PaneId,
mut with_pane: Box<dyn Pane>,
) -> Option<Box<dyn Pane>> {
) -> Result<Box<dyn Pane>> {
let err_context = || format!("failed to replace pane {pane_id:?} with pane");
let with_pane_id = with_pane.pid();
with_pane.set_content_offset(Offset::frame(1));
let removed_pane = self.panes.remove(&pane_id).map(|removed_pane| {
let removed_pane = self
.panes
.remove(&pane_id)
.with_context(|| format!("failed to remove unknown pane with ID {pane_id:?}"))
.and_then(|removed_pane| {
let removed_pane_id = removed_pane.pid();
let with_pane_id = with_pane.pid();
let removed_pane_geom = removed_pane.current_geom();
@ -124,10 +138,11 @@ impl FloatingPanes {
.z_indices
.iter()
.position(|pane_id| pane_id == &removed_pane_id)
.unwrap();
.context("no z-index found for pane to be removed with ID {removed_pane_id:?}")
.with_context(err_context)?;
self.z_indices.remove(z_index);
self.z_indices.insert(z_index, with_pane_id);
removed_pane
Ok(removed_pane)
});
// update the desired_pane_positions to relate to the new pane
@ -222,7 +237,10 @@ impl FloatingPanes {
pane.render_full_viewport();
}
}
pub fn set_pane_frames(&mut self, os_api: &mut Box<dyn ServerOsApi>) {
pub fn set_pane_frames(&mut self, os_api: &mut Box<dyn ServerOsApi>) -> Result<()> {
let err_context =
|pane_id: &PaneId| format!("failed to activate frame on pane {pane_id:?}");
for pane in self.panes.values_mut() {
// floating panes should always have a frame unless explicitly set otherwise
if !pane.borderless() {
@ -231,8 +249,9 @@ impl FloatingPanes {
} else {
pane.set_content_offset(Offset::default());
}
resize_pty!(pane, os_api, self.senders).unwrap();
resize_pty!(pane, os_api, self.senders).with_context(|| err_context(&pane.pid()))?;
}
Ok(())
}
pub fn render(&mut self, output: &mut Output) -> Result<()> {
let err_context = || "failed to render output";
@ -297,6 +316,7 @@ impl FloatingPanes {
}
Ok(())
}
pub fn resize(&mut self, new_screen_size: Size) {
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
@ -306,20 +326,28 @@ impl FloatingPanes {
display_area,
viewport,
);
floating_pane_grid.resize(new_screen_size);
floating_pane_grid.resize(new_screen_size).unwrap();
self.set_force_render();
}
pub fn resize_pty_all_panes(&mut self, os_api: &mut Box<dyn ServerOsApi>) {
pub fn resize_pty_all_panes(&mut self, os_api: &mut Box<dyn ServerOsApi>) -> Result<()> {
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).unwrap();
resize_pty!(pane, os_api, self.senders)
.with_context(|| format!("failed to resize PTY in pane {:?}", pane.pid()))?;
}
Ok(())
}
pub fn resize_active_pane_left(
pub fn resize_active_pane(
&mut self,
client_id: ClientId,
os_api: &mut Box<dyn ServerOsApi>,
) -> bool {
strategy: &ResizeStrategy,
) -> Result<bool> {
// true => successfully resized
let err_context =
|| format!("failed to {strategy} for active floating pane for client {client_id}");
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
if let Some(active_floating_pane_id) = self.active_panes.get(&client_id) {
@ -329,146 +357,40 @@ impl FloatingPanes {
display_area,
viewport,
);
floating_pane_grid.resize_pane_left(active_floating_pane_id);
floating_pane_grid
.change_pane_size(
active_floating_pane_id,
strategy,
(RESIZE_INCREMENT_WIDTH, RESIZE_INCREMENT_HEIGHT),
)
.with_context(err_context)?;
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).unwrap();
resize_pty!(pane, os_api, self.senders).with_context(err_context)?;
}
self.set_force_render();
return true;
return Ok(true);
}
false
}
pub fn resize_active_pane_right(
&mut self,
client_id: ClientId,
os_api: &mut Box<dyn ServerOsApi>,
) -> bool {
// true => successfully resized
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
if let Some(active_floating_pane_id) = self.active_panes.get(&client_id) {
let mut floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
floating_pane_grid.resize_pane_right(active_floating_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).unwrap();
}
self.set_force_render();
return true;
}
false
}
pub fn resize_active_pane_down(
&mut self,
client_id: ClientId,
os_api: &mut Box<dyn ServerOsApi>,
) -> bool {
// true => successfully resized
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
if let Some(active_floating_pane_id) = self.active_panes.get(&client_id) {
let mut floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
floating_pane_grid.resize_pane_down(active_floating_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).unwrap();
}
self.set_force_render();
return true;
}
false
}
pub fn resize_active_pane_up(
&mut self,
client_id: ClientId,
os_api: &mut Box<dyn ServerOsApi>,
) -> bool {
// true => successfully resized
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
if let Some(active_floating_pane_id) = self.active_panes.get(&client_id) {
let mut floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
floating_pane_grid.resize_pane_up(active_floating_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).unwrap();
}
self.set_force_render();
return true;
}
false
}
pub fn resize_active_pane_increase(
&mut self,
client_id: ClientId,
os_api: &mut Box<dyn ServerOsApi>,
) -> bool {
// true => successfully resized
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
if let Some(active_floating_pane_id) = self.active_panes.get(&client_id) {
let mut floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
floating_pane_grid.resize_increase(active_floating_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).unwrap();
}
self.set_force_render();
return true;
}
false
}
pub fn resize_active_pane_decrease(
&mut self,
client_id: ClientId,
os_api: &mut Box<dyn ServerOsApi>,
) -> bool {
// true => successfully resized
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
if let Some(active_floating_pane_id) = self.active_panes.get(&client_id) {
let mut floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
floating_pane_grid.resize_decrease(active_floating_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, os_api, self.senders).unwrap();
}
self.set_force_render();
return true;
}
false
Ok(false)
}
fn set_pane_active_at(&mut self, pane_id: PaneId) {
if let Some(pane) = self.panes.get_mut(&pane_id) {
pane.set_active_at(Instant::now());
}
}
pub fn move_focus_left(
pub fn move_focus(
&mut self,
client_id: ClientId,
connected_clients: &HashSet<ClientId>,
) -> bool {
direction: &Direction,
) -> Result<bool> {
// true => successfully moved
let _err_context = || {
format!("failed to move focus of floating pane {direction:?} for client {client_id}")
};
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
let active_pane_id = self.active_panes.get(&client_id).copied();
@ -479,8 +401,18 @@ impl FloatingPanes {
display_area,
viewport,
);
let next_index =
floating_pane_grid.next_selectable_pane_id_to_the_left(&active_pane_id);
let next_index = match direction {
Direction::Left => {
floating_pane_grid.next_selectable_pane_id_to_the_left(&active_pane_id)
},
Direction::Down => {
floating_pane_grid.next_selectable_pane_id_below(&active_pane_id)
},
Direction::Up => floating_pane_grid.next_selectable_pane_id_above(&active_pane_id),
Direction::Right => {
floating_pane_grid.next_selectable_pane_id_to_the_right(&active_pane_id)
},
};
match next_index {
Some(p) => {
// render previously active pane so that its frame does not remain actively
@ -510,7 +442,7 @@ impl FloatingPanes {
self.set_pane_active_at(p);
self.set_force_render();
return true;
return Ok(true);
},
None => Some(active_pane_id),
}
@ -532,219 +464,9 @@ impl FloatingPanes {
self.z_indices.clear();
},
}
false
}
pub fn move_focus_right(
&mut self,
client_id: ClientId,
connected_clients: &HashSet<ClientId>,
) -> bool {
// true => successfully moved
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
let active_pane_id = self.active_panes.get(&client_id).copied();
let updated_active_pane = if let Some(active_pane_id) = active_pane_id {
let floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
let next_index =
floating_pane_grid.next_selectable_pane_id_to_the_right(&active_pane_id);
match next_index {
Some(p) => {
// render previously active pane so that its frame does not remain actively
// colored
let previously_active_pane = self
.panes
.get_mut(self.active_panes.get(&client_id).unwrap())
.unwrap();
previously_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
previously_active_pane.render_full_viewport();
let next_active_pane = self.panes.get_mut(&p).unwrap();
next_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
next_active_pane.render_full_viewport();
// move all clients
let connected_clients: Vec<ClientId> =
connected_clients.iter().copied().collect();
for client_id in connected_clients {
self.focus_pane(p, client_id);
Ok(false)
}
self.set_pane_active_at(p);
self.set_force_render();
return true;
},
None => Some(active_pane_id),
}
} else {
active_pane_id
};
match updated_active_pane {
Some(updated_active_pane) => {
let connected_clients: Vec<ClientId> = connected_clients.iter().copied().collect();
for client_id in connected_clients {
self.focus_pane(updated_active_pane, client_id);
}
self.set_pane_active_at(updated_active_pane);
self.set_force_render();
},
None => {
// TODO: can this happen?
self.active_panes.clear(&mut self.panes);
self.z_indices.clear();
},
}
false
}
pub fn move_focus_up(
&mut self,
client_id: ClientId,
connected_clients: &HashSet<ClientId>,
) -> bool {
// true => successfully moved
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
let active_pane_id = self.active_panes.get(&client_id).copied();
let updated_active_pane = if let Some(active_pane_id) = active_pane_id {
let floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
let next_index = floating_pane_grid.next_selectable_pane_id_above(&active_pane_id);
match next_index {
Some(p) => {
// render previously active pane so that its frame does not remain actively
// colored
let previously_active_pane = self
.panes
.get_mut(self.active_panes.get(&client_id).unwrap())
.unwrap();
previously_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
previously_active_pane.render_full_viewport();
let next_active_pane = self.panes.get_mut(&p).unwrap();
next_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
next_active_pane.render_full_viewport();
// move all clients
let connected_clients: Vec<ClientId> =
connected_clients.iter().copied().collect();
for client_id in connected_clients {
self.focus_pane(p, client_id);
}
self.set_force_render();
self.set_pane_active_at(p);
return true;
},
None => Some(active_pane_id),
}
} else {
active_pane_id
};
match updated_active_pane {
Some(updated_active_pane) => {
let connected_clients: Vec<ClientId> = connected_clients.iter().copied().collect();
for client_id in connected_clients {
self.focus_pane(updated_active_pane, client_id);
}
self.set_pane_active_at(updated_active_pane);
self.set_force_render();
},
None => {
// TODO: can this happen?
self.active_panes.clear(&mut self.panes);
self.z_indices.clear();
},
}
false
}
pub fn move_focus_down(
&mut self,
client_id: ClientId,
connected_clients: &HashSet<ClientId>,
) -> bool {
// true => successfully moved
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
let active_pane_id = self.active_panes.get(&client_id).copied();
let updated_active_pane = if let Some(active_pane_id) = active_pane_id {
let floating_pane_grid = FloatingPaneGrid::new(
&mut self.panes,
&mut self.desired_pane_positions,
display_area,
viewport,
);
let next_index = floating_pane_grid.next_selectable_pane_id_below(&active_pane_id);
match next_index {
Some(p) => {
// render previously active pane so that its frame does not remain actively
// colored
let previously_active_pane = self
.panes
.get_mut(self.active_panes.get(&client_id).unwrap())
.unwrap();
previously_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
previously_active_pane.render_full_viewport();
let next_active_pane = self.panes.get_mut(&p).unwrap();
next_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
next_active_pane.render_full_viewport();
// move all clients
let connected_clients: Vec<ClientId> =
connected_clients.iter().copied().collect();
for client_id in connected_clients {
self.focus_pane(p, client_id);
}
self.set_pane_active_at(p);
self.set_force_render();
return true;
},
None => Some(active_pane_id),
}
} else {
active_pane_id
};
match updated_active_pane {
Some(updated_active_pane) => {
let connected_clients: Vec<ClientId> = connected_clients.iter().copied().collect();
for client_id in connected_clients {
self.focus_pane(updated_active_pane, client_id);
}
self.set_pane_active_at(updated_active_pane);
self.set_force_render();
},
None => {
// TODO: can this happen?
self.active_panes.clear(&mut self.panes);
self.z_indices.clear();
},
}
false
}
pub fn move_active_pane_down(&mut self, client_id: ClientId) {
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
@ -755,7 +477,7 @@ impl FloatingPanes {
display_area,
viewport,
);
floating_pane_grid.move_pane_down(active_pane_id);
floating_pane_grid.move_pane_down(active_pane_id).unwrap();
self.set_force_render();
}
}
@ -769,7 +491,7 @@ impl FloatingPanes {
display_area,
viewport,
);
floating_pane_grid.move_pane_up(active_pane_id);
floating_pane_grid.move_pane_up(active_pane_id).unwrap();
self.set_force_render();
}
}
@ -783,7 +505,7 @@ impl FloatingPanes {
display_area,
viewport,
);
floating_pane_grid.move_pane_left(active_pane_id);
floating_pane_grid.move_pane_left(active_pane_id).unwrap();
self.set_force_render();
}
}
@ -797,7 +519,7 @@ impl FloatingPanes {
display_area,
viewport,
);
floating_pane_grid.move_pane_right(active_pane_id);
floating_pane_grid.move_pane_right(active_pane_id).unwrap();
self.set_force_render();
}
}
@ -869,36 +591,30 @@ impl FloatingPanes {
pub fn get_pane_mut(&mut self, pane_id: PaneId) -> Option<&mut Box<dyn Pane>> {
self.panes.get_mut(&pane_id)
}
pub fn get_pane_id_at(&self, point: &Position, search_selectable: bool) -> Option<PaneId> {
if search_selectable {
pub fn get_pane_id_at(
&self,
point: &Position,
search_selectable: bool,
) -> Result<Option<PaneId>> {
let _err_context = || format!("failed to determine floating pane at point {point:?}");
// TODO: better - loop through z-indices and check each one if it contains the point
let mut selectable_panes: Vec<_> =
self.panes.iter().filter(|(_, p)| p.selectable()).collect();
selectable_panes.sort_by(|(a_id, _a_pane), (b_id, _b_pane)| {
self.z_indices
.iter()
.position(|id| id == *b_id)
.unwrap()
.cmp(&self.z_indices.iter().position(|id| id == *a_id).unwrap())
});
selectable_panes
.iter()
.find(|(_, p)| p.contains(point))
.map(|(&id, _)| id)
let mut panes: Vec<_> = if search_selectable {
self.panes.iter().filter(|(_, p)| p.selectable()).collect()
} else {
let mut panes: Vec<_> = self.panes.iter().collect();
self.panes.iter().collect()
};
panes.sort_by(|(a_id, _a_pane), (b_id, _b_pane)| {
self.z_indices
.iter()
.position(|id| id == *b_id)
.unwrap()
.cmp(&self.z_indices.iter().position(|id| id == *a_id).unwrap())
// TODO: continue
Ord::cmp(
&self.z_indices.iter().position(|id| id == *b_id).unwrap(),
&self.z_indices.iter().position(|id| id == *a_id).unwrap(),
)
});
panes
Ok(panes
.iter()
.find(|(_, p)| p.contains(point))
.map(|(&id, _)| id)
}
.map(|(&id, _)| id))
}
pub fn get_pane_at_mut(
&mut self,
@ -906,6 +622,7 @@ impl FloatingPanes {
search_selectable: bool,
) -> Option<&mut Box<dyn Pane>> {
self.get_pane_id_at(position, search_selectable)
.unwrap()
.and_then(|pane_id| self.panes.get_mut(&pane_id))
}
pub fn set_pane_being_moved_with_mouse(&mut self, pane_id: PaneId, position: Position) {
@ -930,7 +647,9 @@ impl FloatingPanes {
display_area,
viewport,
);
floating_pane_grid.move_pane_by(pane_id, move_x_by, move_y_by);
floating_pane_grid
.move_pane_by(pane_id, move_x_by, move_y_by)
.unwrap();
self.set_pane_being_moved_with_mouse(pane_id, *click_position);
self.set_force_render();
true

View file

@ -2,7 +2,7 @@ mod pane_resizer;
mod tiled_pane_grid;
use crate::resize_pty;
use tiled_pane_grid::{split, TiledPaneGrid};
use tiled_pane_grid::{split, TiledPaneGrid, RESIZE_PERCENT};
use crate::{
os_input_output::ServerOsApi,
@ -16,7 +16,7 @@ use crate::{
ClientId,
};
use zellij_utils::{
data::{ModeInfo, Style},
data::{ModeInfo, ResizeStrategy, Style},
errors::prelude::*,
input::{command::RunCommand, layout::SplitDirection},
pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport},
@ -521,7 +521,15 @@ impl TiledPanes {
}
self.set_pane_frames(self.draw_pane_frames);
}
pub fn resize_active_pane_left(&mut self, client_id: ClientId) {
pub fn resize_active_pane(
&mut self,
client_id: ClientId,
strategy: &ResizeStrategy,
) -> Result<()> {
let err_context =
|| format!("failed to {strategy} for active tiled pane for client {client_id}");
if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
let mut pane_grid = TiledPaneGrid::new(
&mut self.panes,
@ -529,88 +537,20 @@ impl TiledPanes {
*self.display_area.borrow(),
*self.viewport.borrow(),
);
pane_grid.resize_pane_left(&active_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, self.os_api, self.senders).unwrap();
}
self.reset_boundaries();
}
}
pub fn resize_active_pane_right(&mut self, client_id: ClientId) {
if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
let mut pane_grid = TiledPaneGrid::new(
&mut self.panes,
&self.panes_to_hide,
*self.display_area.borrow(),
*self.viewport.borrow(),
);
pane_grid.resize_pane_right(&active_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, self.os_api, self.senders).unwrap();
}
self.reset_boundaries();
}
}
pub fn resize_active_pane_up(&mut self, client_id: ClientId) {
if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
let mut pane_grid = TiledPaneGrid::new(
&mut self.panes,
&self.panes_to_hide,
*self.display_area.borrow(),
*self.viewport.borrow(),
);
pane_grid.resize_pane_up(&active_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, self.os_api, self.senders).unwrap();
}
self.reset_boundaries();
}
}
pub fn resize_active_pane_down(&mut self, client_id: ClientId) {
if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
let mut pane_grid = TiledPaneGrid::new(
&mut self.panes,
&self.panes_to_hide,
*self.display_area.borrow(),
*self.viewport.borrow(),
);
pane_grid.resize_pane_down(&active_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, self.os_api, self.senders).unwrap();
}
self.reset_boundaries();
}
}
pub fn resize_active_pane_increase(&mut self, client_id: ClientId) {
if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
let mut pane_grid = TiledPaneGrid::new(
&mut self.panes,
&self.panes_to_hide,
*self.display_area.borrow(),
*self.viewport.borrow(),
);
pane_grid.resize_increase(&active_pane_id);
for pane in self.panes.values_mut() {
resize_pty!(pane, self.os_api, self.senders).unwrap();
}
self.reset_boundaries();
}
}
pub fn resize_active_pane_decrease(&mut self, client_id: ClientId) {
if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
let mut pane_grid = TiledPaneGrid::new(
&mut self.panes,
&self.panes_to_hide,
*self.display_area.borrow(),
*self.viewport.borrow(),
);
pane_grid.resize_decrease(&active_pane_id);
pane_grid
.change_pane_size(&active_pane_id, strategy, (RESIZE_PERCENT, RESIZE_PERCENT))
.with_context(err_context)?;
for pane in self.panes.values_mut() {
resize_pty!(pane, self.os_api, self.senders).unwrap();
}
self.reset_boundaries();
}
Ok(())
}
pub fn focus_next_pane(&mut self, client_id: ClientId) {
let connected_clients: Vec<ClientId> =
{ self.connected_clients.borrow().iter().copied().collect() };

View file

@ -8,6 +8,7 @@ use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use zellij_utils::{
errors::prelude::*,
input::layout::SplitDirection,
pane_size::{Constraint, Dimension, PaneGeom},
};
@ -44,10 +45,14 @@ impl<'a> PaneResizer<'a> {
}
}
pub fn layout(&mut self, direction: SplitDirection, space: usize) -> Result<(), String> {
pub fn layout(&mut self, direction: SplitDirection, space: usize) -> Result<()> {
self.solver.reset();
let grid = self.solve(direction, space)?;
let spans = self.discretize_spans(grid, space)?;
let grid = self
.solve(direction, space)
.map_err(|err| anyhow!("{}", err))?;
let spans = self
.discretize_spans(grid, space)
.map_err(|err| anyhow!("{}", err))?;
self.apply_spans(spans);
Ok(())
}

File diff suppressed because it is too large Load diff

View file

@ -9,10 +9,10 @@ use crate::{
};
use zellij_utils::{
channels::SenderWithContext,
data::Event,
data::{Direction, Event, ResizeStrategy},
errors::prelude::*,
input::{
actions::{Action, Direction, ResizeDirection, SearchDirection, SearchOption},
actions::{Action, SearchDirection, SearchOption},
command::TerminalAction,
get_mode_info,
},
@ -102,15 +102,9 @@ pub(crate) fn route_action(
.send_to_screen(ScreenInstruction::Render)
.with_context(err_context)?;
},
Action::Resize(direction) => {
let screen_instr = match direction {
ResizeDirection::Left => ScreenInstruction::ResizeLeft(client_id),
ResizeDirection::Right => ScreenInstruction::ResizeRight(client_id),
ResizeDirection::Up => ScreenInstruction::ResizeUp(client_id),
ResizeDirection::Down => ScreenInstruction::ResizeDown(client_id),
ResizeDirection::Increase => ScreenInstruction::ResizeIncrease(client_id),
ResizeDirection::Decrease => ScreenInstruction::ResizeDecrease(client_id),
};
Action::Resize(resize, direction) => {
let screen_instr =
ScreenInstruction::Resize(client_id, ResizeStrategy::new(resize, direction));
session
.senders
.send_to_screen(screen_instr)

View file

@ -5,6 +5,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use std::rc::Rc;
use std::str;
use zellij_utils::data::{Direction, Resize, ResizeStrategy};
use zellij_utils::errors::prelude::*;
use zellij_utils::input::command::RunCommand;
use zellij_utils::input::options::Clipboard;
@ -137,12 +138,7 @@ pub enum ScreenInstruction {
HorizontalSplit(PaneId, Option<InitialTitle>, HoldForCommand, ClientId),
VerticalSplit(PaneId, Option<InitialTitle>, HoldForCommand, ClientId),
WriteCharacter(Vec<u8>, ClientId),
ResizeLeft(ClientId),
ResizeRight(ClientId),
ResizeDown(ClientId),
ResizeUp(ClientId),
ResizeIncrease(ClientId),
ResizeDecrease(ClientId),
Resize(ClientId, ResizeStrategy),
SwitchFocus(ClientId),
FocusNextPane(ClientId),
FocusPreviousPane(ClientId),
@ -245,12 +241,30 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::HorizontalSplit(..) => ScreenContext::HorizontalSplit,
ScreenInstruction::VerticalSplit(..) => ScreenContext::VerticalSplit,
ScreenInstruction::WriteCharacter(..) => ScreenContext::WriteCharacter,
ScreenInstruction::ResizeLeft(..) => ScreenContext::ResizeLeft,
ScreenInstruction::ResizeRight(..) => ScreenContext::ResizeRight,
ScreenInstruction::ResizeDown(..) => ScreenContext::ResizeDown,
ScreenInstruction::ResizeUp(..) => ScreenContext::ResizeUp,
ScreenInstruction::ResizeIncrease(..) => ScreenContext::ResizeIncrease,
ScreenInstruction::ResizeDecrease(..) => ScreenContext::ResizeDecrease,
ScreenInstruction::Resize(.., strategy) => match strategy {
ResizeStrategy {
resize: Resize::Increase,
direction,
..
} => match direction {
Some(Direction::Left) => ScreenContext::ResizeIncreaseLeft,
Some(Direction::Down) => ScreenContext::ResizeIncreaseDown,
Some(Direction::Up) => ScreenContext::ResizeIncreaseUp,
Some(Direction::Right) => ScreenContext::ResizeIncreaseRight,
None => ScreenContext::ResizeIncreaseAll,
},
ResizeStrategy {
resize: Resize::Decrease,
direction,
..
} => match direction {
Some(Direction::Left) => ScreenContext::ResizeDecreaseLeft,
Some(Direction::Down) => ScreenContext::ResizeDecreaseDown,
Some(Direction::Up) => ScreenContext::ResizeDecreaseUp,
Some(Direction::Right) => ScreenContext::ResizeDecreaseRight,
None => ScreenContext::ResizeDecreaseAll,
},
},
ScreenInstruction::SwitchFocus(..) => ScreenContext::SwitchFocus,
ScreenInstruction::FocusNextPane(..) => ScreenContext::FocusNextPane,
ScreenInstruction::FocusPreviousPane(..) => ScreenContext::FocusPreviousPane,
@ -1491,56 +1505,12 @@ pub(crate) fn screen_thread_main(
screen.update_tabs()?;
}
},
ScreenInstruction::ResizeLeft(client_id) => {
ScreenInstruction::Resize(client_id, strategy) => {
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| tab.resize_left(client_id)
);
screen.unblock_input()?;
screen.render()?;
},
ScreenInstruction::ResizeRight(client_id) => {
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| tab.resize_right(client_id)
);
screen.unblock_input()?;
screen.render()?;
},
ScreenInstruction::ResizeDown(client_id) => {
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| tab.resize_down(client_id)
);
screen.unblock_input()?;
screen.render()?;
},
ScreenInstruction::ResizeUp(client_id) => {
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| tab.resize_up(client_id)
);
screen.unblock_input()?;
screen.render()?;
},
ScreenInstruction::ResizeIncrease(client_id) => {
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| tab.resize_increase(client_id)
);
screen.unblock_input()?;
screen.render()?;
},
ScreenInstruction::ResizeDecrease(client_id) => {
active_tab_and_connected_client_id!(
screen,
client_id,
|tab: &mut Tab, client_id: ClientId| tab.resize_decrease(client_id)
|tab: &mut Tab, client_id: ClientId| tab.resize(client_id, strategy),
?
);
screen.unblock_input()?;
screen.render()?;

View file

@ -7,6 +7,7 @@ mod copy_command;
use copy_command::CopyCommand;
use std::env::temp_dir;
use uuid::Uuid;
use zellij_utils::data::{Direction, ResizeStrategy};
use zellij_utils::errors::prelude::*;
use zellij_utils::input::command::RunCommand;
use zellij_utils::position::{Column, Line};
@ -966,6 +967,7 @@ impl Tab {
let replaced_pane = if self.floating_panes.panes_are_visible() {
self.floating_panes
.replace_active_pane(Box::new(new_pane), client_id)
.ok()
} else {
self.tiled_panes
.replace_active_pane(Box::new(new_pane), client_id)
@ -1290,7 +1292,7 @@ impl Tab {
let err_context = || format!("failed to write to terminal at position {position:?}");
if self.floating_panes.panes_are_visible() {
let pane_id = self.floating_panes.get_pane_id_at(position, false);
let pane_id = self.floating_panes.get_pane_id_at(position, false).unwrap();
if let Some(pane_id) = pane_id {
self.write_to_pane_id(input_bytes, pane_id)
.with_context(err_context)?;
@ -1580,81 +1582,27 @@ impl Tab {
}
pub fn resize_whole_tab(&mut self, new_screen_size: Size) {
self.floating_panes.resize(new_screen_size);
self.floating_panes.resize_pty_all_panes(&mut self.os_api); // we need to do this explicitly because floating_panes.resize does not do this
self.floating_panes
.resize_pty_all_panes(&mut self.os_api)
.unwrap(); // we need to do this explicitly because floating_panes.resize does not do this
self.tiled_panes.resize(new_screen_size);
self.should_clear_display_before_rendering = true;
}
pub fn resize_left(&mut self, client_id: ClientId) {
pub fn resize(&mut self, client_id: ClientId, strategy: ResizeStrategy) -> Result<()> {
if self.floating_panes.panes_are_visible() {
let successfully_resized = self
.floating_panes
.resize_active_pane_left(client_id, &mut self.os_api);
.resize_active_pane(client_id, &mut self.os_api, &strategy)
.unwrap();
if successfully_resized {
self.set_force_render(); // we force render here to make sure the panes under the floating pane render and don't leave "garbage" in case of a decrease
}
} else {
self.tiled_panes.resize_active_pane_left(client_id);
}
}
pub fn resize_right(&mut self, client_id: ClientId) {
if self.floating_panes.panes_are_visible() {
let successfully_resized = self
.floating_panes
.resize_active_pane_right(client_id, &mut self.os_api);
if successfully_resized {
self.set_force_render(); // we force render here to make sure the panes under the floating pane render and don't leave "garbage" in case of a decrease
}
} else {
self.tiled_panes.resize_active_pane_right(client_id);
}
}
pub fn resize_down(&mut self, client_id: ClientId) {
if self.floating_panes.panes_are_visible() {
let successfully_resized = self
.floating_panes
.resize_active_pane_down(client_id, &mut self.os_api);
if successfully_resized {
self.set_force_render(); // we force render here to make sure the panes under the floating pane render and don't leave "garbage" in case of a decrease
}
} else {
self.tiled_panes.resize_active_pane_down(client_id);
}
}
pub fn resize_up(&mut self, client_id: ClientId) {
if self.floating_panes.panes_are_visible() {
let successfully_resized = self
.floating_panes
.resize_active_pane_up(client_id, &mut self.os_api);
if successfully_resized {
self.set_force_render(); // we force render here to make sure the panes under the floating pane render and don't leave "garbage" in case of a decrease
}
} else {
self.tiled_panes.resize_active_pane_up(client_id);
}
}
pub fn resize_increase(&mut self, client_id: ClientId) {
if self.floating_panes.panes_are_visible() {
let successfully_resized = self
.floating_panes
.resize_active_pane_increase(client_id, &mut self.os_api);
if successfully_resized {
self.set_force_render(); // we force render here to make sure the panes under the floating pane render and don't leave "garbage" in case of a decrease
}
} else {
self.tiled_panes.resize_active_pane_increase(client_id);
}
}
pub fn resize_decrease(&mut self, client_id: ClientId) {
if self.floating_panes.panes_are_visible() {
let successfully_resized = self
.floating_panes
.resize_active_pane_decrease(client_id, &mut self.os_api);
if successfully_resized {
self.set_force_render(); // we force render here to make sure the panes under the floating pane render and don't leave "garbage" in case of a decrease
}
} else {
self.tiled_panes.resize_active_pane_decrease(client_id);
self.tiled_panes
.resize_active_pane(client_id, &strategy)
.unwrap();
}
Ok(())
}
fn set_pane_active_at(&mut self, pane_id: PaneId) {
if let Some(pane) = self.tiled_panes.get_pane_mut(pane_id) {
@ -1686,10 +1634,13 @@ impl Tab {
// returns a boolean that indicates whether the focus moved
pub fn move_focus_left(&mut self, client_id: ClientId) -> bool {
if self.floating_panes.panes_are_visible() {
self.floating_panes.move_focus_left(
self.floating_panes
.move_focus(
client_id,
&self.connected_clients.borrow().iter().copied().collect(),
&Direction::Left,
)
.unwrap()
} else {
if !self.has_selectable_panes() {
return false;
@ -1703,10 +1654,13 @@ impl Tab {
}
pub fn move_focus_down(&mut self, client_id: ClientId) -> bool {
if self.floating_panes.panes_are_visible() {
self.floating_panes.move_focus_down(
self.floating_panes
.move_focus(
client_id,
&self.connected_clients.borrow().iter().copied().collect(),
&Direction::Down,
)
.unwrap()
} else {
if !self.has_selectable_panes() {
return false;
@ -1719,10 +1673,13 @@ impl Tab {
}
pub fn move_focus_up(&mut self, client_id: ClientId) -> bool {
if self.floating_panes.panes_are_visible() {
self.floating_panes.move_focus_up(
self.floating_panes
.move_focus(
client_id,
&self.connected_clients.borrow().iter().copied().collect(),
&Direction::Up,
)
.unwrap()
} else {
if !self.has_selectable_panes() {
return false;
@ -1736,10 +1693,13 @@ impl Tab {
// returns a boolean that indicates whether the focus moved
pub fn move_focus_right(&mut self, client_id: ClientId) -> bool {
if self.floating_panes.panes_are_visible() {
self.floating_panes.move_focus_right(
self.floating_panes
.move_focus(
client_id,
&self.connected_clients.borrow().iter().copied().collect(),
&Direction::Right,
)
.unwrap()
} else {
if !self.has_selectable_panes() {
return false;
@ -1920,7 +1880,9 @@ impl Tab {
.and_then(|suppressed_pane| {
let suppressed_pane_id = suppressed_pane.pid();
let replaced_pane = if self.are_floating_panes_visible() {
self.floating_panes.replace_pane(pane_id, suppressed_pane)
Some(self.floating_panes.replace_pane(pane_id, suppressed_pane))
.transpose()
.unwrap()
} else {
self.tiled_panes.replace_pane(pane_id, suppressed_pane)
};
@ -2179,7 +2141,11 @@ impl Tab {
search_selectable: bool,
) -> Result<Option<&mut Box<dyn Pane>>> {
if self.floating_panes.panes_are_visible() {
if let Some(pane_id) = self.floating_panes.get_pane_id_at(point, search_selectable) {
if let Some(pane_id) = self
.floating_panes
.get_pane_id_at(point, search_selectable)
.unwrap()
{
return Ok(self.floating_panes.get_pane_mut(pane_id));
}
}
@ -2321,7 +2287,7 @@ impl Tab {
|| format!("failed to focus pane at position {point:?} for client {client_id}");
if self.floating_panes.panes_are_visible() {
if let Some(clicked_pane) = self.floating_panes.get_pane_id_at(point, true) {
if let Some(clicked_pane) = self.floating_panes.get_pane_id_at(point, true).unwrap() {
self.floating_panes.focus_pane(clicked_pane, client_id);
self.set_pane_active_at(clicked_pane);
return Ok(());

View file

@ -11,6 +11,9 @@ use crate::{
};
use std::path::PathBuf;
use zellij_utils::channels::Receiver;
use zellij_utils::data::Direction;
use zellij_utils::data::Resize;
use zellij_utils::data::ResizeStrategy;
use zellij_utils::envs::set_session_name;
use zellij_utils::errors::{prelude::*, ErrorContext};
use zellij_utils::input::layout::{Layout, PaneLayout};
@ -765,7 +768,8 @@ fn increase_floating_pane_size() {
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
)
.unwrap();
tab.resize_increase(client_id);
tab.resize(client_id, ResizeStrategy::new(Resize::Increase, None))
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().unwrap().get(&client_id).unwrap(),
@ -794,7 +798,8 @@ fn decrease_floating_pane_size() {
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
)
.unwrap();
tab.resize_decrease(client_id);
tab.resize(client_id, ResizeStrategy::new(Resize::Decrease, None))
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().unwrap().get(&client_id).unwrap(),
@ -823,7 +828,11 @@ fn resize_floating_pane_left() {
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
)
.unwrap();
tab.resize_left(client_id);
tab.resize(
client_id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Left)),
)
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().unwrap().get(&client_id).unwrap(),
@ -852,7 +861,11 @@ fn resize_floating_pane_right() {
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
)
.unwrap();
tab.resize_right(client_id);
tab.resize(
client_id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Right)),
)
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().unwrap().get(&client_id).unwrap(),
@ -881,7 +894,11 @@ fn resize_floating_pane_up() {
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
)
.unwrap();
tab.resize_up(client_id);
tab.resize(
client_id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Up)),
)
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().unwrap().get(&client_id).unwrap(),
@ -910,7 +927,11 @@ fn resize_floating_pane_down() {
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
)
.unwrap();
tab.resize_down(client_id);
tab.resize(
client_id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Down)),
)
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().unwrap().get(&client_id).unwrap(),

View file

@ -8,6 +8,7 @@ use crate::{
ClientId,
};
use std::path::PathBuf;
use zellij_utils::data::{Direction, Resize, ResizeStrategy};
use zellij_utils::errors::prelude::*;
use zellij_utils::input::layout::PaneLayout;
use zellij_utils::ipc::IpcReceiverWithContext;
@ -98,6 +99,43 @@ impl ServerOsApi for FakeInputOutput {
}
}
fn tab_resize_increase(tab: &mut Tab, id: ClientId) {
tab.resize(id, ResizeStrategy::new(Resize::Increase, None))
.unwrap();
}
fn tab_resize_left(tab: &mut Tab, id: ClientId) {
tab.resize(
id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Left)),
)
.unwrap();
}
fn tab_resize_down(tab: &mut Tab, id: ClientId) {
tab.resize(
id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Down)),
)
.unwrap();
}
fn tab_resize_up(tab: &mut Tab, id: ClientId) {
tab.resize(
id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Up)),
)
.unwrap();
}
fn tab_resize_right(tab: &mut Tab, id: ClientId) {
tab.resize(
id,
ResizeStrategy::new(Resize::Increase, Some(Direction::Right)),
)
.unwrap();
}
fn create_new_tab(size: Size) -> Tab {
let index = 0;
let position = 0;
@ -1521,7 +1559,7 @@ pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() {
tab.horizontal_split(new_pane_id_5, None, 1).unwrap();
tab.move_focus_left(1);
tab.move_focus_up(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
tab.vertical_split(new_pane_id_6, None, 1).unwrap();
tab.move_focus_down(1);
tab.close_focused_pane(1).unwrap();
@ -1820,7 +1858,7 @@ pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() {
tab.move_focus_right(1);
tab.horizontal_split(new_pane_id_5, None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
tab.vertical_split(new_pane_id_6, None, 1).unwrap();
tab.move_focus_up(1);
tab.close_focused_pane(1).unwrap();
@ -2122,9 +2160,9 @@ pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() {
tab.vertical_split(new_pane_id_5, None, 1).unwrap();
tab.move_focus_up(1);
tab.move_focus_left(1);
tab.resize_right(1);
tab.resize_up(1);
tab.resize_up(1);
tab_resize_right(&mut tab, 1);
tab_resize_up(&mut tab, 1);
tab_resize_up(&mut tab, 1);
tab.horizontal_split(new_pane_id_6, None, 1).unwrap();
tab.move_focus_right(1);
tab.close_focused_pane(1).unwrap();
@ -2425,9 +2463,9 @@ pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() {
tab.move_focus_down(1);
tab.vertical_split(new_pane_id_5, None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_left(1);
tab.resize_up(1);
tab.resize_up(1);
tab_resize_left(&mut tab, 1);
tab_resize_up(&mut tab, 1);
tab_resize_up(&mut tab, 1);
tab.horizontal_split(new_pane_id_6, None, 1).unwrap();
tab.move_focus_left(1);
tab.close_focused_pane(1).unwrap();
@ -3145,7 +3183,7 @@ pub fn resize_down_with_pane_above() {
let mut tab = create_new_tab(size);
let new_pane_id = PaneId::Terminal(2);
tab.horizontal_split(new_pane_id, None, 1).unwrap();
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -3252,7 +3290,7 @@ pub fn resize_down_with_pane_below() {
let new_pane_id = PaneId::Terminal(2);
tab.horizontal_split(new_pane_id, None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -3366,7 +3404,7 @@ pub fn resize_down_with_panes_above_and_below() {
tab.horizontal_split(new_pane_id_1, None, 1).unwrap();
tab.horizontal_split(new_pane_id_2, None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -3520,7 +3558,7 @@ pub fn resize_down_with_multiple_panes_above() {
tab.move_focus_up(1);
tab.vertical_split(new_pane_id_2, None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -3676,7 +3714,7 @@ pub fn resize_down_with_panes_above_aligned_left_with_current_pane() {
tab.move_focus_up(1);
tab.vertical_split(pane_above, None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -3875,7 +3913,7 @@ pub fn resize_down_with_panes_below_aligned_left_with_current_pane() {
tab.vertical_split(pane_below, None, 1).unwrap();
tab.move_focus_up(1);
tab.vertical_split(focused_pane, None, 1).unwrap();
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -4076,7 +4114,7 @@ pub fn resize_down_with_panes_above_aligned_right_with_current_pane() {
tab.vertical_split(pane_above_and_right, None, 1).unwrap();
tab.move_focus_down(1);
tab.move_focus_left(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -4276,7 +4314,7 @@ pub fn resize_down_with_panes_below_aligned_right_with_current_pane() {
tab.move_focus_up(1);
tab.vertical_split(pane_to_the_right, None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -4475,7 +4513,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() {
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_left(1);
tab.move_focus_down(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -4759,7 +4797,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() {
tab.vertical_split(PaneId::Terminal(5), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -5047,7 +5085,7 @@ pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_lef
tab.vertical_split(PaneId::Terminal(7), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(8), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -5423,7 +5461,7 @@ pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_
tab.move_focus_left(1);
tab.move_focus_up(1);
tab.move_focus_left(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -5786,7 +5824,7 @@ pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() {
let mut tab = create_new_tab(size);
tab.horizontal_split(PaneId::Terminal(2), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -5827,7 +5865,7 @@ pub fn resize_left_with_pane_to_the_left() {
};
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -5931,7 +5969,7 @@ pub fn resize_left_with_pane_to_the_right() {
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -6037,7 +6075,7 @@ pub fn resize_left_with_panes_to_the_left_and_right() {
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -6186,7 +6224,7 @@ pub fn resize_left_with_multiple_panes_to_the_left() {
tab.move_focus_left(1);
tab.horizontal_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_right(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -6337,7 +6375,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() {
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -6532,7 +6570,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() {
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_down(1);
tab.move_focus_left(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -6725,7 +6763,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() {
tab.vertical_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -6919,7 +6957,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() {
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -7118,7 +7156,7 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pa
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -7404,7 +7442,7 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_p
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_down(1);
tab.move_focus_left(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -7688,12 +7726,12 @@ pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abov
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(5), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.horizontal_split(PaneId::Terminal(7), None, 1).unwrap();
tab.horizontal_split(PaneId::Terminal(8), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -8063,13 +8101,13 @@ pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_abo
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(5), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_left(1);
tab.horizontal_split(PaneId::Terminal(7), None, 1).unwrap();
tab.horizontal_split(PaneId::Terminal(8), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -8428,7 +8466,7 @@ pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() {
let size = Size { cols: 10, rows: 20 };
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.resize_left(1);
tab_resize_left(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -8469,7 +8507,7 @@ pub fn resize_right_with_pane_to_the_left() {
};
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -8574,7 +8612,7 @@ pub fn resize_right_with_pane_to_the_right() {
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -8680,7 +8718,7 @@ pub fn resize_right_with_panes_to_the_left_and_right() {
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -8830,7 +8868,7 @@ pub fn resize_right_with_multiple_panes_to_the_left() {
tab.move_focus_left(1);
tab.horizontal_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_right(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -8981,7 +9019,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() {
tab.horizontal_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_right(1);
tab.horizontal_split(PaneId::Terminal(4), None, 1).unwrap();
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -9175,7 +9213,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() {
tab.move_focus_right(1);
tab.horizontal_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -9370,7 +9408,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() {
tab.move_focus_right(1);
tab.horizontal_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -9566,7 +9604,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() {
tab.horizontal_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_up(1);
tab.move_focus_left(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -9765,7 +9803,7 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_p
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -10050,7 +10088,7 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_down(1);
tab.move_focus_left(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -10333,12 +10371,12 @@ pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_abo
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(5), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.horizontal_split(PaneId::Terminal(7), None, 1).unwrap();
tab.horizontal_split(PaneId::Terminal(8), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -10707,13 +10745,13 @@ pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_ab
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(5), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_left(1);
tab.horizontal_split(PaneId::Terminal(7), None, 1).unwrap();
tab.horizontal_split(PaneId::Terminal(8), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -11071,7 +11109,7 @@ pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() {
let size = Size { cols: 10, rows: 20 };
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.resize_right(1);
tab_resize_right(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -11113,7 +11151,7 @@ pub fn resize_up_with_pane_above() {
};
let mut tab = create_new_tab(size);
tab.horizontal_split(PaneId::Terminal(2), None, 1).unwrap();
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -11219,7 +11257,7 @@ pub fn resize_up_with_pane_below() {
let mut tab = create_new_tab(size);
tab.horizontal_split(PaneId::Terminal(2), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -11329,7 +11367,7 @@ pub fn resize_up_with_panes_above_and_below() {
tab.horizontal_split(PaneId::Terminal(2), None, 1).unwrap();
tab.horizontal_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -11479,7 +11517,7 @@ pub fn resize_up_with_multiple_panes_above() {
tab.move_focus_up(1);
tab.vertical_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_down(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -11629,7 +11667,7 @@ pub fn resize_up_with_panes_above_aligned_left_with_current_pane() {
tab.vertical_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_down(1);
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -11825,7 +11863,7 @@ pub fn resize_up_with_panes_below_aligned_left_with_current_pane() {
tab.move_focus_down(1);
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_up(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -12021,7 +12059,7 @@ pub fn resize_up_with_panes_above_aligned_right_with_current_pane() {
tab.move_focus_down(1);
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -12218,7 +12256,7 @@ pub fn resize_up_with_panes_below_aligned_right_with_current_pane() {
tab.vertical_split(PaneId::Terminal(4), None, 1).unwrap();
tab.move_focus_left(1);
tab.move_focus_up(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -12415,7 +12453,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() {
tab.vertical_split(PaneId::Terminal(5), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -12699,7 +12737,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() {
tab.vertical_split(PaneId::Terminal(6), None, 1).unwrap();
tab.move_focus_left(1);
tab.move_focus_up(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -12986,7 +13024,7 @@ pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_
tab.vertical_split(PaneId::Terminal(7), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(8), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -13360,7 +13398,7 @@ pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_ri
tab.vertical_split(PaneId::Terminal(7), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(8), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_up(1);
tab_resize_up(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -13722,7 +13760,7 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() {
};
let mut tab = create_new_tab(size);
tab.horizontal_split(PaneId::Terminal(2), None, 1).unwrap();
tab.resize_down(1);
tab_resize_down(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -13755,7 +13793,7 @@ pub fn nondirectional_resize_increase_with_1_pane() {
rows: 10,
};
let mut tab = create_new_tab(size);
tab.resize_increase(1);
tab_resize_increase(&mut tab, 1);
assert_eq!(
tab.get_active_pane(1).unwrap().position_and_size().y,
@ -13779,7 +13817,7 @@ pub fn nondirectional_resize_increase_with_1_pane_to_left() {
let mut tab = create_new_tab(size);
let new_pane_id_1 = PaneId::Terminal(2);
tab.vertical_split(new_pane_id_1, None, 1).unwrap();
tab.resize_increase(1);
tab_resize_increase(&mut tab, 1);
// should behave like `resize_left_with_pane_to_the_left`
assert_eq!(
@ -13815,7 +13853,7 @@ pub fn nondirectional_resize_increase_with_2_panes_to_left() {
tab.move_focus_left(1);
tab.horizontal_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_right(1);
tab.resize_increase(1);
tab_resize_increase(&mut tab, 1);
// should behave like `resize_left_with_multiple_panes_to_the_left`
assert_eq!(
@ -13872,7 +13910,7 @@ pub fn nondirectional_resize_increase_with_1_pane_to_right_1_pane_above() {
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.move_focus_left(1);
tab.horizontal_split(PaneId::Terminal(3), None, 1).unwrap();
tab.resize_increase(1);
tab_resize_increase(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -13928,7 +13966,7 @@ pub fn nondirectional_resize_increase_with_1_pane_to_right_1_pane_to_left() {
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_increase(1);
tab_resize_increase(&mut tab, 1);
assert_eq!(
tab.tiled_panes
@ -13984,7 +14022,7 @@ pub fn nondirectional_resize_increase_with_pane_above_aligned_right_with_current
tab.vertical_split(PaneId::Terminal(2), None, 1).unwrap();
tab.vertical_split(PaneId::Terminal(3), None, 1).unwrap();
tab.move_focus_left(1);
tab.resize_increase(1);
tab_resize_increase(&mut tab, 1);
assert_eq!(
tab.tiled_panes

View file

@ -10,8 +10,9 @@ use crate::{
use insta::assert_snapshot;
use std::path::PathBuf;
use zellij_utils::cli::CliAction;
use zellij_utils::data::Resize;
use zellij_utils::errors::{prelude::*, ErrorContext};
use zellij_utils::input::actions::{Action, Direction, ResizeDirection};
use zellij_utils::input::actions::Action;
use zellij_utils::input::command::{RunCommand, TerminalAction};
use zellij_utils::input::layout::{PaneLayout, SplitDirection};
use zellij_utils::input::options::Options;
@ -28,7 +29,7 @@ use zellij_utils::ipc::PixelDimensions;
use zellij_utils::{
channels::{self, ChannelWithContext, Receiver},
data::{InputMode, ModeInfo, Palette, PluginCapabilities},
data::{Direction, InputMode, ModeInfo, Palette, PluginCapabilities},
interprocess::local_socket::LocalSocketStream,
ipc::{ClientAttributes, ClientToServerMsg, ServerToClientMsg},
};
@ -997,7 +998,8 @@ pub fn send_cli_resize_action_to_screen() {
server_receiver
);
let resize_cli_action = CliAction::Resize {
resize_direction: ResizeDirection::Left,
resize: Resize::Increase,
direction: Some(Direction::Left),
};
send_cli_action_to_server(
&session_metadata,

View file

@ -9,10 +9,14 @@ keybinds {
}
resize {
bind "Ctrl n" { SwitchToMode "Normal"; }
bind "h" "Left" { Resize "Left"; }
bind "j" "Down" { Resize "Down"; }
bind "k" "Up" { Resize "Up"; }
bind "l" "Right" { Resize "Right"; }
bind "h" "Left" { Resize "Increase Left"; }
bind "j" "Down" { Resize "Increase Down"; }
bind "k" "Up" { Resize "Increase Up"; }
bind "l" "Right" { Resize "Increase Right"; }
bind "H" { Resize "Decrease Left"; }
bind "J" { Resize "Decrease Down"; }
bind "K" { Resize "Decrease Up"; }
bind "L" { Resize "Decrease Right"; }
bind "=" "+" { Resize "Increase"; }
bind "-" { Resize "Decrease"; }
}

View file

@ -1,8 +1,7 @@
use crate::data::InputMode;
use crate::data::{Direction, InputMode, Resize};
use crate::setup::Setup;
use crate::{
consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV},
input::actions::{Direction, ResizeDirection},
input::options::CliOptions,
};
use clap::{Parser, Subcommand};
@ -184,8 +183,11 @@ pub enum CliAction {
Write { bytes: Vec<u8> },
/// Write characters to the terminal.
WriteChars { chars: String },
/// Resize the focused pane in the specified direction. [right|left|up|down|+|-]
Resize { resize_direction: ResizeDirection },
/// [increase|decrease] the focused panes area at the [left|down|up|right] border.
Resize {
resize: Resize,
direction: Option<Direction>,
},
/// Change focus to the next pane
FocusNextPane,
/// Change focus to the previous pane

View file

@ -203,6 +203,25 @@ pub enum Direction {
Down,
}
impl Direction {
pub fn invert(&self) -> Direction {
match *self {
Direction::Left => Direction::Right,
Direction::Down => Direction::Up,
Direction::Up => Direction::Down,
Direction::Right => Direction::Left,
}
}
pub fn is_horizontal(&self) -> bool {
matches!(self, Direction::Left | Direction::Right)
}
pub fn is_vertical(&self) -> bool {
matches!(self, Direction::Down | Direction::Up)
}
}
impl fmt::Display for Direction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@ -214,6 +233,215 @@ impl fmt::Display for Direction {
}
}
impl FromStr for Direction {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Left" | "left" => Ok(Direction::Left),
"Right" | "right" => Ok(Direction::Right),
"Up" | "up" => Ok(Direction::Up),
"Down" | "down" => Ok(Direction::Down),
_ => Err(format!(
"Failed to parse Direction. Unknown Direction: {}",
s
)),
}
}
}
/// Resize operation to perform.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub enum Resize {
Increase,
Decrease,
}
impl Resize {
pub fn invert(&self) -> Self {
match self {
Resize::Increase => Resize::Decrease,
Resize::Decrease => Resize::Increase,
}
}
}
impl fmt::Display for Resize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Resize::Increase => write!(f, "+"),
Resize::Decrease => write!(f, "-"),
}
}
}
impl FromStr for Resize {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Increase" | "increase" | "+" => Ok(Resize::Increase),
"Decrease" | "decrease" | "-" => Ok(Resize::Decrease),
_ => Err(format!(
"failed to parse resize type. Unknown specifier '{}'",
s
)),
}
}
}
/// Container type that fully describes resize operations.
///
/// This is best thought of as follows:
///
/// - `resize` commands how the total *area* of the pane will change as part of this resize
/// operation.
/// - `direction` has two meanings:
/// - `None` means to resize all borders equally
/// - Anything else means to move the named border to achieve the change in area
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub struct ResizeStrategy {
/// Whether to increase or resize total area
pub resize: Resize,
/// With which border, if any, to change area
pub direction: Option<Direction>,
/// If set to true (default), increasing resizes towards a viewport border will be inverted.
/// I.e. a scenario like this ("increase right"):
///
/// ```text
/// +---+---+
/// | | X |->
/// +---+---+
/// ```
///
/// turns into this ("decrease left"):
///
/// ```text
/// +---+---+
/// | |-> |
/// +---+---+
/// ```
pub invert_on_boundaries: bool,
}
impl From<Direction> for ResizeStrategy {
fn from(direction: Direction) -> Self {
ResizeStrategy::new(Resize::Increase, Some(direction))
}
}
impl From<Resize> for ResizeStrategy {
fn from(resize: Resize) -> Self {
ResizeStrategy::new(resize, None)
}
}
impl ResizeStrategy {
pub fn new(resize: Resize, direction: Option<Direction>) -> Self {
ResizeStrategy {
resize,
direction,
invert_on_boundaries: true,
}
}
pub fn invert(&self) -> ResizeStrategy {
let resize = match self.resize {
Resize::Increase => Resize::Decrease,
Resize::Decrease => Resize::Increase,
};
let direction = match self.direction {
Some(direction) => Some(direction.invert()),
None => None,
};
ResizeStrategy::new(resize, direction)
}
pub fn resize_type(&self) -> Resize {
self.resize
}
pub fn direction(&self) -> Option<Direction> {
self.direction
}
pub fn direction_horizontal(&self) -> bool {
matches!(
self.direction,
Some(Direction::Left) | Some(Direction::Right)
)
}
pub fn direction_vertical(&self) -> bool {
matches!(self.direction, Some(Direction::Up) | Some(Direction::Down))
}
pub fn resize_increase(&self) -> bool {
self.resize == Resize::Increase
}
pub fn resize_decrease(&self) -> bool {
self.resize == Resize::Decrease
}
pub fn move_left_border_left(&self) -> bool {
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Left))
}
pub fn move_left_border_right(&self) -> bool {
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Left))
}
pub fn move_lower_border_down(&self) -> bool {
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Down))
}
pub fn move_lower_border_up(&self) -> bool {
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Down))
}
pub fn move_upper_border_up(&self) -> bool {
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Up))
}
pub fn move_upper_border_down(&self) -> bool {
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Up))
}
pub fn move_right_border_right(&self) -> bool {
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Right))
}
pub fn move_right_border_left(&self) -> bool {
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Right))
}
pub fn move_all_borders_out(&self) -> bool {
(self.resize == Resize::Increase) && (self.direction == None)
}
pub fn move_all_borders_in(&self) -> bool {
(self.resize == Resize::Decrease) && (self.direction == None)
}
}
impl fmt::Display for ResizeStrategy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let resize = match self.resize {
Resize::Increase => "increase",
Resize::Decrease => "decrease",
};
let border = match self.direction {
Some(Direction::Left) => "left",
Some(Direction::Down) => "bottom",
Some(Direction::Up) => "top",
Some(Direction::Right) => "right",
None => "every",
};
write!(f, "{} size on {} border", resize, border)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
// FIXME: This should be extended to handle different button clicks (not just
// left click) and the `ScrollUp` and `ScrollDown` events could probably be

View file

@ -256,6 +256,16 @@ pub enum ScreenContext {
HorizontalSplit,
VerticalSplit,
WriteCharacter,
ResizeIncreaseAll,
ResizeIncreaseLeft,
ResizeIncreaseDown,
ResizeIncreaseUp,
ResizeIncreaseRight,
ResizeDecreaseAll,
ResizeDecreaseLeft,
ResizeDecreaseDown,
ResizeDecreaseUp,
ResizeDecreaseRight,
ResizeLeft,
ResizeRight,
ResizeDown,

View file

@ -4,6 +4,7 @@ use super::command::RunCommandAction;
use super::layout::{Layout, PaneLayout};
use crate::cli::CliAction;
use crate::data::InputMode;
use crate::data::{Direction, Resize};
use crate::input::config::{ConfigError, KdlError};
use crate::input::options::OnForceClose;
use miette::{NamedSource, Report};
@ -14,30 +15,6 @@ use std::str::FromStr;
use crate::position::Position;
/// The four directions (left, right, up, down).
#[derive(Eq, Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
pub enum Direction {
Left,
Right,
Up,
Down,
}
impl FromStr for Direction {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Left" | "left" => Ok(Direction::Left),
"Right" | "right" => Ok(Direction::Right),
"Up" | "up" => Ok(Direction::Up),
"Down" | "down" => Ok(Direction::Down),
_ => Err(format!(
"Failed to parse Direction. Unknown Direction: {}",
s
)),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum ResizeDirection {
Left,
@ -126,8 +103,8 @@ pub enum Action {
SwitchToMode(InputMode),
/// Switch all connected clients to the specified input mode.
SwitchModeForAllClients(InputMode),
/// Resize focus pane in specified direction.
Resize(ResizeDirection),
/// Shrink/enlarge focused pane at specified border
Resize(Resize, Option<Direction>),
/// Switch focus to next pane in specified direction.
FocusNextPane,
FocusPreviousPane,
@ -235,7 +212,7 @@ impl Action {
match cli_action {
CliAction::Write { bytes } => Ok(vec![Action::Write(bytes)]),
CliAction::WriteChars { chars } => Ok(vec![Action::WriteChars(chars)]),
CliAction::Resize { resize_direction } => Ok(vec![Action::Resize(resize_direction)]),
CliAction::Resize { resize, direction } => Ok(vec![Action::Resize(resize, direction)]),
CliAction::FocusNextPane => Ok(vec![Action::FocusNextPane]),
CliAction::FocusPreviousPane => Ok(vec![Action::FocusPreviousPane]),
CliAction::MoveFocus { direction } => Ok(vec![Action::MoveFocus(direction)]),

View file

@ -1,5 +1,5 @@
//! Trigger a command
use super::actions::Direction;
use crate::data::Direction;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

View file

@ -9,6 +9,7 @@
// If plugins should be able to depend on the layout system
// then [`zellij-utils`] could be a proper place.
use crate::{
data::Direction,
input::{
command::RunCommand,
config::{Config, ConfigError},
@ -48,6 +49,15 @@ impl Not for SplitDirection {
}
}
impl From<Direction> for SplitDirection {
fn from(direction: Direction) -> Self {
match direction {
Direction::Left | Direction::Right => SplitDirection::Horizontal,
Direction::Down | Direction::Up => SplitDirection::Vertical,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
pub enum SplitSize {
#[serde(alias = "percent")]

View file

@ -1,6 +1,6 @@
use super::super::actions::*;
use super::super::keybinds::*;
use crate::data::{self, CharOrArrow, Key};
use crate::data::{self, CharOrArrow, Direction, Key};
use crate::input::config::Config;
use insta::assert_snapshot;
use strum::IntoEnumIterator;

View file

@ -1,5 +1,5 @@
mod kdl_layout_parser;
use crate::data::{InputMode, Key, Palette, PaletteColor};
use crate::data::{Direction, InputMode, Key, Palette, PaletteColor, Resize};
use crate::envs::EnvironmentVariables;
use crate::input::config::{Config, ConfigError, KdlError};
use crate::input::keybinds::Keybinds;
@ -21,7 +21,7 @@ use kdl::{KdlDocument, KdlEntry, KdlNode};
use std::path::PathBuf;
use std::str::FromStr;
use crate::input::actions::{Action, Direction, ResizeDirection, SearchDirection, SearchOption};
use crate::input::actions::{Action, SearchDirection, SearchOption};
use crate::input::command::RunCommandAction;
#[macro_export]
@ -394,14 +394,28 @@ impl Action {
},
},
"Resize" => {
let direction = ResizeDirection::from_str(string.as_str()).map_err(|_| {
ConfigError::new_kdl_error(
format!("Invalid direction: '{}'", string),
let mut resize: Option<Resize> = None;
let mut direction: Option<Direction> = None;
for word in string.to_ascii_lowercase().split_whitespace() {
match Resize::from_str(word) {
Ok(value) => resize = Some(value),
Err(_) => match Direction::from_str(word) {
Ok(value) => direction = Some(value),
Err(_) => {
return Err(ConfigError::new_kdl_error(
format!(
"failed to read either of resize type or direction from '{}'",
word
),
action_node.span().offset(),
action_node.span().len(),
)
})?;
Ok(Action::Resize(direction))
))
},
},
}
}
let resize = resize.unwrap_or(Resize::Increase);
Ok(Action::Resize(resize, direction))
},
"MoveFocus" => {
let direction = Direction::from_str(string.as_str()).map_err(|_| {
@ -691,6 +705,11 @@ impl TryFrom<&KdlNode> for Action {
action_arguments,
kdl_action
),
"ResizeNew" => parse_kdl_action_char_or_string_arguments!(
action_name,
action_arguments,
kdl_action
),
"MoveFocus" => parse_kdl_action_char_or_string_arguments!(
action_name,
action_arguments,

View file

@ -12,6 +12,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -21,6 +22,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -30,6 +32,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -188,23 +191,35 @@ Config {
Resize: {
Left: [
Resize(
Increase,
Some(
Left,
),
),
],
Down: [
Resize(
Increase,
Some(
Down,
),
),
],
Up: [
Resize(
Increase,
Some(
Up,
),
),
],
Right: [
Resize(
Increase,
Some(
Right,
),
),
],
Char(
'\n',
@ -218,6 +233,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
@ -225,6 +241,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Char(
@ -232,35 +249,88 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
'H',
): [
Resize(
Decrease,
Some(
Left,
),
),
],
Char(
'J',
): [
Resize(
Decrease,
Some(
Down,
),
),
],
Char(
'K',
): [
Resize(
Decrease,
Some(
Up,
),
),
],
Char(
'L',
): [
Resize(
Decrease,
Some(
Right,
),
),
],
Char(
'h',
): [
Resize(
Increase,
Some(
Left,
),
),
],
Char(
'j',
): [
Resize(
Increase,
Some(
Down,
),
),
],
Char(
'k',
): [
Resize(
Increase,
Some(
Up,
),
),
],
Char(
'l',
): [
Resize(
Increase,
Some(
Right,
),
),
],
Alt(
Char(
@ -269,6 +339,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -278,6 +349,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -287,6 +359,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -595,6 +668,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -604,6 +678,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -613,6 +688,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -940,6 +1016,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -949,6 +1026,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -958,6 +1036,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1195,6 +1274,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1204,6 +1284,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1213,6 +1294,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1390,6 +1472,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1399,6 +1482,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1408,6 +1492,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1664,6 +1749,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1673,6 +1759,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1682,6 +1769,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1859,6 +1947,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1868,6 +1957,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1877,6 +1967,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2051,6 +2142,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2060,6 +2152,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2069,6 +2162,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2248,6 +2342,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2257,6 +2352,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2266,6 +2362,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2503,6 +2600,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2512,6 +2610,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2521,6 +2620,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2692,6 +2792,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2701,6 +2802,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2710,6 +2812,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3033,6 +3136,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3042,6 +3146,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -3051,6 +3156,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(

View file

@ -12,6 +12,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -21,6 +22,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -30,6 +32,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -188,23 +191,35 @@ Config {
Resize: {
Left: [
Resize(
Increase,
Some(
Left,
),
),
],
Down: [
Resize(
Increase,
Some(
Down,
),
),
],
Up: [
Resize(
Increase,
Some(
Up,
),
),
],
Right: [
Resize(
Increase,
Some(
Right,
),
),
],
Char(
'\n',
@ -218,6 +233,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
@ -225,6 +241,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Char(
@ -232,35 +249,88 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
'H',
): [
Resize(
Decrease,
Some(
Left,
),
),
],
Char(
'J',
): [
Resize(
Decrease,
Some(
Down,
),
),
],
Char(
'K',
): [
Resize(
Decrease,
Some(
Up,
),
),
],
Char(
'L',
): [
Resize(
Decrease,
Some(
Right,
),
),
],
Char(
'h',
): [
Resize(
Increase,
Some(
Left,
),
),
],
Char(
'j',
): [
Resize(
Increase,
Some(
Down,
),
),
],
Char(
'k',
): [
Resize(
Increase,
Some(
Up,
),
),
],
Char(
'l',
): [
Resize(
Increase,
Some(
Right,
),
),
],
Alt(
Char(
@ -269,6 +339,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -278,6 +349,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -287,6 +359,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -595,6 +668,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -604,6 +678,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -613,6 +688,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -940,6 +1016,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -949,6 +1026,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -958,6 +1036,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1195,6 +1274,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1204,6 +1284,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1213,6 +1294,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1390,6 +1472,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1399,6 +1482,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1408,6 +1492,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1664,6 +1749,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1673,6 +1759,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1682,6 +1769,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1859,6 +1947,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1868,6 +1957,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1877,6 +1967,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2051,6 +2142,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2060,6 +2152,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2069,6 +2162,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2248,6 +2342,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2257,6 +2352,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2266,6 +2362,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2503,6 +2600,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2512,6 +2610,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2521,6 +2620,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2692,6 +2792,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2701,6 +2802,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2710,6 +2812,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3033,6 +3136,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3042,6 +3146,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -3051,6 +3156,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(

View file

@ -12,6 +12,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -21,6 +22,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -30,6 +32,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -188,23 +191,35 @@ Config {
Resize: {
Left: [
Resize(
Increase,
Some(
Left,
),
),
],
Down: [
Resize(
Increase,
Some(
Down,
),
),
],
Up: [
Resize(
Increase,
Some(
Up,
),
),
],
Right: [
Resize(
Increase,
Some(
Right,
),
),
],
Char(
'\n',
@ -218,6 +233,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
@ -225,6 +241,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Char(
@ -232,35 +249,88 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
'H',
): [
Resize(
Decrease,
Some(
Left,
),
),
],
Char(
'J',
): [
Resize(
Decrease,
Some(
Down,
),
),
],
Char(
'K',
): [
Resize(
Decrease,
Some(
Up,
),
),
],
Char(
'L',
): [
Resize(
Decrease,
Some(
Right,
),
),
],
Char(
'h',
): [
Resize(
Increase,
Some(
Left,
),
),
],
Char(
'j',
): [
Resize(
Increase,
Some(
Down,
),
),
],
Char(
'k',
): [
Resize(
Increase,
Some(
Up,
),
),
],
Char(
'l',
): [
Resize(
Increase,
Some(
Right,
),
),
],
Alt(
Char(
@ -269,6 +339,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -278,6 +349,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -287,6 +359,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -595,6 +668,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -604,6 +678,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -613,6 +688,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -940,6 +1016,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -949,6 +1026,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -958,6 +1036,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1195,6 +1274,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1204,6 +1284,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1213,6 +1294,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1390,6 +1472,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1399,6 +1482,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1408,6 +1492,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1664,6 +1749,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1673,6 +1759,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1682,6 +1769,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1859,6 +1947,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1868,6 +1957,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1877,6 +1967,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2051,6 +2142,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2060,6 +2152,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2069,6 +2162,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2248,6 +2342,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2257,6 +2352,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2266,6 +2362,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2503,6 +2600,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2512,6 +2610,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2521,6 +2620,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2692,6 +2792,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2701,6 +2802,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2710,6 +2812,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3033,6 +3136,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3042,6 +3146,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -3051,6 +3156,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(

View file

@ -12,6 +12,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -21,6 +22,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -30,6 +32,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -188,23 +191,35 @@ Config {
Resize: {
Left: [
Resize(
Increase,
Some(
Left,
),
),
],
Down: [
Resize(
Increase,
Some(
Down,
),
),
],
Up: [
Resize(
Increase,
Some(
Up,
),
),
],
Right: [
Resize(
Increase,
Some(
Right,
),
),
],
Char(
'\n',
@ -218,6 +233,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
@ -225,6 +241,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Char(
@ -232,35 +249,88 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
'H',
): [
Resize(
Decrease,
Some(
Left,
),
),
],
Char(
'J',
): [
Resize(
Decrease,
Some(
Down,
),
),
],
Char(
'K',
): [
Resize(
Decrease,
Some(
Up,
),
),
],
Char(
'L',
): [
Resize(
Decrease,
Some(
Right,
),
),
],
Char(
'h',
): [
Resize(
Increase,
Some(
Left,
),
),
],
Char(
'j',
): [
Resize(
Increase,
Some(
Down,
),
),
],
Char(
'k',
): [
Resize(
Increase,
Some(
Up,
),
),
],
Char(
'l',
): [
Resize(
Increase,
Some(
Right,
),
),
],
Alt(
Char(
@ -269,6 +339,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -278,6 +349,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -287,6 +359,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -595,6 +668,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -604,6 +678,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -613,6 +688,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -940,6 +1016,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -949,6 +1026,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -958,6 +1036,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1195,6 +1274,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1204,6 +1284,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1213,6 +1294,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1390,6 +1472,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1399,6 +1482,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1408,6 +1492,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1664,6 +1749,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1673,6 +1759,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1682,6 +1769,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1859,6 +1947,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1868,6 +1957,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1877,6 +1967,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2051,6 +2142,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2060,6 +2152,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2069,6 +2162,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2248,6 +2342,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2257,6 +2352,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2266,6 +2362,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2503,6 +2600,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2512,6 +2610,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2521,6 +2620,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2692,6 +2792,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2701,6 +2802,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2710,6 +2812,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3033,6 +3136,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3042,6 +3146,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -3051,6 +3156,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(

View file

@ -12,6 +12,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -21,6 +22,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -30,6 +32,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -188,23 +191,35 @@ Config {
Resize: {
Left: [
Resize(
Increase,
Some(
Left,
),
),
],
Down: [
Resize(
Increase,
Some(
Down,
),
),
],
Up: [
Resize(
Increase,
Some(
Up,
),
),
],
Right: [
Resize(
Increase,
Some(
Right,
),
),
],
Char(
'\n',
@ -218,6 +233,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
@ -225,6 +241,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Char(
@ -232,35 +249,88 @@ Config {
): [
Resize(
Increase,
None,
),
],
Char(
'H',
): [
Resize(
Decrease,
Some(
Left,
),
),
],
Char(
'J',
): [
Resize(
Decrease,
Some(
Down,
),
),
],
Char(
'K',
): [
Resize(
Decrease,
Some(
Up,
),
),
],
Char(
'L',
): [
Resize(
Decrease,
Some(
Right,
),
),
],
Char(
'h',
): [
Resize(
Increase,
Some(
Left,
),
),
],
Char(
'j',
): [
Resize(
Increase,
Some(
Down,
),
),
],
Char(
'k',
): [
Resize(
Increase,
Some(
Up,
),
),
],
Char(
'l',
): [
Resize(
Increase,
Some(
Right,
),
),
],
Alt(
Char(
@ -269,6 +339,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -278,6 +349,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -287,6 +359,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -595,6 +668,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -604,6 +678,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -613,6 +688,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -940,6 +1016,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -949,6 +1026,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -958,6 +1036,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1195,6 +1274,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1204,6 +1284,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1213,6 +1294,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1390,6 +1472,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1399,6 +1482,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1408,6 +1492,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1664,6 +1749,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1673,6 +1759,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1682,6 +1769,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1859,6 +1947,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -1868,6 +1957,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -1877,6 +1967,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2051,6 +2142,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2060,6 +2152,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2069,6 +2162,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2248,6 +2342,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2257,6 +2352,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2266,6 +2362,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2503,6 +2600,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2512,6 +2610,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2521,6 +2620,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2692,6 +2792,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -2701,6 +2802,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -2710,6 +2812,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3033,6 +3136,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(
@ -3042,6 +3146,7 @@ Config {
): [
Resize(
Decrease,
None,
),
],
Alt(
@ -3051,6 +3156,7 @@ Config {
): [
Resize(
Increase,
None,
),
],
Alt(