mirror of
https://github.com/zellij-org/zellij.git
synced 2024-11-22 22:26:54 +03:00
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:
parent
3e052519f9
commit
4ac9344085
@ -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,
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
@ -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,]
|
||||
|
@ -216,6 +216,8 @@ pub enum ScreenContext {
|
||||
ResizeRight,
|
||||
ResizeDown,
|
||||
ResizeUp,
|
||||
ResizeIncrease,
|
||||
ResizeDecrease,
|
||||
SwitchFocus,
|
||||
FocusNextPane,
|
||||
FocusPreviousPane,
|
||||
|
@ -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,
|
||||
|
@ -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()),
|
||||
|
Loading…
Reference in New Issue
Block a user