summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartosz Zbytniewski <50180524+devzbysiu@users.noreply.github.com>2024-02-18 19:40:03 +0100
committerGitHub <noreply@github.com>2024-02-19 03:40:03 +0900
commitdd5ea26cc72f3c39e9f8b4d8452a42c9c2f85442 (patch)
treee37c0d0b75d7edb7538c44ba10ba752d8ff68497
parentb677ffe75fb8e518441a0bd7df02abfb8dcc4989 (diff)
feat: add moving tab to other position (#3047)
* feat: add moving tab to other position * docs(changelog): revert changes * test: update config snapshots * refactor: get rid of HorizontalDirection enum * refactor: cleanup code order * refactor: use debug! instead of info! * refactor: use more defensive way to switch tabs * refactor: revert tip changes * refactor: code formatting * refactor: improve invalid input notification * refactor: inline fns for calculating target index --------- Co-authored-by: Jae-Heon Ji <atx6419@gmail.com>
-rw-r--r--default-plugins/status-bar/src/tip/data/mod.rs9
-rw-r--r--default-plugins/status-bar/src/tip/data/move_tabs.rs69
-rw-r--r--src/tests/e2e/cases.rs123
-rw-r--r--src/tests/e2e/mod.rs1
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left.snap29
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left_until_it_wraps_around.snap28
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right.snap29
-rw-r--r--src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right_until_it_wraps_around.snap28
-rw-r--r--src/tests/e2e/steps.rs153
-rw-r--r--zellij-client/src/input_handler.rs1
-rw-r--r--zellij-server/src/route.rs10
-rw-r--r--zellij-server/src/screen.rs100
-rw-r--r--zellij-server/src/unit/screen_tests.rs144
-rw-r--r--zellij-utils/assets/config/default.kdl2
-rwxr-xr-xzellij-utils/assets/plugins/compact-bar.wasmbin887621 -> 888446 bytes
-rwxr-xr-xzellij-utils/assets/plugins/fixture-plugin-for-tests.wasmbin873465 -> 874943 bytes
-rwxr-xr-xzellij-utils/assets/plugins/session-manager.wasmbin926195 -> 927194 bytes
-rwxr-xr-xzellij-utils/assets/plugins/status-bar.wasmbin1029901 -> 1034014 bytes
-rwxr-xr-xzellij-utils/assets/plugins/strider.wasmbin2109959 -> 2111079 bytes
-rwxr-xr-xzellij-utils/assets/plugins/tab-bar.wasmbin868307 -> 869437 bytes
-rw-r--r--zellij-utils/assets/prost/api.action.rs33
-rw-r--r--zellij-utils/src/errors.rs2
-rw-r--r--zellij-utils/src/input/actions.rs1
-rw-r--r--zellij-utils/src/kdl/mod.rs23
-rw-r--r--zellij-utils/src/plugin_api/action.proto7
-rw-r--r--zellij-utils/src/plugin_api/action.rs52
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap234
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap234
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_plugins_override_config_plugins.snap234
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap234
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap234
31 files changed, 2007 insertions, 7 deletions
diff --git a/default-plugins/status-bar/src/tip/data/mod.rs b/default-plugins/status-bar/src/tip/data/mod.rs
index 1354b1ab4..731fa7772 100644
--- a/default-plugins/status-bar/src/tip/data/mod.rs
+++ b/default-plugins/status-bar/src/tip/data/mod.rs
@@ -8,6 +8,7 @@ mod compact_layout;
mod edit_scrollbuffer;
mod floating_panes_mouse;
mod move_focus_hjkl_tab_switch;
+mod move_tabs;
mod quicknav;
mod send_mouse_click_to_terminal;
mod sync_tab;
@@ -88,5 +89,13 @@ lazy_static! {
full: compact_layout::compact_layout_full,
}
),
+ (
+ "move_tabs",
+ TipBody {
+ short: move_tabs::move_tabs_short,
+ medium: move_tabs::move_tabs_medium,
+ full: move_tabs::move_tabs_full,
+ }
+ )
]);
}
diff --git a/default-plugins/status-bar/src/tip/data/move_tabs.rs b/default-plugins/status-bar/src/tip/data/move_tabs.rs
new file mode 100644
index 000000000..6ad119e49
--- /dev/null
+++ b/default-plugins/status-bar/src/tip/data/move_tabs.rs
@@ -0,0 +1,69 @@
+use ansi_term::{
+ unstyled_len, ANSIString, ANSIStrings,
+ Color::{Fixed, RGB},
+ Style,
+};
+
+use zellij_tile::prelude::*;
+use zellij_tile_utils::palette_match;
+
+use crate::LinePart;
+
+macro_rules! strings {
+ ($ANSIStrings:expr) => {{
+ let strings: &[ANSIString] = $ANSIStrings;
+
+ let ansi_strings = ANSIStrings(strings);
+
+ LinePart {
+ part: format!("{}", ansi_strings),
+ len: unstyled_len(&ansi_strings),
+ }
+ }};
+}
+
+pub fn move_tabs_full(help: &ModeInfo) -> LinePart {
+ // Tip: Wrong order of tabs? You can move them to left and right with:
+ // Alt + i (left) and Alt + o (right)
+ let green_color = palette_match!(help.style.colors.green);
+
+ let bits = vec![
+ Style::new().paint(" Tip: "),
+ Style::new().paint("Wrong order of tabs? You can move them to left and right with: "),
+ Style::new().fg(green_color).bold().paint("Alt + i"),
+ Style::new().paint(" (left) and "),
+ Style::new().fg(green_color).bold().paint("Alt + o"),
+ Style::new().paint(" (right)"),
+ ];
+ strings!(&bits)
+}
+
+pub fn move_tabs_medium(help: &ModeInfo) -> LinePart {
+ // Tip: You can move tabs to left and right with:
+ // Alt + i (left) and Alt + o (right)
+ let green_color = palette_match!(help.style.colors.green);
+
+ let bits = vec![
+ Style::new().paint(" Tip: "),
+ Style::new().paint("You can move tabs to left and right with: "),
+ Style::new().fg(green_color).bold().paint("Alt + i"),
+ Style::new().paint(" (left) and "),
+ Style::new().fg(green_color).bold().paint("Alt + o"),
+ Style::new().paint(" (right)"),
+ ];
+ strings!(&bits)
+}
+
+pub fn move_tabs_short(help: &ModeInfo) -> LinePart {
+ // Move tabs with: Alt + i (left) and Alt + o (right)
+ let green_color = palette_match!(help.style.colors.green);
+
+ let bits = vec![
+ Style::new().paint(" Move tabs with: "),
+ Style::new().fg(green_color).bold().paint("Alt + i"),
+ Style::new().paint(" (left) and "),
+ Style::new().fg(green_color).bold().paint("Alt + o"),
+ Style::new().paint(" (right)"),
+ ];
+ strings!(&bits)
+}
diff --git a/src/tests/e2e/cases.rs b/src/tests/e2e/cases.rs
index be337ea92..f2dd09332 100644
--- a/src/tests/e2e/cases.rs
+++ b/src/tests/e2e/cases.rs
@@ -9,6 +9,13 @@ use regex::Regex;
use std::fmt::Write;
use std::path::Path;
+use crate::tests::e2e::steps::{
+ check_focus_on_second_tab, check_second_tab_opened, check_third_tab_is_left_wrapped,
+ check_third_tab_is_right_wrapped, check_third_tab_moved_left,
+ check_third_tab_moved_to_beginning, check_third_tab_opened, move_tab_left, move_tab_right,
+ new_tab, switch_focus_to_left_tab, type_second_tab_content,
+};
+
use super::remote_runner::{RemoteRunner, RemoteTerminal, Step};
pub const QUIT: [u8; 1] = [17]; // ctrl-q
@@ -56,6 +63,9 @@ pub const SWITCH_PREV_TAB_IN_TAB_MODE: [u8; 1] = [104]; // h
pub const CLOSE_TAB_IN_TAB_MODE: [u8; 1] = [120]; // x
pub const RENAME_TAB_MODE: [u8; 1] = [114]; // r
+pub const MOVE_TAB_LEFT: [u8; 2] = [27, 105]; // Alt + i
+pub const MOVE_TAB_RIGHT: [u8; 2] = [27, 111]; // Alt + o
+
pub const SESSION_MODE: [u8; 1] = [15]; // ctrl-o
pub const DETACH_IN_SESSION_MODE: [u8; 1] = [100]; // d
@@ -63,6 +73,9 @@ pub const BRACKETED_PASTE_START: [u8; 6] = [27, 91, 50, 48, 48, 126]; // \u{1b}[
pub const BRACKETED_PASTE_END: [u8; 6] = [27, 91, 50, 48, 49, 126]; // \u{1b}[201
pub const SLEEP: [u8; 0] = [];
+pub const SECOND_TAB_CONTENT: [u8; 14] =
+ [84, 97, 98, 32, 35, 50, 32, 99, 111, 110, 116, 101, 110, 116]; // Tab #2 content
+
pub fn sgr_mouse_report(position: Position, button: u8) -> Vec<u8> {
// button: (release is with lower case m, not supported here yet)
// 0 => left click
@@ -513,6 +526,116 @@ pub fn close_tab() {
#[test]
#[ignore]
+pub fn move_tab_to_left() {
+ let mut test_attempts = 10;
+ let last_snapshot = loop {
+ RemoteRunner::kill_running_sessions(fake_win_size());
+ let mut runner = RemoteRunner::new(fake_win_size())
+ .add_step(new_tab())
+ .add_step(check_second_tab_opened())
+ .add_step(new_tab())
+ .add_step(check_third_tab_opened()) // should have Tab#1 >> Tab#2 >> Tab#3 (focused on Tab#3)
+ .add_step(move_tab_left()); // now, it should be Tab#1 >> Tab#3 >> Tab#2
+
+ runner.run_all_steps();
+
+ let last_snapshot = runner.take_snapshot_after(check_third_tab_moved_left());
+ if !runner.test_timed_out || test_attempts == 0 {
+ break last_snapshot;
+ }
+ test_attempts -= 1;
+ };
+ assert_snapshot!(account_for_races_in_snapshot(last_snapshot));
+}
+
+fn fake_win_size() -> Size {
+ Size {
+ cols: 120,
+ rows: 24,
+ }
+}
+
+#[test]
+#[ignore]
+pub fn move_tab_to_right() {
+ let mut test_attempts = 10;
+ let last_snapshot = loop {
+ RemoteRunner::kill_running_sessions(fake_win_size());
+ let mut runner = RemoteRunner::new(fake_win_size())
+ .add_step(new_tab())
+ .add_step(check_second_tab_opened())
+ .add_step(type_second_tab_content()) // allows verifying the focus later
+ .add_step(new_tab())
+ .add_step(check_third_tab_opened())
+ .add_step(switch_focus_to_left_tab())
+ .add_step(check_focus_on_second_tab()) // should have Tab#1 >> Tab#2 >> Tab#3 (focused on Tab#2)
+ .add_step(move_tab_right()); // now, it should be Tab#1 >> Tab#3 >> Tab#2
+
+ runner.run_all_steps();
+
+ let last_snapshot = runner.take_snapshot_after(check_third_tab_moved_left());
+ if !runner.test_timed_out || test_attempts == 0 {
+ break last_snapshot;
+ }
+ test_attempts -= 1;
+ };
+ assert_snapshot!(account_for_races_in_snapshot(last_snapshot));
+}
+
+#[test]
+#[ignore]
+pub fn move_tab_to_left_until_it_wraps_around() {
+ let mut test_attempts = 10;
+ let last_snapshot = loop {
+ RemoteRunner::kill_running_sessions(fake_win_size());
+ let mut runner = RemoteRunner::new(fake_win_size())
+ .add_step(new_tab())
+ .add_step(check_second_tab_opened())
+ .add_step(new_tab())
+ .add_step(check_third_tab_opened())
+ .add_step(move_tab_left())
+ .add_step(check_third_tab_moved_left())
+ .add_step(move_tab_left())
+ .add_step(check_third_tab_moved_to_beginning()) // should have Tab#3 >> Tab#1 >> Tab#2 (focused on Tab#3)
+ .add_step(move_tab_left()); // now, it should be Tab#2 >> Tab#1 >> Tab#3
+
+ runner.run_all_steps();
+
+ let last_snapshot = runner.take_snapshot_after(check_third_tab_is_left_wrapped());
+ if !runner.test_timed_out || test_attempts == 0 {
+ break last_snapshot;
+ }
+ test_attempts -= 1;
+ };
+ assert_snapshot!(account_for_races_in_snapshot(last_snapshot));
+}
+
+#[test]
+#[ignore]
+pub fn move_tab_to_right_until_it_wraps_around() {
+ let mut test_attempts = 10;
+ let last_snapshot = loop {
+ RemoteRunner::kill_running_sessions(fake_win_size());
+ let mut runner = RemoteRunner::new(fake_win_size())
+ .add_step(new_tab())
+ .add_step(check_second_tab_opened())
+ .add_step(new_tab())
+ .add_step(check_third_tab_opened()) // should have Tab#1 >> Tab#2 >> Tab#3 (focused on Tab#3)
+ .add_step(move_tab_right()); // now, it should be Tab#3 >> Tab#2 >> Tab#1
+
+ runner.run_all_steps();
+
+ let last_snapshot = runner.take_snapshot_after(check_third_tab_is_right_wrapped());
+ if !runner.test_timed_out || test_attempts == 0 {
+ break last_snapshot;
+ }
+ test_attempts -= 1;
+ };
+ assert_snapshot!(account_for_races_in_snapshot(last_snapshot));
+}
+
+#[test]
+#[ignore]
pub fn close_pane() {
let fake_win_size = Size {
cols: 120,
diff --git a/src/tests/e2e/mod.rs b/src/tests/e2e/mod.rs
index 3cf635425..05f2cc8cd 100644
--- a/src/tests/e2e/mod.rs
+++ b/src/tests/e2e/mod.rs
@@ -1,2 +1,3 @@
pub mod cases;
mod remote_runner;
+mod steps;
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left.snap
new file mode 100644
index 000000000..2e3add784
--- /dev/null
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left.snap
@@ -0,0 +1,29 @@
+---
+source: src/tests/e2e/cases.rs
+assertion_line: 531
+expression: account_for_races_in_snapshot(last_snapshot)
+---
+ Zellij (e2e-test)  Tab #1  Tab #3  Tab #2 
+┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
+│$ █ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+ Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left_until_it_wraps_around.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left_until_it_wraps_around.snap
new file mode 100644
index 000000000..9479e355c
--- /dev/null
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_left_until_it_wraps_around.snap
@@ -0,0 +1,28 @@
+---
+source: src/tests/e2e/cases.rs
+expression: account_for_races_in_snapshot(last_snapshot)
+---
+ Zellij (e2e-test)  Tab #2  Tab #1  Tab #3 
+┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
+│$ █ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+ Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right.snap
new file mode 100644
index 000000000..2aee51c51
--- /dev/null
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right.snap
@@ -0,0 +1,29 @@
+---
+source: src/tests/e2e/cases.rs
+assertion_line: 624
+expression: account_for_races_in_snapshot(last_snapshot)
+---
+ Zellij (e2e-test)  Tab #1  Tab #3  Tab #2 
+┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
+│$ Tab #2 content█ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+│ │
+└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
+ Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
+ Tip: Alt + <n> => new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate. Alt + <+|-> => resize pane.
diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right_until_it_wraps_around.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right_until_it_wraps_around.snap
new file mode 100644
index 000000000..9c2303a56
--- /dev/null
+++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__move_tab_to_right_until_it_wraps_around.snap
@@ -0,0 +1,28 @@
+---
+source: src/tests/e2e/cases.rs
+expression: account_for_races_in_snapshot(last_snapshot)
+---