feat(ui): status bar redesign (#3475)

* work

* work

* working

* get default mode from server and some ui responsiveness

* work

* finish design and get tests to pass

* get e2e tests to pass

* add classic layout

* add classic layout assets

* fix e2e tests

* style(fmt): rustfmt

* fix plugin system test

* style(fmt): some cleanups
This commit is contained in:
Aram Drevekenin 2024-07-05 15:13:51 +02:00 committed by GitHub
parent 8e33b20559
commit a6d6c0e4ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
71 changed files with 2208 additions and 225 deletions

1
Cargo.lock generated
View file

@ -3811,6 +3811,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"thiserror", "thiserror",
"unicode-width",
"zellij-tile", "zellij-tile",
"zellij-tile-utils", "zellij-tile-utils",
] ]

View file

@ -13,6 +13,7 @@ rand = "0.8.4"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
thiserror = "1.0.30" thiserror = "1.0.30"
unicode-width = "0.1.8"
zellij-tile = { path = "../../zellij-tile" } zellij-tile = { path = "../../zellij-tile" }
zellij-tile-utils = { path = "../../zellij-tile-utils" } zellij-tile-utils = { path = "../../zellij-tile-utils" }

View file

@ -8,14 +8,16 @@ use crate::{
}; };
use crate::{ColoredElements, LinePart}; use crate::{ColoredElements, LinePart};
struct KeyShortcut { #[derive(Debug)]
mode: KeyMode, pub struct KeyShortcut {
action: KeyAction, pub mode: KeyMode,
key: Option<KeyWithModifier>, pub action: KeyAction,
pub key: Option<KeyWithModifier>,
} }
#[derive(PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
enum KeyAction { pub enum KeyAction {
Unlock,
Lock, Lock,
Pane, Pane,
Tab, Tab,
@ -27,7 +29,8 @@ enum KeyAction {
Tmux, Tmux,
} }
enum KeyMode { #[derive(Debug, Copy, Clone)]
pub enum KeyMode {
Unselected, Unselected,
UnselectedAlternate, UnselectedAlternate,
Selected, Selected,
@ -42,6 +45,7 @@ impl KeyShortcut {
pub fn full_text(&self) -> String { pub fn full_text(&self) -> String {
match self.action { match self.action {
KeyAction::Lock => String::from("LOCK"), KeyAction::Lock => String::from("LOCK"),
KeyAction::Unlock => String::from("UNLOCK"),
KeyAction::Pane => String::from("PANE"), KeyAction::Pane => String::from("PANE"),
KeyAction::Tab => String::from("TAB"), KeyAction::Tab => String::from("TAB"),
KeyAction::Resize => String::from("RESIZE"), KeyAction::Resize => String::from("RESIZE"),
@ -82,6 +86,35 @@ impl KeyShortcut {
}; };
format!("{}", key) format!("{}", key)
} }
pub fn get_key(&self) -> Option<KeyWithModifier> {
self.key.clone()
}
pub fn get_mode(&self) -> KeyMode {
self.mode
}
pub fn get_action(&self) -> KeyAction {
self.action
}
pub fn is_selected(&self) -> bool {
match self.mode {
KeyMode::Selected => true,
_ => false,
}
}
pub fn short_text(&self) -> String {
match self.action {
KeyAction::Lock => String::from("Lo"),
KeyAction::Unlock => String::from("Un"),
KeyAction::Pane => String::from("Pa"),
KeyAction::Tab => String::from("Ta"),
KeyAction::Resize => String::from("Re"),
KeyAction::Search => String::from("Se"),
KeyAction::Quit => String::from("Qu"),
KeyAction::Session => String::from("Se"),
KeyAction::Move => String::from("Mo"),
KeyAction::Tmux => String::from("Tm"),
}
}
} }
/// Generate long mode shortcut tile. /// Generate long mode shortcut tile.

View file

@ -1,4 +1,5 @@
mod first_line; mod first_line;
mod one_line_ui;
mod second_line; mod second_line;
mod tip; mod tip;
@ -15,6 +16,7 @@ use zellij_tile::prelude::*;
use zellij_tile_utils::{palette_match, style}; use zellij_tile_utils::{palette_match, style};
use first_line::first_line; use first_line::first_line;
use one_line_ui::one_line_ui;
use second_line::{ use second_line::{
floating_panes_are_visible, fullscreen_panes_to_hide, keybinds, floating_panes_are_visible, fullscreen_panes_to_hide, keybinds,
locked_floating_panes_are_visible, locked_fullscreen_panes_to_hide, system_clipboard_error, locked_floating_panes_are_visible, locked_fullscreen_panes_to_hide, system_clipboard_error,
@ -35,6 +37,8 @@ struct State {
mode_info: ModeInfo, mode_info: ModeInfo,
text_copy_destination: Option<CopyDestination>, text_copy_destination: Option<CopyDestination>,
display_system_clipboard_failure: bool, display_system_clipboard_failure: bool,
classic_ui: bool,
base_mode_is_locked: bool,
} }
register_plugin!(State); register_plugin!(State);
@ -177,9 +181,13 @@ fn color_elements(palette: Palette, different_color_alternates: bool) -> Colored
} }
impl ZellijPlugin for State { impl ZellijPlugin for State {
fn load(&mut self, _configuration: BTreeMap<String, String>) { fn load(&mut self, configuration: BTreeMap<String, String>) {
// TODO: Should be able to choose whether to use the cache through config. // TODO: Should be able to choose whether to use the cache through config.
self.tip_name = get_cached_tip_name(); self.tip_name = get_cached_tip_name();
self.classic_ui = configuration
.get("classic")
.map(|c| c == "true")
.unwrap_or(false);
set_selectable(false); set_selectable(false);
subscribe(&[ subscribe(&[
EventType::ModeUpdate, EventType::ModeUpdate,
@ -198,6 +206,7 @@ impl ZellijPlugin for State {
should_render = true; should_render = true;
} }
self.mode_info = mode_info; self.mode_info = mode_info;
self.base_mode_is_locked = self.mode_info.base_mode == Some(InputMode::Locked);
}, },
Event::TabUpdate(tabs) => { Event::TabUpdate(tabs) => {
if self.tabs != tabs { if self.tabs != tabs {
@ -244,6 +253,21 @@ impl ZellijPlugin for State {
"" ""
}; };
if rows == 1 && !self.classic_ui {
let active_tab = self.tabs.iter().find(|t| t.active);
print!(
"{}",
one_line_ui(
&self.mode_info,
active_tab,
cols,
separator,
self.base_mode_is_locked
)
);
return;
}
let active_tab = self.tabs.iter().find(|t| t.active); let active_tab = self.tabs.iter().find(|t| t.active);
let first_line = first_line(&self.mode_info, active_tab, cols, separator); let first_line = first_line(&self.mode_info, active_tab, cols, separator);
let second_line = self.second_line(cols); let second_line = self.second_line(cols);
@ -418,10 +442,6 @@ pub fn style_key_with_modifier(
let common_modifiers = get_common_modifiers(keyvec.iter().collect()); let common_modifiers = get_common_modifiers(keyvec.iter().collect());
// let modifier_str = match get_common_modifier(keyvec.iter().collect()) {
// Some(modifier) => modifier,
// None => "".to_string(),
// };
let no_common_modifier = common_modifiers.is_empty(); let no_common_modifier = common_modifiers.is_empty();
let modifier_str = common_modifiers let modifier_str = common_modifiers
.iter() .iter()

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,14 @@
use ansi_term::ANSIStrings; use ansi_term::ANSIStrings;
use ansi_term::{
Color::{Fixed, RGB},
Style,
};
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use crate::{LinePart, ARROW_SEPARATOR}; use crate::{LinePart, ARROW_SEPARATOR};
use zellij_tile::prelude::actions::Action;
use zellij_tile::prelude::*; use zellij_tile::prelude::*;
use zellij_tile_utils::style; use zellij_tile_utils::{palette_match, style};
fn get_current_title_len(current_title: &[LinePart]) -> usize { fn get_current_title_len(current_title: &[LinePart]) -> usize {
current_title.iter().map(|p| p.len).sum() current_title.iter().map(|p| p.len).sum()
@ -224,6 +229,9 @@ pub fn tab_line(
palette: Palette, palette: Palette,
capabilities: PluginCapabilities, capabilities: PluginCapabilities,
hide_session_name: bool, hide_session_name: bool,
tab_info: Option<&TabInfo>,
mode_info: &ModeInfo,
hide_swap_layout_indicator: bool,
) -> Vec<LinePart> { ) -> Vec<LinePart> {
let mut tabs_after_active = all_tabs.split_off(active_tab_index); let mut tabs_after_active = all_tabs.split_off(active_tab_index);
let mut tabs_before_active = all_tabs; let mut tabs_before_active = all_tabs;
@ -236,10 +244,26 @@ pub fn tab_line(
true => tab_line_prefix(None, palette, cols), true => tab_line_prefix(None, palette, cols),
false => tab_line_prefix(session_name, palette, cols), false => tab_line_prefix(session_name, palette, cols),
}; };
let prefix_len = get_current_title_len(&prefix);
let mut swap_layout_indicator = if hide_swap_layout_indicator {
None
} else {
tab_info.and_then(|tab_info| {
swap_layout_status(
cols,
&tab_info.active_swap_layout_name,
tab_info.is_swap_layout_dirty,
mode_info,
!capabilities.arrow_fonts,
)
})
};
let non_tab_len =
get_current_title_len(&prefix) + swap_layout_indicator.as_ref().map(|s| s.len).unwrap_or(0);
// if active tab alone won't fit in cols, don't draw any tabs // if active tab alone won't fit in cols, don't draw any tabs
if prefix_len + active_tab.len > cols { if non_tab_len + active_tab.len > cols {
return prefix; return prefix;
} }
@ -249,10 +273,189 @@ pub fn tab_line(
&mut tabs_before_active, &mut tabs_before_active,
&mut tabs_after_active, &mut tabs_after_active,
&mut tabs_to_render, &mut tabs_to_render,
cols.saturating_sub(prefix_len), cols.saturating_sub(non_tab_len),
palette, palette,
capabilities, capabilities,
); );
prefix.append(&mut tabs_to_render); prefix.append(&mut tabs_to_render);
if let Some(mut swap_layout_indicator) = swap_layout_indicator.take() {
let remaining_space = cols
.saturating_sub(prefix.iter().fold(0, |len, part| len + part.len))
.saturating_sub(swap_layout_indicator.len);
let mut padding = String::new();
let mut padding_len = 0;
for _ in 0..remaining_space {
padding.push_str(" ");
padding_len += 1;
}
swap_layout_indicator.part = format!("{}{}", padding, swap_layout_indicator.part);
swap_layout_indicator.len += padding_len;
prefix.push(swap_layout_indicator);
}
prefix prefix
} }
fn swap_layout_status(
cols: usize,
swap_layout_name: &Option<String>,
is_swap_layout_dirty: bool,
mode_info: &ModeInfo,
supports_arrow_fonts: bool,
) -> Option<LinePart> {
match swap_layout_name {
Some(swap_layout_name) => {
let mode_keybinds = mode_info.get_mode_keybinds();
let prev_next_keys = action_key_group(
&mode_keybinds,
&[&[Action::PreviousSwapLayout], &[Action::NextSwapLayout]],
);
let mut text = style_key_with_modifier(&prev_next_keys, Some(0));
text.append(&ribbon_as_line_part(
&swap_layout_name.to_uppercase(),
!is_swap_layout_dirty,
supports_arrow_fonts,
));
Some(text)
},
None => None,
}
}
pub fn ribbon_as_line_part(text: &str, is_selected: bool, supports_arrow_fonts: bool) -> LinePart {
let ribbon_text = if is_selected {
Text::new(text).selected()
} else {
Text::new(text)
};
let part = serialize_ribbon(&ribbon_text);
let mut len = text.width() + 2;
if supports_arrow_fonts {
len += 2;
};
LinePart {
part,
len,
tab_index: None,
}
}
pub fn style_key_with_modifier(keyvec: &[KeyWithModifier], color_index: Option<usize>) -> LinePart {
if keyvec.is_empty() {
return LinePart::default();
}
let common_modifiers = get_common_modifiers(keyvec.iter().collect());
let no_common_modifier = common_modifiers.is_empty();
let modifier_str = common_modifiers
.iter()
.map(|m| m.to_string())
.collect::<Vec<_>>()
.join("-");
// Prints the keys
let key = keyvec
.iter()
.map(|key| {
if no_common_modifier || keyvec.len() == 1 {
format!("{}", key)
} else {
format!("{}", key.strip_common_modifiers(&common_modifiers))
}
})
.collect::<Vec<String>>();
// Special handling of some pre-defined keygroups
let key_string = key.join("");
let key_separator = match &key_string[..] {
"HJKL" => "",
"hjkl" => "",
"←↓↑→" => "",
"←→" => "",
"↓↑" => "",
"[]" => "",
_ => "|",
};
if no_common_modifier || key.len() == 1 {
let key_string_text = format!(" {} ", key.join(key_separator));
let text = if let Some(color_index) = color_index {
Text::new(&key_string_text).color_range(color_index, ..)
} else {
Text::new(&key_string_text)
};
LinePart {
part: serialize_text(&text),
len: key_string_text.width(),
..Default::default()
}
} else {
let key_string_without_modifier = format!("{}", key.join(key_separator));
let key_string_text = format!(" {} <{}> ", modifier_str, key_string_without_modifier);
let text = if let Some(color_index) = color_index {
Text::new(&key_string_text)
.color_range(color_index, ..modifier_str.width() + 1)
.color_range(
color_index,
modifier_str.width() + 3
..modifier_str.width() + 3 + key_string_without_modifier.width(),
)
} else {
Text::new(&key_string_text)
};
LinePart {
part: serialize_text(&text),
len: key_string_text.width(),
..Default::default()
}
}
}
pub fn get_common_modifiers(mut keyvec: Vec<&KeyWithModifier>) -> Vec<KeyModifier> {
if keyvec.is_empty() {
return vec![];
}
let mut common_modifiers = keyvec.pop().unwrap().key_modifiers.clone();
for key in keyvec {
common_modifiers = common_modifiers
.intersection(&key.key_modifiers)
.cloned()
.collect();
}
common_modifiers.into_iter().collect()
}
pub fn action_key_group(
keymap: &[(KeyWithModifier, Vec<Action>)],
actions: &[&[Action]],
) -> Vec<KeyWithModifier> {
let mut ret = vec![];
for action in actions {
ret.extend(action_key(keymap, action));
}
ret
}
pub fn action_key(
keymap: &[(KeyWithModifier, Vec<Action>)],
action: &[Action],
) -> Vec<KeyWithModifier> {
keymap
.iter()
.filter_map(|(key, acvec)| {
let matching = acvec
.iter()
.zip(action)
.filter(|(a, b)| a.shallow_eq(b))
.count();
if matching == acvec.len() && matching == action.len() {
Some(key.clone())
} else {
None
}
})
.collect::<Vec<KeyWithModifier>>()
}

View file

@ -18,12 +18,20 @@ pub struct LinePart {
tab_index: Option<usize>, tab_index: Option<usize>,
} }
impl LinePart {
pub fn append(&mut self, to_append: &LinePart) {
self.part.push_str(&to_append.part);
self.len += to_append.len;
}
}
#[derive(Default)] #[derive(Default)]
struct State { struct State {
tabs: Vec<TabInfo>, tabs: Vec<TabInfo>,
active_tab_idx: usize, active_tab_idx: usize,
mode_info: ModeInfo, mode_info: ModeInfo,
tab_line: Vec<LinePart>, tab_line: Vec<LinePart>,
hide_swap_layout_indication: bool,
} }
static ARROW_SEPARATOR: &str = ""; static ARROW_SEPARATOR: &str = "";
@ -31,7 +39,11 @@ static ARROW_SEPARATOR: &str = "";
register_plugin!(State); register_plugin!(State);
impl ZellijPlugin for State { impl ZellijPlugin for State {
fn load(&mut self, _configuration: BTreeMap<String, String>) { fn load(&mut self, configuration: BTreeMap<String, String>) {
self.hide_swap_layout_indication = configuration
.get("hide_swap_layout_indication")
.map(|s| s == "true")
.unwrap_or(false);
set_selectable(false); set_selectable(false);
subscribe(&[ subscribe(&[
EventType::TabUpdate, EventType::TabUpdate,
@ -120,6 +132,9 @@ impl ZellijPlugin for State {
self.mode_info.style.colors, self.mode_info.style.colors,
self.mode_info.capabilities, self.mode_info.capabilities,
self.mode_info.style.hide_session_name, self.mode_info.style.hide_session_name,
self.tabs.iter().find(|t| t.active),
&self.mode_info,
self.hide_swap_layout_indication,
); );
let output = self let output = self

View file

@ -51,7 +51,7 @@ pub fn render_tab(
let right_separator = style!(background_color, foreground_color).paint(separator); let right_separator = style!(background_color, foreground_color).paint(separator);
let tab_styled_text = if !focused_clients.is_empty() { let tab_styled_text = if !focused_clients.is_empty() {
let (cursor_section, extra_length) = cursors(focused_clients, palette); let (cursor_section, extra_length) = cursors(focused_clients, palette);
tab_text_len += extra_length; tab_text_len += extra_length + 2; // 2 for cursor_beginning and cursor_end
let mut s = String::new(); let mut s = String::new();
let cursor_beginning = style!(foreground_color, background_color) let cursor_beginning = style!(foreground_color, background_color)
.bold() .bold()

View file

@ -100,7 +100,7 @@ fn account_for_races_in_snapshot(snapshot: String) -> String {
// to fix this, we should set plugins as unselectable in the layout (before they are loaded), // to fix this, we should set plugins as unselectable in the layout (before they are loaded),
// once that happens, we should be able to remove this hack (and adjust the snapshots for the // once that happens, we should be able to remove this hack (and adjust the snapshots for the
// trailing spaces that we had to get rid of here) // trailing spaces that we had to get rid of here)
let base_replace = Regex::new(r" BASE \s*\n").unwrap(); let base_replace = Regex::new(r"Alt <\[\]>  BASE \s*\n").unwrap();
let eol_arrow_replace = Regex::new(r"\s*\n").unwrap(); let eol_arrow_replace = Regex::new(r"\s*\n").unwrap();
let snapshot = base_replace.replace_all(&snapshot, "\n").to_string(); let snapshot = base_replace.replace_all(&snapshot, "\n").to_string();
let snapshot = eol_arrow_replace.replace_all(&snapshot, "\n").to_string(); let snapshot = eol_arrow_replace.replace_all(&snapshot, "\n").to_string();
@ -134,6 +134,7 @@ pub fn starts_with_one_terminal() {
}, },
}); });
if runner.test_timed_out && test_attempts > 0 { if runner.test_timed_out && test_attempts > 0 {
test_attempts -= 1;
continue; continue;
} else { } else {
break last_snapshot; break last_snapshot;
@ -175,7 +176,8 @@ pub fn split_terminals_vertically() {
name: "Wait for new pane to appear", name: "Wait for new pane to appear",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2) && remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
step_is_complete = true; step_is_complete = true;
} }
@ -219,12 +221,7 @@ pub fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() {
name: "Make sure only one pane appears", name: "Make sure only one pane appears",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2) {
//two empty lines at the bottom to make sure there is no plugin output
&& remote_terminal
.current_snapshot()
.ends_with(" \n ")
{
// ... is the truncated tip line // ... is the truncated tip line
step_is_complete = true; step_is_complete = true;
} }
@ -272,7 +269,9 @@ pub fn scrolling_inside_a_pane() {
name: "Fill terminal with text", name: "Fill terminal with text",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.load_fixture("e2e/scrolling_inside_a_pane"); remote_terminal.load_fixture("e2e/scrolling_inside_a_pane");
step_is_complete = true; step_is_complete = true;
@ -284,7 +283,7 @@ pub fn scrolling_inside_a_pane() {
name: "Scroll up inside pane", name: "Scroll up inside pane",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 20) if remote_terminal.cursor_position_is(63, 21)
&& remote_terminal.snapshot_contains("line21") && remote_terminal.snapshot_contains("line21")
{ {
// all lines have been written to the pane // all lines have been written to the pane
@ -301,9 +300,9 @@ pub fn scrolling_inside_a_pane() {
name: "Wait for scroll to finish", name: "Wait for scroll to finish",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 20) if remote_terminal.cursor_position_is(63, 21)
&& remote_terminal.snapshot_contains("line3 ") && remote_terminal.snapshot_contains("line3 ")
&& remote_terminal.snapshot_contains("SCROLL: 1/4") && remote_terminal.snapshot_contains("SCROLL: 1/3")
{ {
// keyboard scrolls up 1 line, scrollback is 4 lines: cat command + 2 extra lines from fixture + prompt // keyboard scrolls up 1 line, scrollback is 4 lines: cat command + 2 extra lines from fixture + prompt
step_is_complete = true; step_is_complete = true;
@ -352,7 +351,9 @@ pub fn toggle_pane_fullscreen() {
name: "Change newly opened pane to be fullscreen", name: "Change newly opened pane to be fullscreen",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&PANE_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -415,7 +416,9 @@ pub fn open_new_tab() {
name: "Open new tab", name: "Open new tab",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.send_key(&TAB_MODE); remote_terminal.send_key(&TAB_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -431,7 +434,6 @@ pub fn open_new_tab() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2") && remote_terminal.snapshot_contains("Tab #2")
&& remote_terminal.status_bar_appears() && remote_terminal.status_bar_appears()
{ {
@ -482,7 +484,9 @@ pub fn close_tab() {
name: "Open new tab", name: "Open new tab",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.send_key(&TAB_MODE); remote_terminal.send_key(&TAB_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -497,7 +501,6 @@ pub fn close_tab() {
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2") && remote_terminal.snapshot_contains("Tab #2")
&& remote_terminal.status_bar_appears() && remote_terminal.status_bar_appears()
{ {
@ -675,7 +678,9 @@ pub fn close_pane() {
name: "Close pane", name: "Close pane",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.send_key(&PANE_MODE); remote_terminal.send_key(&PANE_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -690,7 +695,8 @@ pub fn close_pane() {
name: "Wait for pane to close", name: "Wait for pane to close",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(3, 2) && remote_terminal.status_bar_appears()
{
// cursor is in the original pane // cursor is in the original pane
step_is_complete = true; step_is_complete = true;
} }
@ -820,7 +826,9 @@ pub fn typing_exit_closes_pane() {
name: "Type exit", name: "Type exit",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
remote_terminal.send_key("e".as_bytes()); remote_terminal.send_key("e".as_bytes());
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
remote_terminal.send_key("x".as_bytes()); remote_terminal.send_key("x".as_bytes());
@ -840,8 +848,8 @@ pub fn typing_exit_closes_pane() {
name: "Wait for pane to close", name: "Wait for pane to close",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
// if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(3, 2) && remote_terminal.status_bar_appears()
if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() { {
// cursor is in the original pane // cursor is in the original pane
step_is_complete = true; step_is_complete = true;
} }
@ -889,7 +897,9 @@ pub fn resize_pane() {
name: "Resize pane", name: "Resize pane",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.send_key(&RESIZE_MODE); remote_terminal.send_key(&RESIZE_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -906,7 +916,8 @@ pub fn resize_pane() {
name: "Wait for pane to be resized", name: "Wait for pane to be resized",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(57, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(57, 2) && remote_terminal.status_bar_appears()
{
// pane has been resized // pane has been resized
step_is_complete = true; step_is_complete = true;
} }
@ -952,7 +963,7 @@ pub fn lock_mode() {
name: "Send keys that should not be intercepted by the app", name: "Send keys that should not be intercepted by the app",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.snapshot_contains("INTERFACE LOCKED") { if !remote_terminal.snapshot_contains("PANE") {
remote_terminal.send_key(&TAB_MODE); remote_terminal.send_key(&TAB_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
remote_terminal.send_key(&NEW_TAB_IN_TAB_MODE); remote_terminal.send_key(&NEW_TAB_IN_TAB_MODE);
@ -1017,7 +1028,9 @@ pub fn resize_terminal_window() {
name: "Change terminal window size", name: "Change terminal window size",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// new pane has been opened and focused // new pane has been opened and focused
remote_terminal.change_size(100, 24); remote_terminal.change_size(100, 24);
step_is_complete = true; step_is_complete = true;
@ -1031,7 +1044,7 @@ pub fn resize_terminal_window() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(53, 2) if remote_terminal.cursor_position_is(53, 2)
&& remote_terminal.tip_appears() && remote_terminal.status_bar_appears()
&& remote_terminal.snapshot_contains("Ctrl +") && remote_terminal.snapshot_contains("Ctrl +")
{ {
// size has been changed // size has been changed
@ -1081,7 +1094,9 @@ pub fn detach_and_attach_session() {
name: "Send some text to the active pane", name: "Send some text to the active pane",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// new pane has been opened and focused // new pane has been opened and focused
remote_terminal.send_key("I am some text".as_bytes()); remote_terminal.send_key("I am some text".as_bytes());
step_is_complete = true; step_is_complete = true;
@ -1275,7 +1290,9 @@ pub fn status_bar_loads_custom_keybindings() {
name: "Wait for app to load", name: "Wait for app to load",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.snapshot_contains("LOCK")
{
step_is_complete = true; step_is_complete = true;
} }
step_is_complete step_is_complete
@ -1323,7 +1340,9 @@ fn focus_pane_with_mouse() {
name: "Click left pane", name: "Click left pane",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
remote_terminal.send_key(&sgr_mouse_report(Position::new(5, 2), 0)); remote_terminal.send_key(&sgr_mouse_report(Position::new(5, 2), 0));
step_is_complete = true; step_is_complete = true;
} }
@ -1335,7 +1354,8 @@ fn focus_pane_with_mouse() {
name: "Wait for left pane to be focused", name: "Wait for left pane to be focused",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(3, 2) && remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
step_is_complete = true; step_is_complete = true;
} }
@ -1383,7 +1403,9 @@ pub fn scrolling_inside_a_pane_with_mouse() {
name: "Fill terminal with text", name: "Fill terminal with text",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
remote_terminal.load_fixture("e2e/scrolling_inside_a_pane"); remote_terminal.load_fixture("e2e/scrolling_inside_a_pane");
step_is_complete = true; step_is_complete = true;
} }
@ -1394,7 +1416,7 @@ pub fn scrolling_inside_a_pane_with_mouse() {
name: "Scroll up inside pane", name: "Scroll up inside pane",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 20) if remote_terminal.cursor_position_is(63, 21)
&& remote_terminal.snapshot_contains("line21") && remote_terminal.snapshot_contains("line21")
{ {
// all lines have been written to the pane // all lines have been written to the pane
@ -1409,11 +1431,10 @@ pub fn scrolling_inside_a_pane_with_mouse() {
name: "Wait for scroll to finish", name: "Wait for scroll to finish",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 20) if remote_terminal.cursor_position_is(63, 21)
&& remote_terminal.snapshot_contains("line1 ") && remote_terminal.snapshot_contains("line1 ")
&& remote_terminal.snapshot_contains("SCROLL: 3/4") && remote_terminal.snapshot_contains("SCROLL: 3/3")
{ {
// mouse wheel scrolls up 3 lines, scrollback is 4 lines: cat command + 2 extra lines from fixture + prompt
step_is_complete = true; step_is_complete = true;
} }
step_is_complete step_is_complete
@ -1460,7 +1481,8 @@ pub fn start_without_pane_frames() {
name: "Wait for new pane to appear", name: "Wait for new pane to appear",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(62, 1) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(62, 1) && remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
step_is_complete = true; step_is_complete = true;
} }
@ -1529,7 +1551,9 @@ pub fn mirrored_sessions() {
name: "Open new tab (second user)", name: "Open new tab (second user)",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.send_key(&TAB_MODE); remote_terminal.send_key(&TAB_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -1544,7 +1568,6 @@ pub fn mirrored_sessions() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2") && remote_terminal.snapshot_contains("Tab #2")
&& remote_terminal.status_bar_appears() && remote_terminal.status_bar_appears()
{ {
@ -1559,7 +1582,7 @@ pub fn mirrored_sessions() {
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears() && remote_terminal.status_bar_appears()
&& remote_terminal.snapshot_contains("Tab #2") && remote_terminal.snapshot_contains("Tab #2")
{ {
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
@ -1584,7 +1607,7 @@ pub fn mirrored_sessions() {
}); });
second_runner.run_all_steps(); second_runner.run_all_steps();
if first_runner.test_timed_out || second_runner.test_timed_out { if (first_runner.test_timed_out || second_runner.test_timed_out) && test_attempts >= 0 {
test_attempts -= 1; test_attempts -= 1;
continue; continue;
} }
@ -1674,7 +1697,7 @@ pub fn multiple_users_in_same_pane_and_tab() {
}); });
second_runner.run_all_steps(); second_runner.run_all_steps();
if first_runner.test_timed_out || second_runner.test_timed_out { if (first_runner.test_timed_out || second_runner.test_timed_out) && test_attempts >= 0 {
test_attempts -= 1; test_attempts -= 1;
continue; continue;
} }
@ -1767,7 +1790,7 @@ pub fn multiple_users_in_different_panes_and_same_tab() {
}); });
second_runner.run_all_steps(); second_runner.run_all_steps();
if first_runner.test_timed_out || second_runner.test_timed_out { if (first_runner.test_timed_out || second_runner.test_timed_out) && test_attempts >= 0 {
test_attempts -= 1; test_attempts -= 1;
continue; continue;
} }
@ -1776,7 +1799,8 @@ pub fn multiple_users_in_different_panes_and_same_tab() {
name: "take snapshot after", name: "take snapshot after",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2) && remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
step_is_complete = true; step_is_complete = true;
} }
@ -1790,6 +1814,7 @@ pub fn multiple_users_in_different_panes_and_same_tab() {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.snapshot_contains("││$") && remote_terminal.snapshot_contains("││$")
&& remote_terminal.tab_bar_appears()
{ {
// cursor is back in the first tab // cursor is back in the first tab
step_is_complete = true; step_is_complete = true;
@ -1847,7 +1872,9 @@ pub fn multiple_users_in_different_tabs() {
name: "Open new tab", name: "Open new tab",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
remote_terminal.send_key(&TAB_MODE); remote_terminal.send_key(&TAB_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
@ -1859,7 +1886,7 @@ pub fn multiple_users_in_different_tabs() {
}); });
second_runner.run_all_steps(); second_runner.run_all_steps();
if first_runner.test_timed_out || second_runner.test_timed_out { if (first_runner.test_timed_out || second_runner.test_timed_out) && test_attempts >= 0 {
test_attempts -= 1; test_attempts -= 1;
continue; continue;
} }
@ -1869,7 +1896,6 @@ pub fn multiple_users_in_different_tabs() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #1 [ ]") && remote_terminal.snapshot_contains("Tab #1 [ ]")
&& remote_terminal.snapshot_contains("Tab #2") && remote_terminal.snapshot_contains("Tab #2")
&& remote_terminal.status_bar_appears() && remote_terminal.status_bar_appears()
@ -1887,7 +1913,6 @@ pub fn multiple_users_in_different_tabs() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(3, 2) if remote_terminal.cursor_position_is(3, 2)
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2 [ ]") && remote_terminal.snapshot_contains("Tab #2 [ ]")
&& remote_terminal.status_bar_appears() && remote_terminal.status_bar_appears()
{ {
@ -2006,9 +2031,7 @@ pub fn toggle_floating_panes() {
name: "Wait for new pane to appear", name: "Wait for new pane to appear",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(33, 7) if remote_terminal.cursor_position_is(33, 8) {
&& remote_terminal.snapshot_contains("FLOATING PANES VISIBLE")
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
step_is_complete = true; step_is_complete = true;
} }
@ -2057,7 +2080,8 @@ pub fn tmux_mode() {
name: "Wait for new pane to appear", name: "Wait for new pane to appear",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { if remote_terminal.cursor_position_is(63, 2) && remote_terminal.status_bar_appears()
{
// cursor is in the newly opened second pane // cursor is in the newly opened second pane
step_is_complete = true; step_is_complete = true;
} }
@ -2163,7 +2187,7 @@ pub fn undo_rename_tab() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.snapshot_contains("Tab #1") if remote_terminal.snapshot_contains("Tab #1")
&& remote_terminal.snapshot_contains("Tip:") && remote_terminal.snapshot_contains("LOCK")
{ {
step_is_complete = true step_is_complete = true
} }
@ -2220,7 +2244,7 @@ pub fn undo_rename_pane() {
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.snapshot_contains("Pane #1") if remote_terminal.snapshot_contains("Pane #1")
&& remote_terminal.snapshot_contains("Tip:") && remote_terminal.snapshot_contains("LOCK")
{ {
step_is_complete = true step_is_complete = true
} }

View file

@ -351,10 +351,6 @@ impl RemoteTerminal {
pub fn cursor_position_is(&self, x: usize, y: usize) -> bool { pub fn cursor_position_is(&self, x: usize, y: usize) -> bool {
x == self.cursor_x && y == self.cursor_y x == self.cursor_x && y == self.cursor_y
} }
pub fn tip_appears(&self) -> bool {
let snapshot = self.last_snapshot.lock().unwrap();
snapshot.contains("Tip:") || snapshot.contains("QuickNav:")
}
pub fn status_bar_appears(&self) -> bool { pub fn status_bar_appears(&self) -> bool {
self.last_snapshot.lock().unwrap().contains("Ctrl +") self.last_snapshot.lock().unwrap().contains("Ctrl +")
} }

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1676 assertion_line: 1975
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 198 assertion_line: 243
expression: last_snapshot expression: last_snapshot
--- ---
Zellij Zellij
@ -20,6 +20,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────┘ └──────┘
Ctrl +

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 557 assertion_line: 707
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 975 assertion_line: 1138
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1071 assertion_line: 1352
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 836 assertion_line: 985
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <> PANE  <> TAB  <> RESIZE  <> MOVE  <> SEARCH  <> SESSION  <> QUIT  Ctrl + <g> LOCK 
-- INTERFACE LOCKED --

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1354 assertion_line: 1625
expression: second_runner_snapshot expression: second_runner_snapshot
--- ---
Zellij (mirrored_sessions)  Tab #1  Tab #2  Zellij (mirrored_sessions)  Tab #1  Tab #2 
@ -24,6 +24,6 @@ expression: second_runner_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Ctrl + <t> TAB   n  New  ←→  Move  x  Close  r  Rename  s  Sync  b  Break out  []  Break  ...
<n> New / <←→> Move / <x> Close / <r> Rename / <s> Sync / <b> Break out / <[]> Break / <TAB> Toggle ...

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1340 assertion_line: 1624
expression: first_runner_snapshot expression: first_runner_snapshot
--- ---
Zellij (mirrored_sessions)  Tab #1  Tab #2  Zellij (mirrored_sessions)  Tab #1  Tab #2 
@ -24,6 +24,6 @@ expression: first_runner_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 531 assertion_line: 558
expression: account_for_races_in_snapshot(last_snapshot) expression: account_for_races_in_snapshot(last_snapshot)
--- ---
Zellij (e2e-test)  Tab #1  Tab #3  Tab #2  Zellij (e2e-test)  Tab #1  Tab #3  Tab #2 
@ -24,6 +24,6 @@ expression: account_for_races_in_snapshot(last_snapshot)
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,5 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 620
expression: account_for_races_in_snapshot(last_snapshot) expression: account_for_races_in_snapshot(last_snapshot)
--- ---
Zellij (e2e-test)  Tab #2  Tab #1  Tab #3  Zellij (e2e-test)  Tab #2  Tab #1  Tab #3 
@ -23,6 +24,6 @@ expression: account_for_races_in_snapshot(last_snapshot)
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 624 assertion_line: 592
expression: account_for_races_in_snapshot(last_snapshot) expression: account_for_races_in_snapshot(last_snapshot)
--- ---
Zellij (e2e-test)  Tab #1  Tab #3  Tab #2  Zellij (e2e-test)  Tab #1  Tab #3  Tab #2 
@ -24,6 +24,6 @@ expression: account_for_races_in_snapshot(last_snapshot)
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,5 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 644
expression: account_for_races_in_snapshot(last_snapshot) expression: account_for_races_in_snapshot(last_snapshot)
--- ---
Zellij (e2e-test)  Tab #3  Tab #2  Tab #1  Zellij (e2e-test)  Tab #3  Tab #2  Tab #1 
@ -23,6 +24,6 @@ expression: account_for_races_in_snapshot(last_snapshot)
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1523 assertion_line: 1809
expression: second_runner_snapshot expression: second_runner_snapshot
--- ---
Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ] Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ]
@ -24,6 +24,6 @@ expression: second_runner_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1522 assertion_line: 1808
expression: first_runner_snapshot expression: first_runner_snapshot
--- ---
Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ] Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ]
@ -24,6 +24,6 @@ expression: first_runner_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1620 assertion_line: 1907
expression: second_runner_snapshot expression: second_runner_snapshot
--- ---
Zellij (multiple_users_in_different_tabs)  Tab #1 [ ] Tab #2  Zellij (multiple_users_in_different_tabs)  Tab #1 [ ] Tab #2 
@ -24,6 +24,6 @@ expression: second_runner_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1619 assertion_line: 1906
expression: first_runner_snapshot expression: first_runner_snapshot
--- ---
Zellij (multiple_users_in_different_tabs)  Tab #1  Tab #2 [ ] Zellij (multiple_users_in_different_tabs)  Tab #1  Tab #2 [ ]
@ -24,6 +24,6 @@ expression: first_runner_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1431 assertion_line: 1716
expression: second_runner_snapshot expression: second_runner_snapshot
--- ---
Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ] Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ]
@ -24,6 +24,6 @@ expression: second_runner_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1430 assertion_line: 1718
expression: first_runner_snapshot expression: first_runner_snapshot
--- ---
Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ] Zellij (multiple_users_in_same_pane_and_tab)  Tab #1 [ ]
@ -24,6 +24,6 @@ expression: first_runner_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 416 assertion_line: 452
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Tab #2  Zellij (e2e-test)  Tab #1  Tab #2 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1171 assertion_line: 1191
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Tab #2  Tab #3  Tab #4  Zellij (e2e-test)  Tab #1  Tab #2  Tab #3  Tab #4 
@ -25,5 +25,5 @@ expression: last_snapshot
│ └────────────────────────────────────────────────────────┘ │ │ └────────────────────────────────────────────────────────┘ │
│ ││ │ │ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  BASE 
(FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide. (FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1232 assertion_line: 1252
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Tab #2  Tab #3  Tab #4  Zellij (e2e-test)  Tab #1  Tab #2  Tab #3  Tab #4 
@ -25,5 +25,5 @@ expression: last_snapshot
│ └────────────────────────────────────────────────────────┘ │ │ └────────────────────────────────────────────────────────┘ │
│ ││ │ │ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  BASE 
(FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide. (FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 765 assertion_line: 923
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└────────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────┘ └────────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 889 assertion_line: 1050
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└────────────────────────────────────────────────┘└────────────────────────────────────────────────┘ └────────────────────────────────────────────────┘└────────────────────────────────────────────────┘
Ctrl + g  p  t  n  h  s  o  q  Alt + <[]> Ctrl + g  p  t  n  h  s  o  q  Alt +  <n> New Pane  <←↓↑→> Change Focus 
QuickNav: Alt + <n> / Alt + <←↓↑→> or Alt + <hjkl> / Alt + <+|->

View file

@ -1,11 +1,12 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 305 assertion_line: 323
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 1/4 ┐ ┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 1/3 ┐
│$ ││line3 │ │$ ││line2 │
│ ││line3 │
│ ││line4 │ │ ││line4 │
│ ││line5 │ │ ││line5 │
│ ││line6 │ │ ││line6 │
@ -25,5 +26,4 @@ expression: last_snapshot
│ ││line20 │ │ ││line20 │
│ ││li█e21 │ │ ││li█e21 │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Ctrl + <s> SEARCH   s  Search  ↓↑  Scroll  PgDn|PgUp  Scroll  d|u  Scroll  e  Edit  ENTER  Select 
<s> Search / <↓↑> Scroll / <PgDn|PgUp> Scroll / <d|u> Scroll / <e> Edit / <ENTER> Select

View file

@ -1,11 +1,12 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1147 assertion_line: 1428
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 3/4 ┐ ┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 3/3 ┐
│$ ││line1 │ │$ ││$ cat /usr/src/zellij/fixtures/e2e/scrolling_inside_a_pane│
│ ││line1 │
│ ││line2 │ │ ││line2 │
│ ││line3 │ │ ││line3 │
│ ││line4 │ │ ││line4 │
@ -26,4 +27,3 @@ expression: last_snapshot
│ ││li█e19 │ │ ││li█e19 │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,9 +1,9 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 2175 assertion_line: 2349
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1  Alt <[]>  VERTICAL 
┌ Pane #1 ────────────────────────────────────────────────────────────────┐┌ /usr/src/zellij/fixtures/append-echo-script.sh ─────────────────────────┐ ┌ Pane #1 ────────────────────────────────────────────────────────────────┐┌ /usr/src/zellij/fixtures/append-echo-script.sh ─────────────────────────┐
│$ /usr/src/zellij/x86_64-unknown-linux-musl/release/zellij run -s -- "/us││foo │ │$ /usr/src/zellij/x86_64-unknown-linux-musl/release/zellij run -s -- "/us││foo │
│r/src/zellij/fixtures/append-echo-script.sh" ││foo │ │r/src/zellij/fixtures/append-echo-script.sh" ││foo │
@ -24,6 +24,6 @@ expression: last_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└─────────────────────────────────────────────────────────────────────────┘└ [ EXIT CODE: 0 ] <ENTER> re-run, <ESC> drop to shell, <Ctrl-c> exit ────┘ └─────────────────────────────────────────────────────────────────────────┘└ [ EXIT CODE: 0 ] <ENTER> re-run, <ESC> drop to shell, <Ctrl-c> exit ────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt + <[]>  VERTICAL  Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Alt +  <n> New  <←↓↑→> Focus 
Tip: Alt + <n> => open new pane. Alt + <←↓↑→> or Alt + <hjkl> => navigate between panes. Alt + <+|-> => increase/decrease pane size.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 168 assertion_line: 194
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1326 assertion_line: 1476
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -25,5 +25,5 @@ $ │
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 120 assertion_line: 145
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1266 assertion_line: 1293
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
<F1> LOCK  <F2> PANE  <F3> TAB  <F4> RESIZE  <F5> MOVE  <F6> SEARCH  <Alt F7> SESSION  <Ctrl F8> QUIT  F1  LOCK  F2  PANE  F3  TAB  F4  RESIZE  F5  MOVE  F6  SEARCH  Alt F7  SESSION  Ctrl F8  QUIT 
Tip: UNBOUND => open new pane. UNBOUND => navigate between panes. UNBOUND => increase/decrease pane size.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1772 assertion_line: 2070
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │ │ ││ │
│ ││ │
└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,14 +1,15 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1984 assertion_line: 2027
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1  Alt <[]>  STAGGERED 
┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ ┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│$ │ │$ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │
│ ┌ Pane #2 ─────────────────────────────────────────────────┐ │ │ ┌ Pane #2 ─────────────────────────────────────────────────┐ │
│ │$ █ │ │ │ │$ █ │ │
│ │ │ │ │ │ │ │
@ -18,12 +19,11 @@ expression: last_snapshot
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────┘ │ │ └──────────────────────────────────────────────────────────┘ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
(FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 351 assertion_line: 386
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT 
(FULLSCREEN): + 1 hidden panes

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 702 assertion_line: 858
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1921 assertion_line: 2240
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -1,6 +1,6 @@
--- ---
source: src/tests/e2e/cases.rs source: src/tests/e2e/cases.rs
assertion_line: 1871 assertion_line: 2183
expression: last_snapshot expression: last_snapshot
--- ---
Zellij (e2e-test)  Tab #1  Zellij (e2e-test)  Tab #1 
@ -24,6 +24,6 @@ expression: last_snapshot
│ │ │ │
│ │ │ │
│ │ │ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Ctrl + <g> LOCK  <p> PANE  <t> TAB  <n> RESIZE  <h> MOVE  <s> SEARCH  <o> SESSION  <q> QUIT  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.

View file

@ -9,7 +9,7 @@ pub fn new_tab() -> Step {
name: "Open new tab", name: "Open new tab",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.tip_appears() && remote_terminal.status_bar_appears() { if remote_terminal.status_bar_appears() {
remote_terminal.send_key(&TAB_MODE); remote_terminal.send_key(&TAB_MODE);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
remote_terminal.send_key(&NEW_TAB_IN_TAB_MODE); remote_terminal.send_key(&NEW_TAB_IN_TAB_MODE);
@ -24,9 +24,7 @@ pub fn check_second_tab_opened() -> Step {
Step { Step {
name: "Check second tab opened", name: "Check second tab opened",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
remote_terminal.status_bar_appears() remote_terminal.status_bar_appears() && remote_terminal.snapshot_contains("Tab #2")
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2")
}, },
} }
} }
@ -36,7 +34,7 @@ pub fn move_tab_left() -> Step {
name: "Move tab left", name: "Move tab left",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.tip_appears() && remote_terminal.status_bar_appears() { if remote_terminal.status_bar_appears() {
remote_terminal.send_key(&MOVE_TAB_LEFT); remote_terminal.send_key(&MOVE_TAB_LEFT);
std::thread::sleep(std::time::Duration::from_millis(100)); std::thread::sleep(std::time::Duration::from_millis(100));
step_is_complete = true; step_is_complete = true;
@ -51,7 +49,6 @@ pub fn check_third_tab_moved_left() -> Step {
name: "Check third tab is in the middle", name: "Check third tab is in the middle",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
remote_terminal.status_bar_appears() remote_terminal.status_bar_appears()
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #1  Tab #3  Tab #2") && remote_terminal.snapshot_contains("Tab #1  Tab #3  Tab #2")
}, },
} }
@ -62,7 +59,7 @@ pub fn type_second_tab_content() -> Step {
name: "Type second tab content", name: "Type second tab content",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.tip_appears() && remote_terminal.status_bar_appears() { if remote_terminal.status_bar_appears() {
remote_terminal.send_key(&SECOND_TAB_CONTENT); remote_terminal.send_key(&SECOND_TAB_CONTENT);
step_is_complete = true; step_is_complete = true;
} }
@ -75,9 +72,7 @@ pub fn check_third_tab_opened() -> Step {
Step { Step {
name: "Check third tab opened", name: "Check third tab opened",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
remote_terminal.status_bar_appears() remote_terminal.status_bar_appears() && remote_terminal.snapshot_contains("Tab #3")
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #3")
}, },
} }
} }
@ -87,7 +82,7 @@ pub fn switch_focus_to_left_tab() -> Step {
name: "Move focus to tab on the left", name: "Move focus to tab on the left",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.tip_appears() && remote_terminal.status_bar_appears() { if remote_terminal.status_bar_appears() {
remote_terminal.send_key(&MOVE_FOCUS_LEFT_IN_NORMAL_MODE); remote_terminal.send_key(&MOVE_FOCUS_LEFT_IN_NORMAL_MODE);
step_is_complete = true; step_is_complete = true;
} }
@ -101,7 +96,6 @@ pub fn check_focus_on_second_tab() -> Step {
name: "Check focus is on the second tab", name: "Check focus is on the second tab",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
remote_terminal.status_bar_appears() remote_terminal.status_bar_appears()
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2 content") && remote_terminal.snapshot_contains("Tab #2 content")
}, },
} }
@ -112,7 +106,7 @@ pub fn move_tab_right() -> Step {
name: "Move tab right", name: "Move tab right",
instruction: |mut remote_terminal: RemoteTerminal| -> bool { instruction: |mut remote_terminal: RemoteTerminal| -> bool {
let mut step_is_complete = false; let mut step_is_complete = false;
if remote_terminal.tip_appears() && remote_terminal.status_bar_appears() { if remote_terminal.status_bar_appears() {
remote_terminal.send_key(&MOVE_TAB_RIGHT); remote_terminal.send_key(&MOVE_TAB_RIGHT);
step_is_complete = true; step_is_complete = true;
} }
@ -126,7 +120,6 @@ pub fn check_third_tab_moved_to_beginning() -> Step {
name: "Check third tab moved to beginning", name: "Check third tab moved to beginning",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
remote_terminal.status_bar_appears() remote_terminal.status_bar_appears()
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #3  Tab #1  Tab #2") && remote_terminal.snapshot_contains("Tab #3  Tab #1  Tab #2")
}, },
} }
@ -137,7 +130,6 @@ pub fn check_third_tab_is_left_wrapped() -> Step {
name: "Check third tab is in last position", name: "Check third tab is in last position",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
remote_terminal.status_bar_appears() remote_terminal.status_bar_appears()
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #2  Tab #1  Tab #3") && remote_terminal.snapshot_contains("Tab #2  Tab #1  Tab #3")
}, },
} }
@ -148,7 +140,6 @@ pub fn check_third_tab_is_right_wrapped() -> Step {
name: "Check third tab is in last position", name: "Check third tab is in last position",
instruction: |remote_terminal: RemoteTerminal| -> bool { instruction: |remote_terminal: RemoteTerminal| -> bool {
remote_terminal.status_bar_appears() remote_terminal.status_bar_appears()
&& remote_terminal.tip_appears()
&& remote_terminal.snapshot_contains("Tab #3  Tab #2  Tab #1") && remote_terminal.snapshot_contains("Tab #3  Tab #2  Tab #1")
}, },
} }

View file

@ -149,6 +149,7 @@ pub(crate) struct SessionMetaData {
pub config_options: Box<Options>, pub config_options: Box<Options>,
pub client_keybinds: HashMap<ClientId, Keybinds>, pub client_keybinds: HashMap<ClientId, Keybinds>,
pub client_input_modes: HashMap<ClientId, InputMode>, pub client_input_modes: HashMap<ClientId, InputMode>,
pub default_mode: InputMode,
screen_thread: Option<thread::JoinHandle<()>>, screen_thread: Option<thread::JoinHandle<()>>,
pty_thread: Option<thread::JoinHandle<()>>, pty_thread: Option<thread::JoinHandle<()>>,
plugin_thread: Option<thread::JoinHandle<()>>, plugin_thread: Option<thread::JoinHandle<()>>,
@ -565,7 +566,12 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
.send_to_plugin(PluginInstruction::AddClient(client_id)) .send_to_plugin(PluginInstruction::AddClient(client_id))
.unwrap(); .unwrap();
let default_mode = options.default_mode.unwrap_or_default(); let default_mode = options.default_mode.unwrap_or_default();
let mode_info = get_mode_info(default_mode, &attrs, session_data.capabilities); let mode_info = get_mode_info(
default_mode,
&attrs,
session_data.capabilities,
Some(default_mode),
);
session_data session_data
.senders .senders
.send_to_screen(ScreenInstruction::ChangeMode(mode_info.clone(), client_id)) .send_to_screen(ScreenInstruction::ChangeMode(mode_info.clone(), client_id))
@ -999,6 +1005,8 @@ fn init_session(
.clone() .clone()
.unwrap_or_else(|| get_default_shell()); .unwrap_or_else(|| get_default_shell());
let default_mode = config_options.default_mode.unwrap_or_default();
let pty_thread = thread::Builder::new() let pty_thread = thread::Builder::new()
.name("pty".to_string()) .name("pty".to_string())
.spawn({ .spawn({
@ -1089,6 +1097,7 @@ fn init_session(
client_attributes, client_attributes,
default_shell, default_shell,
plugin_aliases, plugin_aliases,
default_mode,
) )
.fatal() .fatal()
} }
@ -1158,6 +1167,7 @@ fn init_session(
plugin_thread: Some(plugin_thread), plugin_thread: Some(plugin_thread),
pty_writer_thread: Some(pty_writer_thread), pty_writer_thread: Some(pty_writer_thread),
background_jobs_thread: Some(background_jobs_thread), background_jobs_thread: Some(background_jobs_thread),
default_mode,
} }
} }

View file

@ -25,8 +25,8 @@ use wasm_bridge::WasmBridge;
use zellij_utils::{ use zellij_utils::{
async_std::{channel, future::timeout, task}, async_std::{channel, future::timeout, task},
data::{ data::{
Event, EventType, MessageToPlugin, PermissionStatus, PermissionType, PipeMessage, Event, EventType, InputMode, MessageToPlugin, PermissionStatus, PermissionType,
PipeSource, PluginCapabilities, PipeMessage, PipeSource, PluginCapabilities,
}, },
errors::{prelude::*, ContextType, PluginContext}, errors::{prelude::*, ContextType, PluginContext},
input::{ input::{
@ -198,6 +198,7 @@ pub(crate) fn plugin_thread_main(
client_attributes: ClientAttributes, client_attributes: ClientAttributes,
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
plugin_aliases: Box<PluginAliases>, plugin_aliases: Box<PluginAliases>,
default_mode: InputMode,
) -> Result<()> { ) -> Result<()> {
info!("Wasm main thread starts"); info!("Wasm main thread starts");
let plugin_dir = data_dir.join("plugins/"); let plugin_dir = data_dir.join("plugins/");
@ -219,6 +220,7 @@ pub(crate) fn plugin_thread_main(
default_shell, default_shell,
layout.clone(), layout.clone(),
layout_dir, layout_dir,
default_mode,
); );
loop { loop {

View file

@ -26,7 +26,7 @@ use crate::{
use zellij_utils::plugin_api::action::ProtobufPluginConfiguration; use zellij_utils::plugin_api::action::ProtobufPluginConfiguration;
use zellij_utils::{ use zellij_utils::{
consts::{ZELLIJ_CACHE_DIR, ZELLIJ_SESSION_CACHE_DIR, ZELLIJ_TMP_DIR}, consts::{ZELLIJ_CACHE_DIR, ZELLIJ_SESSION_CACHE_DIR, ZELLIJ_TMP_DIR},
data::PluginCapabilities, data::{InputMode, PluginCapabilities},
errors::prelude::*, errors::prelude::*,
input::command::TerminalAction, input::command::TerminalAction,
input::layout::Layout, input::layout::Layout,
@ -68,6 +68,7 @@ pub struct PluginLoader<'a> {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
} }
impl<'a> PluginLoader<'a> { impl<'a> PluginLoader<'a> {
@ -87,6 +88,7 @@ impl<'a> PluginLoader<'a> {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Result<()> { ) -> Result<()> {
let err_context = || format!("failed to reload plugin {plugin_id} from memory"); let err_context = || format!("failed to reload plugin {plugin_id} from memory");
let mut connected_clients: Vec<ClientId> = let mut connected_clients: Vec<ClientId> =
@ -112,6 +114,7 @@ impl<'a> PluginLoader<'a> {
default_shell, default_shell,
default_layout, default_layout,
layout_dir, layout_dir,
default_mode,
)?; )?;
plugin_loader plugin_loader
.load_module_from_memory() .load_module_from_memory()
@ -148,6 +151,7 @@ impl<'a> PluginLoader<'a> {
default_layout: Box<Layout>, default_layout: Box<Layout>,
skip_cache: bool, skip_cache: bool,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Result<()> { ) -> Result<()> {
let err_context = || format!("failed to start plugin {plugin_id} for client {client_id}"); let err_context = || format!("failed to start plugin {plugin_id} for client {client_id}");
let mut plugin_loader = PluginLoader::new( let mut plugin_loader = PluginLoader::new(
@ -168,6 +172,7 @@ impl<'a> PluginLoader<'a> {
default_shell, default_shell,
default_layout, default_layout,
layout_dir, layout_dir,
default_mode,
)?; )?;
if skip_cache { if skip_cache {
plugin_loader plugin_loader
@ -220,6 +225,7 @@ impl<'a> PluginLoader<'a> {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Result<()> { ) -> Result<()> {
let mut new_plugins = HashSet::new(); let mut new_plugins = HashSet::new();
for plugin_id in plugin_map.lock().unwrap().plugin_ids() { for plugin_id in plugin_map.lock().unwrap().plugin_ids() {
@ -242,6 +248,7 @@ impl<'a> PluginLoader<'a> {
default_shell.clone(), default_shell.clone(),
default_layout.clone(), default_layout.clone(),
layout_dir.clone(), layout_dir.clone(),
default_mode,
)?; )?;
plugin_loader plugin_loader
.load_module_from_memory() .load_module_from_memory()
@ -270,6 +277,7 @@ impl<'a> PluginLoader<'a> {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Result<()> { ) -> Result<()> {
let err_context = || format!("failed to reload plugin id {plugin_id}"); let err_context = || format!("failed to reload plugin id {plugin_id}");
@ -296,6 +304,7 @@ impl<'a> PluginLoader<'a> {
default_shell, default_shell,
default_layout, default_layout,
layout_dir, layout_dir,
default_mode,
)?; )?;
plugin_loader plugin_loader
.compile_module() .compile_module()
@ -328,6 +337,7 @@ impl<'a> PluginLoader<'a> {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Result<Self> { ) -> Result<Self> {
let plugin_own_data_dir = ZELLIJ_SESSION_CACHE_DIR let plugin_own_data_dir = ZELLIJ_SESSION_CACHE_DIR
.join(Url::from(&plugin.location).to_string()) .join(Url::from(&plugin.location).to_string())
@ -355,6 +365,7 @@ impl<'a> PluginLoader<'a> {
default_shell, default_shell,
default_layout, default_layout,
layout_dir, layout_dir,
default_mode,
}) })
} }
pub fn new_from_existing_plugin_attributes( pub fn new_from_existing_plugin_attributes(
@ -373,6 +384,7 @@ impl<'a> PluginLoader<'a> {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Result<Self> { ) -> Result<Self> {
let err_context = || "Failed to find existing plugin"; let err_context = || "Failed to find existing plugin";
let (running_plugin, _subscriptions, _workers) = { let (running_plugin, _subscriptions, _workers) = {
@ -407,6 +419,7 @@ impl<'a> PluginLoader<'a> {
default_shell, default_shell,
default_layout, default_layout,
layout_dir, layout_dir,
default_mode,
) )
} }
pub fn new_from_different_client_id( pub fn new_from_different_client_id(
@ -425,6 +438,7 @@ impl<'a> PluginLoader<'a> {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Result<Self> { ) -> Result<Self> {
let err_context = || "Failed to find existing plugin"; let err_context = || "Failed to find existing plugin";
let running_plugin = { let running_plugin = {
@ -460,6 +474,7 @@ impl<'a> PluginLoader<'a> {
default_shell, default_shell,
default_layout, default_layout,
layout_dir, layout_dir,
default_mode,
) )
} }
pub fn load_module_from_memory(&mut self) -> Result<Module> { pub fn load_module_from_memory(&mut self) -> Result<Module> {
@ -715,6 +730,7 @@ impl<'a> PluginLoader<'a> {
self.default_shell.clone(), self.default_shell.clone(),
self.default_layout.clone(), self.default_layout.clone(),
self.layout_dir.clone(), self.layout_dir.clone(),
self.default_mode,
)?; )?;
plugin_loader_for_client plugin_loader_for_client
.load_module_from_memory() .load_module_from_memory()
@ -814,6 +830,7 @@ impl<'a> PluginLoader<'a> {
input_pipes_to_unblock: Arc::new(Mutex::new(HashSet::new())), input_pipes_to_unblock: Arc::new(Mutex::new(HashSet::new())),
input_pipes_to_block: Arc::new(Mutex::new(HashSet::new())), input_pipes_to_block: Arc::new(Mutex::new(HashSet::new())),
layout_dir: self.layout_dir.clone(), layout_dir: self.layout_dir.clone(),
default_mode: self.default_mode.clone(),
subscriptions: Arc::new(Mutex::new(HashSet::new())), subscriptions: Arc::new(Mutex::new(HashSet::new())),
stdin_pipe, stdin_pipe,
stdout_pipe, stdout_pipe,

View file

@ -19,6 +19,7 @@ use crate::{thread_bus::ThreadSenders, ClientId};
use zellij_utils::async_channel::Sender; use zellij_utils::async_channel::Sender;
use zellij_utils::{ use zellij_utils::{
data::EventType, data::EventType,
data::InputMode,
data::PluginCapabilities, data::PluginCapabilities,
input::command::TerminalAction, input::command::TerminalAction,
input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation}, input::layout::{Layout, PluginUserConfiguration, RunPlugin, RunPluginLocation},
@ -284,6 +285,7 @@ pub struct PluginEnv {
pub plugin_cwd: PathBuf, pub plugin_cwd: PathBuf,
pub input_pipes_to_unblock: Arc<Mutex<HashSet<String>>>, pub input_pipes_to_unblock: Arc<Mutex<HashSet<String>>>,
pub input_pipes_to_block: Arc<Mutex<HashSet<String>>>, pub input_pipes_to_block: Arc<Mutex<HashSet<String>>>,
pub default_mode: InputMode,
pub subscriptions: Arc<Mutex<Subscriptions>>, pub subscriptions: Arc<Mutex<Subscriptions>>,
pub stdin_pipe: Arc<Mutex<VecDeque<u8>>>, pub stdin_pipe: Arc<Mutex<VecDeque<u8>>>,
pub stdout_pipe: Arc<Mutex<VecDeque<u8>>>, pub stdout_pipe: Arc<Mutex<VecDeque<u8>>>,

View file

@ -7,7 +7,8 @@ use std::path::PathBuf;
use tempfile::tempdir; use tempfile::tempdir;
use wasmtime::Engine; use wasmtime::Engine;
use zellij_utils::data::{ use zellij_utils::data::{
BareKey, Event, KeyWithModifier, PermissionStatus, PermissionType, PluginCapabilities, BareKey, Event, InputMode, KeyWithModifier, PermissionStatus, PermissionType,
PluginCapabilities,
}; };
use zellij_utils::errors::ErrorContext; use zellij_utils::errors::ErrorContext;
use zellij_utils::input::layout::{ use zellij_utils::input::layout::{
@ -280,6 +281,7 @@ fn create_plugin_thread(
client_attributes, client_attributes,
default_shell_action, default_shell_action,
Box::new(plugin_aliases), Box::new(plugin_aliases),
InputMode::Normal,
) )
.expect("TEST") .expect("TEST")
}) })
@ -359,6 +361,7 @@ fn create_plugin_thread_with_server_receiver(
client_attributes, client_attributes,
default_shell_action, default_shell_action,
Box::new(PluginAliases::default()), Box::new(PluginAliases::default()),
InputMode::Normal,
) )
.expect("TEST"); .expect("TEST");
}) })
@ -444,6 +447,7 @@ fn create_plugin_thread_with_pty_receiver(
client_attributes, client_attributes,
default_shell_action, default_shell_action,
Box::new(PluginAliases::default()), Box::new(PluginAliases::default()),
InputMode::Normal,
) )
.expect("TEST") .expect("TEST")
}) })
@ -524,6 +528,7 @@ fn create_plugin_thread_with_background_jobs_receiver(
client_attributes, client_attributes,
default_shell_action, default_shell_action,
Box::new(PluginAliases::default()), Box::new(PluginAliases::default()),
InputMode::Normal,
) )
.expect("TEST") .expect("TEST")
}) })

View file

@ -1,12 +1,15 @@
--- ---
source: zellij-server/src/plugins/./unit/plugin_tests.rs source: zellij-server/src/plugins/./unit/plugin_tests.rs
assertion_line: 455 assertion_line: 1043
expression: "format!(\"{:#?}\", switch_to_mode_event)" expression: "format!(\"{:#?}\", switch_to_mode_event)"
--- ---
Some( Some(
ChangeMode( ChangeMode(
ModeInfo { ModeInfo {
mode: Tab, mode: Tab,
base_mode: Some(
Normal,
),
keybinds: [], keybinds: [],
style: Style { style: Style {
colors: Palette { colors: Palette {

View file

@ -19,7 +19,7 @@ use wasmtime::{Engine, Module};
use zellij_utils::async_channel::Sender; use zellij_utils::async_channel::Sender;
use zellij_utils::async_std::task::{self, JoinHandle}; use zellij_utils::async_std::task::{self, JoinHandle};
use zellij_utils::consts::ZELLIJ_CACHE_DIR; use zellij_utils::consts::ZELLIJ_CACHE_DIR;
use zellij_utils::data::{PermissionStatus, PermissionType, PipeMessage, PipeSource}; use zellij_utils::data::{InputMode, PermissionStatus, PermissionType, PipeMessage, PipeSource};
use zellij_utils::downloader::Downloader; use zellij_utils::downloader::Downloader;
use zellij_utils::input::permission::PermissionCache; use zellij_utils::input::permission::PermissionCache;
use zellij_utils::notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap}; use zellij_utils::notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap};
@ -102,6 +102,7 @@ pub struct WasmBridge {
HashMap<RunPluginLocation, HashMap<PluginUserConfiguration, Vec<(PluginId, ClientId)>>>, HashMap<RunPluginLocation, HashMap<PluginUserConfiguration, Vec<(PluginId, ClientId)>>>,
pending_pipes: PendingPipes, pending_pipes: PendingPipes,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
} }
impl WasmBridge { impl WasmBridge {
@ -116,6 +117,7 @@ impl WasmBridge {
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
default_mode: InputMode,
) -> Self { ) -> Self {
let plugin_map = Arc::new(Mutex::new(PluginMap::default())); let plugin_map = Arc::new(Mutex::new(PluginMap::default()));
let connected_clients: Arc<Mutex<Vec<ClientId>>> = Arc::new(Mutex::new(vec![])); let connected_clients: Arc<Mutex<Vec<ClientId>>> = Arc::new(Mutex::new(vec![]));
@ -146,6 +148,7 @@ impl WasmBridge {
cached_plugin_map: HashMap::new(), cached_plugin_map: HashMap::new(),
pending_pipes: Default::default(), pending_pipes: Default::default(),
layout_dir, layout_dir,
default_mode,
} }
} }
pub fn load_plugin( pub fn load_plugin(
@ -202,6 +205,7 @@ impl WasmBridge {
let default_shell = self.default_shell.clone(); let default_shell = self.default_shell.clone();
let default_layout = self.default_layout.clone(); let default_layout = self.default_layout.clone();
let layout_dir = self.layout_dir.clone(); let layout_dir = self.layout_dir.clone();
let default_mode = self.default_mode;
async move { async move {
let _ = senders.send_to_background_jobs( let _ = senders.send_to_background_jobs(
BackgroundJob::AnimatePluginLoading(plugin_id), BackgroundJob::AnimatePluginLoading(plugin_id),
@ -249,6 +253,7 @@ impl WasmBridge {
default_layout, default_layout,
skip_cache, skip_cache,
layout_dir, layout_dir,
default_mode,
) { ) {
Ok(_) => handle_plugin_successful_loading(&senders, plugin_id), Ok(_) => handle_plugin_successful_loading(&senders, plugin_id),
Err(e) => handle_plugin_loading_failure( Err(e) => handle_plugin_loading_failure(
@ -340,6 +345,7 @@ impl WasmBridge {
let default_shell = self.default_shell.clone(); let default_shell = self.default_shell.clone();
let default_layout = self.default_layout.clone(); let default_layout = self.default_layout.clone();
let layout_dir = self.layout_dir.clone(); let layout_dir = self.layout_dir.clone();
let default_mode = self.default_mode;
async move { async move {
match PluginLoader::reload_plugin( match PluginLoader::reload_plugin(
first_plugin_id, first_plugin_id,
@ -357,6 +363,7 @@ impl WasmBridge {
default_shell.clone(), default_shell.clone(),
default_layout.clone(), default_layout.clone(),
layout_dir.clone(), layout_dir.clone(),
default_mode,
) { ) {
Ok(_) => { Ok(_) => {
handle_plugin_successful_loading(&senders, first_plugin_id); handle_plugin_successful_loading(&senders, first_plugin_id);
@ -382,6 +389,7 @@ impl WasmBridge {
default_shell.clone(), default_shell.clone(),
default_layout.clone(), default_layout.clone(),
layout_dir.clone(), layout_dir.clone(),
default_mode,
) { ) {
Ok(_) => handle_plugin_successful_loading(&senders, *plugin_id), Ok(_) => handle_plugin_successful_loading(&senders, *plugin_id),
Err(e) => handle_plugin_loading_failure( Err(e) => handle_plugin_loading_failure(
@ -434,6 +442,7 @@ impl WasmBridge {
self.default_shell.clone(), self.default_shell.clone(),
self.default_layout.clone(), self.default_layout.clone(),
self.layout_dir.clone(), self.layout_dir.clone(),
self.default_mode,
) { ) {
Ok(_) => { Ok(_) => {
let _ = self let _ = self

View file

@ -61,6 +61,7 @@ macro_rules! apply_action {
$env.default_shell.clone(), $env.default_shell.clone(),
$env.default_layout.clone(), $env.default_layout.clone(),
None, None,
$env.default_mode.clone(),
) { ) {
log::error!("{}: {:?}", $error_message(), e); log::error!("{}: {:?}", $error_message(), e);
} }

View file

@ -13,7 +13,7 @@ use crate::{
use uuid::Uuid; use uuid::Uuid;
use zellij_utils::{ use zellij_utils::{
channels::SenderWithContext, channels::SenderWithContext,
data::{Direction, Event, PluginCapabilities, ResizeStrategy}, data::{Direction, Event, InputMode, PluginCapabilities, ResizeStrategy},
errors::prelude::*, errors::prelude::*,
input::{ input::{
actions::{Action, SearchDirection, SearchOption}, actions::{Action, SearchDirection, SearchOption},
@ -38,6 +38,7 @@ pub(crate) fn route_action(
default_shell: Option<TerminalAction>, default_shell: Option<TerminalAction>,
default_layout: Box<Layout>, default_layout: Box<Layout>,
mut seen_cli_pipes: Option<&mut HashSet<String>>, mut seen_cli_pipes: Option<&mut HashSet<String>>,
default_mode: InputMode,
) -> Result<bool> { ) -> Result<bool> {
let mut should_break = false; let mut should_break = false;
let err_context = || format!("failed to route action for client {client_id}"); let err_context = || format!("failed to route action for client {client_id}");
@ -98,7 +99,7 @@ pub(crate) fn route_action(
.send_to_plugin(PluginInstruction::Update(vec![( .send_to_plugin(PluginInstruction::Update(vec![(
None, None,
Some(client_id), Some(client_id),
Event::ModeUpdate(get_mode_info(mode, attrs, capabilities)), Event::ModeUpdate(get_mode_info(mode, attrs, capabilities, Some(default_mode))),
)])) )]))
.with_context(err_context)?; .with_context(err_context)?;
senders senders
@ -106,7 +107,7 @@ pub(crate) fn route_action(
.with_context(err_context)?; .with_context(err_context)?;
senders senders
.send_to_screen(ScreenInstruction::ChangeMode( .send_to_screen(ScreenInstruction::ChangeMode(
get_mode_info(mode, attrs, capabilities), get_mode_info(mode, attrs, capabilities, Some(default_mode)),
client_id, client_id,
)) ))
.with_context(err_context)?; .with_context(err_context)?;
@ -344,7 +345,12 @@ pub(crate) fn route_action(
.send_to_plugin(PluginInstruction::Update(vec![( .send_to_plugin(PluginInstruction::Update(vec![(
None, None,
None, None,
Event::ModeUpdate(get_mode_info(input_mode, attrs, capabilities)), Event::ModeUpdate(get_mode_info(
input_mode,
attrs,
capabilities,
Some(default_mode),
)),
)])) )]))
.with_context(err_context)?; .with_context(err_context)?;
@ -357,6 +363,7 @@ pub(crate) fn route_action(
input_mode, input_mode,
attrs, attrs,
capabilities, capabilities,
Some(default_mode),
))) )))
.with_context(err_context)?; .with_context(err_context)?;
}, },
@ -1018,6 +1025,7 @@ pub(crate) fn route_thread_main(
rlocked_sessions.default_shell.clone(), rlocked_sessions.default_shell.clone(),
rlocked_sessions.layout.clone(), rlocked_sessions.layout.clone(),
Some(&mut seen_cli_pipes), Some(&mut seen_cli_pipes),
rlocked_sessions.default_mode,
)? { )? {
should_break = true; should_break = true;
} }
@ -1042,6 +1050,7 @@ pub(crate) fn route_thread_main(
rlocked_sessions.default_shell.clone(), rlocked_sessions.default_shell.clone(),
rlocked_sessions.layout.clone(), rlocked_sessions.layout.clone(),
Some(&mut seen_cli_pipes), Some(&mut seen_cli_pipes),
rlocked_sessions.default_mode,
)? { )? {
should_break = true; should_break = true;
} }

View file

@ -2363,6 +2363,7 @@ pub(crate) fn screen_thread_main(
// ¯\_(ツ)_/¯ // ¯\_(ツ)_/¯
arrow_fonts: !arrow_fonts, arrow_fonts: !arrow_fonts,
}, },
config_options.default_mode,
), ),
draw_pane_frames, draw_pane_frames,
auto_layout, auto_layout,

View file

@ -114,6 +114,7 @@ fn send_cli_action_to_server(
let get_current_dir = || PathBuf::from("."); let get_current_dir = || PathBuf::from(".");
let actions = Action::actions_from_cli(cli_action, Box::new(get_current_dir), None).unwrap(); let actions = Action::actions_from_cli(cli_action, Box::new(get_current_dir), None).unwrap();
let senders = session_metadata.senders.clone(); let senders = session_metadata.senders.clone();
let default_mode = session_metadata.default_mode.clone();
let capabilities = PluginCapabilities::default(); let capabilities = PluginCapabilities::default();
let client_attributes = ClientAttributes::default(); let client_attributes = ClientAttributes::default();
let default_shell = None; let default_shell = None;
@ -129,6 +130,7 @@ fn send_cli_action_to_server(
default_shell.clone(), default_shell.clone(),
default_layout.clone(), default_layout.clone(),
None, None,
default_mode,
) )
.unwrap(); .unwrap();
} }
@ -516,6 +518,7 @@ impl MockScreen {
layout, layout,
client_input_modes: HashMap::new(), client_input_modes: HashMap::new(),
client_keybinds: HashMap::new(), client_keybinds: HashMap::new(),
default_mode: self.session_metadata.default_mode.clone(),
} }
} }
} }
@ -575,6 +578,7 @@ impl MockScreen {
layout, layout,
client_input_modes: HashMap::new(), client_input_modes: HashMap::new(),
client_keybinds: HashMap::new(), client_keybinds: HashMap::new(),
default_mode: InputMode::Normal,
}; };
let os_input = FakeInputOutput::default(); let os_input = FakeInputOutput::default();

View file

@ -0,0 +1,13 @@
layout {
pane size=1 borderless=true {
plugin location="tab-bar" {
hide_swap_layout_indication true
}
}
pane
pane size=2 borderless=true {
plugin location="status-bar" {
classic true
}
}
}

View file

@ -0,0 +1,104 @@
tab_template name="ui" {
pane size=1 borderless=true {
plugin location="tab-bar" {
hide_swap_layout_indication true
}
}
children
pane size=2 borderless=true {
plugin location="status-bar" {
classic true
}
}
}
swap_tiled_layout name="vertical" {
ui max_panes=5 {
pane split_direction="vertical" {
pane
pane { children; }
}
}
ui max_panes=8 {
pane split_direction="vertical" {
pane { children; }
pane { pane; pane; pane; pane; }
}
}
ui max_panes=12 {
pane split_direction="vertical" {
pane { children; }
pane { pane; pane; pane; pane; }
pane { pane; pane; pane; pane; }
}
}
}
swap_tiled_layout name="horizontal" {
ui max_panes=5 {
pane
pane
}
ui max_panes=8 {
pane {
pane split_direction="vertical" { children; }
pane split_direction="vertical" { pane; pane; pane; pane; }
}
}
ui max_panes=12 {
pane {
pane split_direction="vertical" { children; }
pane split_direction="vertical" { pane; pane; pane; pane; }
pane split_direction="vertical" { pane; pane; pane; pane; }
}
}
}
swap_tiled_layout name="stacked" {
ui min_panes=5 {
pane split_direction="vertical" {
pane
pane stacked=true { children; }
}
}
}
swap_floating_layout name="staggered" {
floating_panes
}
swap_floating_layout name="enlarged" {
floating_panes max_panes=10 {
pane { x "5%"; y 1; width "90%"; height "90%"; }
pane { x "5%"; y 2; width "90%"; height "90%"; }
pane { x "5%"; y 3; width "90%"; height "90%"; }
pane { x "5%"; y 4; width "90%"; height "90%"; }
pane { x "5%"; y 5; width "90%"; height "90%"; }
pane { x "5%"; y 6; width "90%"; height "90%"; }
pane { x "5%"; y 7; width "90%"; height "90%"; }
pane { x "5%"; y 8; width "90%"; height "90%"; }
pane { x "5%"; y 9; width "90%"; height "90%"; }
pane focus=true { x 10; y 10; width "90%"; height "90%"; }
}
}
swap_floating_layout name="spread" {
floating_panes max_panes=1 {
pane {y "50%"; x "50%"; }
}
floating_panes max_panes=2 {
pane { x "1%"; y "25%"; width "45%"; }
pane { x "50%"; y "25%"; width "45%"; }
}
floating_panes max_panes=3 {
pane focus=true { y "55%"; width "45%"; height "45%"; }
pane { x "1%"; y "1%"; width "45%"; }
pane { x "50%"; y "1%"; width "45%"; }
}
floating_panes max_panes=4 {
pane { x "1%"; y "55%"; width "45%"; height "45%"; }
pane focus=true { x "50%"; y "55%"; width "45%"; height "45%"; }
pane { x "1%"; y "1%"; width "45%"; height "45%"; }
pane { x "50%"; y "1%"; width "45%"; height "45%"; }
}
}

View file

@ -3,7 +3,7 @@ layout {
plugin location="tab-bar" plugin location="tab-bar"
} }
pane pane
pane size=2 borderless=true { pane size=1 borderless=true {
plugin location="status-bar" plugin location="status-bar"
} }
} }

View file

@ -3,7 +3,7 @@ tab_template name="ui" {
plugin location="tab-bar" plugin location="tab-bar"
} }
children children
pane size=2 borderless=true { pane size=1 borderless=true {
plugin location="status-bar" plugin location="status-bar"
} }
} }

View file

@ -293,6 +293,8 @@ pub struct ModeUpdatePayload {
pub arrow_fonts_support: bool, pub arrow_fonts_support: bool,
#[prost(string, optional, tag = "5")] #[prost(string, optional, tag = "5")]
pub session_name: ::core::option::Option<::prost::alloc::string::String>, pub session_name: ::core::option::Option<::prost::alloc::string::String>,
#[prost(enumeration = "super::input_mode::InputMode", optional, tag = "6")]
pub base_mode: ::core::option::Option<i32>,
} }
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]

View file

@ -1114,6 +1114,7 @@ pub type KeybindsVec = Vec<(InputMode, Vec<(KeyWithModifier, Vec<Action>)>)>;
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ModeInfo { pub struct ModeInfo {
pub mode: InputMode, pub mode: InputMode,
pub base_mode: Option<InputMode>,
pub keybinds: KeybindsVec, pub keybinds: KeybindsVec,
pub style: Style, pub style: Style,
pub capabilities: PluginCapabilities, pub capabilities: PluginCapabilities,

View file

@ -709,6 +709,37 @@ impl Action {
CliAction::ListClients => Ok(vec![Action::ListClients]), CliAction::ListClients => Ok(vec![Action::ListClients]),
} }
} }
pub fn launches_plugin(&self, plugin_url: &str) -> bool {
match self {
Action::LaunchPlugin(run_plugin_or_alias, ..) => {
log::info!(
"1: {:?} == {:?}",
run_plugin_or_alias.location_string(),
plugin_url
);
eprintln!(
"1: {:?} == {:?}",
run_plugin_or_alias.location_string(),
plugin_url
);
&run_plugin_or_alias.location_string() == plugin_url
},
Action::LaunchOrFocusPlugin(run_plugin_or_alias, ..) => {
log::info!(
"2: {:?} == {:?}",
run_plugin_or_alias.location_string(),
plugin_url
);
eprintln!(
"2: {:?} == {:?}",
run_plugin_or_alias.location_string(),
plugin_url
);
&run_plugin_or_alias.location_string() == plugin_url
},
_ => false,
}
}
} }
impl From<OnForceClose> for Action { impl From<OnForceClose> for Action {

View file

@ -1121,6 +1121,7 @@ impl Layout {
available_layouts.push(LayoutInfo::BuiltIn("strider".to_owned())); available_layouts.push(LayoutInfo::BuiltIn("strider".to_owned()));
available_layouts.push(LayoutInfo::BuiltIn("disable-status-bar".to_owned())); available_layouts.push(LayoutInfo::BuiltIn("disable-status-bar".to_owned()));
available_layouts.push(LayoutInfo::BuiltIn("compact".to_owned())); available_layouts.push(LayoutInfo::BuiltIn("compact".to_owned()));
available_layouts.push(LayoutInfo::BuiltIn("classic".to_owned()));
available_layouts.sort_by(|a, b| { available_layouts.sort_by(|a, b| {
let a_name = a.name(); let a_name = a.name();
let b_name = b.name(); let b_name = b.name();
@ -1359,6 +1360,14 @@ impl Layout {
Self::stringified_compact_swap_from_assets()?, Self::stringified_compact_swap_from_assets()?,
)), )),
)), )),
Some("classic") => Ok((
"Classic layout".into(),
Self::stringified_classic_from_assets()?,
Some((
"Classiclayout swap".into(),
Self::stringified_classic_swap_from_assets()?,
)),
)),
Some("welcome") => Ok(( Some("welcome") => Ok((
"Welcome screen layout".into(), "Welcome screen layout".into(),
Self::stringified_welcome_from_assets()?, Self::stringified_welcome_from_assets()?,
@ -1395,6 +1404,14 @@ impl Layout {
Ok(String::from_utf8(setup::COMPACT_BAR_SWAP_LAYOUT.to_vec())?) Ok(String::from_utf8(setup::COMPACT_BAR_SWAP_LAYOUT.to_vec())?)
} }
pub fn stringified_classic_from_assets() -> Result<String, ConfigError> {
Ok(String::from_utf8(setup::CLASSIC_LAYOUT.to_vec())?)
}
pub fn stringified_classic_swap_from_assets() -> Result<String, ConfigError> {
Ok(String::from_utf8(setup::CLASSIC_SWAP_LAYOUT.to_vec())?)
}
pub fn stringified_welcome_from_assets() -> Result<String, ConfigError> { pub fn stringified_welcome_from_assets() -> Result<String, ConfigError> {
Ok(String::from_utf8(setup::WELCOME_LAYOUT.to_vec())?) Ok(String::from_utf8(setup::WELCOME_LAYOUT.to_vec())?)
} }

View file

@ -33,12 +33,14 @@ mod not_wasm {
mode: InputMode, mode: InputMode,
attributes: &ClientAttributes, attributes: &ClientAttributes,
capabilities: PluginCapabilities, capabilities: PluginCapabilities,
base_mode: Option<InputMode>,
) -> ModeInfo { ) -> ModeInfo {
let keybinds = attributes.keybinds.to_keybinds_vec(); let keybinds = attributes.keybinds.to_keybinds_vec();
let session_name = envs::get_session_name().ok(); let session_name = envs::get_session_name().ok();
ModeInfo { ModeInfo {
mode, mode,
base_mode,
keybinds, keybinds,
style: attributes.style, style: attributes.style,
capabilities, capabilities,

View file

@ -218,6 +218,7 @@ message ModeUpdatePayload {
style.Style style = 3; style.Style style = 3;
bool arrow_fonts_support = 4; bool arrow_fonts_support = 4;
optional string session_name = 5; optional string session_name = 5;
optional input_mode.InputMode base_mode = 6;
} }
message InputModeKeybinds { message InputModeKeybinds {

View file

@ -813,6 +813,9 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
ProtobufInputMode::from_i32(protobuf_mode_update_payload.current_mode) ProtobufInputMode::from_i32(protobuf_mode_update_payload.current_mode)
.ok_or("Malformed InputMode in the ModeUpdate Event")? .ok_or("Malformed InputMode in the ModeUpdate Event")?
.try_into()?; .try_into()?;
let base_mode: Option<InputMode> = protobuf_mode_update_payload
.base_mode
.and_then(|b_m| ProtobufInputMode::from_i32(b_m)?.try_into().ok());
let keybinds: Vec<(InputMode, Vec<(KeyWithModifier, Vec<Action>)>)> = let keybinds: Vec<(InputMode, Vec<(KeyWithModifier, Vec<Action>)>)> =
protobuf_mode_update_payload protobuf_mode_update_payload
.keybinds .keybinds
@ -851,6 +854,7 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo {
style, style,
capabilities, capabilities,
session_name, session_name,
base_mode,
}; };
Ok(mode_info) Ok(mode_info)
} }
@ -860,6 +864,9 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
type Error = &'static str; type Error = &'static str;
fn try_from(mode_info: ModeInfo) -> Result<Self, &'static str> { fn try_from(mode_info: ModeInfo) -> Result<Self, &'static str> {
let current_mode: ProtobufInputMode = mode_info.mode.try_into()?; let current_mode: ProtobufInputMode = mode_info.mode.try_into()?;
let base_mode: Option<ProtobufInputMode> = mode_info
.base_mode
.and_then(|mode| ProtobufInputMode::try_from(mode).ok());
let style: ProtobufStyle = mode_info.style.try_into()?; let style: ProtobufStyle = mode_info.style.try_into()?;
let arrow_fonts_support: bool = mode_info.capabilities.arrow_fonts; let arrow_fonts_support: bool = mode_info.capabilities.arrow_fonts;
let session_name = mode_info.session_name; let session_name = mode_info.session_name;
@ -893,6 +900,7 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload {
keybinds: protobuf_input_mode_keybinds, keybinds: protobuf_input_mode_keybinds,
arrow_fonts_support, arrow_fonts_support,
session_name, session_name,
base_mode: base_mode.map(|b_m| b_m as i32),
}) })
} }
} }
@ -1112,6 +1120,7 @@ fn serialize_mode_update_event_with_non_default_values() {
}, },
capabilities: PluginCapabilities { arrow_fonts: false }, capabilities: PluginCapabilities { arrow_fonts: false },
session_name: Some("my awesome test session".to_owned()), session_name: Some("my awesome test session".to_owned()),
base_mode: Some(InputMode::Locked),
}); });
let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap(); let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap();
let serialized_protobuf_event = protobuf_event.encode_to_vec(); let serialized_protobuf_event = protobuf_event.encode_to_vec();

View file

@ -167,6 +167,18 @@ pub const COMPACT_BAR_SWAP_LAYOUT: &[u8] = include_bytes!(concat!(
"assets/layouts/compact.swap.kdl" "assets/layouts/compact.swap.kdl"
)); ));
pub const CLASSIC_LAYOUT: &[u8] = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/",
"assets/layouts/classic.kdl"
));
pub const CLASSIC_SWAP_LAYOUT: &[u8] = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/",
"assets/layouts/classic.swap.kdl"
));
pub const WELCOME_LAYOUT: &[u8] = include_bytes!(concat!( pub const WELCOME_LAYOUT: &[u8] = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"), env!("CARGO_MANIFEST_DIR"),
"/", "/",
@ -230,6 +242,7 @@ pub fn dump_specified_layout(layout: &str) -> std::io::Result<()> {
"default" => dump_asset(DEFAULT_LAYOUT), "default" => dump_asset(DEFAULT_LAYOUT),
"compact" => dump_asset(COMPACT_BAR_LAYOUT), "compact" => dump_asset(COMPACT_BAR_LAYOUT),
"disable-status" => dump_asset(NO_STATUS_LAYOUT), "disable-status" => dump_asset(NO_STATUS_LAYOUT),
"classic" => dump_asset(CLASSIC_LAYOUT),
custom => { custom => {
info!("Dump {custom} layout"); info!("Dump {custom} layout");
let custom = add_layout_ext(custom); let custom = add_layout_ext(custom);
@ -256,6 +269,7 @@ pub fn dump_specified_swap_layout(swap_layout: &str) -> std::io::Result<()> {
"strider" => dump_asset(STRIDER_SWAP_LAYOUT), "strider" => dump_asset(STRIDER_SWAP_LAYOUT),
"default" => dump_asset(DEFAULT_SWAP_LAYOUT), "default" => dump_asset(DEFAULT_SWAP_LAYOUT),
"compact" => dump_asset(COMPACT_BAR_SWAP_LAYOUT), "compact" => dump_asset(COMPACT_BAR_SWAP_LAYOUT),
"classic" => dump_asset(CLASSIC_SWAP_LAYOUT),
not_found => Err(std::io::Error::new( not_found => Err(std::io::Error::new(
std::io::ErrorKind::Other, std::io::ErrorKind::Other,
format!("Swap Layout not found for: {}", not_found), format!("Swap Layout not found for: {}", not_found),

View file

@ -1,6 +1,6 @@
--- ---
source: zellij-utils/src/setup.rs source: zellij-utils/src/setup.rs
assertion_line: 699 assertion_line: 740
expression: "format!(\"{:#?}\", layout)" expression: "format!(\"{:#?}\", layout)"
--- ---
Layout { Layout {
@ -69,7 +69,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(
@ -233,7 +233,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(
@ -455,7 +455,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(
@ -758,7 +758,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(
@ -903,7 +903,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(
@ -1125,7 +1125,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(
@ -1428,7 +1428,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(
@ -1592,7 +1592,7 @@ Layout {
children: [], children: [],
split_size: Some( split_size: Some(
Fixed( Fixed(
2, 1,
), ),
), ),
run: Some( run: Some(