feature(resize): Non directional resize (#520)

* feature(resize): Non directional resize

* Implement special cases

* fix resizing for panes that have `+` cross section

* fix resizing for panes that have `T` cross section

* fix panics

* Add Nondirection resize keys to plugin

* fix formatting

* fix: clippy warnings

* fix the last edge case

* implemented some of the suggested changes

* Remove helper function and elevate comment to top of function

* Use `=` to keep it consistent with Normal mode mapping as its easier to use

* Remove extra reference borrowing

* fix an edge case

* add test for nondirectional resize increase/decrease

* fix(controls): add + to resize

* refactor(resize): simplify methods

* fix(resize): properly resize opposite corner pane

Co-authored-by: Aram Drevekenin <aram@poor.dev>
This commit is contained in:
Henil Dedania 2021-11-05 13:59:45 +05:30 committed by GitHub
parent 3e052519f9
commit 4ac9344085
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 743 additions and 21 deletions

View File

@ -90,14 +90,18 @@ fn quicknav_full(palette: Palette) -> LinePart {
let text_first_part = " Tip: ";
let alt = "Alt";
let text_second_part = " + ";
let new_pane_shortcut = "n";
let new_pane_shortcut = "<n>";
let text_third_part = " => open new pane. ";
let second_alt = "Alt";
let text_fourth_part = " + ";
let brackets_navigation = "[]";
let brackets_navigation = "<[]";
let text_fifth_part = " or ";
let hjkl_navigation = "hjkl";
let text_sixths_part = " => navigate between panes.";
let hjkl_navigation = "hjkl>";
let text_sixths_part = " => navigate between panes. ";
let third_alt = "Alt";
let text_seventh_parth = " + ";
let increase_decrease_parth = "<+->";
let text_eighth_parth = " => increase/decrease pane size.";
let len = text_first_part.chars().count()
+ alt.chars().count()
+ text_second_part.chars().count()
@ -108,7 +112,11 @@ fn quicknav_full(palette: Palette) -> LinePart {
+ brackets_navigation.chars().count()
+ text_fifth_part.chars().count()
+ hjkl_navigation.chars().count()
+ text_sixths_part.chars().count();
+ text_sixths_part.chars().count()
+ third_alt.chars().count()
+ text_seventh_parth.chars().count()
+ increase_decrease_parth.chars().count()
+ text_eighth_parth.chars().count();
let green_color = match palette.green {
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
PaletteColor::EightBit(color) => Fixed(color),
@ -119,7 +127,7 @@ fn quicknav_full(palette: Palette) -> LinePart {
};
LinePart {
part: format!(
"{}{}{}{}{}{}{}{}{}{}{}",
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
text_first_part,
Style::new().fg(orange_color).bold().paint(alt),
text_second_part,
@ -134,6 +142,13 @@ fn quicknav_full(palette: Palette) -> LinePart {
text_fifth_part,
Style::new().fg(green_color).bold().paint(hjkl_navigation),
text_sixths_part,
Style::new().fg(orange_color).bold().paint(third_alt),
text_seventh_parth,
Style::new()
.fg(green_color)
.bold()
.paint(increase_decrease_parth),
text_eighth_parth,
),
len,
}
@ -143,14 +158,18 @@ fn quicknav_medium(palette: Palette) -> LinePart {
let text_first_part = " Tip: ";
let alt = "Alt";
let text_second_part = " + ";
let new_pane_shortcut = "n";
let new_pane_shortcut = "<n>";
let text_third_part = " => new pane. ";
let second_alt = "Alt";
let text_fourth_part = " + ";
let brackets_navigation = "[]";
let brackets_navigation = "<[]";
let text_fifth_part = " or ";
let hjkl_navigation = "hjkl";
let text_sixths_part = " => navigate.";
let hjkl_navigation = "hjkl>";
let text_sixths_part = " => navigate. ";
let third_alt = "Alt";
let text_seventh_parth = " + ";
let increase_decrease_parth = "<+->";
let text_eighth_parth = " => resize pane. ";
let len = text_first_part.chars().count()
+ alt.chars().count()
+ text_second_part.chars().count()
@ -161,7 +180,11 @@ fn quicknav_medium(palette: Palette) -> LinePart {
+ brackets_navigation.chars().count()
+ text_fifth_part.chars().count()
+ hjkl_navigation.chars().count()
+ text_sixths_part.chars().count();
+ text_sixths_part.chars().count()
+ third_alt.chars().count()
+ text_seventh_parth.chars().count()
+ increase_decrease_parth.chars().count()
+ text_eighth_parth.chars().count();
let green_color = match palette.green {
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
PaletteColor::EightBit(color) => Fixed(color),
@ -172,7 +195,7 @@ fn quicknav_medium(palette: Palette) -> LinePart {
};
LinePart {
part: format!(
"{}{}{}{}{}{}{}{}{}{}{}",
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
text_first_part,
Style::new().fg(orange_color).bold().paint(alt),
text_second_part,
@ -187,6 +210,13 @@ fn quicknav_medium(palette: Palette) -> LinePart {
text_fifth_part,
Style::new().fg(green_color).bold().paint(hjkl_navigation),
text_sixths_part,
Style::new().fg(orange_color).bold().paint(third_alt),
text_seventh_parth,
Style::new()
.fg(green_color)
.bold()
.paint(increase_decrease_parth),
text_eighth_parth,
),
len,
}
@ -201,6 +231,8 @@ fn quicknav_short(palette: Palette) -> LinePart {
let brackets_navigation = "[]";
let text_fifth_part = "/";
let hjkl_navigation = "hjkl";
let text_sixth_part = "/";
let increase_decrease_part = "+-";
let len = text_first_part.chars().count()
+ alt.chars().count()
+ text_second_part.chars().count()
@ -208,7 +240,9 @@ fn quicknav_short(palette: Palette) -> LinePart {
+ text_third_part.chars().count()
+ brackets_navigation.chars().count()
+ text_fifth_part.chars().count()
+ hjkl_navigation.chars().count();
+ hjkl_navigation.chars().count()
+ text_sixth_part.chars().count()
+ increase_decrease_part.chars().count();
let green_color = match palette.green {
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
PaletteColor::EightBit(color) => Fixed(color),
@ -219,7 +253,7 @@ fn quicknav_short(palette: Palette) -> LinePart {
};
LinePart {
part: format!(
"{}{}{}{}{}{}{}{}",
"{}{}{}{}{}{}{}{}{}{}",
text_first_part,
Style::new().fg(orange_color).bold().paint(alt),
text_second_part,
@ -231,6 +265,11 @@ fn quicknav_short(palette: Palette) -> LinePart {
.paint(brackets_navigation),
text_fifth_part,
Style::new().fg(green_color).bold().paint(hjkl_navigation),
text_sixth_part,
Style::new()
.fg(green_color)
.bold()
.paint(increase_decrease_part),
),
len,
}

View File

@ -12,7 +12,7 @@ use crate::{
use zellij_utils::{
channels::SenderWithContext,
input::{
actions::{Action, Direction},
actions::{Action, Direction, ResizeDirection},
command::TerminalAction,
get_mode_info,
},
@ -87,10 +87,12 @@ fn route_action(
}
Action::Resize(direction) => {
let screen_instr = match direction {
Direction::Left => ScreenInstruction::ResizeLeft(client_id),
Direction::Right => ScreenInstruction::ResizeRight(client_id),
Direction::Up => ScreenInstruction::ResizeUp(client_id),
Direction::Down => ScreenInstruction::ResizeDown(client_id),
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),
};
session.senders.send_to_screen(screen_instr).unwrap();
}

View File

@ -35,6 +35,8 @@ pub(crate) enum ScreenInstruction {
ResizeRight(ClientId),
ResizeDown(ClientId),
ResizeUp(ClientId),
ResizeIncrease(ClientId),
ResizeDecrease(ClientId),
SwitchFocus(ClientId),
FocusNextPane(ClientId),
FocusPreviousPane(ClientId),
@ -95,6 +97,8 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::ResizeRight(..) => ScreenContext::ResizeRight,
ScreenInstruction::ResizeDown(..) => ScreenContext::ResizeDown,
ScreenInstruction::ResizeUp(..) => ScreenContext::ResizeUp,
ScreenInstruction::ResizeIncrease(..) => ScreenContext::ResizeIncrease,
ScreenInstruction::ResizeDecrease(..) => ScreenContext::ResizeDecrease,
ScreenInstruction::SwitchFocus(..) => ScreenContext::SwitchFocus,
ScreenInstruction::FocusNextPane(..) => ScreenContext::FocusNextPane,
ScreenInstruction::FocusPreviousPane(..) => ScreenContext::FocusPreviousPane,
@ -659,6 +663,22 @@ pub(crate) fn screen_thread_main(
screen.render();
}
ScreenInstruction::ResizeIncrease(client_id) => {
screen
.get_active_tab_mut(client_id)
.unwrap()
.resize_increase();
screen.render();
}
ScreenInstruction::ResizeDecrease(client_id) => {
screen
.get_active_tab_mut(client_id)
.unwrap()
.resize_decrease();
screen.render();
}
ScreenInstruction::SwitchFocus(client_id) => {
screen.get_active_tab_mut(client_id).unwrap().move_focus();

View File

@ -1749,6 +1749,308 @@ impl Tab {
false
}
}
fn try_increase_pane_and_surroundings_right(
&mut self,
pane_id: &PaneId,
reduce_by: f64,
) -> bool {
if self.can_increase_pane_and_surroundings_right(pane_id, reduce_by) {
self.increase_pane_and_surroundings_right(pane_id, reduce_by);
self.relayout_tab(Direction::Horizontal);
return true;
}
false
}
fn try_increase_pane_and_surroundings_left(
&mut self,
pane_id: &PaneId,
reduce_by: f64,
) -> bool {
if self.can_increase_pane_and_surroundings_left(pane_id, reduce_by) {
self.increase_pane_and_surroundings_left(pane_id, reduce_by);
self.relayout_tab(Direction::Horizontal);
return true;
}
false
}
fn try_increase_pane_and_surroundings_up(&mut self, pane_id: &PaneId, reduce_by: f64) -> bool {
if self.can_increase_pane_and_surroundings_up(pane_id, reduce_by) {
self.increase_pane_and_surroundings_up(pane_id, reduce_by);
self.relayout_tab(Direction::Vertical);
return true;
}
false
}
fn try_increase_pane_and_surroundings_down(
&mut self,
pane_id: &PaneId,
reduce_by: f64,
) -> bool {
if self.can_increase_pane_and_surroundings_down(pane_id, reduce_by) {
self.increase_pane_and_surroundings_down(pane_id, reduce_by);
self.relayout_tab(Direction::Vertical);
return true;
}
false
}
fn try_increase_pane_and_surroundings_right_and_up(&mut self, pane_id: &PaneId) -> bool {
let can_increase_pane_right =
self.can_increase_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
let can_increase_pane_up =
self.can_increase_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if can_increase_pane_right && can_increase_pane_up {
let pane_above_with_right_aligned_border = self
.viewport_pane_ids_directly_above(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() + active_pane.cols() == pane.x()
});
self.try_increase_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
self.try_increase_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if let Some(pane_above_with_right_aligned_border) = pane_above_with_right_aligned_border
{
self.try_reduce_pane_and_surroundings_right(
&pane_above_with_right_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_increase_pane_and_surroundings_left_and_up(&mut self, pane_id: &PaneId) -> bool {
let can_increase_pane_left =
self.can_increase_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
let can_increase_pane_up =
self.can_increase_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if can_increase_pane_left && can_increase_pane_up {
let pane_above_with_left_aligned_border = self
.viewport_pane_ids_directly_above(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() == pane.x() + pane.cols()
});
self.try_increase_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
self.try_increase_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if let Some(pane_above_with_left_aligned_border) = pane_above_with_left_aligned_border {
self.try_reduce_pane_and_surroundings_left(
&pane_above_with_left_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_increase_pane_and_surroundings_right_and_down(&mut self, pane_id: &PaneId) -> bool {
let can_increase_pane_right =
self.can_increase_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
let can_increase_pane_down =
self.can_increase_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if can_increase_pane_right && can_increase_pane_down {
let pane_below_with_right_aligned_border = self
.viewport_pane_ids_directly_below(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() + active_pane.cols() == pane.x()
});
self.try_increase_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
self.try_increase_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if let Some(pane_below_with_right_aligned_border) = pane_below_with_right_aligned_border
{
self.try_reduce_pane_and_surroundings_right(
&pane_below_with_right_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_increase_pane_and_surroundings_left_and_down(&mut self, pane_id: &PaneId) -> bool {
let can_increase_pane_left =
self.can_increase_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
let can_increase_pane_down =
self.can_increase_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if can_increase_pane_left && can_increase_pane_down {
let pane_below_with_left_aligned_border = self
.viewport_pane_ids_directly_below(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() == pane.x() + pane.cols()
});
self.try_increase_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
self.try_increase_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if let Some(pane_below_with_left_aligned_border) = pane_below_with_left_aligned_border {
self.try_reduce_pane_and_surroundings_left(
&pane_below_with_left_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_reduce_pane_and_surroundings_right_and_up(&mut self, pane_id: &PaneId) -> bool {
let can_reduce_pane_right =
self.can_reduce_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
let can_reduce_pane_up = self.can_reduce_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if can_reduce_pane_right && can_reduce_pane_up {
let pane_below_with_left_aligned_border = self
.viewport_pane_ids_directly_below(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() == pane.x() + pane.cols()
});
self.try_reduce_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
self.try_reduce_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if let Some(pane_below_with_left_aligned_border) = pane_below_with_left_aligned_border {
self.try_increase_pane_and_surroundings_right(
&pane_below_with_left_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_reduce_pane_and_surroundings_left_and_up(&mut self, pane_id: &PaneId) -> bool {
let can_reduce_pane_left =
self.can_reduce_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
let can_reduce_pane_up = self.can_reduce_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if can_reduce_pane_left && can_reduce_pane_up {
let pane_below_with_right_aligned_border = self
.viewport_pane_ids_directly_below(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() + active_pane.cols() == pane.x()
});
self.try_reduce_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
self.try_reduce_pane_and_surroundings_up(pane_id, RESIZE_PERCENT);
if let Some(pane_below_with_right_aligned_border) = pane_below_with_right_aligned_border
{
self.try_increase_pane_and_surroundings_left(
&pane_below_with_right_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_reduce_pane_and_surroundings_right_and_down(&mut self, pane_id: &PaneId) -> bool {
let can_reduce_pane_right =
self.can_reduce_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
let can_reduce_pane_down =
self.can_reduce_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if can_reduce_pane_right && can_reduce_pane_down {
let pane_above_with_left_aligned_border = self
.viewport_pane_ids_directly_above(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() == pane.x() + pane.cols()
});
self.try_reduce_pane_and_surroundings_right(pane_id, RESIZE_PERCENT);
self.try_reduce_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if let Some(pane_above_with_left_aligned_border) = pane_above_with_left_aligned_border {
self.try_increase_pane_and_surroundings_right(
&pane_above_with_left_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_reduce_pane_and_surroundings_left_and_down(&mut self, pane_id: &PaneId) -> bool {
let can_reduce_pane_left =
self.can_reduce_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
let can_reduce_pane_down =
self.can_reduce_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if can_reduce_pane_left && can_reduce_pane_down {
let pane_above_with_right_aligned_border = self
.viewport_pane_ids_directly_above(pane_id)
.iter()
.copied()
.find(|p_id| {
let pane = self.panes.get(p_id).unwrap();
let active_pane = self.panes.get(pane_id).unwrap();
active_pane.x() + active_pane.cols() == pane.x()
});
self.try_reduce_pane_and_surroundings_left(pane_id, RESIZE_PERCENT);
self.try_reduce_pane_and_surroundings_down(pane_id, RESIZE_PERCENT);
if let Some(pane_above_with_right_aligned_border) = pane_above_with_right_aligned_border
{
self.try_increase_pane_and_surroundings_left(
&pane_above_with_right_aligned_border,
RESIZE_PERCENT,
);
}
true
} else {
false
}
}
fn try_reduce_pane_and_surroundings_right(&mut self, pane_id: &PaneId, reduce_by: f64) -> bool {
if self.can_reduce_pane_and_surroundings_right(pane_id, reduce_by) {
self.reduce_pane_and_surroundings_right(pane_id, reduce_by);
self.relayout_tab(Direction::Horizontal);
return true;
}
false
}
fn try_reduce_pane_and_surroundings_left(&mut self, pane_id: &PaneId, reduce_by: f64) -> bool {
if self.can_reduce_pane_and_surroundings_left(pane_id, reduce_by) {
self.reduce_pane_and_surroundings_left(pane_id, reduce_by);
self.relayout_tab(Direction::Horizontal);
return true;
}
false
}
fn try_reduce_pane_and_surroundings_up(&mut self, pane_id: &PaneId, reduce_by: f64) -> bool {
if self.can_reduce_pane_and_surroundings_up(pane_id, reduce_by) {
self.reduce_pane_and_surroundings_up(pane_id, reduce_by);
self.relayout_tab(Direction::Vertical);
return true;
}
false
}
fn try_reduce_pane_and_surroundings_down(&mut self, pane_id: &PaneId, reduce_by: f64) -> bool {
if self.can_reduce_pane_and_surroundings_down(pane_id, reduce_by) {
self.reduce_pane_and_surroundings_down(pane_id, reduce_by);
self.relayout_tab(Direction::Vertical);
return true;
}
false
}
fn ids_are_flexible(&self, direction: Direction, pane_ids: Option<Vec<PaneId>>) -> bool {
pane_ids.is_some()
&& pane_ids.unwrap().iter().all(|id| {
@ -1840,6 +2142,60 @@ impl Tab {
}
self.relayout_tab(Direction::Vertical);
}
pub fn resize_increase(&mut self) {
if let Some(active_pane_id) = self.get_active_pane_id() {
if self.try_increase_pane_and_surroundings_right_and_down(&active_pane_id) {
return;
}
if self.try_increase_pane_and_surroundings_left_and_down(&active_pane_id) {
return;
}
if self.try_increase_pane_and_surroundings_right_and_up(&active_pane_id) {
return;
}
if self.try_increase_pane_and_surroundings_left_and_up(&active_pane_id) {
return;
}
if self.try_increase_pane_and_surroundings_right(&active_pane_id, RESIZE_PERCENT) {
return;
}
if self.try_increase_pane_and_surroundings_down(&active_pane_id, RESIZE_PERCENT) {
return;
}
if self.try_increase_pane_and_surroundings_left(&active_pane_id, RESIZE_PERCENT) {
return;
}
self.try_increase_pane_and_surroundings_up(&active_pane_id, RESIZE_PERCENT);
}
}
pub fn resize_decrease(&mut self) {
if let Some(active_pane_id) = self.get_active_pane_id() {
if self.try_reduce_pane_and_surroundings_left_and_up(&active_pane_id) {
return;
}
if self.try_reduce_pane_and_surroundings_right_and_up(&active_pane_id) {
return;
}
if self.try_reduce_pane_and_surroundings_right_and_down(&active_pane_id) {
return;
}
if self.try_reduce_pane_and_surroundings_left_and_down(&active_pane_id) {
return;
}
if self.try_reduce_pane_and_surroundings_left(&active_pane_id, RESIZE_PERCENT) {
return;
}
if self.try_reduce_pane_and_surroundings_right(&active_pane_id, RESIZE_PERCENT) {
return;
}
if self.try_reduce_pane_and_surroundings_up(&active_pane_id, RESIZE_PERCENT) {
return;
}
self.try_reduce_pane_and_surroundings_down(&active_pane_id, RESIZE_PERCENT);
}
}
pub fn move_focus(&mut self) {
if !self.has_selectable_panes() {
return;
@ -2420,6 +2776,20 @@ impl Tab {
pub fn get_pane_ids(&self) -> Vec<PaneId> {
self.get_panes().map(|(&pid, _)| pid).collect()
}
fn viewport_pane_ids_directly_above(&self, active_pane_id: &PaneId) -> Vec<PaneId> {
self.pane_ids_directly_above(active_pane_id)
.unwrap_or_default()
.into_iter()
.filter(|id| self.is_inside_viewport(id))
.collect()
}
fn viewport_pane_ids_directly_below(&self, active_pane_id: &PaneId) -> Vec<PaneId> {
self.pane_ids_directly_below(active_pane_id)
.unwrap_or_default()
.into_iter()
.filter(|id| self.is_inside_viewport(id))
.collect()
}
pub fn set_pane_selectable(&mut self, id: PaneId, selectable: bool) {
if let Some(pane) = self.panes.get_mut(&id) {
pane.set_selectable(selectable);

View File

@ -12387,3 +12387,267 @@ pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() {
"pane 2 height stayed the same"
);
}
#[test]
pub fn nondirectional_resize_increase_with_1_pane() {
let size = Size {
cols: 121,
rows: 10,
};
let mut tab = create_new_tab(size);
tab.resize_increase();
assert_eq!(
tab.get_active_pane().unwrap().position_and_size().y,
0,
"There is only 1 pane so both coordinates should be 0"
);
assert_eq!(
tab.get_active_pane().unwrap().position_and_size().x,
0,
"There is only 1 pane so both coordinates should be 0"
);
}
#[test]
pub fn nondirectional_resize_increase_with_1_pane_to_left() {
let size = Size {
cols: 121,
rows: 10,
};
let mut tab = create_new_tab(size);
let new_pane_id_1 = PaneId::Terminal(2);
tab.vertical_split(new_pane_id_1);
tab.resize_increase();
// should behave like `resize_left_with_pane_to_the_left`
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.x,
54,
"pane 2 x position"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.y,
0,
"pane 2 y position"
);
}
#[test]
pub fn nondirectional_resize_increase_with_2_panes_to_left() {
let size = Size {
cols: 121,
rows: 20,
};
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2));
tab.move_focus_left();
tab.horizontal_split(PaneId::Terminal(3));
tab.move_focus_right();
tab.resize_increase();
// should behave like `resize_left_with_multiple_panes_to_the_left`
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.x,
54,
"pane 2 x position"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.y,
0,
"pane 2 y position"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.cols
.as_usize(),
67,
"pane 2 column count"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.rows
.as_usize(),
20,
"pane 2 row count"
);
}
#[test]
pub fn nondirectional_resize_increase_with_1_pane_to_right_1_pane_above() {
let size = Size {
cols: 121,
rows: 20,
};
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2));
tab.move_focus_left();
tab.horizontal_split(PaneId::Terminal(3));
tab.resize_increase();
assert_eq!(
tab.panes
.get(&PaneId::Terminal(3))
.unwrap()
.position_and_size()
.y,
9,
"Pane 3 y coordinate"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(3))
.unwrap()
.position_and_size()
.x,
0,
"Pane 3 x coordinate"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(3))
.unwrap()
.position_and_size()
.rows
.as_usize(),
11,
"Pane 3 row count"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(3))
.unwrap()
.position_and_size()
.cols
.as_usize(),
67,
"Pane 3 col count"
);
}
#[test]
pub fn nondirectional_resize_increase_with_1_pane_to_right_1_pane_to_left() {
let size = Size {
cols: 121,
rows: 20,
};
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2));
tab.vertical_split(PaneId::Terminal(3));
tab.move_focus_left();
tab.resize_increase();
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.y,
0,
"Pane 3 y coordinate"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.x,
61,
"Pane 3 x coordinate"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.rows
.as_usize(),
20,
"Pane 3 row count"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.cols
.as_usize(),
36,
"Pane 3 col count"
);
}
#[test]
pub fn nondirectional_resize_increase_with_pane_above_aligned_right_with_current_pane() {
let size = Size {
cols: 121,
rows: 20,
};
let mut tab = create_new_tab(size);
tab.vertical_split(PaneId::Terminal(2));
tab.vertical_split(PaneId::Terminal(3));
tab.move_focus_left();
tab.resize_increase();
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.y,
0,
"Pane 3 y coordinate"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.x,
61,
"Pane 3 x coordinate"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.rows
.as_usize(),
20,
"Pane 3 row count"
);
assert_eq!(
tab.panes
.get(&PaneId::Terminal(2))
.unwrap()
.position_and_size()
.cols
.as_usize(),
36,
"Pane 3 col count"
);
}

View File

@ -38,6 +38,12 @@ keybinds:
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
- action: [Resize: Increase,]
key: [ Alt: '=']
- action: [Resize: Increase,]
key: [ Alt: '+']
- action: [Resize: Decrease,]
key: [ Alt: '-']
locked:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'g',]
@ -66,6 +72,12 @@ keybinds:
key: [Char: 'k', Up, ]
- action: [Resize: Right,]
key: [Char: 'l', Right,]
- action: [Resize: Increase,]
key: [Char: '=']
- action: [Resize: Increase,]
key: [ Alt: '+']
- action: [Resize: Decrease,]
key: [Char: '-']
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]

View File

@ -216,6 +216,8 @@ pub enum ScreenContext {
ResizeRight,
ResizeDown,
ResizeUp,
ResizeIncrease,
ResizeDecrease,
SwitchFocus,
FocusNextPane,
FocusPreviousPane,

View File

@ -17,6 +17,16 @@ pub enum Direction {
Down,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub enum ResizeDirection {
Left,
Right,
Up,
Down,
Increase,
Decrease,
}
// As these actions are bound to the default config, please
// do take care when refactoring - or renaming.
// They might need to be adjusted in the default config
@ -33,7 +43,7 @@ pub enum Action {
/// Switch to the specified input mode.
SwitchToMode(InputMode),
/// Resize focus pane in specified direction.
Resize(Direction),
Resize(ResizeDirection),
/// Switch focus to next pane in specified direction.
FocusNextPane,
FocusPreviousPane,

View File

@ -22,7 +22,10 @@ pub fn get_mode_info(
) -> ModeInfo {
let keybinds = match mode {
InputMode::Normal | InputMode::Locked => Vec::new(),
InputMode::Resize => vec![("←↓↑→".to_string(), "Resize".to_string())],
InputMode::Resize => vec![
("←↓↑→".to_string(), "Resize".to_string()),
("+-".to_string(), "Increase/Decrease size".to_string()),
],
InputMode::Move => vec![
("←↓↑→".to_string(), "Move".to_string()),
("n/Tab".to_string(), "Next Pane".to_string()),