New behavior for h and l

New behavior for h and l, will change tabs if there are no available
panes in the direction.

cargo clippy

Ensuring atomicity for the MoveFocusOrTab

- Blocking the input thread for the action MoveFocusOrTab
- Using "unreachable" macro in match arm to make it clear that the
directions Up and Down should not be used with the action MoveFocusOrTab

Adding tests
This commit is contained in:
Dante Pippi 2021-05-07 18:19:23 -03:00
parent 2cd433d0d6
commit 9c09cf1658
13 changed files with 169 additions and 19 deletions

View File

@ -16,9 +16,9 @@ keybinds:
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
- action: [MoveFocusOrTab: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
- action: [MoveFocusOrTab: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]

View File

@ -16,9 +16,9 @@ keybinds:
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
- action: [MoveFocusOrTab: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
- action: [MoveFocusOrTab: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]

View File

@ -17,9 +17,9 @@ keybinds:
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
- action: [MoveFocusOrTab: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
- action: [MoveFocusOrTab: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]

View File

@ -1848,12 +1848,13 @@ impl Tab {
}
self.render();
}
pub fn move_focus_left(&mut self) {
// returns a boolean to allow the caller to know if the move happened or not
pub fn move_focus_left(&mut self) -> bool {
if !self.has_selectable_panes() {
return;
return false;
}
if self.fullscreen_is_active {
return;
return false;
}
let active_terminal = self.get_active_pane();
if let Some(active) = active_terminal {
@ -1868,6 +1869,8 @@ impl Tab {
match next_index {
Some(&p) => {
self.active_terminal = Some(p);
self.render();
return true;
}
None => {
self.active_terminal = Some(active.pid());
@ -1876,7 +1879,7 @@ impl Tab {
} else {
self.active_terminal = Some(active_terminal.unwrap().pid());
}
self.render();
false
}
pub fn move_focus_down(&mut self) {
if !self.has_selectable_panes() {
@ -1938,12 +1941,13 @@ impl Tab {
}
self.render();
}
pub fn move_focus_right(&mut self) {
// returns a boolean to allow the caller to know if the move happened or not
pub fn move_focus_right(&mut self) -> bool {
if !self.has_selectable_panes() {
return;
return false;
}
if self.fullscreen_is_active {
return;
return false;
}
let active_terminal = self.get_active_pane();
if let Some(active) = active_terminal {
@ -1958,6 +1962,8 @@ impl Tab {
match next_index {
Some(&p) => {
self.active_terminal = Some(p);
self.render();
return true;
}
None => {
self.active_terminal = Some(active.pid());
@ -1966,7 +1972,7 @@ impl Tab {
} else {
self.active_terminal = Some(active_terminal.unwrap().pid());
}
self.render();
false
}
fn horizontal_borders(&self, terminals: &[PaneId]) -> HashSet<usize> {
terminals.iter().fold(HashSet::new(), |mut borders, t| {

View File

@ -192,9 +192,11 @@ pub enum ScreenContext {
FocusNextPane,
FocusPreviousPane,
MoveFocusLeft,
MoveFocusLeftOrPreviousTab,
MoveFocusDown,
MoveFocusUp,
MoveFocusRight,
MoveFocusRightOrNextTab,
Exit,
ScrollUp,
ScrollDown,
@ -237,9 +239,13 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::FocusNextPane => ScreenContext::FocusNextPane,
ScreenInstruction::FocusPreviousPane => ScreenContext::FocusPreviousPane,
ScreenInstruction::MoveFocusLeft => ScreenContext::MoveFocusLeft,
ScreenInstruction::MoveFocusLeftOrPreviousTab => {
ScreenContext::MoveFocusLeftOrPreviousTab
}
ScreenInstruction::MoveFocusDown => ScreenContext::MoveFocusDown,
ScreenInstruction::MoveFocusUp => ScreenContext::MoveFocusUp,
ScreenInstruction::MoveFocusRight => ScreenContext::MoveFocusRight,
ScreenInstruction::MoveFocusRightOrNextTab => ScreenContext::MoveFocusRightOrNextTab,
ScreenInstruction::Exit => ScreenContext::Exit,
ScreenInstruction::ScrollUp => ScreenContext::ScrollUp,
ScreenInstruction::ScrollDown => ScreenContext::ScrollDown,

View File

@ -29,6 +29,9 @@ pub enum Action {
/// Move the focus pane in specified direction.
SwitchFocus,
MoveFocus(Direction),
/// Tries to move the focus pane in specified direction.
/// If there is no pane in the direction, move to previous/next Tab.
MoveFocusOrTab(Direction),
/// Scroll up in focus pane.
ScrollUp,
/// Scroll down in focus pane.

View File

@ -119,7 +119,8 @@ impl InputHandler {
| Action::GoToNextTab
| Action::GoToPreviousTab
| Action::CloseTab
| Action::GoToTab(_) => {
| Action::GoToTab(_)
| Action::MoveFocusOrTab(_) => {
self.command_is_executing.blocking_input_thread();
self.os_input
.send_to_server(ServerInstruction::Action(action));

View File

@ -33,9 +33,11 @@ pub enum ScreenInstruction {
FocusNextPane,
FocusPreviousPane,
MoveFocusLeft,
MoveFocusLeftOrPreviousTab,
MoveFocusDown,
MoveFocusUp,
MoveFocusRight,
MoveFocusRightOrNextTab,
Exit,
ScrollUp,
ScrollDown,

View File

@ -7,8 +7,9 @@ use crate::{start, CliArgs};
use crate::common::input::config::Config;
use crate::tests::utils::commands::{
MOVE_FOCUS_LEFT_IN_PANE_MODE, MOVE_FOCUS_RIGHT_IN_PANE_MODE, PANE_MODE, QUIT,
SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
ENTER, MOVE_FOCUS_LEFT_IN_NORMAL_MODE, MOVE_FOCUS_LEFT_IN_PANE_MODE,
MOVE_FOCUS_RIGHT_IN_PANE_MODE, NEW_TAB_IN_TAB_MODE, PANE_MODE, QUIT, SPLIT_DOWN_IN_PANE_MODE,
SPLIT_RIGHT_IN_PANE_MODE, TAB_MODE,
};
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
@ -86,3 +87,41 @@ pub fn move_focus_left_to_the_most_recently_used_pane() {
get_next_to_last_snapshot(snapshots).expect("could not find snapshot");
assert_snapshot!(snapshot_before_quit);
}
#[test]
pub fn move_focus_left_changes_tab() {
let fake_win_size = PositionAndSize {
columns: 121,
rows: 20,
x: 0,
y: 0,
..Default::default()
};
let mut fake_input_output = get_fake_os_input(&fake_win_size);
fake_input_output.add_terminal_input(&[
&PANE_MODE,
&SPLIT_DOWN_IN_PANE_MODE,
&ENTER,
&TAB_MODE,
&NEW_TAB_IN_TAB_MODE,
&ENTER,
&MOVE_FOCUS_LEFT_IN_NORMAL_MODE,
&QUIT,
]);
start(
Box::new(fake_input_output.clone()),
CliArgs::default(),
Box::new(fake_input_output.clone()),
Config::default(),
);
let output_frames = fake_input_output
.stdout_writer
.output_frames
.lock()
.unwrap();
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
let snapshot_before_quit =
get_next_to_last_snapshot(snapshots).expect("could not find snapshot");
assert_snapshot!(snapshot_before_quit);
}

View File

@ -7,8 +7,9 @@ use crate::{start, CliArgs};
use crate::common::input::config::Config;
use crate::tests::utils::commands::{
MOVE_FOCUS_LEFT_IN_PANE_MODE, MOVE_FOCUS_RIGHT_IN_PANE_MODE, PANE_MODE, QUIT,
SPLIT_DOWN_IN_PANE_MODE, SPLIT_RIGHT_IN_PANE_MODE,
ENTER, MOVE_FOCUS_LEFT_IN_PANE_MODE, MOVE_FOCUS_RIGHT_IN_NORMAL_MODE,
MOVE_FOCUS_RIGHT_IN_PANE_MODE, NEW_TAB_IN_TAB_MODE, PANE_MODE, QUIT, SPLIT_DOWN_IN_PANE_MODE,
SPLIT_RIGHT_IN_PANE_MODE, TAB_MODE,
};
fn get_fake_os_input(fake_win_size: &PositionAndSize) -> FakeInputOutput {
@ -86,3 +87,41 @@ pub fn move_focus_right_to_the_most_recently_used_pane() {
get_next_to_last_snapshot(snapshots).expect("could not find snapshot");
assert_snapshot!(snapshot_before_quit);
}
#[test]
pub fn move_focus_right_changes_tab() {
let fake_win_size = PositionAndSize {
columns: 121,
rows: 20,
x: 0,
y: 0,
..Default::default()
};
let mut fake_input_output = get_fake_os_input(&fake_win_size);
fake_input_output.add_terminal_input(&[
&PANE_MODE,
&SPLIT_DOWN_IN_PANE_MODE,
&ENTER,
&TAB_MODE,
&NEW_TAB_IN_TAB_MODE,
&ENTER,
&MOVE_FOCUS_RIGHT_IN_NORMAL_MODE,
&QUIT,
]);
start(
Box::new(fake_input_output.clone()),
CliArgs::default(),
Box::new(fake_input_output.clone()),
Config::default(),
);
let output_frames = fake_input_output
.stdout_writer
.output_frames
.lock()
.unwrap();
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
let snapshot_before_quit =
get_next_to_last_snapshot(snapshots).expect("could not find snapshot");
assert_snapshot!(snapshot_before_quit);
}

View File

@ -0,0 +1,25 @@
---
source: src/tests/integration/move_focus_left.rs
expression: snapshot_before_quit
---
line11-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line12-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line13-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line14-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line15-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line16-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line17-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line18-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line19-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
prompt $
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
line12-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line13-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line14-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line15-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line16-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line17-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line18-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line19-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
prompt $ █

View File

@ -0,0 +1,25 @@
---
source: src/tests/integration/move_focus_right.rs
expression: snapshot_before_quit
---
line11-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line12-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line13-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line14-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line15-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line16-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line17-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line18-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line19-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
prompt $
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
line12-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line13-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line14-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line15-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line16-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line17-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line18-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
line19-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
prompt $ █

View File

@ -47,6 +47,10 @@ pub fn get_next_to_last_snapshot(mut snapshots: Vec<String>) -> Option<String> {
pub mod commands {
pub const QUIT: [u8; 1] = [17]; // ctrl-q
pub const ESC: [u8; 1] = [27];
pub const ENTER: [u8; 1] = [10]; // char '\n'
pub const MOVE_FOCUS_LEFT_IN_NORMAL_MODE: [u8; 2] = [27, 104]; // alt-h
pub const MOVE_FOCUS_RIGHT_IN_NORMAL_MODE: [u8; 2] = [27, 108]; // alt-l
pub const PANE_MODE: [u8; 1] = [16]; // ctrl-p
pub const SPAWN_TERMINAL_IN_PANE_MODE: [u8; 1] = [110]; // n