diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-06-29 18:10:59 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-06-29 18:10:59 +0200 |
| commit | 245f5141c9bb7eb91f003efac4defc94470243fd (patch) | |
| tree | 52ae6d003366f97e41c8a1450602aef63c8fdca2 | |
| parent | feat: reload config on theme change (#5135) (diff) | |
| download | sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.tar.gz sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.tar.xz sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.zip | |
Title frames (#5318)
* initial implementation
* improve single line title design
* hint text plugin infra
* add proto regen task
* display alt text in status bar
* don't display text with full frames
* style alt hover text
* fix + style control own pane hover
* make multiplayer indications responsive
* update snapshots
* plugin api
* single pane as tab
* better scroll styling
* fix tests
* tab-bar plus hover
* plugin surface tests
* integration tests
* adjust all integration tests
* reduce hover noise
* add pane id to in place
* more integration tests
* style: rustfmt
* update plugin assets
* update assets and snapshots
* add pr
292 files changed, 5558 insertions, 3152 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d5d8372..d0bfd03b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * chore: new integration testing infra (https://github.com/zellij-org/zellij/pull/5269) * feat: FocusLastPane bindable action (https://github.com/zellij-org/zellij/pull/4241) * fix: live reload on theme dir changes (https://github.com/zellij-org/zellij/pull/5135) +* feat: new title-frames UI (https://github.com/zellij-org/zellij/pull/5318) ## [0.44.3] - 2026-05-13 * fix(windows): bump windows-sys to 0.59 to align manifest with code, fixing source builds via `cargo install`/`cargo binstall` (https://github.com/zellij-org/zellij/pull/5139) diff --git a/default-plugins/fixture-plugin-for-tests/src/main.rs b/default-plugins/fixture-plugin-for-tests/src/main.rs index 4885054c..ec656443 100644 --- a/default-plugins/fixture-plugin-for-tests/src/main.rs +++ b/default-plugins/fixture-plugin-for-tests/src/main.rs @@ -173,6 +173,8 @@ impl ZellijPlugin for State { BareKey::Char('6') if key.has_no_modifiers() => close_focused_tab(), BareKey::Char('7') if key.has_no_modifiers() => undo_rename_tab(), BareKey::Char('8') if key.has_no_modifiers() => quit_zellij(), + BareKey::Char('9') if key.has_no_modifiers() => new_pane(), + BareKey::Char('0') if key.has_no_modifiers() => toggle_floating_panes(None), BareKey::Char('a') if key.has_only_modifiers(&[KeyModifier::Ctrl]) => { previous_swap_layout() }, @@ -626,6 +628,9 @@ impl ZellijPlugin for State { // Test clear_pane_highlights clear_pane_highlights(PaneId::Terminal(1)); }, + BareKey::Char('i') if key.has_only_modifiers(&[KeyModifier::Super]) => { + toggle_floating_panes(Some(2)); + }, BareKey::Char('a') if key.has_only_modifiers(&[KeyModifier::Ctrl, KeyModifier::Shift]) => { diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs index 5412e6b6..6cffc5c7 100644 --- a/default-plugins/status-bar/src/main.rs +++ b/default-plugins/status-bar/src/main.rs @@ -42,6 +42,12 @@ struct State { classic_ui: bool, base_mode_is_locked: bool, cached_keybinds: KeybindsVec, + hint_text: Option<BTreeMap<usize, StyledText>>, + outstanding_hint_timeouts: usize, + new_pane_ribbon_range: Option<(usize, usize)>, + floating_ribbon_range: Option<(usize, usize)>, + new_pane_ribbon_hovered: bool, + floating_ribbon_hovered: bool, } register_plugin!(State); @@ -192,6 +198,13 @@ fn color_elements(palette: Styling, different_color_alternates: bool) -> Colored } } +fn col_in_range(range: Option<(usize, usize)>, col: usize) -> bool { + match range { + Some((start, end)) => col >= start && col < end, + None => false, + } +} + impl ZellijPlugin for State { fn load(&mut self, configuration: BTreeMap<String, String>) { // TODO: Should be able to choose whether to use the cache through config. @@ -209,6 +222,9 @@ impl ZellijPlugin for State { EventType::InputReceived, EventType::SystemClipboardFailure, EventType::InitialKeybinds, + EventType::HintText, + EventType::Timer, + EventType::Mouse, ]); } @@ -260,11 +276,55 @@ impl ZellijPlugin for State { Event::InputReceived => { if self.text_copy_destination.is_some() || self.display_system_clipboard_failure == true + || self.hint_text.is_some() { should_render = true; } self.text_copy_destination = None; self.display_system_clipboard_failure = false; + self.hint_text = None; + }, + Event::HintText(hint_variants) => { + if hint_variants.is_empty() { + if self.hint_text.is_some() { + self.hint_text = None; + should_render = true; + } + } else { + self.hint_text = Some(hint_variants); + self.outstanding_hint_timeouts += 1; + set_timeout(5.0); + should_render = true; + } + }, + Event::Timer(_) => { + self.outstanding_hint_timeouts = self.outstanding_hint_timeouts.saturating_sub(1); + if self.outstanding_hint_timeouts == 0 && self.hint_text.is_some() { + self.hint_text = None; + should_render = true; + } + }, + Event::Mouse(mouse_event) => match mouse_event { + Mouse::LeftClick(_, col) => { + if col_in_range(self.new_pane_ribbon_range, col) { + new_pane(); + } else if col_in_range(self.floating_ribbon_range, col) { + toggle_floating_panes(None); + } + }, + Mouse::Hover(_, col) => { + let new_pane_hovered = col_in_range(self.new_pane_ribbon_range, col); + let floating_hovered = + !new_pane_hovered && col_in_range(self.floating_ribbon_range, col); + if self.new_pane_ribbon_hovered != new_pane_hovered + || self.floating_ribbon_hovered != floating_hovered + { + self.new_pane_ribbon_hovered = new_pane_hovered; + self.floating_ribbon_hovered = floating_hovered; + should_render = true; + } + }, + _ => {}, }, _ => {}, }; @@ -287,21 +347,31 @@ impl ZellijPlugin for State { PaletteColor::EightBit(color) => format!("\u{1b}[48;5;{}m\u{1b}[0K", color), }; 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, - self.text_copy_destination, - self.display_system_clipboard_failure, - ), - fill_bg, + let full_pane_frames = self.mode_info.pane_frame_style == Some(PaneFrameStyle::Full); + let hint_text = if full_pane_frames { + None + } else { + self.hint_text.as_ref() + }; + let (line, new_pane_ribbon_range, floating_ribbon_range) = one_line_ui( + &self.mode_info, + active_tab, + cols, + separator, + self.base_mode_is_locked, + self.text_copy_destination, + self.display_system_clipboard_failure, + hint_text, + self.new_pane_ribbon_hovered, + self.floating_ribbon_hovered, ); + self.new_pane_ribbon_range = new_pane_ribbon_range; + self.floating_ribbon_range = floating_ribbon_range; + print!("{}{}", line, fill_bg); return; } + self.new_pane_ribbon_range = None; + self.floating_ribbon_range = None; //TODO: Switch to UI components here let active_tab = self.tabs.iter().find(|t| t.active); diff --git a/default-plugins/status-bar/src/one_line_ui.rs b/default-plugins/status-bar/src/one_line_ui.rs index d997fb36..97721167 100644 --- a/default-plugins/status-bar/src/one_line_ui.rs +++ b/default-plugins/status-bar/src/one_line_ui.rs @@ -3,10 +3,10 @@ use ansi_term::{ Color::{Fixed, RGB}, Style, }; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use zellij_tile::prelude::actions::Action; use zellij_tile::prelude::*; -use zellij_tile_utils::palette_match; +use zellij_tile_utils::{palette_match, style}; use crate::first_line::{to_char, KeyAction, KeyMode, KeyShortcut}; use crate::second_line::{system_clipboard_error, text_copied_hint}; @@ -22,30 +22,69 @@ pub fn one_line_ui( base_mode_is_locked: bool, text_copied_to_clipboard_destination: Option<CopyDestination>, clipboard_failure: bool, -) -> LinePart { + hint: Option<&BTreeMap<usize, StyledText>>, + new_pane_hovered: bool, + floating_hovered: bool, +) -> (LinePart, Option<(usize, usize)>, Option<(usize, usize)>) { if let Some(text_copied_to_clipboard_destination) = text_copied_to_clipboard_destination { - return text_copied_hint(text_copied_to_clipboard_destination); + return ( + text_copied_hint(text_copied_to_clipboard_destination), + None, + None, + ); } if clipboard_failure { - return system_clipboard_error(&help.style.colors); + return (system_clipboard_error(&help.style.colors), None, None); } let mut line_part_to_render = LinePart::default(); - let mut append = |line_part: &LinePart, max_len: &mut usize| { - line_part_to_render.append(line_part); - *max_len = max_len.saturating_sub(line_part.len); - }; + let mut new_pane_range = None; + let mut floating_range = None; + + let left_part = hint + .and_then(|hint| hint_line_part(hint, max_len)) + .or_else(|| render_mode_key_indicators(help, max_len, separator, base_mode_is_locked)); + if let Some(left) = left_part { + line_part_to_render.append(&left); + max_len = max_len.saturating_sub(left.len); + match help.mode { + InputMode::Normal | InputMode::Locked => { + let secondary_offset = line_part_to_render.len; + if let Some((secondary_info, new_pane, floating)) = render_secondary_info( + help, + tab_info, + max_len, + new_pane_hovered, + floating_hovered, + ) { + new_pane_range = new_pane + .map(|(start, end)| (secondary_offset + start, secondary_offset + end)); + floating_range = floating + .map(|(start, end)| (secondary_offset + start, secondary_offset + end)); + line_part_to_render.append(&secondary_info); + } + }, + _ => { + if let Some(key_group_separator) = add_keygroup_separator(help, max_len) { + line_part_to_render.append(&key_group_separator); + max_len = max_len.saturating_sub(key_group_separator.len); + if let Some(keybinds) = keybinds(help, max_len) { + line_part_to_render.append(&keybinds); + } + } + }, + } + } + (line_part_to_render, new_pane_range, floating_range) +} - render_mode_key_indicators(help, max_len, separator, base_mode_is_locked) - .map(|mode_key_indicators| append(&mode_key_indicators, &mut max_len)) - .and_then(|_| match help.mode { - InputMode::Normal | InputMode::Locked => render_secondary_info(help, tab_info, max_len) - .map(|secondary_info| append(&secondary_info, &mut max_len)), - _ => add_keygroup_separator(help, max_len) - .map(|key_group_separator| append(&key_group_separator, &mut max_len)) - .and_then(|_| keybinds(help, max_len)) - .map(|keybinds| append(&keybinds, &mut max_len)), - }); - line_part_to_render +fn hint_line_part(hint: &BTreeMap<usize, StyledText>, max_len: usize) -> Option<LinePart> { + let fitting_variant = hint + .range(..=max_len) + .next_back() + .map(|(_width, styled_text)| styled_text)?; + let len = fitting_variant.text.width(); + let part = serialize_text(&Text::from(fitting_variant.clone())); + Some(LinePart { part, len }) } fn to_base_mode(base_mode: InputMode) -> Action { @@ -730,11 +769,14 @@ fn render_secondary_info( help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usize, -) -> Option<LinePart> { + new_pane_hovered: bool, + floating_hovered: bool, +) -> Option<(LinePart, Option<(usize, usize)>, Option<(usize, usize)>)> { let mut secondary_info = LinePart::default(); let supports_arrow_fonts = !help.capabilities.arrow_fonts; let colored_elements = color_elements(help.style.colors, !supports_arrow_fonts); - let secondary_keybinds = secondary_keybinds(&help, tab_info, max_len); + let (secondary_keybinds, new_pane_range, floating_range) = + secondary_keybinds(&help, tab_info, max_len, new_pane_hovered, floating_hovered); secondary_info.append(&secondary_keybinds); let remaining_space = max_len.saturating_sub(secondary_info.len).saturating_sub(1); // 1 for the end padding of the line let mut padding = String::new(); @@ -746,7 +788,10 @@ fn render_secondary_info( secondary_info.part = format!("{}{}", padding, secondary_info.part); secondary_info.len += padding_len; if secondary_info.len <= max_len { - Some(secondary_info) + let shift = |range: Option<(usize, usize)>| { + range.map(|(start, end)| (start + padding_len, end + padding_len)) + }; + Some((secondary_info, shift(new_pane_range), shift(floating_range))) } else { None } @@ -764,8 +809,16 @@ fn should_show_focus_and_resize_shortcuts(tab_info: Option<&TabInfo>) -> bool { } } -fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usize) -> LinePart { +fn secondary_keybinds( + help: &ModeInfo, + tab_info: Option<&TabInfo>, + max_len: usize, + new_pane_hovered: bool, + floating_hovered: bool, +) -> (LinePart, Option<(usize, usize)>, Option<(usize, usize)>) { let mut secondary_info = LinePart::default(); + let mut new_pane_range; + let mut floating_range; let binds = &help.get_mode_keybinds(); let should_show_focus_and_resize_shortcuts = should_show_focus_and_resize_shortcuts(tab_info); // New Pane @@ -908,13 +961,24 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz let no_common_modifier = common_modifiers.is_empty(); if no_common_modifier { - secondary_info.append(&add_shortcut( - help, - "New Pane", - &new_pane_key_to_display, - false, - Some(0), - )); + let new_pane_start = secondary_info.len; + if new_pane_hovered { + secondary_info.append(&add_shortcut_hovered( + help, + "New Pane", + &new_pane_key_to_display, + Some(0), + )); + } else { + secondary_info.append(&add_shortcut( + help, + "New Pane", + &new_pane_key_to_display, + false, + Some(0), + )); + } + new_pane_range = ribbon_range(new_pane_start, secondary_info.len); if should_show_focus_and_resize_shortcuts { secondary_info.append(&add_shortcut( help, @@ -931,13 +995,24 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz Some(0), )); } - secondary_info.append(&add_shortcut( - help, - "Floating", - &toggle_floating_key_to_display, - are_floating_panes_visible, - Some(0), - )); + let floating_start = secondary_info.len; + if floating_hovered { + secondary_info.append(&add_shortcut_hovered( + help, + "Floating", + &toggle_floating_key_to_display, + Some(0), + )); + } else { + secondary_info.append(&add_shortcut( + help, + "Floating", + &toggle_floating_key_to_display, + are_floating_panes_visible, + Some(0), + )); + } + floating_range = ribbon_range(floating_start, secondary_info.len); } else { let modifier_str = text_as_line_part_with_emphasis( format!( @@ -967,12 +1042,22 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz .iter() .map(|k| k.strip_common_modifiers(&common_modifiers)) .collect(); - secondary_info.append(&add_shortcut_with_inline_key( - help, - "New Pane", - new_pane_key_to_display, - false, - )); + let new_pane_start = secondary_info.len; + if new_pane_hovered { + secondary_info.append(&add_shortcut_with_inline_key_hovered( + help, + "New Pane", + new_pane_key_to_display, + )); + } else { + secondary_info.append(&add_shortcut_with_inline_key( + help, + "New Pane", + new_pane_key_to_display, + false, + )); + } + new_pane_range = ribbon_range(new_pane_start, secondary_info.len); if should_show_focus_and_resize_shortcuts { secondary_info.append(&add_shortcut_with_inline_key( help, @@ -987,19 +1072,38 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz false, )); } - secondary_info.append(&add_shortcut_with_inline_key( - help, - "Floating", - toggle_floating_key_to_display, - are_floating_panes_visible, - )); + let floating_start = secondary_info.len; + if floating_hovered { + secondary_info.append(&add_shortcut_with_inline_key_hovered( + help, + "Floating", + toggle_floating_key_to_display, + )); + } else { + secondary_info.append(&add_shortcut_with_inline_key( + help, + "Floating", + toggle_floating_key_to_display, + are_floating_panes_visible, + )); + } + floating_range = ribbon_range(floating_start, secondary_info.len); } if secondary_info.len <= max_len { - secondary_info - } else { - let mut short_line = LinePart::default(); - if no_common_modifier { + return (secondary_info, new_pane_range, floating_range); + } + let mut short_line = LinePart::default(); + if no_common_modifier { + let new_pane_start = short_line.len; + if new_pane_hovered { + short_line.append(&add_shortcut_hovered( + help, + "New", + &new_pane_key_to_display, + Some(0), + )); + } else { short_line.append(&add_shortcut( help, "New", @@ -1007,22 +1111,33 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz false, Some(0), )); - if should_show_focus_and_resize_shortcuts { - short_line.append(&add_shortcut( - help, - "Focus", - &move_focus_shortcuts, - false, - Some(0), - )); - short_line.append(&add_shortcut( - help, - "Resize", - &resize_shortcuts, - false, - Some(0), - )); - } + } + new_pane_range = ribbon_range(new_pane_start, short_line.len); + if should_show_focus_and_resize_shortcuts { + short_line.append(&add_shortcut( + help, + "Focus", + &move_focus_shortcuts, + false, + Some(0), + )); + short_line.append(&add_shortcut( + help, + "Resize", + &resize_shortcuts, + false, + Some(0), + )); + } + let floating_start = short_line.len; + if floating_hovered { + short_line.append(&add_shortcut_hovered( + help, + "Floating", + &toggle_floating_key_to_display, + Some(0), + )); + } else { short_line.append(&add_shortcut( help, "Floating", @@ -1030,56 +1145,75 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz are_floating_panes_visible, Some(0), )); - } else { - let modifier_str = text_as_line_part_with_emphasis( - format!( - "{} + ", - common_modifiers - .iter() - .map(|m| m.to_string()) - .collect::<Vec<_>>() - .join("-") - ), - 0, - ); - short_line.append(&modifier_str); - let new_pane_key_to_display: Vec<KeyWithModifier> = new_pane_key_to_display - .iter() - .map(|k| k.strip_common_modifiers(&common_modifiers)) - .collect(); - let move_focus_shortcuts: Vec<KeyWithModifier> = move_focus_shortcuts - .iter() - .map(|k| k.strip_common_modifiers(&common_modifiers)) - .collect(); - let resize_shortcuts: Vec<KeyWithModifier> = resize_shortcuts - .iter() - .map(|k| k.strip_common_modifiers(&common_modifiers)) - .collect(); - let toggle_floating_key_to_display: Vec<KeyWithModifier> = - toggle_floating_key_to_display + } + floating_range = ribbon_range(floating_start, short_line.len); + } else { + let modifier_str = text_as_line_part_with_emphasis( + format!( + "{} + ", + common_modifiers .iter() - .map(|k| k.strip_common_modifiers(&common_modifiers)) - .collect(); + .map(|m| m.to_string()) + .collect::<Vec<_>>() + .join("-") + ), + 0, + ); + short_line.append(&modifier_str); + let new_pane_key_to_display: Vec<KeyWithModifier> = new_pane_key_to_display + .iter() + .map(|k| k.strip_common_modifiers(&common_modifiers)) + .collect(); + let move_focus_shortcuts: Vec<KeyWithModifier> = move_focus_shortcuts + .iter() + .map(|k| k.strip_common_modifiers(&common_modifiers)) + .collect(); + let resize_shortcuts: Vec<KeyWithModifier> = resize_shortcuts + .iter() + .map(|k| k.strip_common_modifiers(&common_modifiers)) + .collect(); + let toggle_floating_key_to_display: Vec<KeyWithModifier> = toggle_floating_key_to_display + .iter() + .map(|k| k.strip_common_modifiers(&common_modifiers)) + .collect(); + let new_pane_start = short_line.len; + if new_pane_hovered { + short_line.append(&add_shortcut_with_inline_key_hovered( + help, + "New", + new_pane_key_to_display, + )); + } else { short_line.append(&add_shortcut_with_inline_key( help, "New", new_pane_key_to_display, false, )); - if should_show_focus_and_resize_shortcuts { - short_line.append(&add_shortcut_with_inline_key( - help, - "Focus", - move_focus_shortcuts, - false, - )); - short_line.append(&add_shortcut_with_inline_key( - help, - "Resize", - resize_shortcuts, - false, - )); - } + } + new_pane_range = ribbon_range(new_pane_start, short_line.len); + if should_show_focus_and_resize_shortcuts { + short_line.append(&add_shortcut_with_inline_key( + help, + "Focus", + move_focus_shortcuts, + false, + )); + short_line.append(&add_shortcut_with_inline_key( + help, + "Resize", + resize_shortcuts, + false, + )); + } + let floating_start = short_line.len; + if floating_hovered { + short_line.append(&add_shortcut_with_inline_key_hovered( + help, + "Floating", + toggle_floating_key_to_display, + )); + } else { short_line.append(&add_shortcut_with_inline_key( help, "Floating", @@ -1087,22 +1221,27 @@ fn secondary_keybinds(help: &ModeInfo, tab_info: Option<&TabInfo>, max_len: usiz are_floating_panes_visible, )); } - if short_line.len <= max_len { - short_line - } else if max_len >= 3 { - let part = serialize_text( - &Text::new(format!("{:>width$}", "...", width = max_len)) - .color_range(0, ..) - .opaque(), - ); - let len = max_len; - LinePart { part, len } - } else { + floating_range = ribbon_range(floating_start, short_line.len); + } + if short_line.len <= max_len { + (short_line, new_pane_range, floating_range) + } else if max_len >= 3 { + let part = serialize_text( + &Text::new(format!("{:>width$}", "...", width = max_len)) + .color_range(0, ..) + .opaque(), + ); + let len = max_len; + (LinePart { part, len }, None, None) + } else { + ( LinePart { part: "".to_owned(), len: 0, - } - } + }, + None, + None, + ) } } @@ -1126,6 +1265,107 @@ fn keybinds(help: &ModeInfo, max_width: usize) -> Option<LinePart> { Some(best_effort_shortcut_list(help, max_width)) } +fn ribbon_range(start: usize, end: usize) -> Option<(usize, usize)> { + if end > start { + Some((start, end)) + } else { + None + } +} + +fn hovered_ribbon_wrap(body: String, palette: Styling, supports_arrow_fonts: bool) -> String { + let ribbon_bg = palette.ribbon_unselected.emphasis_1; + let outer_bg = palette.text_unselected.background; + let arrow = if supports_arrow_fonts { + crate::ARROW_SEPARATOR + } else { + "" + }; + let left = style!(outer_bg, ribbon_bg).paint(arrow).to_string(); + let right = style!(ribbon_bg, outer_bg).paint(arrow).to_string(); + format!("{}{}{}", left, body, right) +} + +fn add_shortcut_hovered( + help: &ModeInfo, + text: &str, + keys: &Vec<KeyWithModifier>, + key_color_index: Option<usize>, +) -> LinePart { + let mut ret = LinePart::default(); + if keys.is_empty() { + return ret; + } + ret.append(&style_key_with_modifier(&keys, key_color_index)); + let palette = help.style.colors; + let supports_arrow_fonts = !help.capabilities.arrow_fonts; + let ribbon_bg = palette.ribbon_unselected.emphasis_1; + let body = style!(palette.ribbon_unselected.base, ribbon_bg) + .bold() + .paint(format!(" {} ", text)) + .to_string(); + let ribbon = hovered_ribbon_wrap(body, palette, supports_arrow_fonts); + ret.part = format!("{}{}", ret.part, ribbon); + ret.len += if supports_arrow_fonts { + text.width() + 4 + } else { + text.width() + 2 + }; + ret +} + +fn add_shortcut_with_inline_key_hovered( + help: &ModeInfo, + text: &str, + key: Vec<KeyWithModifier>, +) -> LinePart { + let mut ret = LinePart::default(); + if key.is_empty() { + return ret; + } + let key_separator = match key + .iter() + .map(|k| k.to_string()) + .collect::<Vec<_>>() + .join("") + .as_str() + { + "HJKL" => "", + "hjkl" => "", + "←↓↑→" => "", + "←→" => "", + "↓↑" => "", + "[]" => "", + "+-" => "", + _ => "|", + }; + let key_string = format!( + "{}", + key.iter() + .map(|k| k.to_string()) + .collect::<Vec<_>>() + .join(key_separator) + ); + let palette = help.style.colors; + let supports_arrow_fonts = !help.capabilities.arrow_fonts; + let ribbon_bg = palette.ribbon_unselected.emphasis_1; + let base = style!(palette.ribbon_unselected.base, ribbon_bg).bold(); + let emph = style!(palette.ribbon_unselected.emphasis_0, ribbon_bg).bold(); + let body = format!( + "{}{}{}", + base.paint(" <").to_string(), + emph.paint(key_string.clone()).to_string(), + base.paint(format!("> {} ", text)).to_string(), + ); + ret.part = hovered_ribbon_wrap(body, palette, supports_arrow_fonts); + ret.len += if supports_arrow_fonts { + text.width() + key_string.width() + 7 + } else { + text.width() + key_string.width() + 5 + }; + ret +} + fn add_shortcut( help: &ModeInfo, text: &str, diff --git a/default-plugins/tab-bar/src/line.rs b/default-plugins/tab-bar/src/line.rs index aa76ce27..99b85f05 100644 --- a/default-plugins/tab-bar/src/line.rs +++ b/default-plugins/tab-bar/src/line.rs @@ -224,7 +224,10 @@ pub fn tab_line( mode_info: &ModeInfo, hide_swap_layout_indicator: bool, background: &PaletteColor, -) -> Vec<LinePart> { + active_pane_scroll: Option<(usize, usize)>, + is_alternate_tab: bool, + new_tab_button_is_hovered: bool, +) -> (Vec<LinePart>, Option<(usize, usize)>) { let mut tabs_after_active = all_tabs.split_off(active_tab_index); let mut tabs_before_active = all_tabs; let active_tab = if !tabs_after_active.is_empty() { @@ -249,6 +252,9 @@ pub fn tab_line( ) }) }; + if swap_layout_indicator.is_none() { + swap_layout_indicator = active_pane_scroll.map(|scroll| scroll_status(scroll, palette)); + } // Drop indicator if it would cause wrapping (active tab always rendered unconditionally) let prefix_len = get_current_title_len(&prefix); @@ -279,6 +285,33 @@ pub fn tab_line( tab_index: None, }]); + let supports_arrow_fonts = !capabilities.arrow_fonts; + let new_tab_button_background = if supports_arrow_fonts { + if new_tab_button_is_hovered { + palette.ribbon_unselected.emphasis_1 + } else { + palette.ribbon_unselected.background + } + } else if is_alternate_tab { + palette.ribbon_unselected.emphasis_1 + } else { + palette.ribbon_unselected.background + }; + let new_tab_button = new_tab_button_line_part(palette, capabilities, new_tab_button_background); + let used = prefix.iter().map(|p| p.len).sum::<usize>(); + let current_indicator_len = swap_layout_indicator.as_ref().map(|s| s.len).unwrap_or(0); + let room = cols + .saturating_sub(used) + .saturating_sub(current_indicator_len); + let new_tab_button_range = if room >= new_tab_button.len { + let button_start = used; + let button_end = button_start + new_tab_button.len; + prefix.push(new_tab_button); + Some((button_start, button_end)) + } else { + None + }; + 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)) @@ -301,7 +334,7 @@ pub fn tab_line( prefix.push(swap_layout_indicator); } - prefix + (prefix, new_tab_button_range) } fn swap_layout_status( @@ -329,6 +362,43 @@ fn swap_layout_status( } } +fn scroll_status(scroll: (usize, usize), palette: Styling) -> LinePart { + let (position, length) = scroll; + let text = format!("[ SCROLL {}/{} ]", position, length); + let text_color = palette.text_unselected.base; + let bg_color = palette.text_unselected.background; + let styled_text = style!(text_color, bg_color).bold().paint(&text); + LinePart { + part: styled_text.to_string(), + len: text.width(), + tab_index: None, + } +} + +fn new_tab_button_line_part( + palette: Styling, + capabilities: PluginCapabilities, + background_color: PaletteColor, +) -> LinePart { + let separator = tab_separator(capabilities); + let separator_width = separator.width(); + let foreground_color = palette.ribbon_unselected.base; + let separator_fill_color = palette.text_unselected.background; + let left_separator = style!(separator_fill_color, background_color).paint(separator); + let right_separator = style!(background_color, separator_fill_color).paint(separator); + let text = "+"; + let styled_text = style!(foreground_color, background_color) + .bold() + .paint(format!(" {} ", text)); + let part = ANSIStrings(&[left_separator, styled_text, right_separator]).to_string(); + let len = text.width() + (separator_width * 2) + 2; + LinePart { + part, + len, + tab_index: 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() diff --git a/default-plugins/tab-bar/src/main.rs b/default-plugins/tab-bar/src/main.rs index 6a3db351..6fa92c75 100644 --- a/default-plugins/tab-bar/src/main.rs +++ b/default-plugins/tab-bar/src/main.rs @@ -33,6 +33,10 @@ struct State { tab_line: Vec<LinePart>, hide_swap_layout_indication: bool, cached_keybinds: KeybindsVec, + active_pane_scroll: Option<(usize, usize)>, + new_tab_button_range: Option<(usize, usize)>, + hovered_tab_idx: Option<usize>, + hovered_new_tab_button: bool, } static ARROW_SEPARATOR: &str = ""; @@ -51,6 +55,7 @@ impl ZellijPlugin for State { EventType::ModeUpdate, EventType::Mouse, EventType::InitialKeybinds, + EventType::ActivePaneScroll, ]); } @@ -89,13 +94,48 @@ impl ZellijPlugin for State { eprintln!("Could not find active tab."); } }, + Event::ActivePaneScroll(scroll) => { + if self.active_pane_scroll != scroll { + should_render = true; + } + self.active_pane_scroll = scroll; + }, Event::Mouse(me) => match me { Mouse::LeftClick(_, col) => { + if let Some((start, end)) = self.new_tab_button_range { + if col >= start && col < end { + new_tab::<&str>(None, None); + return should_render; + } + } let tab_to_focus = get_tab_to_focus(&self.tab_line, self.active_tab_idx, col); if let Some(idx) = tab_to_focus { switch_tab_to(idx.try_into().unwrap()); } }, + Mouse::Hover(_, col) => { + let simplified_ui = self.mode_info.capabilities.arrow_fonts; + let mut new_hovered_new_tab_button = false; + let mut new_hovered_tab_idx = None; + if !simplified_ui { + if let Some((start, end)) = self.new_tab_button_range { + if col >= start && col < end { + new_hovered_new_tab_button = true; + } + } + if !new_hovered_new_tab_button { + new_hovered_tab_idx = + get_tab_to_focus(&self.tab_line, self.active_tab_idx, col); + } + } + if self.hovered_new_tab_button != new_hovered_new_tab_button + || self.hovered_tab_idx != new_hovered_tab_idx + { + self.hovered_new_tab_button = new_hovered_new_tab_button; + self.hovered_tab_idx = new_hovered_tab_idx; + should_render = true; + } + }, Mouse::ScrollUp(_) => { switch_tab_to(min(self.active_tab_idx + 1, self.tabs.len()) as u32); }, @@ -133,10 +173,12 @@ impl ZellijPlugin for State { } else if t.active { active_tab_index = t.position; } + let is_hovered = self.hovered_tab_idx == Some(t.position + 1); let tab = tab_style( tabname, t, is_alternate_tab, + is_hovered, self.mode_info.style.colors, self.mode_info.capabilities, ); @@ -146,7 +188,7 @@ impl ZellijPlugin for State { let background = self.mode_info.style.colors.text_unselected.background; - self.tab_line = tab_line( + let (line, new_tab_button_range) = tab_line( self.mode_info.session_name.as_deref(), all_tabs, active_tab_index, @@ -158,7 +200,12 @@ impl ZellijPlugin for State { &self.mode_info, self.hide_swap_layout_indication, &background, + self.active_pane_scroll, + is_alternate_tab, + self.hovered_new_tab_button, ); + self.tab_line = line; + self.new_tab_button_range = new_tab_button_range; let output = self .tab_line diff --git a/default-plugins/tab-bar/src/tab.rs b/default-plugins/tab-bar/src/tab.rs index d211d142..3db1bbb6 100644 --- a/default-plugins/tab-bar/src/tab.rs +++ b/default-plugins/tab-bar/src/tab.rs @@ -24,6 +24,7 @@ pub fn render_tab( text: String, tab: &TabInfo, is_alternate_tab: bool, + is_hovered: bool, palette: Styling, separator: &str, ) -> LinePart { @@ -37,6 +38,8 @@ pub fn render_tab( }; let background_color = if tab.active { palette.ribbon_selected.background + } else if is_hovered { + palette.ribbon_unselected.emphasis_1 } else if is_alternate_tab { alternate_tab_color } else { @@ -98,6 +101,7 @@ pub fn tab_style( mut tabname: String, tab: &TabInfo, mut is_alternate_tab: bool, + is_hovered: bool, palette: Styling, capabilities: PluginCapabilities, ) -> LinePart { @@ -116,7 +120,14 @@ pub fn tab_style( is_alternate_tab = false; } - render_tab(tabname, tab, is_alternate_tab, palette, separator) + render_tab( + tabname, + tab, + is_alternate_tab, + is_hovered, + palette, + separator, + ) } pub(crate) fn get_tab_to_focus( diff --git a/src/main.rs b/src/main.rs index c6ebebea..a5faf7d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,6 +76,7 @@ fn main() { floating, in_place, close_replaced_pane, + pane_id: None, name, close_on_exit, start_suspended, @@ -127,6 +128,7 @@ fn main() { floating, in_place, close_replaced_pane, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, diff --git a/src/tests/e2e/cases.rs b/src/tests/e2e/cases.rs index c20eb2c8..b83a7c6a 100644 --- a/src/tests/e2e/cases.rs +++ b/src/tests/e2e/cases.rs @@ -125,7 +125,7 @@ pub fn starts_with_one_terminal() { name: "Wait for app to load", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(3, 2) + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 1) { step_is_complete = true; } @@ -160,7 +160,7 @@ pub fn typing_exit_closes_pane() { instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; if remote_terminal.status_bar_appears() - && remote_terminal.cursor_position_is(3, 2) + && remote_terminal.cursor_position_is(2, 1) { remote_terminal.send_key(&PANE_MODE); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -174,7 +174,7 @@ pub fn typing_exit_closes_pane() { name: "Type exit", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(63, 2) + if remote_terminal.cursor_position_is(62, 2) && remote_terminal.status_bar_appears() { remote_terminal.send_key("e".as_bytes()); @@ -196,7 +196,7 @@ pub fn typing_exit_closes_pane() { name: "Wait for pane to close", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(3, 2) && remote_terminal.status_bar_appears() + if remote_terminal.cursor_position_is(2, 1) && remote_terminal.status_bar_appears() { // cursor is in the original pane step_is_complete = true; @@ -232,7 +232,7 @@ pub fn resize_terminal_window() { instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; if remote_terminal.status_bar_appears() - && remote_terminal.cursor_position_is(3, 2) + && remote_terminal.cursor_position_is(2, 1) { remote_terminal.send_key(&PANE_MODE); std::thread::sleep(std::time::Duration::from_millis(100)); @@ -246,7 +246,7 @@ pub fn resize_terminal_window() { name: "Change terminal window size", instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(63, 2) + if remote_terminal.cursor_position_is(62, 2) && remote_terminal.status_bar_appears() { // new pane has been opened and focused @@ -261,7 +261,7 @@ pub fn resize_terminal_window() { name: "wait for terminal to be resized and app to be re-rendered", instruction: |remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; - if remote_terminal.cursor_position_is(53, 2) && remote_terminal.ctrl_plus_appears() + if remote_terminal.cursor_position_is(52, 2) && remote_terminal.ctrl_plus_appears() { // size has been changed step_is_complete = true; @@ -358,7 +358,7 @@ pub fn send_blocking_command_through_the_cli() { instruction: |mut remote_terminal: RemoteTerminal| -> bool { let mut step_is_complete = false; if remote_terminal.status_bar_appears() - && remote_terminal.cursor_position_is(3, 2) + && remote_terminal.cursor_position_is(2, 1) { std::thread::sleep(std::time::Duration::from_millis(100)); remote_terminal @@ -415,7 +415,7 @@ pub fn send_blocking_command_through_the_cli() { // wait until echo $? is visible, the exit status rendered, and the cursor is back // at a blank prompt, which means the shell command actually executed if remote_terminal.snapshot_contains("echo $?") - && remote_terminal.snapshot_contains("│42") + && remote_terminal.snapshot_contains("42") && remote_terminal.snapshot_contains("$ \u{2588}") && remote_terminal.status_bar_appears() { diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap index 2cc662bb..cee30f74 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__quit_and_resurrect_session.snap @@ -1,29 +1,28 @@ --- source: src/tests/e2e/cases.rs -assertion_line: 1212 expression: last_snapshot --- - Zellij (e2e-test) Tab #1 Tab #2 Tab #3 Tab #4 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ┌ Pane #4 ────────────────────────────────────── PIN [ ] ┐ │ -│ │$ │ │ -│ │ ┌ top ────────────────────────────────────────── PIN [ ] ┐ │ -│ │ │ │ │ -│ │ │ │ ┐ │ -│ │ │ │ │────────────────────────────┘ -│ │ │ Waiting to run: top │ │────────────────────────────┐ -│ │ │ │ │ │ -│ │ │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │ │ -│ └─│ │ │ │ -│ │ │ │ │ -│ └─ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit ──────┘ │ │ -│ │ │ │ -│ └────────────────────────────────────────────────────────┘ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (e2e-test) Tab #1 Tab #2 Tab #3 Tab #4 + + Pane #1 │ Pane #2 +$ │$ + │ + │ + │ + ┌ Pane #4 ────────────────────────────────────── PIN [ ] ┐ + │$ │ + │ ┌ top ────────────────────────────────────────── PIN [ ] ┐ + │ │ │ + │ │ │ ┐ + │ │ │ │───────────────────────────── + │ │ Waiting to run: top │ │ #3 + │ │ │ │ + │ │ <ENTER> run, <ESC> drop to shell, <Ctrl-c> exit │ │ + └─│ │ │ + │ │ │ + └─ <ENTER> 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 BASE - (FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide. + (FLOATING PANES VISIBLE): Press Ctrl p, <w> to hide. diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap index 86285b60..f7e731a0 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__resize_terminal_window.snap @@ -2,27 +2,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij (e2e-test) Tab #1 -┌ Pane #1 ───────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└────────────────────────────────────────────────┘└────────────────────────────────────────────────┘ + Zellij (e2e-test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + g p t n h s o q ... diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap index 38453712..c1a0ac4c 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__send_blocking_command_through_the_cli.snap @@ -2,27 +2,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij (e2e-test) Tab #1 -┌ Pane #1 ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ /usr/src/zellij/zellij run --blocking --floating --close-on-exit -- bash -c 'sleep 2 && exit 42' │ -│$ │ -│$ echo $? │ -│42 │ -│$ │ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT Alt + <n> New Pane <f> Floating + Zellij (e2e-test) Tab #1 + +$ /usr/src/zellij/zellij run --blocking --floating --close-on-exit -- bash -c 'sleep 2 && exit 42' +$ +$ echo $? +42 +$ +$ █ + + + + + + + + + + + + + + + + + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT Alt + <n> New Pane <f> Floating diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap index 9a9b2265..cb5cc64c 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__starts_with_one_terminal.snap @@ -2,27 +2,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij (e2e-test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (e2e-test) Tab #1 + +$ █ + + + + + + + + + + + + + + + + + + + + + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap index 9a9b2265..cb5cc64c 100644 --- a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__typing_exit_closes_pane.snap @@ -2,27 +2,27 @@ source: src/tests/e2e/cases.rs expression: last_snapshot --- - Zellij (e2e-test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (e2e-test) Tab #1 + +$ █ + + + + + + + + + + + + + + + + + + + + + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/xtask/src/build.rs b/xtask/src/build.rs index 53ab8ade..b736897f 100644 --- a/xtask/src/build.rs +++ b/xtask/src/build.rs @@ -27,7 +27,7 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> { // See [this PR][1] for details. // // [1]: https://github.com/zellij-org/zellij/pull/2711#issuecomment-1695015818 - run_proto_codegen(sh); + run_proto_codegen(sh, false); // Build all plugins in a single invocation so Cargo can unify transitive dependency // features across all of them and compile shared crates (e.g. zellij-utils) only once. @@ -114,7 +114,16 @@ pub fn build(sh: &Shell, flags: flags::Build) -> anyhow::Result<()> { Ok(()) } -fn run_proto_codegen(sh: &Shell) { +pub fn proto(sh: &Shell) -> anyhow::Result<()> { + let msg = ">> Generating protobuffer code"; + crate::status(msg); + println!("{}", msg); + + run_proto_codegen(sh, true); + Ok(()) +} + +fn run_proto_codegen(sh: &Shell, force: bool) { let zellij_utils_basedir = crate::project_root().join("zellij-utils"); let _pd = sh.push_dir(&zellij_utils_basedir); @@ -142,7 +151,7 @@ fn run_proto_codegen(sh: &Shell) { .metadata() .and_then(|m| m.modified()); let mut proto_files = vec![]; - let mut needs_regeneration = false; + let mut needs_regeneration = force; for entry in std::fs::read_dir(&src_dir).unwrap() { let entry_path = entry.unwrap().path(); diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs index 82302e45..bd963770 100644 --- a/xtask/src/flags.rs +++ b/xtask/src/flags.rs @@ -42,6 +42,8 @@ xflags::xflags! { /// Build the manpage cmd manpage {} + cmd proto {} + /// Publish zellij and all the sub-crates cmd publish { /// Perform a dry-run (don't push/publish anything) @@ -142,6 +144,7 @@ pub enum XtaskCmd { Deprecated(Deprecated), Ci(Ci), Manpage(Manpage), + Proto(Proto), Publish(Publish), Dist(Dist), Clippy(Clippy), @@ -195,6 +198,9 @@ pub struct BuildRelease { pub struct Manpage; #[derive(Debug)] +pub struct Proto; + +#[derive(Debug)] pub struct Publish { pub dry_run: bool, pub no_push: bool, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 0e99d0b3..cb378b44 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -134,6 +134,7 @@ fn main() -> anyhow::Result<()> { flags::XtaskCmd::Test(flags) => test::test(shell, flags), flags::XtaskCmd::IntegrationTest(flags) => integration_test::integration_test(shell, flags), flags::XtaskCmd::Manpage(_flags) => build::manpage(shell), + flags::XtaskCmd::Proto(_flags) => build::proto(shell), // Pipelines // These are composite commands, made up of multiple "stages" defined above. flags::XtaskCmd::Make(flags) => pipelines::make(shell, flags), diff --git a/zellij-integration-tests/src/harness.rs b/zellij-integration-tests/src/harness.rs index eb860f8f..cda8a253 100644 --- a/zellij-integration-tests/src/harness.rs +++ b/zellij-integration-tests/src/harness.rs @@ -18,7 +18,7 @@ pub fn claim_first_terminal_and_wait_for_prompt(zellij: &TestSession) -> FakePty |grid_snapshot| { grid_snapshot.tab_bar_appears() && grid_snapshot.status_bar_appears() - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }, ); terminal @@ -30,7 +30,7 @@ pub fn split_right_and_wait_for_prompt(zellij: &TestSession) -> FakePtyHandle { let terminal = zellij.expect_pty_spawn(); terminal.output(PROMPT); zellij.wait_until("right terminal prompt rendered", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2)) }); terminal } @@ -41,7 +41,7 @@ pub fn split_down_and_wait_for_prompt(zellij: &TestSession) -> FakePtyHandle { let terminal = zellij.expect_pty_spawn(); terminal.output(PROMPT); zellij.wait_until("lower terminal prompt rendered", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(13)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(13)) }); terminal } diff --git a/zellij-integration-tests/src/runner.rs b/zellij-integration-tests/src/runner.rs index c430f94b..76544ecd 100644 --- a/zellij-integration-tests/src/runner.rs +++ b/zellij-integration-tests/src/runner.rs @@ -127,6 +127,7 @@ fn new_pane_cli_action( floating, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit, start_suspended, diff --git a/zellij-integration-tests/src/test_env.rs b/zellij-integration-tests/src/test_env.rs index a70c4e75..f5a9aa74 100644 --- a/zellij-integration-tests/src/test_env.rs +++ b/zellij-integration-tests/src/test_env.rs @@ -156,6 +156,7 @@ disable_session_metadata true visual_bell false mouse_mode false advanced_mouse_actions false +pane_frame_style "titles" theme "default" "#; diff --git a/zellij-integration-tests/tests/app.rs b/zellij-integration-tests/tests/app.rs index 74ed11e4..45e57512 100644 --- a/zellij-integration-tests/tests/app.rs +++ b/zellij-integration-tests/tests/app.rs @@ -54,7 +54,7 @@ fn resize_terminal_window() { zellij.wait_until("app re-rendered at the new window size", |grid_snapshot| { grid_snapshot.contains("Ctrl +") && grid_snapshot.tab_bar_appears() - && grid_snapshot.cursor_is_at(col(53).row(2)) + && grid_snapshot.cursor_is_at(col(52).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -70,7 +70,7 @@ fn status_bar_loads_custom_keybindings() { let grid_snapshot = zellij.wait_until( "status bar reflects the custom keybindings", - |grid_snapshot| grid_snapshot.cursor_is_at(col(3).row(2)) && grid_snapshot.contains("LOCK"), + |grid_snapshot| grid_snapshot.cursor_is_at(col(2).row(1)) && grid_snapshot.contains("LOCK"), ); assert_snapshot!(normalized(&grid_snapshot)); } @@ -91,6 +91,7 @@ fn use_custom_layout_with_relative_path() { let grid_snapshot = zellij.wait_until("upside-down layout loaded from disk", |grid_snapshot| { grid_snapshot.tab_bar_appears() + && grid_snapshot.status_bar_appears() && grid_snapshot.contains("Zellij (test") && grid_snapshot.cursor.is_some() }); diff --git a/zellij-integration-tests/tests/basic.rs b/zellij-integration-tests/tests/basic.rs index e72cd1c6..1ed5b46a 100644 --- a/zellij-integration-tests/tests/basic.rs +++ b/zellij-integration-tests/tests/basic.rs @@ -23,7 +23,7 @@ fn starts_with_one_terminal() { let grid_snapshot = zellij.wait_until("steady loaded state", |grid_snapshot| { grid_snapshot.tab_bar_appears() && grid_snapshot.status_bar_appears() - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -35,7 +35,7 @@ fn split_terminals_vertically() { claim_first_terminal_and_wait_for_prompt(&zellij); split_right_and_wait_for_prompt(&zellij); let grid_snapshot = zellij.wait_until("split rendered in normal mode", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -58,7 +58,7 @@ fn resize_pane() { let cursor_shift_left = (resized_cols.saturating_sub(initial_cols)) as usize; let grid_snapshot = zellij.wait_until("resized layout in normal mode", |grid_snapshot| { grid_snapshot.status_bar_appears() - && grid_snapshot.cursor_is_at(col(63 - cursor_shift_left).row(2)) + && grid_snapshot.cursor_is_at(col(62 - cursor_shift_left).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -79,7 +79,7 @@ fn command_pane_closes_on_exit() { zellij.wait_until( "right terminal closed, focus back on first", |grid_snapshot| { - !grid_snapshot.contains("about to exit") && grid_snapshot.cursor_is_at(col(3).row(2)) + !grid_snapshot.contains("about to exit") && grid_snapshot.cursor_is_at(col(2).row(1)) }, ); zellij.quit(); diff --git a/zellij-integration-tests/tests/cli.rs b/zellij-integration-tests/tests/cli.rs index 75c3ce4a..3460994e 100644 --- a/zellij-integration-tests/tests/cli.rs +++ b/zellij-integration-tests/tests/cli.rs @@ -75,7 +75,7 @@ fn send_blocking_command_through_the_cli() { assert_eq!(blocking_command.wait_for_exit(), 42); let grid_snapshot = zellij.wait_until("floating pane closed on exit", |grid_snapshot| { - !grid_snapshot.contains("PIN") && grid_snapshot.cursor_is_at(col(3).row(2)) + !grid_snapshot.contains("PIN") && grid_snapshot.cursor_is_at(col(2).row(1)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -100,7 +100,7 @@ fn watcher_client_functionality() { let right_terminal = zellij.expect_pty_spawn(); right_terminal.output(PROMPT); watcher.wait_until("watcher sees the split", |grid_snapshot| { - grid_snapshot.contains("┐┌") + grid_snapshot.contains("│") }); let ignored_new_tab_from_watcher = [keys::ctrl('t'), keys::key('n')].concat(); @@ -112,7 +112,7 @@ fn watcher_client_functionality() { "watcher keeps receiving output while no main client is attached", |grid_snapshot| { grid_snapshot.contains("WATCHER_DONE") - && grid_snapshot.contains("┐┌") + && grid_snapshot.contains("│") && !grid_snapshot.contains("Tab #2") }, ); @@ -123,7 +123,7 @@ fn watcher_client_functionality() { |grid_snapshot| { grid_snapshot.status_bar_appears() && grid_snapshot.contains("WATCHER_DONE") - && grid_snapshot.contains("┐┌") + && grid_snapshot.contains("│") }, ); assert_snapshot!(normalized(&main_snapshot)); @@ -132,7 +132,7 @@ fn watcher_client_functionality() { watcher.wait_until("watcher mirrors the re-attached session", |grid_snapshot| { grid_snapshot.status_bar_appears() && grid_snapshot.contains("WATCHER_DONE") - && grid_snapshot.contains("┐┌") + && grid_snapshot.contains("│") && !grid_snapshot.contains("Tab #2") }); assert_snapshot!(normalized(&watcher_snapshot)); diff --git a/zellij-integration-tests/tests/clients.rs b/zellij-integration-tests/tests/clients.rs index 669e5aa3..06996b5b 100644 --- a/zellij-integration-tests/tests/clients.rs +++ b/zellij-integration-tests/tests/clients.rs @@ -21,7 +21,7 @@ fn mirrored_sessions() { second_client.wait_until("second client loaded on the first tab", |grid_snapshot| { grid_snapshot.tab_bar_appears() && grid_snapshot.status_bar_appears() - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }); second_client.send_stdin(&keys::ctrl('p')); @@ -34,7 +34,7 @@ fn mirrored_sessions() { && session_name_rendered(grid_snapshot) && grid_snapshot.status_bar_appears() && grid_snapshot.contains("Pane #2") - && grid_snapshot.cursor_is_at(col(63).row(2)) + && grid_snapshot.cursor_is_at(col(62).row(2)) }; let main_grid = zellij.wait_until( "main client follows the second client's focus into the split it never asked for", @@ -56,8 +56,16 @@ fn mirrored_sessions() { #[test] fn multiple_users_in_same_pane_and_tab() { - let mut zellij = start_zellij(); - claim_first_terminal_and_wait_for_prompt(&zellij); + let mut zellij = TestRunner::new(TERMINAL_SIZE) + .with_config("pane_frame_style \"full\"") + .start(); + let terminal = zellij.expect_pty_spawn(); + terminal.output(PROMPT); + zellij.wait_until("first terminal prompt rendered", |grid_snapshot| { + grid_snapshot.tab_bar_appears() + && grid_snapshot.status_bar_appears() + && grid_snapshot.contains("$ ") + }); let second_client = zellij.attach_client(TERMINAL_SIZE); let second_grid = @@ -91,7 +99,7 @@ fn multiple_users_in_different_panes_and_same_tab() { let second_client = zellij.attach_client(TERMINAL_SIZE); second_client.wait_until("second client loaded on the first tab", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1)) }); second_client.send_stdin(&keys::ctrl('p')); @@ -105,7 +113,7 @@ fn multiple_users_in_different_panes_and_same_tab() { grid_snapshot.tab_bar_appears() && session_name_rendered(grid_snapshot) && grid_snapshot.status_bar_appears() - && grid_snapshot.cursor_is_at(col(63).row(2)) + && grid_snapshot.cursor_is_at(col(62).row(2)) }, ); let main_grid = zellij.wait_until( @@ -115,7 +123,7 @@ fn multiple_users_in_different_panes_and_same_tab() { && session_name_rendered(grid_snapshot) && grid_snapshot.contains("Pane #2") && grid_snapshot.status_bar_appears() - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(2)) }, ); assert_snapshot!(normalized(&main_grid)); @@ -131,7 +139,7 @@ fn multiple_users_in_different_tabs() { let second_client = zellij.attach_client(TERMINAL_SIZE); second_client.wait_until("second client loaded on the first tab", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1)) }); second_client.send_stdin(&keys::ctrl('t')); @@ -145,7 +153,7 @@ fn multiple_users_in_different_tabs() { && session_name_rendered(grid_snapshot) && grid_snapshot.status_bar_appears() && grid_snapshot.contains("Tab #2") - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }); let main_grid = zellij.wait_until( "main client sees the new tab while staying on the first tab", @@ -154,7 +162,7 @@ fn multiple_users_in_different_tabs() { && session_name_rendered(grid_snapshot) && grid_snapshot.status_bar_appears() && grid_snapshot.contains("Tab #2") - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }, ); assert_snapshot!(normalized(&main_grid)); @@ -173,7 +181,7 @@ fn detach_and_attach_session() { let right_terminal = zellij.expect_pty_spawn(); right_terminal.output(PROMPT); zellij.wait_until("right terminal prompt rendered", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2)) }); right_terminal.output(b"I am some text"); diff --git a/zellij-integration-tests/tests/misc.rs b/zellij-integration-tests/tests/misc.rs index 83a02878..3bd14624 100644 --- a/zellij-integration-tests/tests/misc.rs +++ b/zellij-integration-tests/tests/misc.rs @@ -48,7 +48,7 @@ fn focus_next_pane_via_tmux_mode() { zellij.send_stdin(&keys::ENTER); let grid_snapshot = zellij.wait_until("focus cycled to the other pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); diff --git a/zellij-integration-tests/tests/modes.rs b/zellij-integration-tests/tests/modes.rs index 0fc093be..c2f61d67 100644 --- a/zellij-integration-tests/tests/modes.rs +++ b/zellij-integration-tests/tests/modes.rs @@ -138,7 +138,7 @@ fn return_to_normal_mode() { zellij.send_stdin(&keys::ENTER); let grid_snapshot = zellij.wait_until("returned to normal mode", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -187,7 +187,7 @@ fn tmux_mode() { right_terminal.output(PROMPT); let grid_snapshot = zellij.wait_until("right terminal opened via tmux mode", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -226,14 +226,14 @@ fn scrolling_inside_a_pane() { let right_terminal = zellij.expect_pty_spawn(); right_terminal.output(PROMPT); zellij.wait_until("right terminal prompt rendered", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2)) }); - for line in 1..=21 { + for line in 1..=22 { right_terminal.output(format!("line{}\r\n", line).as_bytes()); } zellij.wait_until("right terminal filled past its viewport", |grid_snapshot| { - grid_snapshot.contains("line21") + grid_snapshot.contains("line22") }); zellij.send_stdin(&keys::ctrl('s')); @@ -242,7 +242,7 @@ fn scrolling_inside_a_pane() { let grid_snapshot = zellij.wait_until("scrolled up one line inside the pane", |grid_snapshot| { - grid_snapshot.contains("SCROLL: 2/2") && grid_snapshot.contains("PgDn|PgUp") + grid_snapshot.contains("SCROLL: 2/2") && grid_snapshot.contains("PgDn|PgUp") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); diff --git a/zellij-integration-tests/tests/mouse.rs b/zellij-integration-tests/tests/mouse.rs index e4aa038c..4d134723 100644 --- a/zellij-integration-tests/tests/mouse.rs +++ b/zellij-integration-tests/tests/mouse.rs @@ -24,7 +24,7 @@ fn focus_pane_with_mouse() { zellij.send_stdin(&sgr_mouse_report(2, 5, 0)); let grid_snapshot = zellij.wait_until("focus moved back to the left pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -78,7 +78,7 @@ fn pin_floating_panes() { |grid_snapshot| { grid_snapshot.status_bar_appears() && grid_snapshot.contains("PIN [+]") - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }, ); diff --git a/zellij-integration-tests/tests/panes.rs b/zellij-integration-tests/tests/panes.rs index 9defe5f2..61c3cd5a 100644 --- a/zellij-integration-tests/tests/panes.rs +++ b/zellij-integration-tests/tests/panes.rs @@ -13,7 +13,7 @@ fn cannot_split_terminals_vertically_when_active_terminal_is_too_small() { let terminal = zellij.expect_pty_spawn(); terminal.output(PROMPT); zellij.wait_until("first terminal prompt rendered", |grid_snapshot| { - grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.cursor_is_at(col(2).row(1)) }); let (width_before_split, _) = terminal.wait_for_size("first terminal sized", |_, _| true); @@ -50,7 +50,7 @@ fn key_after_mode_switch_is_interpreted_in_new_mode_not_leaked_to_pane() { let second_terminal = zellij.expect_pty_spawn(); second_terminal.output(PROMPT); zellij.wait_until("split-right interpreted in pane mode", |grid_snapshot| { - grid_snapshot.cursor_is_at(col(63).row(2)) + grid_snapshot.cursor_is_at(col(62).row(2)) }); assert!(!first_terminal.stdin_bytes().contains(&keys::key('r')[0])); @@ -67,7 +67,7 @@ fn toggle_pane_fullscreen() { zellij.send_stdin(&keys::key('f')); let grid_snapshot = zellij.wait_until("focused pane is fullscreen", |grid_snapshot| { - grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.cursor_is_at(col(2).row(2)) && grid_snapshot.contains("LOCK") && grid_snapshot.contains("(FULLSCREEN)") }); @@ -86,7 +86,7 @@ fn close_pane() { let grid_snapshot = zellij.wait_until("right pane closed, focus back on first", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -116,7 +116,7 @@ fn pane_closes_when_its_process_exits() { let grid_snapshot = zellij.wait_until("right pane closed, focus back on first", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(1)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -145,6 +145,7 @@ fn toggle_floating_panes() { fn undo_rename_pane() { let mut zellij = start_zellij(); claim_first_terminal_and_wait_for_prompt(&zellij); + split_right_and_wait_for_prompt(&zellij); zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('c')); @@ -153,7 +154,9 @@ fn undo_rename_pane() { zellij.send_stdin(&keys::ESC); let grid_snapshot = zellij.wait_until("pane name reverted to default", |grid_snapshot| { - grid_snapshot.contains("Pane #1") && grid_snapshot.contains("LOCK") + grid_snapshot.contains("Pane #2") + && !grid_snapshot.contains("aa") + && grid_snapshot.contains("LOCK") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -200,7 +203,7 @@ fn move_focus_up_in_pane_mode() { zellij.send_stdin(&keys::ENTER); let grid_snapshot = zellij.wait_until("focus moved to the upper pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -215,14 +218,14 @@ fn move_focus_down_in_pane_mode() { zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('k')); zellij.wait_until("focus moved to the upper pane", |grid_snapshot| { - grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.cursor_is_at(col(2).row(2)) }); zellij.send_stdin(&keys::key('j')); zellij.send_stdin(&keys::ENTER); let grid_snapshot = zellij.wait_until("focus moved back to the lower pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(13)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(13)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -368,7 +371,7 @@ fn move_focus_or_tab_moves_focus_between_panes() { zellij.send_stdin(&keys::alt('h')); let grid_snapshot = zellij.wait_until("focus moved to the left pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -408,7 +411,7 @@ fn new_pane_in_pane_mode() { zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('n')); - let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(63).row(2)); + let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(62).row(2)); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); } @@ -419,7 +422,7 @@ fn new_pane_in_normal_mode() { claim_first_terminal_and_wait_for_prompt(&zellij); zellij.send_stdin(&keys::alt('n')); - let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(63).row(2)); + let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(62).row(2)); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); } @@ -431,7 +434,7 @@ fn split_pane_downward() { zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('d')); - let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(3).row(13)); + let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(2).row(13)); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); } @@ -443,7 +446,7 @@ fn new_stacked_pane() { zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('s')); - let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(3).row(3)); + let grid_snapshot = spawn_second_pane_and_wait_for_grid(&zellij, col(2).row(3)); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); } @@ -459,7 +462,7 @@ fn move_focus_left_in_pane_mode() { zellij.send_stdin(&keys::ENTER); let grid_snapshot = zellij.wait_until("focus moved to the left pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -474,14 +477,14 @@ fn move_focus_right_in_pane_mode() { zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('h')); zellij.wait_until("focus moved to the left pane", |grid_snapshot| { - grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.cursor_is_at(col(2).row(2)) }); zellij.send_stdin(&keys::key('l')); zellij.send_stdin(&keys::ENTER); let grid_snapshot = zellij.wait_until("focus moved back to the right pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(63).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(62).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -498,27 +501,147 @@ fn switch_focus_in_pane_mode() { zellij.send_stdin(&keys::ENTER); let grid_snapshot = zellij.wait_until("focus switched to the other pane", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.status_bar_appears() && grid_snapshot.cursor_is_at(col(2).row(2)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); } +fn cycle_pane_frames(zellij: &TestSession) { + zellij.send_stdin(&keys::ctrl('p')); + zellij.send_stdin(&keys::key('z')); +} + #[test] fn toggle_pane_frames() { let mut zellij = start_zellij(); claim_first_terminal_and_wait_for_prompt(&zellij); split_right_and_wait_for_prompt(&zellij); - zellij.send_stdin(&keys::ctrl('p')); - zellij.send_stdin(&keys::key('z')); + zellij.wait_until("tiled panes start in titles mode", |grid_snapshot| { + grid_snapshot.contains("Pane #1") + && grid_snapshot.contains("Pane #2") + && !grid_snapshot.contains("┌") + }); - let grid_snapshot = zellij.wait_until("pane frames removed from both panes", |grid_snapshot| { + cycle_pane_frames(&zellij); + zellij.wait_until("titles cycle to frameless", |grid_snapshot| { grid_snapshot.status_bar_appears() && !grid_snapshot.contains("Pane #1") && !grid_snapshot.contains("Pane #2") + && !grid_snapshot.contains("┌") && grid_snapshot.cursor_is_at(col(62).row(1)) }); + + cycle_pane_frames(&zellij); + zellij.wait_until("frameless cycles to full frames", |grid_snapshot| { + grid_snapshot.contains("┌") + && grid_snapshot.contains("Pane #1") + && grid_snapshot.contains("Pane #2") + }); + + cycle_pane_frames(&zellij); + let grid_snapshot = zellij.wait_until("full frames cycle back to titles", |grid_snapshot| { + grid_snapshot.status_bar_appears() + && grid_snapshot.contains("Pane #1") + && grid_snapshot.contains("Pane #2") + && !grid_snapshot.contains("┌") + }); + assert_snapshot!(normalized(&grid_snapshot)); + zellij.quit(); +} + +#[test] +fn toggle_frames_with_single_pane() { + let mut zellij = start_zellij(); + claim_first_terminal_and_wait_for_prompt(&zellij); + + zellij.wait_until( + "lone pane in titles mode omits its title", + |grid_snapshot| { + grid_snapshot.status_bar_appears() + && !grid_snapshot.contains("Pane #1") + && !grid_snapshot.contains("┌") + }, + ); + + cycle_pane_frames(&zellij); + zellij.wait_until("lone frameless pane stays untitled", |grid_snapshot| { + grid_snapshot.status_bar_appears() + && !grid_snapshot.contains("Pane #1") + && !grid_snapshot.contains("┌") + }); + + cycle_pane_frames(&zellij); + let grid_snapshot = + zellij.wait_until("lone pane gains a full frame and title", |grid_snapshot| { + grid_snapshot.status_bar_appears() + && grid_snapshot.contains("┌") + && grid_snapshot.contains("Pane #1") + }); + assert_snapshot!(normalized(&grid_snapshot)); + zellij.quit(); +} + +#[test] +fn toggle_frames_with_floating_pane() { + let mut zellij = start_zellij(); + claim_first_terminal_and_wait_for_prompt(&zellij); + + zellij.send_stdin(&keys::ctrl('p')); + zellij.send_stdin(&keys::key('w')); + let floating_terminal = zellij.expect_pty_spawn(); + floating_terminal.output(PROMPT); + zellij.wait_until("floating pane appeared with a frame", |grid_snapshot| { + grid_snapshot.contains("STAGGERED") && grid_snapshot.contains("┌") + }); + + cycle_pane_frames(&zellij); + zellij.wait_until( + "floating pane keeps its frame in frameless mode", + |grid_snapshot| grid_snapshot.status_bar_appears() && grid_snapshot.contains("┌"), + ); + + cycle_pane_frames(&zellij); + let grid_snapshot = zellij.wait_until( + "floating pane keeps its frame in full mode", + |grid_snapshot| { + grid_snapshot.status_bar_appears() + && grid_snapshot.contains("┌") + && grid_snapshot.contains("Pane #1") + }, + ); + assert_snapshot!(normalized(&grid_snapshot)); + zellij.quit(); +} + +#[test] +fn toggle_frames_with_stacked_panes() { + let mut zellij = start_zellij(); + claim_first_terminal_and_wait_for_prompt(&zellij); + + zellij.send_stdin(&keys::ctrl('p')); + zellij.send_stdin(&keys::key('s')); + spawn_second_pane_and_wait_for_grid(&zellij, col(2).row(3)); + + zellij.wait_until("stacked panes show their titles", |grid_snapshot| { + grid_snapshot.contains("Pane #1") + && grid_snapshot.contains("Pane #2") + && !grid_snapshot.contains("┌") + }); + + cycle_pane_frames(&zellij); + zellij.wait_until("stacked panes cycle to frameless", |grid_snapshot| { + grid_snapshot.status_bar_appears() && !grid_snapshot.contains("┌") + }); + + cycle_pane_frames(&zellij); + let grid_snapshot = zellij.wait_until("stacked panes cycle to full frames", |grid_snapshot| { + grid_snapshot.status_bar_appears() + && grid_snapshot.contains("┌") + && grid_snapshot.contains("Pane #1") + && grid_snapshot.contains("Pane #2") + }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); } diff --git a/zellij-integration-tests/tests/resize.rs b/zellij-integration-tests/tests/resize.rs index bf1263c3..ba9fae4b 100644 --- a/zellij-integration-tests/tests/resize.rs +++ b/zellij-integration-tests/tests/resize.rs @@ -11,7 +11,7 @@ fn focus_left_pane(zellij: &TestSession) { zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('h')); zellij.wait_until("focus moved to the left pane", |grid_snapshot| { - grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.cursor_is_at(col(2).row(2)) }); } @@ -19,7 +19,7 @@ fn focus_upper_pane(zellij: &TestSession) { zellij.send_stdin(&keys::ctrl('p')); zellij.send_stdin(&keys::key('k')); zellij.wait_until("focus moved to the upper pane", |grid_snapshot| { - grid_snapshot.cursor_is_at(col(3).row(2)) + grid_snapshot.cursor_is_at(col(2).row(2)) }); } diff --git a/zellij-integration-tests/tests/resurrection.rs b/zellij-integration-tests/tests/resurrection.rs index 7f6a10b0..63ed1626 100644 --- a/zellij-integration-tests/tests/resurrection.rs +++ b/zellij-integration-tests/tests/resurrection.rs @@ -50,7 +50,7 @@ fn quit_and_resurrect_session() { let new_pane = zellij.expect_pty_spawn(); new_pane.output(PROMPT); zellij.wait_until("new pane opened before serialization", |grid_snapshot| { - grid_snapshot.contains("┐┌") + grid_snapshot.contains("│") }); zellij.save_session(); @@ -64,7 +64,7 @@ fn quit_and_resurrect_session() { grid_snapshot.contains("Zellij (test") && grid_snapshot.contains("alpha") && grid_snapshot.contains("beta") - && grid_snapshot.contains("┐┌") + && grid_snapshot.contains("│") && grid_snapshot.status_bar_appears() }, ); diff --git a/zellij-integration-tests/tests/scroll.rs b/zellij-integration-tests/tests/scroll.rs index 35316957..1a88b84a 100644 --- a/zellij-integration-tests/tests/scroll.rs +++ b/zellij-integration-tests/tests/scroll.rs @@ -28,7 +28,9 @@ fn page_scroll_up() { zellij.send_stdin(&keys::ctrl('b')); let grid_snapshot = zellij.wait_until("scrolled up by a page", |grid_snapshot| { - grid_snapshot.contains("PgDn|PgUp") && !grid_snapshot.contains(LAST_LINE) + grid_snapshot.contains("PgDn|PgUp") + && !grid_snapshot.contains(LAST_LINE) + && grid_snapshot.contains("SCROLL 19/") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -47,9 +49,11 @@ fn page_scroll_down() { zellij.send_stdin(&keys::ctrl('f')); - let grid_snapshot = zellij - .wait_until("scrolled back down toward the bottom", |grid_snapshot| { - grid_snapshot.contains("line39") && grid_snapshot.contains("PgDn|PgUp") + let grid_snapshot = + zellij.wait_until("scrolled back down toward the bottom", |grid_snapshot| { + grid_snapshot.contains("line39") + && grid_snapshot.contains("PgDn|PgUp") + && grid_snapshot.contains("SCROLL 0/") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -64,7 +68,9 @@ fn half_page_scroll_up() { zellij.send_stdin(&keys::key('u')); let grid_snapshot = zellij.wait_until("scrolled up by half a page", |grid_snapshot| { - grid_snapshot.contains("PgDn|PgUp") && !grid_snapshot.contains(LAST_LINE) + grid_snapshot.contains("PgDn|PgUp") + && !grid_snapshot.contains(LAST_LINE) + && grid_snapshot.contains("SCROLL 10/") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -83,9 +89,11 @@ fn half_page_scroll_down() { zellij.send_stdin(&keys::key('d')); - let grid_snapshot = zellij - .wait_until("scrolled back down toward the bottom", |grid_snapshot| { - grid_snapshot.contains("line39") && grid_snapshot.contains("PgDn|PgUp") + let grid_snapshot = + zellij.wait_until("scrolled back down toward the bottom", |grid_snapshot| { + grid_snapshot.contains("line39") + && grid_snapshot.contains("PgDn|PgUp") + && grid_snapshot.contains("SCROLL 0/") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -100,13 +108,13 @@ fn scroll_down_one_line() { zellij.send_stdin(&keys::key('k')); zellij.send_stdin(&keys::key('k')); zellij.wait_until("scrolled up two lines", |grid_snapshot| { - grid_snapshot.contains("SCROLL: 2/") + grid_snapshot.contains("SCROLL 2/") }); zellij.send_stdin(&keys::key('j')); let grid_snapshot = zellij.wait_until("scrolled back down one line", |grid_snapshot| { - grid_snapshot.contains("SCROLL: 1/") && grid_snapshot.contains("PgDn|PgUp") + grid_snapshot.contains("SCROLL 1/") && grid_snapshot.contains("PgDn|PgUp") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -125,9 +133,11 @@ fn scroll_to_bottom() { zellij.send_stdin(&keys::ctrl('c')); - let grid_snapshot = zellij - .wait_until("returned to the bottom in normal mode", |grid_snapshot| { - grid_snapshot.status_bar_appears() && grid_snapshot.contains(LAST_LINE) + let grid_snapshot = + zellij.wait_until("returned to the bottom in normal mode", |grid_snapshot| { + grid_snapshot.status_bar_appears() + && grid_snapshot.contains(LAST_LINE) + && grid_snapshot.contains("SCROLL 0/") }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); diff --git a/zellij-integration-tests/tests/search.rs b/zellij-integration-tests/tests/search.rs index c15fe76e..6c750b0b 100644 --- a/zellij-integration-tests/tests/search.rs +++ b/zellij-integration-tests/tests/search.rs @@ -3,9 +3,24 @@ use insta::assert_snapshot; use zellij_integration_tests::{ claim_first_terminal_and_wait_for_prompt, keys, normalized, start_zellij, FakePtyHandle, - TestSession, + TestRunner, TestSession, TERMINAL_SIZE, }; +fn start_zellij_with_full_frames() -> TestSession { + TestRunner::new(TERMINAL_SIZE) + .with_config("pane_frame_style \"full\"") + .start() +} + +fn enter_search_on_visible_match_with_full_frames(zellij: &TestSession) { + let terminal = zellij.expect_pty_spawn(); + terminal.output(b"NEEDLE on screen\r\n"); + zellij.wait_until("match visible on screen", |grid_snapshot| { + grid_snapshot.contains("NEEDLE on screen") + }); + enter_search_for_needle(zellij); +} + fn fill_pane_with_two_matches(zellij: &TestSession) -> FakePtyHandle { let terminal = claim_first_terminal_and_wait_for_prompt(zellij); for line in 1..=40 { @@ -38,15 +53,6 @@ fn enter_search_for_needle(zellij: &TestSession) { }); } -fn enter_search_on_visible_match(zellij: &TestSession) { - let terminal = claim_first_terminal_and_wait_for_prompt(zellij); - terminal.output(b"NEEDLE on screen\r\n"); - zellij.wait_until("match visible on screen", |grid_snapshot| { - grid_snapshot.contains("NEEDLE on screen") - }); - enter_search_for_needle(zellij); -} - #[test] fn search_input_jumps_to_a_match() { let mut zellij = start_zellij(); @@ -120,8 +126,8 @@ fn search_down_to_next_match() { #[test] fn search_toggle_case_sensitivity() { - let mut zellij = start_zellij(); - enter_search_on_visible_match(&zellij); + let mut zellij = start_zellij_with_full_frames(); + enter_search_on_visible_match_with_full_frames(&zellij); zellij.send_stdin(&keys::key('c')); @@ -134,8 +140,8 @@ fn search_toggle_case_sensitivity() { #[test] fn search_toggle_wrap() { - let mut zellij = start_zellij(); - enter_search_on_visible_match(&zellij); + let mut zellij = start_zellij_with_full_frames(); + enter_search_on_visible_match_with_full_frames(&zellij); zellij.send_stdin(&keys::key('w')); @@ -148,8 +154,8 @@ fn search_toggle_wrap() { #[test] fn search_toggle_whole_word() { - let mut zellij = start_zellij(); - enter_search_on_visible_match(&zellij); + let mut zellij = start_zellij_with_full_frames(); + enter_search_on_visible_match_with_full_frames(&zellij); zellij.send_stdin(&keys::key('o')); diff --git a/zellij-integration-tests/tests/set_pane_frame_style.rs b/zellij-integration-tests/tests/set_pane_frame_style.rs new file mode 100644 index 00000000..5b18f965 --- /dev/null +++ b/zellij-integration-tests/tests/set_pane_frame_style.rs @@ -0,0 +1,120 @@ +#![cfg(unix)] + +use zellij_integration_tests::{ + claim_first_terminal_and_wait_for_prompt, split_right_and_wait_for_prompt, start_zellij, Size, + TestRunner, +}; +use zellij_utils::cli::CliAction; +use zellij_utils::input::options::PaneFrameStyle; + +const FULL_FRAME_CORNER: &str = "┌"; + +fn ctrl_y() -> [u8; 1] { + [0x19] +} + +#[test] +fn set_pane_frame_style_through_the_cli() { + let mut zellij = start_zellij(); + claim_first_terminal_and_wait_for_prompt(&zellij); + + zellij.wait_until("lone titles pane has no frame", |grid_snapshot| { + grid_snapshot.status_bar_appears() && !grid_snapshot.contains(FULL_FRAME_CORNER) + }); + + let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle { + style: PaneFrameStyle::Full, + }); + assert_eq!(exit_code, 0, "set-pane-frame-style exited cleanly"); + + zellij.wait_until( + "full frames drawn after switching to full", + |grid_snapshot| { + grid_snapshot.contains(FULL_FRAME_CORNER) && grid_snapshot.contains("Pane #1") + }, + ); + + let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle { + style: PaneFrameStyle::Titles, + }); + assert_eq!(exit_code, 0, "set-pane-frame-style exited cleanly"); + + zellij.wait_until( + "frame removed after switching back to titles", + |grid_snapshot| { + grid_snapshot.status_bar_appears() + && !grid_snapshot.contains(FULL_FRAME_CORNER) + && !grid_snapshot.contains("Pane #1") + }, + ); + + zellij.quit(); +} + +#[test] +fn set_pane_frame_style_none_through_the_cli() { + let mut zellij = start_zellij(); + claim_first_terminal_and_wait_for_prompt(&zellij); + split_right_and_wait_for_prompt(&zellij); + + zellij.wait_until( + "two titled panes start without full frames", + |grid_snapshot| { + grid_snapshot.contains("Pane #1") + && grid_snapshot.contains("Pane #2") + && !grid_snapshot.contains(FULL_FRAME_CORNER) + }, + ); + + let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle { + style: PaneFrameStyle::None, + }); + assert_eq!(exit_code, 0, "set-pane-frame-style none exited cleanly"); + + zellij.wait_until( + "titles and frames both removed in none mode", + |grid_snapshot| { + grid_snapshot.status_bar_appears() + && !grid_snapshot.contains("Pane #1") + && !grid_snapshot.contains("Pane #2") + && !grid_snapshot.contains(FULL_FRAME_CORNER) + }, + ); + + let exit_code = zellij.run_cli_action(CliAction::SetPaneFrameStyle { + style: PaneFrameStyle::Titles, + }); + assert_eq!(exit_code, 0, "set-pane-frame-style titles exited cleanly"); + + zellij.wait_until("pane titles return in titles mode", |grid_snapshot| { + grid_snapshot.contains("Pane #1") && !grid_snapshot.contains(FULL_FRAME_CORNER) + }); + + zellij.quit(); +} + +#[test] +fn set_pane_frame_style_through_a_keybinding() { + let mut zellij = TestRunner::new(Size { + cols: 120, + rows: 24, + }) + .with_config("keybinds {\n normal {\n bind \"Ctrl y\" { SetPaneFrameStyle \"full\"; }\n }\n}") + .start(); + claim_first_terminal_and_wait_for_prompt(&zellij); + + zellij.wait_until("lone titles pane has no frame", |grid_snapshot| { + grid_snapshot.status_bar_appears() && !grid_snapshot.contains(FULL_FRAME_CORNER) + }); + + zellij.send_stdin(&ctrl_y()); + + zellij.wait_until( + "keybinding switched the pane to full frames", + |grid_snapshot| { + grid_snapshot.contains(FULL_FRAME_CORNER) && grid_snapshot.contains("Pane #1") + }, + ); + + zellij.quit(); +} diff --git a/zellij-integration-tests/tests/single_pane_tab_title.rs b/zellij-integration-tests/tests/single_pane_tab_title.rs new file mode 100644 index 00000000..1fd1a553 --- /dev/null +++ b/zellij-integration-tests/tests/single_pane_tab_title.rs @@ -0,0 +1,128 @@ +#![cfg(unix)] + +use zellij_integration_tests::{ + claim_first_terminal_and_wait_for_prompt, split_right_and_wait_for_prompt, start_zellij, + FakePtyHandle, TestSession, +}; +use zellij_utils::cli::CliAction; + +fn replace_pane_in_place_with_held_command( + zellij: &TestSession, + pane_id: &str, + command: &str, +) -> FakePtyHandle { + zellij.run_cli_action(CliAction::NewPane { + direction: None, + command: vec![command.to_string()], + plugin: None, + cwd: None, + floating: false, + in_place: true, + close_replaced_pane: true, + pane_id: Some(pane_id.to_string()), + name: None, + close_on_exit: false, + start_suspended: false, + configuration: None, + skip_plugin_cache: false, + x: None, + y: None, + width: None, + height: None, + pinned: None, + stacked: false, + blocking: false, + block_until_exit_success: false, + block_until_exit_failure: false, + block_until_exit: false, + unblock_condition: None, + near_current_pane: false, + borderless: None, + tab_id: None, + }); + zellij.expect_pty_spawn() +} + +#[test] +fn lone_pane_title_becomes_the_tab_name() { + let mut zellij = start_zellij(); + let terminal = claim_first_terminal_and_wait_for_prompt(&zellij); + + terminal.output(b"\x1b]0;my-title\x07"); + let grid_snapshot = zellij.wait_until("tab borrows the pane title", |grid_snapshot| { + grid_snapshot.status_bar_appears() && grid_snapshot.contains("my-title") + }); + assert!( + !grid_snapshot.contains("Tab #1"), + "the borrowed pane title replaces the default tab name:\n{}", + grid_snapshot.text + ); + + zellij.quit(); +} + +#[test] +fn lone_default_pane_keeps_the_default_tab_name() { + let mut zellij = start_zellij(); + claim_first_terminal_and_wait_for_prompt(&zellij); + + let grid_snapshot = zellij.wait_until("default tab name is shown", |grid_snapshot| { + grid_snapshot.status_bar_appears() && grid_snapshot.contains("Tab #1") + }); + assert!( + !grid_snapshot.contains("Pane #1"), + "the default pane name never leaks into the tab name:\n{}", + grid_snapshot.text + ); + + zellij.quit(); +} + +#[test] +fn tab_name_reverts_when_a_second_pane_is_opened() { + let mut zellij = start_zellij(); + let terminal = claim_first_terminal_and_wait_for_prompt(&zellij); + + terminal.output(b"\x1b]0;my-title\x07"); + zellij.wait_until("tab borrows the pane title", |grid_snapshot| { + grid_snapshot.contains("my-title") && !grid_snapshot.contains("Tab #1") + }); + + split_right_and_wait_for_prompt(&zellij); + let grid_snapshot = zellij.wait_until( + "tab name reverts once a second pane exists", + |grid_snapshot| { + grid_snapshot + .lines() + .first() + .is_some_and(|tab_bar| tab_bar.contains("Tab #1")) + }, + ); + assert!( + grid_snapshot.contains("my-title"), + "the original pane keeps its title in its frame:\n{}", + grid_snapshot.text + ); + + zellij.quit(); +} + +#[test] +fn lone_held_pane_tab_name_shows_exit_status() { + let mut zellij = start_zellij(); + let shell_terminal = claim_first_terminal_and_wait_for_prompt(&zellij); + + let command_pane_id = format!("terminal_{}", shell_terminal.terminal_id()); + let command_terminal = + replace_pane_in_place_with_held_command(&zellij, &command_pane_id, "held-command"); + zellij.wait_until("command pane took over the lone tab", |grid_snapshot| { + grid_snapshot.status_bar_appears() && grid_snapshot.tab_bar_appears() + }); + + command_terminal.exit(Some(0)); + zellij.wait_until("tab name carries the exit status", |grid_snapshot| { + grid_snapshot.contains("EXIT CODE: 0") + }); + + zellij.quit(); +} diff --git a/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap b/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap index 80505f55..f28120d7 100644 --- a/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap +++ b/zellij-integration-tests/tests/snapshots/app__edit_scrollback.snap @@ -2,27 +2,8 @@ source: zellij-integration-tests/tests/app.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ EDITING SCROLLBACK ──────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ SCROLLBACK_MARKER_ONE │ -│SCROLLBACK_MARKER_TWO │ -│█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) EDITING SCROLLBACK + +$ SCROLLBACK_MARKER_ONE +SCROLLBACK_MARKER_TWO +█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap b/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap index 2a285443..b9e64ea2 100644 --- a/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap +++ b/zellij-integration-tests/tests/snapshots/app__resize_terminal_window.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/app.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ───────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└────────────────────────────────────────────────┘└────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + g p t n h s o q ... diff --git a/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap b/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap index 0670f288..9c8fa8c7 100644 --- a/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap +++ b/zellij-integration-tests/tests/snapshots/app__status_bar_loads_custom_keybindings.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/app.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - F1 LOCK F2 PANE F3 TAB F4 RESIZE F5 MOVE F6 SEARCH Alt F7 SESSION Ctrl F8 QUIT + Zellij (test) Tab #1 + +$ █ + F1 LOCK F2 PANE F3 TAB F4 RESIZE F5 MOVE F6 SEARCH Alt F7 SESSION Ctrl F8 QUIT diff --git a/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap b/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap index 03d134ea..120ef352 100644 --- a/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap +++ b/zellij-integration-tests/tests/snapshots/app__use_custom_layout_with_relative_path.snap @@ -2,26 +2,6 @@ source: zellij-integration-tests/tests/app.rs expression: normalized(&grid_snapshot) --- - -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Zellij (test) Tab #1 + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT +$ █ + Zellij (test) Tab #1 + diff --git a/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap b/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap index ba160d8c..50538a08 100644 --- a/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap +++ b/zellij-integration-tests/tests/snapshots/basic__resize_pane.snap @@ -1,28 +1,28 @@ --- source: zellij-integration-tests/tests/basic.rs -expression: normalized(&snapshot) +expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ───────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└────────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap b/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap index 7f5f5a69..b50409e2 100644 --- a/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap +++ b/zellij-integration-tests/tests/snapshots/basic__split_terminals_vertically.snap @@ -1,28 +1,28 @@ --- source: zellij-integration-tests/tests/basic.rs -expression: normalized(&snapshot) +expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap b/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap index 7fff8f8f..f4846229 100644 --- a/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap +++ b/zellij-integration-tests/tests/snapshots/basic__starts_with_one_terminal.snap @@ -1,28 +1,7 @@ --- source: zellij-integration-tests/tests/basic.rs -expression: normalized(&snapshot) +expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap b/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap index 386bd7e5..eaa7659e 100644 --- a/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap +++ b/zellij-integration-tests/tests/snapshots/cli__override_layout_from_default_to_compact.snap @@ -2,27 +2,5 @@ source: zellij-integration-tests/tests/cli.rs expression: normalized(&grid_snapshot) --- -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Zellij (test) NORMAL Tab #1 +$ █ + Zellij (test) NORMAL Tab #1 diff --git a/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap b/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap index 6b2d58e7..8901dad4 100644 --- a/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap +++ b/zellij-integration-tests/tests/snapshots/cli__send_blocking_command_through_the_cli.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/cli.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap b/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap index 42573137..97f46d06 100644 --- a/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap +++ b/zellij-integration-tests/tests/snapshots/cli__send_command_through_the_cli.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/cli.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ suspended-command ───────────────────────────────────────┐ -│$ ││foo │ -│ ││foo │ -│ ││█ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ suspended-command +$ │foo + │foo + │█ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap index 707da328..c713a934 100644 --- a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap +++ b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality-2.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/cli.rs expression: normalized(&watcher_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│WATCHER_OUTPUT_1 ││ │ -│WATCHER_OUTPUT_2 ││ │ -│WATCHER_OUTPUT_3 ││ │ -│WATCHER_DONE ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ +WATCHER_OUTPUT_1 │ +WATCHER_OUTPUT_2 │ +WATCHER_OUTPUT_3 │ +WATCHER_DONE │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap index 633d8f3b..dc904dd6 100644 --- a/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap +++ b/zellij-integration-tests/tests/snapshots/cli__watcher_client_functionality.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/cli.rs expression: normalized(&main_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│WATCHER_OUTPUT_1 ││ │ -│WATCHER_OUTPUT_2 ││ │ -│WATCHER_OUTPUT_3 ││ │ -│WATCHER_DONE ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ +WATCHER_OUTPUT_1 │ +WATCHER_OUTPUT_2 │ +WATCHER_OUTPUT_3 │ +WATCHER_DONE │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap b/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap index 14b6ad52..966b41df 100644 --- a/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap +++ b/zellij-integration-tests/tests/snapshots/clients__detach_and_attach_session.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ I am some text█ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ I am some text█ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap b/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap index 0e6e31cb..4b190af2 100644 --- a/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap +++ b/zellij-integration-tests/tests/snapshots/clients__mirrored_sessions.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&main_grid) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap index 59e690c5..2da66244 100644 --- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap +++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab-2.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&second_grid) --- - Zellij (test) Tab #1 [ ] -┌ Pane #1 ───────────┤ FOCUSED USER: ├───────────────────┐┌ Pane #2 ──────────────┤ MY FOCUS ├───────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 [ ] + + [ FOCUSED USER: ] Pane #1 │ [ MY FOCUS ] Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap index 6ad8e0cd..9a2de537 100644 --- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap +++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_panes_and_same_tab.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&main_grid) --- - Zellij (test) Tab #1 [ ] -┌ Pane #1 ──────────────┤ MY FOCUS ├───────────────────────┐┌ Pane #2 ───────────┤ FOCUSED USER: ├───────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 [ ] + + [ MY FOCUS ] Pane #1 │ [ FOCUSED USER: ] Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap index 0806898d..9d514fe8 100644 --- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap +++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs-2.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&second_grid) --- - Zellij (test) Tab #1 [ ] Tab #2 -┌ Pane #1 ────────────────────────────────────────────┤ MY FOCUS ├─────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 [ ] Tab #2 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap index fe0a78a9..26f7c371 100644 --- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap +++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_different_tabs.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&main_grid) --- - Zellij (test) Tab #1 Tab #2 [ ] -┌ Pane #1 ────────────────────────────────────────────┤ MY FOCUS ├─────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 [ ] + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap index ea21dde0..803a2105 100644 --- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap +++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab-2.snap @@ -2,7 +2,7 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&second_grid) --- - Zellij (test) Tab #1 [ ] + Zellij (test) Tab #1 [ ] + ┌ Pane #1 ─────────────────────────────────────────┤ MY FOCUS AND: ├─────────────────────────────────────────────────┐ │$ █ │ │ │ diff --git a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap index 5e27178e..13d85f0b 100644 --- a/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap +++ b/zellij-integration-tests/tests/snapshots/clients__multiple_users_in_same_pane_and_tab.snap @@ -2,7 +2,7 @@ source: zellij-integration-tests/tests/clients.rs expression: normalized(&main_grid) --- - Zellij (test) Tab #1 [ ] + Zellij (test) Tab #1 [ ] + ┌ Pane #1 ─────────────────────────────────────────┤ MY FOCUS AND: ├─────────────────────────────────────────────────┐ │$ █ │ │ │ diff --git a/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap b/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap index a114ffc5..8a7dc160 100644 --- a/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap +++ b/zellij-integration-tests/tests/snapshots/misc__focus_next_pane_via_tmux_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/misc.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap b/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap index 8e954ab9..9ec7cc4b 100644 --- a/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap +++ b/zellij-integration-tests/tests/snapshots/misc__next_swap_layout.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/misc.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap b/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap index 8e954ab9..9ec7cc4b 100644 --- a/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap +++ b/zellij-integration-tests/tests/snapshots/misc__previous_swap_layout.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/misc.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap b/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap index 9932251c..c704e688 100644 --- a/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap +++ b/zellij-integration-tests/tests/snapshots/misc__toggle_group_marking.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/misc.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ┌ Multiple Pane Select ────────────────────────┐ ││ │ -│ │<ESC> - cancel, <TAB> - move │ ││ │ -│ │ │ ││ │ -│ │GROUP ACTIONS (1 SELECTED PANE) │ ││ │ -│ │<b> - break out, <s> - stack, <c> - close │ ││ │ -│ │<l> - break left, <r> - break right │ ││ │ -│ │<e> - embed, <f> - float │ ││ │ -│ │ │ ││ │ -│ │Alt + <p> Toggle <Shift p> Follow Focus │ ││ │ -│ └──────────────────────────────────────────────┘ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + ┌ Multiple Pane Select ────────────────────────┐ │ + │<ESC> - cancel, <TAB> - move │ │ + │ │ │ + │GROUP ACTIONS (1 SELECTED PANE) │ │ + │<b> - break out, <s> - stack, <c> - close │ │ + │<l> - break left, <r> - break right │ │ + │<e> - embed, <f> - float │ │ + │ │ │ + │Alt + <p> Toggle <Shift p> Follow Focus │ │ + └──────────────────────────────────────────────┘ │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap b/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap index 9932251c..c704e688 100644 --- a/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap +++ b/zellij-integration-tests/tests/snapshots/misc__toggle_pane_in_group.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/misc.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ┌ Multiple Pane Select ────────────────────────┐ ││ │ -│ │<ESC> - cancel, <TAB> - move │ ││ │ -│ │ │ ││ │ -│ │GROUP ACTIONS (1 SELECTED PANE) │ ││ │ -│ │<b> - break out, <s> - stack, <c> - close │ ││ │ -│ │<l> - break left, <r> - break right │ ││ │ -│ │<e> - embed, <f> - float │ ││ │ -│ │ │ ││ │ -│ │Alt + <p> Toggle <Shift p> Follow Focus │ ││ │ -│ └──────────────────────────────────────────────┘ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + ┌ Multiple Pane Select ────────────────────────┐ │ + │<ESC> - cancel, <TAB> - move │ │ + │ │ │ + │GROUP ACTIONS (1 SELECTED PANE) │ │ + │<b> - break out, <s> - stack, <c> - close │ │ + │<l> - break left, <r> - break right │ │ + │<e> - embed, <f> - float │ │ + │ │ │ + │Alt + <p> Toggle <Shift p> Follow Focus │ │ + └──────────────────────────────────────────────┘ │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap b/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap index 29857afc..f2a692e7 100644 --- a/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap +++ b/zellij-integration-tests/tests/snapshots/misc__write_byte_to_focused_pane_via_tmux_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/misc.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap b/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap index 421627c3..b2ae0119 100644 --- a/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap +++ b/zellij-integration-tests/tests/snapshots/modes__bracketed_paste.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ nabc█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ nabc█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap b/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap index e2170783..1fb9dee7 100644 --- a/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__enter_search_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Enter search... ─────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - ENTERING SEARCH TERM ENTER When done + Zellij (test) Tab #1 + +$ █ + ENTERING SEARCH TERM ENTER When done diff --git a/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap b/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap index 8dde2b5b..744d0373 100644 --- a/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__lock_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ nabc█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <g> LOCK + Zellij (test) Tab #1 + +$ nabc█ + Ctrl + <g> LOCK diff --git a/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap b/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap index b8e8dc2c..b0605346 100644 --- a/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__return_to_normal_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap b/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap index 0af68b35..96506ac6 100644 --- a/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap +++ b/zellij-integration-tests/tests/snapshots/modes__scrolling_inside_a_pane.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 2/2 ┐ -│$ ││$ line1 │ -│ ││line2 │ -│ ││line3 │ -│ ││line4 │ -│ ││line5 │ -│ ││line6 │ -│ ││line7 │ -│ ││line8 │ -│ ││line9 │ -│ ││line10 │ -│ ││line11 │ -│ ││line12 │ -│ ││line13 │ -│ ││line14 │ -│ ││line15 │ -│ ││line16 │ -│ ││line17 │ -│ ││line18 │ -│ ││line19 │ -│ ││█ine20 │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 [ SCROLL: 2/2 ] +$ │$ line1 + │line2 + │line3 + │line4 + │line5 + │line6 + │line7 + │line8 + │line9 + │line10 + │line11 + │line12 + │line13 + │line14 + │line15 + │line16 + │line17 + │line18 + │line19 + │line20 + │█ine21 Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap index 2c38ca5b..7c5a8166 100644 --- a/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_move_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <h> MOVE ←↓↑→ Switch Location ENTER When done + Zellij (test) Tab #1 + +$ █ + Ctrl + <h> MOVE ←↓↑→ Switch Location ENTER When done diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap index 77a3a87a..cf9153c1 100644 --- a/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_pane_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <p> PANE n New ←↓↑→ Move x Close c Rename f Fullscreen Alt f Floating ... + Zellij (test) Tab #1 + +$ █ + Ctrl + <p> PANE n New ←↓↑→ Move x Close c Rename f Fullscreen Alt f Floating ... diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap index 934b93fa..cabc4035 100644 --- a/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_resize_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <n> RESIZE +|- Increase/Decrease ←↓↑→ Increase HJKL Decrease ENTER Select + Zellij (test) Tab #1 + +$ █ + Ctrl + <n> RESIZE +|- Increase/Decrease ←↓↑→ Increase HJKL Decrease ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap index bb92c9f8..fd74b0c0 100644 --- a/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_scroll_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select + Zellij (test) Tab #1 + +$ █ + Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap index 9e647b1a..8bef38dd 100644 --- a/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_search_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole + Zellij (test) Tab #1 + +$ █ + SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap index df752793..55785d6e 100644 --- a/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_session_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <o> SESSION d Detach w Manager s Share c Config l Layouts p Plugins ... + Zellij (test) Tab #1 + +$ █ + Ctrl + <o> SESSION d Detach w Manager s Share c Config l Layouts p Plugins ... diff --git a/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap b/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap index 0bd07696..efb2bc6a 100644 --- a/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__switch_to_tab_mode.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <t> TAB n New ←→ Move x Close r Rename s Sync b Break out [] Break ... + Zellij (test) Tab #1 + +$ █ + Ctrl + <t> TAB n New ←→ Move x Close r Rename s Sync b Break out [] Break ... diff --git a/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap b/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap index 42363818..88429ed3 100644 --- a/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap +++ b/zellij-integration-tests/tests/snapshots/modes__tmux_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/modes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap b/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap index f007cf9d..4b400874 100644 --- a/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap +++ b/zellij-integration-tests/tests/snapshots/mouse__focus_pane_with_mouse.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/mouse.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap b/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap index 6bdb9ca6..7ec4a10d 100644 --- a/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap +++ b/zellij-integration-tests/tests/snapshots/mouse__pin_floating_panes.snap @@ -2,27 +2,22 @@ source: zellij-integration-tests/tests/mouse.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ line1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa│ -│a │ -│line2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line5aaaaaaaaaaaaaaaaaaaaaaaa┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐aaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line6aaaaaaaaaaaaaaaaaaaaaaaa│$ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line7aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line8aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line9aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa │ -│line10aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│ -│line11aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│ -│line12aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│ -│line13aaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaaa│ -│█ │ │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ line1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +line2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +line3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +line4aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +line5aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +line6aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +line7aaaaaaaaaaaaaaaaaaaaaaaaa┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐aaaaaaaaaaaaaaaaaaaaaaaaaaa +line8aaaaaaaaaaaaaaaaaaaaaaaaa│$ │aaaaaaaaaaaaaaaaaaaaaaaaaaa +line9aaaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaa +line10aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa +line11aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa +line12aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa +line13aaaaaaaaaaaaaaaaaaaaaaaa│ │aaaaaaaaaaaaaaaaaaaaaaaaaaaa +█ │ │ + │ │ + │ │ + └──────────────────────────────────────────────────────────┘ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap b/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap index 629cc513..0a1495df 100644 --- a/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap +++ b/zellij-integration-tests/tests/snapshots/mouse__scrolling_inside_a_pane_with_mouse.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/mouse.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────── SCROLL: 2/2 ┐ -│$ ││$ line1 │ -│ ││line2 │ -│ ││line3 │ -│ ││line4 │ -│ ││line5 │ -│ ││line6 │ -│ ││line7 │ -│ ││line8 │ -│ ││line9 │ -│ ││line10 │ -│ ││line11 │ -│ ││line12 │ -│ ││line13 │ -│ ││line14 │ -│ ││line15 │ -│ ││line16 │ -│ ││line17 │ -│ ││line18 │ -│ ││line19 │ -│ ││█ine20 │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 [ SCROLL: 1/1 ] +$ │$ line1 + │line2 + │line3 + │line4 + │line5 + │line6 + │line7 + │line8 + │line9 + │line10 + │line11 + │line12 + │line13 + │line14 + │line15 + │line16 + │line17 + │line18 + │line19 + │line20 + │█ine21 Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap b/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap index 0800ee6c..0e53b7b2 100644 --- a/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap +++ b/zellij-integration-tests/tests/snapshots/panes__cannot_split_terminals_vertically_when_active_terminal_is_too_small.snap @@ -3,22 +3,5 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- -┌──────┐ -│$ done│ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────┘ +$ done█ Ctrl + diff --git a/zellij-integration-tests/tests/snapshots/panes__close_pane.snap b/zellij-integration-tests/tests/snapshots/panes__close_pane.snap index b9d0bb9c..717e5a5e 100644 --- a/zellij-integration-tests/tests/snapshots/panes__close_pane.snap +++ b/zellij-integration-tests/tests/snapshots/panes__close_pane.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap index bf220375..12bf79f3 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_down_in_pane_mode.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap index fbbe4940..dc72368a 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_left_in_pane_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap index fbbe4940..dc72368a 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_moves_focus_between_panes.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap index f0254ce4..a4690066 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_or_tab_switches_tab_when_single_pane.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ oneone█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + +$ oneone█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap index f68a25e2..143b1902 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_right_in_pane_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap index 1bf6e70d..9919d65f 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_focus_up_in_pane_mode.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ █ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap index a5ec291c..b8007c7b 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_backwards_swaps_with_neighbor.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #2 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐ -│$ BBB█ ││$ AAA │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #2 │ Pane #1 +$ BBB█ │$ AAA + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap index 3efaa27f..f14d9dea 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_down.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ BBB█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ AAA │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #2 +$ BBB█ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #1 +$ AAA Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap index a5ec291c..b8007c7b 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_left.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #2 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐ -│$ BBB█ ││$ AAA │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #2 │ Pane #1 +$ BBB█ │$ AAA + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap b/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap index a5ec291c..b8007c7b 100644 --- a/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap +++ b/zellij-integration-tests/tests/snapshots/panes__move_pane_swaps_with_neighbor.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #2 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐ -│$ BBB█ ││$ AAA │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #2 │ Pane #1 +$ BBB█ │$ AAA + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap index f68a25e2..143b1902 100644 --- a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap +++ b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_normal_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap index f68a25e2..143b1902 100644 --- a/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap +++ b/zellij-integration-tests/tests/snapshots/panes__new_pane_in_pane_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap b/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap index 64abb7f3..b47edec4 100644 --- a/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap +++ b/zellij-integration-tests/tests/snapshots/panes__new_stacked_pane.snap @@ -2,27 +2,8 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +──────────────────────────────────────────────────────── Pane #1 ─────────────────────────────────────────────────────── +──────────────────────────────────────────────────────── Pane #2 ─────────────────────────────────────────────────────── +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap b/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap index b9d0bb9c..717e5a5e 100644 --- a/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap +++ b/zellij-integration-tests/tests/snapshots/panes__pane_closes_when_its_process_exits.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap b/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap index bf220375..12bf79f3 100644 --- a/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap +++ b/zellij-integration-tests/tests/snapshots/panes__split_pane_downward.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap b/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap index e58b8c3e..be4beb78 100644 --- a/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap +++ b/zellij-integration-tests/tests/snapshots/panes__start_without_pane_frames.snap @@ -2,7 +2,7 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 + Zellij (test) Tab #1 + $ │$ █ │ │ diff --git a/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap b/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap index fbbe4940..dc72368a 100644 --- a/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap +++ b/zellij-integration-tests/tests/snapshots/panes__switch_focus_in_pane_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap index 3a4e1240..00b7b4b4 100644 --- a/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_floating_panes.snap @@ -2,27 +2,17 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ │ -│ │$ █ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ + ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ + │$ █ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + └──────────────────────────────────────────────────────────┘ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_floating_pane.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_floating_pane.snap new file mode 100644 index 00000000..be296cab --- /dev/null +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_floating_pane.snap @@ -0,0 +1,28 @@ +--- +source: zellij-integration-tests/tests/panes.rs +expression: normalized(&grid_snapshot) +--- + Zellij (test) Tab #1 + +┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ │ +│ │ +│ │ +│ │ +│ │ +│ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ │ +│ │$ █ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ └──────────────────────────────────────────────────────────┘ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_single_pane.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_single_pane.snap new file mode 100644 index 00000000..b89372c8 --- /dev/null +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_single_pane.snap @@ -0,0 +1,28 @@ +--- +source: zellij-integration-tests/tests/panes.rs +expression: normalized(&grid_snapshot) +--- + Zellij (test) Tab #1 + +┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ █ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_stacked_panes.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_stacked_panes.snap new file mode 100644 index 00000000..4f752a1b --- /dev/null +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_frames_with_stacked_panes.snap @@ -0,0 +1,28 @@ +--- +source: zellij-integration-tests/tests/panes.rs +expression: normalized(&grid_snapshot) +--- + Zellij (test) Tab #1 + +┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ +│$ █ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap index 3a4e1240..00b7b4b4 100644 --- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_embed_or_floating.snap @@ -2,27 +2,17 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ │ -│ │$ █ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ + ┌ Pane #2 ──────────────────────────────────────── PIN [ ] ┐ + │$ █ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + └──────────────────────────────────────────────────────────┘ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap index e58b8c3e..143b1902 100644 --- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_frames.snap @@ -2,7 +2,8 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 $ │$ █ │ │ @@ -24,5 +25,4 @@ $ │$ █ │ │ │ - │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap index fcb1eba9..ad010e60 100644 --- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_fullscreen.snap @@ -2,27 +2,7 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 (FULLSCREEN) -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 (FULLSCREEN) + + Pane #2 +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap index 858b2446..de6f7edb 100644 --- a/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap +++ b/zellij-integration-tests/tests/snapshots/panes__toggle_pane_pinned.snap @@ -2,27 +2,17 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ ┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐ │ -│ │$ █ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ + ┌ Pane #2 ──────────────────────────────────────── PIN [+] ┐ + │$ █ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + └──────────────────────────────────────────────────────────┘ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap b/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap index b9d0bb9c..143b1902 100644 --- a/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap +++ b/zellij-integration-tests/tests/snapshots/panes__undo_rename_pane.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/panes.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap b/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap index 7341d7a6..034a2c02 100644 --- a/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap +++ b/zellij-integration-tests/tests/snapshots/plugins__load_plugins_in_background_on_startup.snap @@ -2,27 +2,17 @@ source: zellij-integration-tests/tests/plugins.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ ┌ (.) - permission-requester ───────────────────── PIN [ ] ┐ │ -│ │This plugin asks permission to: ReadApplicationState, Chan│ │ -│ │geApplicationState, OpenFiles, RunCommands, OpenTerminalsO│ │ -│ │rPlugins, WriteToStdin, WebAccess, ReadCliPipes, MessageAn│ │ -│ │dLaunchOtherPlugins, Reconfigure, RunActionsAsUser, WriteT│ │ -│ │oClipboard, ReadSessionEnvironmentVariables. Allow? (y/n) │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ │ │ │ -│ └──────────────────────────────────────────────────────────┘ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - + Zellij (test) Tab #1 + +$ + ┌ (.) - permission-requester ───────────────────── PIN [ ] ┐ + │This plugin asks permission to: ReadApplicationState, Chan│ + │geApplicationState, OpenFiles, RunCommands, OpenTerminalsO│ + │rPlugins, WriteToStdin, WebAccess, ReadCliPipes, MessageAn│ + │dLaunchOtherPlugins, Reconfigure, RunActionsAsUser, WriteT│ + │oClipboard, ReadSessionEnvironmentVariables. Allow? (y/n) │ + │ │ + │ │ + │ │ + │ │ + │ │ + └──────────────────────────────────────────────────────────┘ diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap index 6bb097ff..53311e6d 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_down.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ █ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap index 6d94b5be..89aa0ab6 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_normal_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────┐┌ Pane #2 ─────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────────────────────────────────────────┘└──────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap index 6d94b5be..89aa0ab6 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_in_resize_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────┐┌ Pane #2 ─────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────────────────────────────────────────┘└──────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap index 31a95ba2..086c9ed1 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_left.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ───────────────────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap index 8071443e..811b464d 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_right.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ───────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└────────────────────────────────────────────────────┘└────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap index f60a7abc..9469e37a 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_decrease_up.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap index b04b511a..53311e6d 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_down.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ █ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap index 1da118af..2a1f23f0 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_normal_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────┐┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────┘└──────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap index 1da118af..2a1f23f0 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_in_resize_mode.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────┐┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────┘└──────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap index fca16a54..416be42d 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_right.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ───────────────────────────────────────────────────────┐┌ Pane #2 ───────────────────────────────────────────┐ -│$ █ ││$ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap b/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap index 5ff0c7aa..9469e37a 100644 --- a/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap +++ b/zellij-integration-tests/tests/snapshots/resize__resize_increase_up.snap @@ -2,27 +2,10 @@ source: zellij-integration-tests/tests/resize.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 +$ +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + Pane #2 +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap index 414fdd10..70894a4e 100644 --- a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap +++ b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/resurrection.rs expression: normalized(&grid_snapshot) --- - Zellij (test) alpha beta -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│ ││█ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) alpha beta + + Pane #1 │ Pane #2 + │█ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap index 9cdf365b..4c6f5ee3 100644 --- a/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap +++ b/zellij-integration-tests/tests/snapshots/resurrection__quit_and_resurrect_session_with_viewport_serialization.snap @@ -2,27 +2,7 @@ source: zellij-integration-tests/tests/resurrection.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│ │ -│VIEWPORT_CONTENT_TO_RESTORE │ -│ │ -│█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +VIEWPORT_CONTENT_TO_RESTORE +█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap index 2ce2743f..e51bd7c6 100644 --- a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap +++ b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_down.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/scroll.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 0/21 ┐ -│line22 │ -│line23 │ -│line24 │ -│line25 │ -│line26 │ -│line27 │ -│line28 │ -│line29 │ -│line30 │ -│line31 │ -│line32 │ -│line33 │ -│line34 │ -│line35 │ -│line36 │ -│line37 │ -│line38 │ -│line39 │ -│line40 │ -│█ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select + Zellij (test) Tab #1 + [ SCROLL 0/19 ] +line20 +line21 +line22 +line23 +line24 +line25 +line26 +line27 +line28 +line29 +line30 +line31 +line32 +line33 +line34 +line35 +line36 +line37 +line38 +line39 +line40 +█ + Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap index 4adb7c17..1b2b0967 100644 --- a/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap +++ b/zellij-integration-tests/tests/snapshots/scroll__half_page_scroll_up.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/scroll.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ───────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 10/21 ┐ -│line12 │ -│line13 │ -│line14 │ -│line15 │ -│line16 │ -│line17 │ -│line18 │ -│line19 │ -│line20 │ -│line21 │ -│line22 │ -│line23 │ -│line24 │ -│line25 │ -│line26 │ -│line27 │ -│line28 │ -│line29 │ -│line30 │ -│█ine31 │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select + Zellij (test) Tab #1 + [ SCROLL 10/19 ] +line10 +line11 +line12 +line13 +line14 +line15 +line16 +line17 +line18 +line19 +line20 +line21 +line22 +line23 +line24 +line25 +line26 +line27 +line28 +line29 +line30 +█ine31 + Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap index 6b3cec51..e51bd7c6 100644 --- a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap +++ b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_down.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/scroll.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 1/21 ┐ -│line21 │ -│line22 │ -│line23 │ -│line24 │ -│line25 │ -│line26 │ -│line27 │ -│line28 │ -│line29 │ -│line30 │ -│line31 │ -│line32 │ -│line33 │ -│line34 │ -│line35 │ -│line36 │ -│line37 │ -│line38 │ -│line39 │ -│█ine40 │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select + Zellij (test) Tab #1 + [ SCROLL 0/19 ] +line20 +line21 +line22 +line23 +line24 +line25 +line26 +line27 +line28 +line29 +line30 +line31 +line32 +line33 +line34 +line35 +line36 +line37 +line38 +line39 +line40 +█ + Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap index d742f0d3..54718511 100644 --- a/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap +++ b/zellij-integration-tests/tests/snapshots/scroll__page_scroll_up.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/scroll.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ───────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 21/21 ┐ -│$ line01 │ -│line02 │ -│line03 │ -│line04 │ -│line05 │ -│line06 │ -│line07 │ -│line08 │ -│line09 │ -│line10 │ -│line11 │ -│line12 │ -│line13 │ -│line14 │ -│line15 │ -│line16 │ -│line17 │ -│line18 │ -│line19 │ -│█ine20 │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select + Zellij (test) Tab #1 + [ SCROLL 19/19 ] +$ line01 +line02 +line03 +line04 +line05 +line06 +line07 +line08 +line09 +line10 +line11 +line12 +line13 +line14 +line15 +line16 +line17 +line18 +line19 +line20 +line21 +█ine22 + Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap b/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap index 6b3cec51..873db2ac 100644 --- a/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap +++ b/zellij-integration-tests/tests/snapshots/scroll__scroll_down_one_line.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/scroll.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 1/21 ┐ -│line21 │ -│line22 │ -│line23 │ -│line24 │ -│line25 │ -│line26 │ -│line27 │ -│line28 │ -│line29 │ -│line30 │ -│line31 │ -│line32 │ -│line33 │ -│line34 │ -│line35 │ -│line36 │ -│line37 │ -│line38 │ -│line39 │ -│█ine40 │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select + Zellij (test) Tab #1 + [ SCROLL 1/19 ] +line19 +line20 +line21 +line22 +line23 +line24 +line25 +line26 +line27 +line28 +line29 +line30 +line31 +line32 +line33 +line34 +line35 +line36 +line37 +line38 +line39 +█ine40 + Ctrl + <s> SEARCH s Search ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll e Edit ENTER Select diff --git a/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap b/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap index 4e486cc2..50481925 100644 --- a/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap +++ b/zellij-integration-tests/tests/snapshots/scroll__scroll_to_bottom.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/scroll.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ────────────────────────────────────────────────────────────────────────────────────────────── SCROLL: 0/21 ┐ -│line22 │ -│line23 │ -│line24 │ -│line25 │ -│line26 │ -│line27 │ -│line28 │ -│line29 │ -│line30 │ -│line31 │ -│line32 │ -│line33 │ -│line34 │ -│line35 │ -│line36 │ -│line37 │ -│line38 │ -│line39 │ -│line40 │ -│█ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + [ SCROLL 0/19 ] +line20 +line21 +line22 +line23 +line24 +line25 +line26 +line27 +line28 +line29 +line30 +line31 +line32 +line33 +line34 +line35 +line36 +line37 +line38 +line39 +line40 +█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap b/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap index 7f89ceaa..af4123ad 100644 --- a/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap +++ b/zellij-integration-tests/tests/snapshots/search__search_down_to_next_match.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/search.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ SEARCHING: NEEDLE ──────────────────────────────────────────────────────────────────────────────────── SCROLL: 6/21 ┐ -│line16 │ -│line17 │ -│line18 │ -│line19 │ -│line20 │ -│line21 │ -│line22 │ -│line23 │ -│line24 │ -│line25 │ -│line26 │ -│line27 │ -│line28 │ -│line29 │ -│line30 │ -│line31 │ -│line32 │ -│line33 │ -│line34 │ -│█ine35 NEEDLE lower │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole + Zellij (test) Tab #1 + [ SCROLL 15/19 ] +line14 +line15 +line16 +line17 +line18 +line19 +line20 +line21 +line22 +line23 +line24 +line25 +line26 +line27 +line28 +line29 +line30 +line31 +line32 +line33 +line34 +█ine35 NEEDLE lower + SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole diff --git a/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap b/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap index d3c4a72d..bdceee74 100644 --- a/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap +++ b/zellij-integration-tests/tests/snapshots/search__search_input_jumps_to_a_match.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/search.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ SEARCHING: NEEDLE ─────────────────────────────────────────────────────────────────────────────────── SCROLL: 17/21 ┐ -│line05 NEEDLE │ -│line06 │ -│line07 │ -│line08 │ -│line09 │ -│line10 │ -│line11 │ -│line12 │ -│line13 │ -│line14 │ -│line15 │ -│line16 │ -│line17 │ -│line18 │ -│line19 │ -│line20 │ -│line21 │ -│line22 │ -│line23 │ -│█ine24 │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - ENTERING SEARCH TERM ENTER When done + Zellij (test) Tab #1 + [ SCROLL 0/19 ] +line05 NEEDLE +line06 +line07 +line08 +line09 +line10 +line11 +line12 +line13 +line14 +line15 +line16 +line17 +line18 +line19 +line20 +line21 +line22 +line23 +line24 +line25 +█ine26 + ENTERING SEARCH TERM ENTER When done diff --git a/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap b/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap index 8fab3747..b1642d5b 100644 --- a/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap +++ b/zellij-integration-tests/tests/snapshots/search__search_toggle_case_sensitivity.snap @@ -2,9 +2,9 @@ source: zellij-integration-tests/tests/search.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 + Zellij (test) Tab #1 + ┌ SEARCHING: NEEDLE [c] ───────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ NEEDLE on screen │ +│NEEDLE on screen │ │█ │ │ │ │ │ @@ -25,4 +25,4 @@ expression: normalized(&grid_snapshot) │ │ │ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole + SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole diff --git a/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap b/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap index a611c034..9011cc91 100644 --- a/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap +++ b/zellij-integration-tests/tests/snapshots/search__search_toggle_whole_word.snap @@ -2,9 +2,9 @@ source: zellij-integration-tests/tests/search.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 + Zellij (test) Tab #1 + ┌ SEARCHING: NEEDLE [o] ───────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ NEEDLE on screen │ +│NEEDLE on screen │ │█ │ │ │ │ │ @@ -25,4 +25,4 @@ expression: normalized(&grid_snapshot) │ │ │ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole + SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole diff --git a/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap b/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap index 42903ace..5d52b7ed 100644 --- a/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap +++ b/zellij-integration-tests/tests/snapshots/search__search_toggle_wrap.snap @@ -2,9 +2,9 @@ source: zellij-integration-tests/tests/search.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 + Zellij (test) Tab #1 + ┌ SEARCHING: NEEDLE [w] ───────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ NEEDLE on screen │ +│NEEDLE on screen │ │█ │ │ │ │ │ @@ -25,4 +25,4 @@ expression: normalized(&grid_snapshot) │ │ │ │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole + SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole diff --git a/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap b/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap index c113cdad..b723f787 100644 --- a/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap +++ b/zellij-integration-tests/tests/snapshots/search__search_up_to_previous_match.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/search.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ SEARCHING: NEEDLE ─────────────────────────────────────────────────────────────────────────────────── SCROLL: 17/21 ┐ -│line05 NEEDLE upper │ -│line06 │ -│line07 │ -│line08 │ -│line09 │ -│line10 │ -│line11 │ -│line12 │ -│line13 │ -│line14 │ -│line15 │ -│line16 │ -│line17 │ -│line18 │ -│line19 │ -│line20 │ -│line21 │ -│line22 │ -│line23 │ -│█ine24 │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ - SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole + Zellij (test) Tab #1 + [ SCROLL 0/19 ] +line05 NEEDLE upper +line06 +line07 +line08 +line09 +line10 +line11 +line12 +line13 +line14 +line15 +line16 +line17 +line18 +line19 +line20 +line21 +line22 +line23 +line24 +line25 +█ine26 + SEARCHING ↓↑ Scroll PgDn|PgUp Scroll d|u Scroll n Down p Up c Case w Wrap o Whole diff --git a/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap index 83ddbab4..91c4eebe 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__break_pane_into_new_tab.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #2 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap index f64e72ee..2b03a0f3 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_left.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #1 ─────────────────────────────────────────────────┐ -│$ alpha ││$ beta█ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + + Pane #1 │ Pane #1 +$ alpha │$ beta█ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap index db5fb026..7235b444 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__break_pane_to_the_right.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ gamma ││$ beta█ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + + Pane #1 │ Pane #2 +$ gamma │$ beta█ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap index f1544d42..5ffc3a99 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__close_tab.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap index 9441a9b1..403e5945 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__go_to_next_tab.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ twotwo█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + +$ twotwo█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap index e60935a0..47ff0263 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__go_to_previous_tab.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ oneone█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + +$ oneone█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap b/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap index e60935a0..47ff0263 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__go_to_tab_by_number.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ oneone█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + +$ oneone█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap index 5afe4d28..d6207d33 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #3 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #3 Tab #2 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap index d045b135..95e5f3f3 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_left_until_it_wraps_around.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 Tab #3 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 Tab #3 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap index 5afe4d28..d6207d33 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #3 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #3 Tab #2 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap index 2b4f6227..f2a22412 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__move_tab_to_right_until_it_wraps_around.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #3 Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #3 Tab #1 Tab #2 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap index da0f2839..91c4eebe 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__open_new_tab.snap @@ -1,28 +1,7 @@ --- source: zellij-integration-tests/tests/tabs.rs -expression: normalized(&zellij.snapshot()) +expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap index f34fad73..bd955b1a 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__toggle_active_sync_tab.snap @@ -2,27 +2,27 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 (SYNC) -┌ Pane #1 ─────────────────────────────────────────────────┐┌ Pane #2 ─────────────────────────────────────────────────┐ -│$ ││$ █ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -│ ││ │ -└──────────────────────────────────────────────────────────┘└──────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 (SYNC) + + Pane #1 │ Pane #2 +$ │$ █ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap b/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap index e60935a0..47ff0263 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__toggle_tab_returns_to_last_used.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 Tab #2 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ oneone█ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 Tab #2 + +$ oneone█ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap b/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap index f1544d42..5ffc3a99 100644 --- a/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap +++ b/zellij-integration-tests/tests/snapshots/tabs__undo_rename_tab.snap @@ -2,27 +2,6 @@ source: zellij-integration-tests/tests/tabs.rs expression: normalized(&grid_snapshot) --- - Zellij (test) Tab #1 -┌ Pane #1 ─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ -│$ █ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -│ │ -└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + Zellij (test) Tab #1 + +$ █ Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT ... diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane.snap new file mode 100644 index 00000000..ef47b9b9 --- /dev/null +++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane.snap @@ -0,0 +1,18 @@ +--- +source: zellij-integration-tests/tests/title_frame_mouse.rs +expression: normalized(&grid_snapshot) +--- + Zellij (test) Tab #1 + +$ + ┌ Pane #2 ─────────────────────────────────────────────────────────────────────────── PIN [ ] ┐ + │$ █ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + │ │ + └─────────────────────────────────────────────────────────────────────────────────────────────┘ + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT Alt + <n> New Pane <f> Floating diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_opens_a_new_pane.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_opens_a_new_pane.snap new file mode 100644 index 00000000..7a7db894 --- /dev/null +++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_opens_a_new_pane.snap @@ -0,0 +1,28 @@ +--- +source: zellij-integration-tests/tests/title_frame_mouse.rs +expression: normalized(&grid_snapshot) +--- + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │opened from the status bar█ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT Alt + <n> New Pane <←↓↑→> Change Focus <+-> Resize <f> Floating diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_twice_opens_two_panes.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_twice_opens_two_panes.snap new file mode 100644 index 00000000..e3fbdb82 --- /dev/null +++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_pane_in_status_bar_twice_opens_two_panes.snap @@ -0,0 +1,28 @@ +--- +source: zellij-integration-tests/tests/title_frame_mouse.rs +expression: normalized(&grid_snapshot) +--- + Zellij (test) Tab #1 + + Pane #1 │ Pane #2 +$ │first pane from the status bar + │ + │ + │ + │ + │ + │ + │ + │ + ├─────────────────────────────────────────────────────────────────────────────────────────────── + │ Pane #3 + │second pane from the status bar█ + │ + │ + │ + │ + │ + │ + │ + │ + │ + Ctrl + <g> LOCK <p> PANE <t> TAB <n> RESIZE <h> MOVE <s> SEARCH <o> SESSION <q> QUIT Alt + <n> New Pane <←↓↑→> Change Focus <+-> Resize <f> Floating diff --git a/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab.snap b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab.snap new file mode 100644 index 00000000..f05439e3 --- /dev/null +++ b/zellij-integration-tests/tests/snapshots/title_frame_mouse__mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab.snap @@ -0,0 +1,7 @@ +--- +source: zellij-integration-tests/tests/title_frame_mouse.rs +expression: normalized(&grid_snapshot) +--- + Zellij (test) Tab #1 Tab #2 + +$ █ + diff --git a/zellij-integration-tests/tests/tabs.rs b/zellij-integration-tests/tests/tabs.rs index 7ba3194a..cd37e251 100644 --- a/zellij-integration-tests/tests/tabs.rs +++ b/zellij-integration-tests/tests/tabs.rs @@ -26,7 +26,7 @@ fn open_new_tab_and_wait_for_prompt(zellij: &TestSession, expected_tab: &str) -> zellij.wait_until("new tab opened with prompt", move |grid_snapshot| { grid_snapshot.status_bar_appears() && grid_snapshot.contains(&expected_tab) - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }); terminal } @@ -201,9 +201,8 @@ fn break_pane_into_new_tab() { let grid_snapshot = zellij.wait_until("focused pane broken into a new tab", |grid_snapshot| { grid_snapshot.status_bar_appears() && grid_snapshot.contains("Tab #2") - && grid_snapshot.contains("Pane #2") && !grid_snapshot.contains("Pane #1") - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -273,7 +272,7 @@ fn open_new_tab() { let grid_snapshot = zellij.wait_until("second tab steady in normal mode", |grid_snapshot| { grid_snapshot.status_bar_appears() && grid_snapshot.contains("Tab #2") - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }); assert_snapshot!(normalized(&grid_snapshot)); zellij.quit(); @@ -294,7 +293,7 @@ fn close_tab() { grid_snapshot.status_bar_appears() && grid_snapshot.contains("Tab #1") && !grid_snapshot.contains("Tab #2") - && grid_snapshot.cursor_is_at(col(3).row(2)) + && grid_snapshot.cursor_is_at(col(2).row(1)) }, ); assert_snapshot!(normalized(&grid_snapshot)); diff --git a/zellij-integration-tests/tests/title_frame_hints.rs b/zellij-integration-tests/tests/title_frame_hints.rs new file mode 100644 index 00000000..5f841486 --- /dev/null +++ b/zellij-integration-tests/tests/title_frame_hints.rs @@ -0,0 +1,233 @@ +#![cfg(unix)] + +use zellij_integration_tests::{ + claim_first_terminal_and_wait_for_prompt, keys, split_right_and_wait_for_prompt, FakePtyHandle, + Size, TestRunner, TestSession, PROMPT, +}; + +const FOCUSED_PANE_COLUMN: usize = 90; +const ALTERNATE_FOCUSED_PANE_COLUMN: usize = 100; +const OTHER_PANE_COLUMN: usize = 10; +const HOVER_LINE: usize = 12; + +fn start_zellij_with_mouse() -> TestSession { + TestRunner::new(Size { + cols: 120, + rows: 24, + }) + .with_config("mouse_mode true\nadvanced_mouse_actions true\nmouse_hover_effects true") + .start() +} + +fn start_full_frame_zellij_with_mouse(cols: usize) -> TestSession { + TestRunner::new(Size { cols, rows: 24 }) + .with_config( + "pane_frame_style \"full\"\nmouse_mode true\nadvanced_mouse_actions true\nmouse_hover_effects true", + ) + .start() +} + +fn sgr_motion(column: usize, line: usize) -> Vec<u8> { + format!("\u{1b}[<35;{};{}M", column, line).into_bytes() +} + +fn two_pane_session_with_handles() -> (TestSession, FakePtyHandle, FakePtyHandle) { + let zellij = start_zellij_with_mouse(); + let left_terminal = claim_first_terminal_and_wait_for_prompt(&zellij); + let right_terminal = split_right_and_wait_for_prompt(&zellij); + zellij.wait_until("two panes settled in locked base mode", |grid_snapshot| { + grid_snapshot.status_bar_appears() && grid_snapshot.tab_bar_appears() + }); + (zellij, left_terminal, right_terminal) +} + +fn two_pane_session() -> TestSession { + two_pane_session_with_handles().0 +} + +fn full_frame_two_pane_session(cols: usize) -> TestSession { + let zellij = start_full_frame_zellij_with_mouse(cols); + let left_terminal = zellij.expect_pty_spawn(); + left_terminal.output(PROMPT); + zellij.wait_until("first full-frame pane rendered", |grid_snapshot| { + grid_snapshot.status_bar_appears() + && grid_snapshot.contains("┌") + && grid_snapshot.contains("$ ") + }); + zellij.send_stdin(&keys::ctrl('p')); + zellij.send_stdin(&keys::key('r')); + let right_terminal = zellij.expect_pty_spawn(); + right_terminal.output(PROMPT); + zellij.wait_until("two full-frame panes rendered", |grid_snapshot| { + grid_snapshot.contains("Pane #1") + && grid_snapshot.contains("Pane #2") + && grid_snapshot.status_bar_appears() + }); + zellij +} + +#[test] +fn hovering_a_pane_shows_a_hint_on_the_status_bar() { + let mut zellij = two_pane_session(); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until( + "resize hint shown when hovering the focused pane", + |grid_snapshot| grid_snapshot.contains("resize"), + ); + + zellij.send_stdin(&sgr_motion(OTHER_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until( + "group hint shown when hovering the other pane", + |grid_snapshot| grid_snapshot.contains("group"), + ); + + zellij.quit(); +} + +#[test] +fn any_input_dismisses_the_hint() { + let mut zellij = two_pane_session(); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until("resize hint shown", |grid_snapshot| { + grid_snapshot.contains("resize") + }); + + zellij.send_stdin(b"x"); + zellij.wait_until("hint cleared by input", |grid_snapshot| { + !grid_snapshot.contains("resize") && !grid_snapshot.contains("group") + }); + + zellij.quit(); +} + +#[test] +fn hint_only_re_fires_when_entering_a_different_pane() { + let mut zellij = two_pane_session(); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until("resize hint shown on first entry", |grid_snapshot| { + grid_snapshot.contains("resize") + }); + + zellij.send_stdin(b"x"); + zellij.wait_until("hint dismissed by input", |grid_snapshot| { + !grid_snapshot.contains("resize") && !grid_snapshot.contains("group") + }); + + zellij.send_stdin(&sgr_motion(ALTERNATE_FOCUSED_PANE_COLUMN, HOVER_LINE)); + let after_within_pane_motion = zellij.wait_until( + "a render settles after within-pane motion", + |grid_snapshot| grid_snapshot.status_bar_appears(), + ); + assert!( + !after_within_pane_motion.contains("resize"), + "within-pane motion must not re-show the resize hint:\n{}", + after_within_pane_motion.text + ); + + zellij.send_stdin(&sgr_motion(OTHER_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until( + "group hint shown when crossing into the other pane", + |grid_snapshot| grid_snapshot.contains("group"), + ); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until( + "resize hint shown again when crossing back", + |grid_snapshot| grid_snapshot.contains("resize"), + ); + + zellij.quit(); +} + +#[test] +fn full_frame_help_renders_on_the_pane_not_the_status_bar() { + let mut zellij = full_frame_two_pane_session(120); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + let grid_snapshot = zellij.wait_until("resize help drawn on the pane frame", |grid_snapshot| { + grid_snapshot.contains("to resize") + }); + let status_bar = grid_snapshot.lines().last().cloned().unwrap(); + assert!( + !status_bar.contains("resize"), + "in full-frame mode the resize help belongs on the pane frame, not the status bar:\n{}", + grid_snapshot.text + ); + + zellij.quit(); +} + +#[test] +fn resize_hint_shortens_when_the_status_bar_narrows() { + let mut zellij = two_pane_session(); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until( + "full-width status bar shows the long resize hint", + |grid_snapshot| grid_snapshot.contains("to resize"), + ); + + zellij.resize(Size { cols: 46, rows: 24 }); + zellij.wait_until( + "narrowed status bar shortens the resize hint", + |grid_snapshot| { + grid_snapshot.contains("drag borders") && !grid_snapshot.contains("to resize") + }, + ); + + zellij.quit(); +} + +#[test] +fn resize_hint_absent_with_a_single_pane() { + let (mut zellij, left_terminal, _right_terminal) = two_pane_session_with_handles(); + left_terminal.output(b"LEFT_PANE_MARKER"); + zellij.wait_until("the other pane is populated", |grid_snapshot| { + grid_snapshot.contains("LEFT_PANE_MARKER") + }); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + zellij.wait_until("resize hint shown with two panes", |grid_snapshot| { + grid_snapshot.contains("resize") + }); + + left_terminal.exit(Some(0)); + zellij.wait_until( + "resize hint cleared once a single pane remains", + |grid_snapshot| { + !grid_snapshot.contains("LEFT_PANE_MARKER") + && grid_snapshot.status_bar_appears() + && !grid_snapshot.contains("resize") + }, + ); + + zellij.quit(); +} + +#[test] +fn resize_hint_absent_in_fullscreen() { + let (mut zellij, _left_terminal, _right_terminal) = two_pane_session_with_handles(); + + zellij.send_stdin(&keys::ctrl('p')); + zellij.send_stdin(&keys::key('f')); + zellij.wait_until("focused pane entered fullscreen", |grid_snapshot| { + grid_snapshot.contains("(FULLSCREEN)") && grid_snapshot.contains("LOCK") + }); + + zellij.send_stdin(&sgr_motion(FOCUSED_PANE_COLUMN, HOVER_LINE)); + zellij.send_stdin(&sgr_motion(ALTERNATE_FOCUSED_PANE_COLUMN, HOVER_LINE)); + let grid_snapshot = zellij + .wait_until("fullscreen stays settled after hovering", |grid_snapshot| { + grid_snapshot.contains("(FULLSCREEN)") && grid_snapshot.contains("LOCK") + }); + assert!( + !grid_snapshot.contains("resize"), + "fullscreen must suppress the resize hint:\n{}", + grid_snapshot.text + ); + + zellij.quit(); +} diff --git a/zellij-integration-tests/tests/title_frame_mouse.rs b/zellij-integration-tests/tests/title_frame_mouse.rs new file mode 100644 index 00000000..68467068 --- /dev/null +++ b/zellij-integration-tests/tests/title_frame_mouse.rs @@ -0,0 +1,158 @@ +#![cfg(unix)] + +use insta::assert_snapshot; +use zellij_integration_tests::{normalized, FakePtyHandle, Size, TestRunner, TestSession}; + +const PROMPT: &[u8] = b"$ "; +const STATUS_BAR_TEST_COLS: usize = 190; + +fn start_zellij(cols: usize) -> TestSession { + TestRunner::new(Size { cols, rows: 24 }) + .with_config("mouse_mode true\npane_frame_style \"titles\"") + .start() +} + +fn sgr_left_click(column: usize, line: usize) -> Vec<u8> { + format!( + "\u{1b}[<0;{};{}M\u{1b}[<0;{};{}m", + column, line, column, line + ) + .into_bytes() +} + +fn display_column_of(line: &str, needle: &str) -> Option<usize> { + line.find(needle) + .map(|byte_offset| line[..byte_offset].chars().count()) +} + +fn claim_first_terminal_and_wait_for_prompt(zellij: &TestSession) -> FakePtyHandle { + let terminal = zellij.expect_pty_spawn(); + terminal.output(PROMPT); + zellij.wait_until("first terminal prompt rendered", |grid_snapshot| { + grid_snapshot.tab_bar_appears() + && grid_snapshot.status_bar_appears() + && grid_snapshot.contains("$ ") + }); + terminal +} + +fn click_new_pane_button_in_status_bar(zellij: &TestSession, pane_output: &[u8]) -> FakePtyHandle { + let grid_snapshot = + zellij.wait_until("status bar shows the new pane button", |grid_snapshot| { + grid_snapshot + .lines() + .last() + .is_some_and(|status_bar| status_bar.contains("New Pane")) + }); + let status_bar = grid_snapshot.lines().last().cloned().unwrap(); + let new_pane_column = display_column_of(&status_bar, "New Pane") + .expect("new pane button is on the status bar") + + 1; + let status_bar_line = grid_snapshot.lines().len(); + + zellij.send_stdin(&sgr_left_click(new_pane_column, status_bar_line)); + let new_terminal = zellij.expect_pty_spawn(); + new_terminal.output(pane_output); + new_terminal +} + +#[test] +fn mouse_click_new_pane_in_status_bar_opens_a_new_pane() { + let mut zellij = start_zellij(STATUS_BAR_TEST_COLS); + claim_first_terminal_and_wait_for_prompt(&zellij); + + click_new_pane_button_in_status_bar(&zellij, b"opened from the status bar"); + + let grid_snapshot = zellij.wait_until("the clicked new pane rendered", |grid_snapshot| { + grid_snapshot.contains("opened from the status bar") + && grid_snapshot.contains("Change Focus") + }); + assert_snapshot!(normalized(&grid_snapshot)); + zellij.quit(); +} + +#[test] +fn mouse_click_new_pane_in_status_bar_twice_opens_two_panes() { + let mut zellij = start_zellij(STATUS_BAR_TEST_COLS); + claim_first_terminal_and_wait_for_prompt(&zellij); + + click_new_pane_button_in_status_bar(&zellij, b"first pane from the status bar"); + zellij.wait_until( + "the first clicked pane rendered and the status bar gained the multi-pane controls", + |grid_snapshot| { + grid_snapshot.contains("first pane from the status bar") + && grid_snapshot.contains("Change Focus") + }, + ); + + click_new_pane_button_in_status_bar(&zellij, b"second pane from the status bar"); + + let grid_snapshot = zellij.wait_until( + "the second clicked pane rendered alongside the first", + |grid_snapshot| { + grid_snapshot.contains("first pane from the status bar") + && grid_snapshot.contains("second pane from the status bar") + }, + ); + assert_snapshot!(normalized(&grid_snapshot)); + zellij.quit(); +} + +fn click_floating_ribbon_in_status_bar(zellij: &TestSession) { + let grid_snapshot = + zellij.wait_until("status bar shows the floating ribbon", |grid_snapshot| { + grid_snapshot + .lines() + .last() + .is_some_and(|status_bar| status_bar.contains("Floating")) + }); + let status_bar = grid_snapshot.lines().last().cloned().unwrap(); + let floating_ribbon_column = display_column_of(&status_bar, "Floating") + .expect("floating ribbon is on the status bar") + + 1; + let status_bar_line = grid_snapshot.lines().len(); + + zellij.send_stdin(&sgr_left_click(floating_ribbon_column, status_bar_line)); +} + +#[test] +fn mouse_click_floating_ribbon_in_status_bar_opens_a_floating_pane() { + let mut zellij = start_zellij(STATUS_BAR_TEST_COLS); + claim_first_terminal_and_wait_for_prompt(&zellij); + + click_floating_ribbon_in_status_bar(&zellij); + let floating_terminal = zellij.expect_pty_spawn(); + floating_terminal.output(PROMPT); + + let grid_snapshot = zellij.wait_until("a floating pane appeared", |grid_snapshot| { + grid_snapshot.contains("STAGGERED") && grid_snapshot.contains("┌") + }); + assert_snapshot!(normalized(&grid_snapshot)); + zellij.quit(); +} + +#[test] +fn mouse_click_new_tab_button_in_tab_bar_opens_a_new_tab() { + let mut zellij = start_zellij(120); + claim_first_terminal_and_wait_for_prompt(&zellij); + + let grid_snapshot = zellij.wait_until("tab bar shows the new tab button", |grid_snapshot| { + grid_snapshot + .lines() + .first() + .is_some_and(|tab_bar| tab_bar.contains('+')) + }); + let tab_bar = grid_snapshot.lines().first().cloned().unwrap(); + let new_tab_button_column = + display_column_of(&tab_bar, "+").expect("new tab button is on the tab bar") + 1; + + zellij.send_stdin(&sgr_left_click(new_tab_button_column, 1)); + let new_tab_terminal = zellij.expect_pty_spawn(); + new_tab_terminal.output(PROMPT); + + let grid_snapshot = zellij.wait_until("a second tab opened", |grid_snapshot| { + grid_snapshot.contains("Tab #1") && grid_snapshot.contains("Tab #2") + }); + assert_snapshot!(normalized(&grid_snapshot)); + zellij.quit(); +} diff --git a/zellij-integration-tests/tests/title_frame_scroll.rs b/zellij-integration-tests/tests/title_frame_scroll.rs new file mode 100644 index 00000000..a99e98dd --- /dev/null +++ b/zellij-integration-tests/tests/title_frame_scroll.rs @@ -0,0 +1,58 @@ +#![cfg(unix)] + +use zellij_integration_tests::{ + claim_first_terminal_and_wait_for_prompt, keys, split_right_and_wait_for_prompt, start_zellij, + FakePtyHandle, GridSnapshot, TestSession, +}; + +const LAST_LINE: &str = "line40"; + +fn tab_line_shows_scroll(grid_snapshot: &GridSnapshot) -> bool { + grid_snapshot + .lines() + .first() + .is_some_and(|tab_bar| tab_bar.contains("SCROLL")) +} + +fn fill_pane_past_viewport(zellij: &TestSession) -> FakePtyHandle { + let terminal = claim_first_terminal_and_wait_for_prompt(zellij); + for line in 1..=40 { + terminal.output(format!("line{:02}\r\n", line).as_bytes()); + } + zellij.wait_until("pane filled past its viewport", |grid_snapshot| { + grid_snapshot.contains(LAST_LINE) + }); + terminal +} + +#[test] +fn single_pane_scroll_shows_on_the_tab_line() { + let mut zellij = start_zellij(); + fill_pane_past_viewport(&zellij); + + zellij.send_stdin(&keys::ctrl('s')); + zellij.send_stdin(&keys::ctrl('b')); + + let grid_snapshot = zellij.wait_until( + "scroll indicator appears on the tab line", + |grid_snapshot| tab_line_shows_scroll(grid_snapshot) && !grid_snapshot.contains(LAST_LINE), + ); + assert!( + !grid_snapshot.contains("SCROLL:"), + "the single-pane tab-line indicator uses the colon-free format:\n{}", + grid_snapshot.text + ); + + zellij.send_stdin(&keys::ESC); + zellij.wait_until("back in the base mode after scrolling", |grid_snapshot| { + grid_snapshot.status_bar_appears() + }); + split_right_and_wait_for_prompt(&zellij); + + zellij.wait_until( + "tab-line scroll indicator clears once a second pane exists", + |grid_snapshot| !tab_line_shows_scroll(grid_snapshot), + ); + + zellij.quit(); +} diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index f9fcb649..62f8d651 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -40,6 +40,7 @@ use zellij_utils::envs; use zellij_utils::pane_size::Size; use zellij_utils::input::cli_assets::CliAssets; +use zellij_utils::input::options::PaneFrameStyle; use wasmi::Engine; @@ -402,6 +403,7 @@ impl SessionMetaData { new_config.options.theme_light.as_deref().unwrap_or("?") ); } + let pane_frame_style = PaneFrameStyle::from_options(&new_config.options); self.senders .send_to_screen(ScreenInstruction::Reconfigure { client_id, @@ -417,7 +419,7 @@ impl SessionMetaData { host_theme_light, simplified_ui: new_config.options.simplified_ui.unwrap_or(false), default_shell: new_config.options.default_shell, - pane_frames: new_config.options.pane_frames.unwrap_or(true), + pane_frame_style, copy_command: new_config.options.copy_command, copy_to_clipboard: new_config.options.copy_clipboard, copy_on_select: new_config.options.copy_on_select.unwrap_or(true), diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs index 4093e488..5dbc7fb2 100644 --- a/zellij-server/src/panes/floating_panes/mod.rs +++ b/zellij-server/src/panes/floating_panes/mod.rs @@ -491,6 +491,7 @@ impl FloatingPanes { mouse_hover_pane_id, current_pane_group.clone(), show_help_text, + false, ); for client_id in &connected_clients { let client_mode = self diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs index 477185a4..84c2e970 100644 --- a/zellij-server/src/panes/terminal_pane.rs +++ b/zellij-server/src/panes/terminal_pane.rs @@ -377,10 +377,12 @@ impl Pane for TerminalPane { fn render_frame( &mut self, client_id: ClientId, - frame_params: FrameParams, + mut frame_params: FrameParams, input_mode: InputMode, ) -> Result<Option<(Vec<CharacterChunk>, Option<String>)>> { let err_context = || format!("failed to render frame for client {client_id}"); + frame_params.omit_title = frame_params.omit_title + && !(input_mode == InputMode::RenamePane && frame_params.is_main_client); // TODO: remove the cursor stuff from here let normal_title = if self.pane_name.is_empty() && input_mode == InputMode::RenamePane @@ -902,6 +904,12 @@ impl Pane for TerminalPane { Some(self.pane_name.clone()) } } + fn has_explicit_title(&self) -> bool { + !self.pane_name.is_empty() || self.grid.title.is_some() + } + fn scroll_position(&self) -> (usize, usize) { + self.grid.scrollback_position_and_length() + } fn exit_status(&self) -> Option<i32> { self.is_held .as_ref() diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs index 04ca0a8b..e3f66c37 100644 --- a/zellij-server/src/panes/tiled_panes/mod.rs +++ b/zellij-server/src/panes/tiled_panes/mod.rs @@ -23,6 +23,7 @@ use zellij_utils::{ input::{ command::RunCommand, layout::{Run, RunPluginOrAlias, SplitDirection}, + options::PaneFrameStyle, }, pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport}, }; @@ -66,7 +67,7 @@ pub struct TiledPanes { style: Style, session_is_mirrored: bool, active_panes: ActivePanes, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, panes_to_hide: HashSet<PaneId>, fullscreen_is_active: Option<PaneId>, senders: ThreadSenders, @@ -87,7 +88,7 @@ impl TiledPanes { character_cell_size: Rc<RefCell<Option<SizeInPixels>>>, stacked_resize: Rc<RefCell<bool>>, session_is_mirrored: bool, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, default_mode_info: ModeInfo, style: Style, os_api: Box<dyn ServerOsApi>, @@ -106,7 +107,7 @@ impl TiledPanes { style, session_is_mirrored, active_panes: ActivePanes::new(&os_api), - draw_pane_frames, + pane_frame_style, panes_to_hide: HashSet::new(), fullscreen_is_active: None, senders, @@ -117,7 +118,7 @@ impl TiledPanes { } } pub fn add_pane_with_existing_geom(&mut self, pane_id: PaneId, mut pane: Box<dyn Pane>) { - if self.draw_pane_frames { + if self.pane_frame_style.draws_full_frames() { pane.set_content_offset(Offset::frame(1)); } self.panes.insert(pane_id, pane); @@ -148,7 +149,7 @@ impl TiledPanes { mut with_pane: Box<dyn Pane>, ) -> Option<Box<dyn Pane>> { let with_pane_id = with_pane.pid(); - if self.draw_pane_frames && !with_pane.borderless() { + if self.pane_frame_style.draws_full_frames() && !with_pane.borderless() { with_pane.set_content_offset(Offset::frame(1)); } let removed_pane = self.panes.remove(&pane_id).map(|removed_pane| { @@ -547,14 +548,22 @@ impl TiledPanes { .with_context(|| format!("{:?} relayout of tab failed", direction)) .non_fatal(); - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } pub fn reapply_pane_frames(&mut self) { // same as set_pane_frames except it reapplies the current situation - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } - pub fn set_pane_frames(&mut self, draw_pane_frames: bool) { - self.draw_pane_frames = draw_pane_frames; + pub fn set_pane_frames(&mut self, pane_frame_style: PaneFrameStyle) { + self.pane_frame_style = pane_frame_style; + let draws_full_frames = pane_frame_style.draws_full_frames(); + let draws_titles = pane_frame_style.draws_titles(); + let single_selectable_tiled_pane = self + .panes + .values() + .filter(|p| p.selectable() && !p.borderless()) + .count() + == 1; let viewport = *self.viewport.borrow(); let position_and_sizes_of_stacks = { StackedPanes::new_from_btreemap(&mut self.panes, &self.panes_to_hide) @@ -563,41 +572,35 @@ impl TiledPanes { }; for pane in self.panes.values_mut() { if !pane.borderless() { - pane.set_frame(draw_pane_frames); + pane.set_frame(draws_full_frames); } #[allow(clippy::if_same_then_else)] - if draw_pane_frames && !pane.borderless() { - // there's definitely a frame around this pane, offset its contents + if draws_full_frames && !pane.borderless() { pane.set_content_offset(Offset::frame(1)); - } else if draw_pane_frames && pane.borderless() { - // there's no frame around this pane, and the tab isn't handling the boundaries - // between panes (they each draw their own frames as they please) - // this one doesn't - do not offset its content + } else if draws_full_frames && pane.borderless() { pane.set_content_offset(Offset::default()); } else if !is_inside_viewport(&viewport, pane) { - // this pane is outside the viewport and has no border - it should not have an offset pane.set_content_offset(Offset::default()); } else { - // no draw_pane_frames and this pane should have a separation to other panes - // according to its position in the viewport (eg. no separation if it's at the - // viewport bottom) - offset its content accordingly let mut position_and_size = pane.current_geom(); let is_stacked = position_and_size.is_stacked(); let is_flexible = !position_and_size.rows.is_fixed(); + let pane_is_borderless = pane.borderless(); if let Some(position_and_size_of_stack) = position_and_size .stacked .and_then(|s_id| position_and_sizes_of_stacks.get(&s_id)) { - // we want to check the offset against the position_and_size of the whole - // stack rather than the pane, because the stack needs to have a consistent - // offset with itself position_and_size = *position_and_size_of_stack; }; let (pane_columns_offset, pane_rows_offset) = pane_content_offset(&position_and_size, &viewport); - if is_stacked && is_flexible { - // 1 to save room for the pane title + let reserve_title_row = if draws_titles { + !pane_is_borderless && is_flexible && !single_selectable_tiled_pane + } else { + is_stacked && is_flexible + }; + if reserve_title_row { pane.set_content_offset(Offset::shift_right_top_and_bottom( pane_columns_offset, 1, @@ -1062,6 +1065,12 @@ impl TiledPanes { .with_context(err_context)? }; let selectable_pane_count = self.panes.iter().filter(|(_, p)| p.selectable()).count(); + let content_pane_count = self + .panes + .iter() + .filter(|(_, p)| p.selectable() && !p.borderless()) + .count(); + let omit_pane_title = self.pane_frame_style.draws_titles() && content_pane_count == 1; for (kind, pane) in self.panes.iter_mut() { match kind { PaneId::Terminal(_) => { @@ -1105,7 +1114,7 @@ impl TiledPanes { stacked_pane_ids_on_top_of_stacks.contains(&pane.pid()); let pane_is_on_bottom_of_stack = stacked_pane_ids_on_bottom_of_stacks.contains(&pane.pid()); - let should_draw_pane_frames = self.draw_pane_frames; + let should_draw_pane_frames = self.pane_frame_style.draws_full_frames(); let pane_is_stacked = pane.current_geom().is_stacked(); let pane_is_one_liner_in_stack = pane_is_stacked && pane.current_geom().rows.is_fixed(); @@ -1128,6 +1137,7 @@ impl TiledPanes { &mouse_hover_pane_id, current_pane_group.clone(), show_help_text, + omit_pane_title, ); for client_id in &connected_clients { let client_mode = self @@ -1146,7 +1156,7 @@ impl TiledPanes { } } let is_floating = false; - if self.draw_pane_frames { + if self.pane_frame_style.draws_full_frames() { pane_contents_and_ui .render_pane_frame( *client_id, @@ -1156,9 +1166,7 @@ impl TiledPanes { pane_is_selectable, ) .with_context(err_context)?; - } else if pane_is_stacked { - // if we have no pane frames but the pane is stacked, we need to render its - // frame which will amount to only rendering the title line + } else if self.pane_frame_style.draws_titles() || pane_is_stacked { pane_contents_and_ui .render_pane_frame( *client_id, @@ -1168,7 +1176,6 @@ impl TiledPanes { pane_is_selectable, ) .with_context(err_context)?; - // we also need to render its boundaries as normal let boundaries = client_id_to_boundaries .entry(*client_id) .or_insert_with(|| Boundaries::new(*self.viewport.borrow())); @@ -1255,7 +1262,7 @@ impl TiledPanes { } else { pane.set_content_offset(Offset::frame(1)); } - } else if self.draw_pane_frames { + } else if self.pane_frame_style.draws_full_frames() { pane.set_content_offset(Offset::frame(1)); } }, @@ -1353,7 +1360,7 @@ impl TiledPanes { display_area.rows = rows; display_area.cols = cols; } - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } pub fn resize_active_pane( @@ -2178,7 +2185,7 @@ impl TiledPanes { .unwrap(); current_position.set_should_render(true); self.focus_pane_for_all_clients(active_pane_id); - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } } pub fn move_active_pane(&mut self, search_backwards: bool, client_id: ClientId) { @@ -2244,7 +2251,7 @@ impl TiledPanes { .unwrap(); current_position.set_should_render(true); self.reapply_pane_focus(); - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } pub fn move_active_pane_down(&mut self, client_id: ClientId) { if let Some(active_pane_id) = self.get_active_pane_id(client_id) { @@ -2296,7 +2303,7 @@ impl TiledPanes { .unwrap(); current_position.set_should_render(true); self.reapply_pane_focus(); - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } } pub fn move_active_pane_left(&mut self, client_id: ClientId) { @@ -2347,7 +2354,7 @@ impl TiledPanes { .unwrap(); current_position.set_should_render(true); self.reapply_pane_focus(); - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } } pub fn move_active_pane_right(&mut self, client_id: ClientId) { @@ -2398,7 +2405,7 @@ impl TiledPanes { .unwrap(); current_position.set_should_render(true); self.reapply_pane_focus(); - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } } pub fn move_active_pane_up(&mut self, client_id: ClientId) { @@ -2451,7 +2458,7 @@ impl TiledPanes { .unwrap(); current_position.set_should_render(true); self.reapply_pane_focus(); - self.set_pane_frames(self.draw_pane_frames); + self.set_pane_frames(self.pane_frame_style); } } pub fn move_clients_out_of_pane(&mut self, pane_id: PaneId) { @@ -2522,7 +2529,7 @@ impl TiledPanes { // successfully filled space over pane let closed_pane = self.panes.remove(&pane_id); self.move_clients_out_of_pane(pane_id); - self.set_pane_frames(self.draw_pane_frames); // recalculate pane frames and update size + self.set_pane_frames(self.pane_frame_style); closed_pane } else { let closed_pane = self.panes.remove(&pane_id); diff --git a/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs b/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs index 0c989a9e..985e2c42 100644 --- a/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs +++ b/zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs @@ -2330,13 +2330,15 @@ pub fn split(direction: SplitDirection, rect: &PaneGeom) -> Option<(PaneGeom, Pa SplitDirection::Horizontal => rect.rows, }; if let Some(p) = space.as_percent() { + let mut halved = Dimension::percent(p / 2.0); + halved.set_inner((space.as_usize() / 2).max(1)); let first_rect = match direction { SplitDirection::Vertical => PaneGeom { - cols: Dimension::percent(p / 2.0), + cols: halved, ..*rect }, SplitDirection::Horizontal => PaneGeom { - rows: Dimension::percent(p / 2.0), + rows: halved, ..*rect }, }; diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs index 5cc5835b..e92d7204 100644 --- a/zellij-server/src/plugins/mod.rs +++ b/zellij-server/src/plugins/mod.rs @@ -773,6 +773,11 @@ pub(crate) fn plugin_thread_main( if events.contains(&EventType::InitialKeybinds) { wasm_bridge.send_initial_keybinds_to_plugin(plugin_id, client_id); } + if events.contains(&EventType::HintText) { + let _ = bus + .senders + .send_to_screen(ScreenInstruction::ClearHintTextCache); + } }, PluginInstruction::PermissionRequestResult( plugin_id, diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs index 431d550e..a5dd5f9c 100644 --- a/zellij-server/src/plugins/unit/plugin_tests.rs +++ b/zellij-server/src/plugins/unit/plugin_tests.rs @@ -3351,6 +3351,238 @@ pub fn toggle_pane_embed_or_eject_plugin_command() { #[test] #[ignore] +pub fn new_pane_plugin_command() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, pty_receiver, screen_receiver, teardown) = + create_plugin_thread_with_pty_receiver(Some(plugin_host_folder), None, None); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, + PtyInstruction::SpawnTerminal, + pty_receiver, + 1 + ); + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let _screen_thread = grant_permissions_and_log_actions_in_thread_naked_variant!( + received_screen_instructions, + ScreenInstruction::Exit, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + std::thread::sleep(std::time::Duration::from_millis(500)); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('9'))), + )])); + pty_thread.join().unwrap(); + teardown(); + let new_pane_event = received_pty_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let PtyInstruction::SpawnTerminal(..) = i { + Some(i.clone()) + } else { + None + } + }) + .clone(); + assert_snapshot!(format!("{:#?}", new_pane_event)); +} + +#[test] +#[ignore] +pub fn toggle_floating_panes_plugin_command() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder), None); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = grant_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::ToggleFloatingPanes, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + std::thread::sleep(std::time::Duration::from_millis(500)); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('0'))), + )])); + screen_thread.join().unwrap(); + teardown(); + let toggle_floating_panes_event = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::ToggleFloatingPanes(..) = i { + Some(i.clone()) + } else { + None + } + }) + .clone(); + assert_snapshot!(format!("{:#?}", toggle_floating_panes_event)); +} + +#[test] +#[ignore] +pub fn toggle_floating_panes_with_tab_id_plugin_command() { + let temp_folder = tempdir().unwrap(); + let plugin_host_folder = PathBuf::from(temp_folder.path()); + let cache_path = plugin_host_folder.join("permissions_test.kdl"); + let (plugin_thread_sender, screen_receiver, teardown) = + create_plugin_thread(Some(plugin_host_folder), None); + let plugin_should_float = Some(false); + let plugin_title = Some("test_plugin".to_owned()); + let run_plugin = RunPluginOrAlias::RunPlugin(RunPlugin { + _allow_exec_host_cmd: false, + location: RunPluginLocation::File(PathBuf::from(&*PLUGIN_FIXTURE)), + configuration: Default::default(), + ..Default::default() + }); + let tab_index = 1; + let client_id = 1; + let size = Size { + cols: 121, + rows: 20, + }; + let received_screen_instructions = Arc::new(Mutex::new(vec![])); + let screen_thread = grant_permissions_and_log_actions_in_thread!( + received_screen_instructions, + ScreenInstruction::ToggleFloatingPanesWithTabId, + screen_receiver, + 1, + &PermissionType::ChangeApplicationState, + cache_path, + plugin_thread_sender, + client_id + ); + + let _ = plugin_thread_sender.send(PluginInstruction::AddClient(client_id)); + let _ = plugin_thread_sender.send(PluginInstruction::Load( + plugin_should_float, + false, + false, + plugin_title, + run_plugin, + Some(tab_index), + None, + client_id, + size, + None, + None, + false, + None, + None, + None, + )); + std::thread::sleep(std::time::Duration::from_millis(500)); + let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![( + None, + Some(client_id), + Event::Key(KeyWithModifier::new(BareKey::Char('i')).with_super_modifier()), + )])); + screen_thread.join().unwrap(); + teardown(); + let toggle_floating_panes_event = received_screen_instructions + .lock() + .unwrap() + .iter() + .find_map(|i| { + if let ScreenInstruction::ToggleFloatingPanesWithTabId(..) = i { + Some(i.clone()) + } else { + None + } + }) + .clone(); + assert_snapshot!(format!("{:#?}", toggle_floating_panes_event)); +} + +#[test] +#[ignore] pub fn undo_rename_pane_plugin_command() { let temp_folder = tempdir().unwrap(); // placed explicitly in the test scope because its // destructor removes the directory diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_pane_plugin_command.snap new file mode 100644 index 00000000..9b2efb21 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__new_pane_plugin_command.snap @@ -0,0 +1,29 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", new_pane_event)" +--- +Some( + SpawnTerminal( + None, + None, + NoPreference { + borderless: None, + }, + false, + ClientId( + 1, + ), + Some( + NotificationEnd { + channel: None, + exit_status: None, + unblock_condition: None, + affected_pane_id: None, + affected_tab_id: None, + error_message: None, + stdout_message: None, + }, + ), + false, + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_plugin_command.snap new file mode 100644 index 00000000..fac5fcd5 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_plugin_command.snap @@ -0,0 +1,21 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", toggle_floating_panes_event)" +--- +Some( + ToggleFloatingPanes( + 1, + None, + Some( + NotificationEnd { + channel: None, + exit_status: None, + unblock_condition: None, + affected_pane_id: None, + affected_tab_id: None, + error_message: None, + stdout_message: None, + }, + ), + ), +) diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_with_tab_id_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_with_tab_id_plugin_command.snap new file mode 100644 index 00000000..6668b899 --- /dev/null +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__toggle_floating_panes_with_tab_id_plugin_command.snap @@ -0,0 +1,21 @@ +--- +source: zellij-server/src/plugins/./unit/plugin_tests.rs +expression: "format!(\"{:#?}\", toggle_floating_panes_event)" +--- +Some( + ToggleFloatingPanesWithTabId( + 2, + None, + Some( + NotificationEnd { + channel: None, + exit_status: None, + unblock_condition: None, + affected_pane_id: None, + affected_tab_id: None, + error_message: None, + stdout_message: None, + }, + ), + ), +) diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs index 13e5ff82..4121684b 100644 --- a/zellij-server/src/plugins/wasm_bridge.rs +++ b/zellij-server/src/plugins/wasm_bridge.rs @@ -2170,6 +2170,8 @@ fn check_event_permission( | Event::PluginConfigurationChanged(..) | Event::HighlightClicked { .. } | Event::SoftKeyboardVisibilityChanged(..) + | Event::HintText(..) + | Event::ActivePaneScroll(..) | Event::InputReceived => PermissionType::ReadApplicationState, Event::WebServerStatus(..) => PermissionType::StartWebServer, Event::PaneRenderReport(..) | Event::PaneRenderReportWithAnsi(..) => { diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index c9c3515e..4dd559ed 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -37,8 +37,8 @@ use zellij_utils::data::{ OpenPluginPaneFloatingResponse, OpenTerminalFloatingNearPluginResponse, OpenTerminalFloatingResponse, OpenTerminalInPlaceOfPluginResponse, OpenTerminalInPlaceResponse, OpenTerminalNearPluginResponse, OpenTerminalPaneInPlaceOfPaneIdResponse, OpenTerminalResponse, - OriginatingPlugin, PaneScrollbackResponse, PermissionStatus, PermissionType, PluginPermission, - RegexHighlight, RenameLayoutResponse, SaveLayoutResponse, TabMetadata, + OriginatingPlugin, PaneFrameStyle, PaneScrollbackResponse, PermissionStatus, PermissionType, + PluginPermission, RegexHighlight, RenameLayoutResponse, SaveLayoutResponse, TabMetadata, }; use zellij_utils::home::default_layout_dir; use zellij_utils::input::permission::PermissionCache; @@ -304,6 +304,10 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::NewTiledPaneInTab { tab_position } => { new_tiled_pane_in_tab(env, tab_position) }, + PluginCommand::ToggleFloatingPanes { tab_id } => { + toggle_floating_panes(env, tab_id) + }, + PluginCommand::NewPane => new_pane(env), PluginCommand::GoToNextTab => go_to_next_tab(env), PluginCommand::GoToPreviousTab => go_to_previous_tab(env), PluginCommand::Resize(resize_payload) => resize(env, resize_payload), @@ -334,6 +338,9 @@ fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) { PluginCommand::PageScrollDown => page_scroll_down(env), PluginCommand::ToggleFocusFullscreen => toggle_focus_fullscreen(env), PluginCommand::TogglePaneFrames => toggle_pane_frames(env), + PluginCommand::SetPaneFrameStyle(pane_frame_style) => { + set_pane_frame_style(env, pane_frame_style) + }, PluginCommand::TogglePaneEmbedOrEject => toggle_pane_embed_or_eject(env), PluginCommand::UndoRenamePane => undo_rename_pane(env), PluginCommand::CloseFocus => close_focus(env), @@ -3146,6 +3153,12 @@ fn toggle_pane_frames(env: &PluginEnv) { apply_action!(action, error_msg, env); } +fn set_pane_frame_style(env: &PluginEnv, pane_frame_style: PaneFrameStyle) { + let error_msg = || format!("failed to set pane frame style in plugin {}", env.name()); + let action = Action::SetPaneFrameStyle(pane_frame_style); + apply_action!(action, error_msg, env); +} + fn toggle_pane_embed_or_eject(env: &PluginEnv) { let error_msg = || { format!( @@ -3157,6 +3170,25 @@ fn toggle_pane_embed_or_eject(env: &PluginEnv) { apply_action!(action, error_msg, env); } +fn toggle_floating_panes(env: &PluginEnv, tab_id: Option<u64>) { + let error_msg = || format!("failed to toggle floating panes in plugin {}", env.name()); + let action = match tab_id { + Some(id) => Action::ToggleFloatingPanesByTabId { id }, + None => Action::ToggleFloatingPanes, + }; + apply_action!(action, error_msg, env); +} + +fn new_pane(env: &PluginEnv) { + let error_msg = || format!("failed to open new pane in plugin {}", env.name()); + let action = Action::NewPane { + direction: None, + pane_name: None, + start_suppressed: false, + }; + apply_action!(action, error_msg, env); +} + fn undo_rename_pane(env: &PluginEnv) { let error_msg = || format!("failed to undo rename pane in plugin {}", env.name()); let action = Action::UndoRenamePane; @@ -5494,6 +5526,9 @@ fn check_command_permission( | PluginCommand::ToggleFocusFullscreen | PluginCommand::TogglePaneIdFullscreen(..) | PluginCommand::TogglePaneFrames + | PluginCommand::SetPaneFrameStyle(..) + | PluginCommand::ToggleFloatingPanes { .. } + | PluginCommand::NewPane | PluginCommand::TogglePaneEmbedOrEject | PluginCommand::TogglePaneEmbedOrEjectForPaneId(..) | PluginCommand::UndoRenamePane diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 9b9de0ec..529a93b9 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -596,6 +596,14 @@ pub(crate) fn route_action( ))) .with_context(err_context)?; }, + Action::SetPaneFrameStyle(pane_frame_style) => { + senders + .send_to_screen(ScreenInstruction::SetPaneFrameStyle( + pane_frame_style, + Some(NotificationEnd::new(completion_tx)), + )) + .with_context(err_context)?; + }, Action::NewPane { direction, pane_name, @@ -787,14 +795,15 @@ pub(crate) fn route_action( let run_cmd = run_command .map(|cmd| TerminalAction::RunCommand(cmd.into())) .or_else(|| default_shell.clone()); - let pane_id = match pane_id_to_replace { - Some(pane_id_to_replace) => pane_id_to_replace.try_into().ok(), - None => pane_id, - }; + let explicit_pane_id_to_replace: Option<PaneId> = pane_id_to_replace + .and_then(|pane_id_to_replace| pane_id_to_replace.try_into().ok()); + let pane_id = explicit_pane_id_to_replace.or(pane_id); let client_tab_index_or_paneid = if let Some(tab_id) = tab_id { ClientTabIndexOrPaneId::TabIndex(tab_id) - } else if near_current_pane && pane_id.is_some() { - ClientTabIndexOrPaneId::PaneId(pane_id.unwrap()) + } else if let Some(pane_id) = + pane_id.filter(|_| explicit_pane_id_to_replace.is_some() || near_current_pane) + { + ClientTabIndexOrPaneId::PaneId(pane_id) } else { ClientTabIndexOrPaneId::ClientId(client_id) }; diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index e6bbbf82..b876b0e4 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -51,7 +51,7 @@ use zellij_utils::input::command::RunCommand; use zellij_utils::input::config::Config; use zellij_utils::input::keybinds::Keybinds; use zellij_utils::input::mouse::{MouseEvent, MouseEventType}; -use zellij_utils::input::options::{Clipboard, MobileLayoutConfiguration}; +use zellij_utils::input::options::{Clipboard, MobileLayoutConfiguration, PaneFrameStyle}; use zellij_utils::ipc::{ExitReason, ServerToClientMsg}; use zellij_utils::pane_size::{PaneGeom, Size, SizeInPixels}; use zellij_utils::shared::clean_string_from_control_and_linebreak; @@ -430,6 +430,7 @@ pub enum ScreenInstruction { CloseFocusedPane(ClientId, Option<NotificationEnd>), ToggleActiveTerminalFullscreen(ClientId, Option<NotificationEnd>), TogglePaneFrames(Option<NotificationEnd>), + SetPaneFrameStyle(PaneFrameStyle, Option<NotificationEnd>), SetSelectable(PaneId, bool), ShowPluginCursor(u32, ClientId, Option<(usize, usize)>), ClosePane( @@ -735,7 +736,7 @@ pub enum ScreenInstruction { host_theme_light: Option<Styling>, simplified_ui: bool, default_shell: Option<PathBuf>, - pane_frames: bool, + pane_frame_style: PaneFrameStyle, copy_command: Option<String>, copy_to_clipboard: Option<Clipboard>, copy_on_select: bool, @@ -852,6 +853,7 @@ pub enum ScreenInstruction { DesktopNotificationResponse(Vec<u8>, ClientId), PluginSubscribedToAnsiPaneContents(bool), // true = at least one plugin needs ANSI content UpdateBackgroundPluginSubscriptions(PluginId, ClientId, HashSet<EventType>), + ClearHintTextCache, BroadcastModeUpdate(ModeInfo, Option<ClientId>), // ModeInfo, optional specific client_id (None = all clients) // Pane-targeting CLI variants ScrollUpWithPaneId(PaneId, Option<NotificationEnd>), @@ -985,6 +987,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenContext::ToggleActiveTerminalFullscreen }, ScreenInstruction::TogglePaneFrames(..) => ScreenContext::TogglePaneFrames, + ScreenInstruction::SetPaneFrameStyle(..) => ScreenContext::SetPaneFrameStyle, ScreenInstruction::SetSelectable(..) => ScreenContext::SetSelectable, ScreenInstruction::ShowPluginCursor(..) => ScreenContext::ShowPluginCursor, ScreenInstruction::ClosePane(..) => ScreenContext::ClosePane, @@ -1203,6 +1206,7 @@ impl From<&ScreenInstruction> for ScreenContext { ScreenInstruction::UpdateBackgroundPluginSubscriptions(..) => { ScreenContext::UpdateBackgroundPluginSubscriptions }, + ScreenInstruction::ClearHintTextCache => ScreenContext::ClearHintTextCache, ScreenInstruction::BroadcastModeUpdate(..) => ScreenContext::BroadcastModeUpdate, // Pane-targeting CLI variants ScreenInstruction::ScrollUpWithPaneId(..) => ScreenContext::ScrollUpWithPaneId, @@ -1401,6 +1405,7 @@ pub(crate) struct Screen { max_panes: Option<usize>, /// A map between this [`Screen`]'s tabs and their ID/key. tabs: BTreeMap<usize, Tab>, + last_single_pane_tab_names: HashMap<usize, Option<String>>, /// The full size of this [`Screen`]. size: Size, pixel_dimensions: PixelDimensions, @@ -1419,7 +1424,7 @@ pub(crate) struct Screen { mode_info: BTreeMap<ClientId, ModeInfo>, default_mode_info: ModeInfo, // TODO: restructure ModeInfo to prevent this duplication style: Style, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, auto_layout: bool, session_serialization: bool, serialize_pane_viewport: bool, @@ -1527,7 +1532,7 @@ impl Screen { client_attributes: &ClientAttributes, max_panes: Option<usize>, mode_info: ModeInfo, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, auto_layout: bool, session_is_mirrored: bool, copy_options: CopyOptions, @@ -1575,13 +1580,14 @@ impl Screen { client_sizes: HashMap::new(), global_last_active_tab_id: 0, tabs: BTreeMap::new(), + last_single_pane_tab_names: HashMap::new(), terminal_emulator_colors: Rc::new(RefCell::new(Palette::default())), terminal_emulator_color_codes: Rc::new(RefCell::new(HashMap::new())), tab_history: BTreeMap::new(), pane_history: BTreeMap::new(), mode_info: BTreeMap::new(), default_mode_info: mode_info, - draw_pane_frames, + pane_frame_style, auto_layout, session_is_mirrored, copy_options, @@ -2971,7 +2977,8 @@ impl Screen { } } - if bell_state_changed { + let single_pane_names_changed = self.update_single_pane_tab_names(); + if bell_state_changed || single_pane_names_changed { self.log_and_report_session_state()?; } } else { @@ -3308,7 +3315,7 @@ impl Screen { self.max_panes, self.style, self.default_mode_info.clone(), - self.draw_pane_frames, + self.pane_frame_style, self.auto_layout, self.connected_clients.clone(), self.session_is_mirrored, @@ -3696,7 +3703,9 @@ impl Screen { let selectable_floating_panes_count = tab.get_selectable_floating_panes_count(); let tab_info_for_plugins = TabInfo { position: tab.position, - name: tab.name.clone(), + name: tab + .single_pane_tab_name() + .unwrap_or_else(|| tab.name.clone()), active: *active_tab_index == tab.id, panes_to_hide: tab.panes_to_hide_count(), is_fullscreen_active: tab.is_fullscreen_active(), @@ -3818,6 +3827,19 @@ impl Screen { } } + fn update_single_pane_tab_names(&mut self) -> bool { + let current: HashMap<usize, Option<String>> = self + .tabs + .values() + .map(|tab| (tab.id, tab.single_pane_tab_name())) + .collect(); + if current != self.last_single_pane_tab_names { + self.last_single_pane_tab_names = current; + true + } else { + false + } + } fn log_and_report_session_state(&mut self) -> Result<()> { let err_context = || format!("Failed to log and report session state"); @@ -4997,7 +5019,7 @@ impl Screen { theme: Styling, simplified_ui: bool, default_shell: Option<PathBuf>, - pane_frames: bool, + pane_frame_style: PaneFrameStyle, copy_command: Option<String>, copy_to_clipboard: Option<Clipboard>, copy_on_select: bool, @@ -5014,6 +5036,7 @@ impl Screen { client_id: ClientId, ) -> Result<()> { let should_support_arrow_fonts = !simplified_ui; + self.arrow_fonts = should_support_arrow_fonts; // global configuration self.default_mode_info.update_theme(theme); @@ -5029,7 +5052,7 @@ impl Screen { self.auto_layout = auto_layout; self.copy_options.command = copy_command.clone(); self.copy_options.copy_on_select = copy_on_select; - self.draw_pane_frames = pane_frames; + self.pane_frame_style = pane_frame_style; self.advanced_mouse_actions = advanced_mouse_actions; self.mouse_hover_effects = mouse_hover_effects; self.visual_bell = visual_bell; @@ -5052,7 +5075,7 @@ impl Screen { tab.update_default_editor(self.default_editor.clone()); tab.update_auto_layout(auto_layout); tab.update_copy_options(&self.copy_options); - tab.set_pane_frames(pane_frames); + tab.set_pane_frames(pane_frame_style); tab.update_arrow_fonts(should_support_arrow_fonts); tab.update_advanced_mouse_actions(advanced_mouse_actions); tab.update_mouse_hover_effects(mouse_hover_effects); @@ -6125,7 +6148,7 @@ pub(crate) fn screen_thread_main( let config_options = config.options; let arrow_fonts = !config_options.simplified_ui.unwrap_or_default(); - let draw_pane_frames = config_options.pane_frames.unwrap_or(true); + let pane_frame_style = PaneFrameStyle::from_options(&config_options); let auto_layout = config_options.auto_layout.unwrap_or(true); let session_serialization = config_options.session_serialization.unwrap_or(true); let serialize_pane_viewport = config_options.serialize_pane_viewport.unwrap_or(false); @@ -6194,7 +6217,7 @@ pub(crate) fn screen_thread_main( &config.keybinds, config_options.default_mode, ), - draw_pane_frames, + pane_frame_style, auto_layout, session_is_mirrored, copy_options, @@ -7494,9 +7517,23 @@ pub(crate) fn screen_thread_main( _completion_tx, // the action ends here, dropping this will release anything // waiting for it ) => { - screen.draw_pane_frames = !screen.draw_pane_frames; + screen.pane_frame_style = match screen.pane_frame_style { + PaneFrameStyle::Full => PaneFrameStyle::Titles, + PaneFrameStyle::Titles => PaneFrameStyle::None, + PaneFrameStyle::None => PaneFrameStyle::Full, + }; for tab in screen.tabs.values_mut() { - tab.set_pane_frames(screen.draw_pane_frames); + tab.set_pane_frames(screen.pane_frame_style); + tab.update_input_modes()?; + } + screen.render(None)?; + screen.log_and_report_session_state()?; + }, + ScreenInstruction::SetPaneFrameStyle(pane_frame_style, _completion_tx) => { + screen.pane_frame_style = pane_frame_style; + for tab in screen.tabs.values_mut() { + tab.set_pane_frames(screen.pane_frame_style); + tab.update_input_modes()?; } screen.render(None)?; screen.log_and_report_session_state()?; @@ -9328,7 +9365,7 @@ pub(crate) fn screen_thread_main( host_theme_light, simplified_ui, default_shell, - pane_frames, + pane_frame_style, copy_to_clipboard, copy_command, copy_on_select, @@ -9352,7 +9389,7 @@ pub(crate) fn screen_thread_main( theme, simplified_ui, default_shell, - pane_frames, + pane_frame_style, copy_command, copy_to_clipboard, copy_on_select, @@ -10048,6 +10085,12 @@ pub(crate) fn screen_thread_main( .insert((plugin_id, client_id), subscriptions); } }, + ScreenInstruction::ClearHintTextCache => { + for tab in screen.tabs.values_mut() { + tab.clear_hint_text_cache(); + } + screen.render(None)?; + }, ScreenInstruction::BroadcastModeUpdate(mode_info, target_client_id) => { screen.broadcast_mode_update(mode_info, target_client_id)?; }, diff --git a/zellij-server/src/tab/layout_applier.rs b/zellij-server/src/tab/layout_applier.rs index 21d8c92a..1c3a604d 100644 --- a/zellij-server/src/tab/layout_applier.rs +++ b/zellij-server/src/tab/layout_applier.rs @@ -19,6 +19,7 @@ use std::rc::Rc; use zellij_utils::{ data::{Palette, Style}, input::layout::{FloatingPaneLayout, Run, RunPluginOrAlias, TiledPaneLayout}, + input::options::PaneFrameStyle, pane_size::{PaneGeom, Size, SizeInPixels, Viewport}, }; @@ -35,7 +36,7 @@ pub struct LayoutApplier<'a> { display_area: Rc<RefCell<Size>>, // includes all panes (including eg. the status bar and tab bar in the default layout) tiled_panes: &'a mut TiledPanes, floating_panes: &'a mut FloatingPanes, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, focus_pane_id: &'a mut Option<PaneId>, os_api: Box<dyn ServerOsApi>, debug: bool, @@ -60,7 +61,7 @@ impl<'a> LayoutApplier<'a> { display_area: &Rc<RefCell<Size>>, // includes all panes (including eg. the status bar and tab bar in the default layout) tiled_panes: &'a mut TiledPanes, floating_panes: &'a mut FloatingPanes, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, focus_pane_id: &'a mut Option<PaneId>, os_api: &Box<dyn ServerOsApi>, debug: bool, @@ -94,7 +95,7 @@ impl<'a> LayoutApplier<'a> { display_area, tiled_panes, floating_panes, - draw_pane_frames, + pane_frame_style, focus_pane_id, os_api, debug, @@ -228,7 +229,7 @@ impl<'a> LayoutApplier<'a> { self.viewport.clone(), self.display_area.clone(), self.tiled_panes, - self.draw_pane_frames, + self.pane_frame_style, ); Ok(()) } @@ -321,7 +322,7 @@ impl<'a> LayoutApplier<'a> { self.viewport.clone(), self.display_area.clone(), self.tiled_panes, - self.draw_pane_frames, + self.pane_frame_style, ); Ok(()) } @@ -1033,7 +1034,7 @@ impl<'a> LayoutApplier<'a> { viewport: Rc<RefCell<Viewport>>, display_area: Rc<RefCell<Size>>, tiled_panes: &mut TiledPanes, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, ) { { // reset viewport before reapplying offset @@ -1071,7 +1072,7 @@ impl<'a> LayoutApplier<'a> { } } } - tiled_panes.set_pane_frames(draw_pane_frames); + tiled_panes.set_pane_frames(pane_frame_style); } fn adjust_viewport(&mut self) -> Result<()> { // here we offset the viewport after applying a tiled panes layout @@ -1091,7 +1092,7 @@ impl<'a> LayoutApplier<'a> { self.viewport.clone(), self.display_area.clone(), self.tiled_panes, - self.draw_pane_frames, + self.pane_frame_style, ); Ok(()) } diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 02e7bece..a2601966 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -17,7 +17,7 @@ use uuid::Uuid; use zellij_utils::data::PaneContents; use zellij_utils::data::{ Direction, KeyWithModifier, NewPanePlacement, PaneInfo, PermissionStatus, PermissionType, - PluginPermission, RegexHighlight, ResizeStrategy, Style, WebSharing, + PluginPermission, RegexHighlight, ResizeStrategy, Style, StyledText, WebSharing, }; use zellij_utils::errors::prelude::*; use zellij_utils::input::command::RunCommand; @@ -30,6 +30,9 @@ use crate::background_jobs::BackgroundJob; use crate::pane_groups::PaneGroups; use crate::pty_writer::PtyWriteInstruction; use crate::screen::{CopyOptions, ScreenInstruction}; +use crate::ui::hint_text::{ + held_hint_variants, hover_hint_variants, resize_hint_variants, HintExitStatus, +}; use crate::ui::{loading_indication::LoadingIndication, pane_boundaries_frame::FrameParams}; use layout_applier::LayoutApplier; use swap_layouts::SwapLayouts; @@ -64,6 +67,7 @@ use zellij_utils::{ FloatingPaneLayout, Run, RunPluginOrAlias, SwapFloatingLayout, SwapTiledLayout, TiledPaneLayout, }, + options::PaneFrameStyle, parse_keys, }, pane_size::{Offset, PaneGeom, Size, SizeInPixels, Viewport}, @@ -158,6 +162,7 @@ pub(crate) struct Tab { pub position: usize, pub name: String, pub prev_name: String, + default_name: String, pub size: Size, pub visible_to: Option<HashSet<ClientId>>, tiled_panes: TiledPanes, @@ -176,7 +181,7 @@ pub(crate) struct Tab { default_mode_info: ModeInfo, pub style: Style, connected_clients: Rc<RefCell<HashSet<ClientId>>>, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, auto_layout: bool, pending_vte_events: HashMap<u32, Vec<VteBytes>>, pub selecting_with_mouse_in_pane: Option<PaneId>, // this is only pub for the tests @@ -207,8 +212,12 @@ pub(crate) struct Tab { web_clients_allowed: bool, web_sharing: WebSharing, mouse_hover_pane_id: HashMap<ClientId, PaneId>, + plugin_hover_pane_id: HashMap<ClientId, PaneId>, + mouse_last_pane_id: HashMap<ClientId, PaneId>, mouse_help_text_visible: HashMap<ClientId, bool>, last_mouse_activity_time: HashMap<ClientId, Instant>, + last_hint_text: HashMap<ClientId, BTreeMap<usize, StyledText>>, + last_active_pane_scroll: HashMap<ClientId, Option<(usize, usize)>>, current_pane_group: Rc<RefCell<PaneGroups>>, advanced_mouse_actions: bool, mouse_hover_effects: bool, @@ -620,6 +629,12 @@ pub trait Pane { fn progress_animation_offset(&mut self) {} // only relevant for plugins fn current_title(&self) -> String; fn custom_title(&self) -> Option<String>; + fn has_explicit_title(&self) -> bool { + false + } + fn scroll_position(&self) -> (usize, usize) { + (0, 0) + } fn is_held(&self) -> bool { false } @@ -736,7 +751,7 @@ impl Tab { max_panes: Option<usize>, style: Style, default_mode_info: ModeInfo, - draw_pane_frames: bool, + pane_frame_style: PaneFrameStyle, auto_layout: bool, connected_clients_in_app: Rc<RefCell<HashMap<ClientId, bool>>>, // bool -> is_web_client session_is_mirrored: bool, @@ -764,9 +779,14 @@ impl Tab { web_server_port: u16, mobile_tab_count: usize, ) -> Self { - let name = if name.is_empty() { + let default_name = if name.is_empty() { format!("Tab #{}", (id + 1).saturating_sub(mobile_tab_count)) } else { + String::new() + }; + let name = if name.is_empty() { + default_name.clone() + } else { name }; @@ -790,7 +810,7 @@ impl Tab { character_cell_size.clone(), stacked_resize.clone(), session_is_mirrored, - draw_pane_frames, + pane_frame_style, default_mode_info.clone(), style, os_api.clone(), @@ -824,6 +844,7 @@ impl Tab { suppressed_panes: HashMap::new(), name: name.clone(), prev_name: name, + default_name, size: initial_size, visible_to: None, max_panes, @@ -838,7 +859,7 @@ impl Tab { style, mode_info, default_mode_info, - draw_pane_frames, + pane_frame_style, auto_layout, pending_vte_events: HashMap::new(), connected_clients, @@ -865,8 +886,12 @@ impl Tab { web_clients_allowed, web_sharing, mouse_hover_pane_id: HashMap::new(), + plugin_hover_pane_id: HashMap::new(), + mouse_last_pane_id: HashMap::new(), mouse_help_text_visible: HashMap::new(), last_mouse_activity_time: HashMap::new(), + last_hint_text: HashMap::new(), + last_active_pane_scroll: HashMap::new(), current_pane_group, currently_marking_pane_group, advanced_mouse_actions, @@ -908,7 +933,7 @@ impl Tab { &self.display_area, &mut self.tiled_panes, &mut self.floating_panes, - self.draw_pane_frames, + self.pane_frame_style, &mut self.focus_pane_id, &self.os_api, self.debug, @@ -986,7 +1011,7 @@ impl Tab { &self.display_area, &mut self.tiled_panes, &mut self.floating_panes, - self.draw_pane_frames, + self.pane_frame_style, &mut self.focus_pane_id, &self.os_api, self.debug, @@ -1032,7 +1057,7 @@ impl Tab { self.viewport.clone(), self.display_area.clone(), &mut self.tiled_panes, - self.draw_pane_frames, + self.pane_frame_style, ); self.apply_buffered_instructions().non_fatal(); @@ -1079,7 +1104,7 @@ impl Tab { &self.display_area, &mut self.tiled_panes, &mut self.floating_panes, - self.draw_pane_frames, + self.pane_frame_style, &mut self.focus_pane_id, &self.os_api, self.debug, @@ -1119,7 +1144,7 @@ impl Tab { &self.display_area, &mut self.tiled_panes, &mut self.floating_panes, - self.draw_pane_frames, + self.pane_frame_style, &mut self.focus_pane_id, &self.os_api, self.debug, @@ -1227,6 +1252,7 @@ impl Tab { } else { mode_info.web_server_capability = Some(false); } + mode_info.pane_frame_style = Some(self.pane_frame_style); for plugin_id in &tab_plugin_ids { plugin_updates.push(( Some(*plugin_id), @@ -1242,6 +1268,131 @@ impl Tab { } Ok(()) } + fn resolve_hint_text(&self, client_id: ClientId) -> BTreeMap<usize, StyledText> { + let focused_pane_id = self.get_active_pane_id(client_id); + let hovered_pane_id = self.mouse_hover_pane_id.get(&client_id).copied(); + if let Some(hovered_pane_id) = hovered_pane_id { + if Some(hovered_pane_id) != focused_pane_id { + return hover_hint_variants(); + } + } + if let Some(focused_pane) = self.get_active_pane(client_id) { + if focused_pane.is_held() { + let exited = focused_pane.exited(); + let is_first_run = !exited; + let exit_status = if exited { + Some(match focused_pane.exit_status() { + Some(exit_code) => HintExitStatus::Code(exit_code), + None => HintExitStatus::Exited, + }) + } else { + None + }; + return held_hint_variants(is_first_run, exit_status); + } + } + let resize_help_visible = self + .mouse_help_text_visible + .get(&client_id) + .copied() + .unwrap_or(false); + if resize_help_visible { + let selectable_pane_count = self.get_selectable_tiled_panes().count() + + self.get_selectable_floating_panes().count(); + if selectable_pane_count > 1 && !self.is_fullscreen_active() { + let focused_pane_is_floating = self.floating_panes.panes_are_visible(); + return resize_hint_variants(focused_pane_is_floating); + } + } + BTreeMap::new() + } + pub fn emit_hint_text_if_changed(&mut self) -> Result<()> { + let connected_clients: Vec<ClientId> = + self.connected_clients.borrow().iter().copied().collect(); + let mut plugin_updates = vec![]; + for client_id in connected_clients { + let hint_text = self.resolve_hint_text(client_id); + if self.last_hint_text.get(&client_id) != Some(&hint_text) { + self.last_hint_text.insert(client_id, hint_text.clone()); + plugin_updates.push((None, Some(client_id), Event::HintText(hint_text))); + } + } + if !plugin_updates.is_empty() { + self.senders + .send_to_plugin(PluginInstruction::Update(plugin_updates)) + .with_context(|| format!("failed to update plugins with hint text"))?; + } + Ok(()) + } + pub fn clear_hint_text_cache(&mut self) { + self.last_hint_text.clear(); + } + fn get_selectable_tiled_content_panes( + &self, + ) -> impl Iterator<Item = (&PaneId, &Box<dyn Pane>)> { + self.get_selectable_tiled_panes() + .filter(|(_, p)| !p.borderless()) + } + pub fn single_pane_titles(&self) -> bool { + self.pane_frame_style.draws_titles() + && self.get_selectable_tiled_content_panes().count() == 1 + } + fn tab_name_is_default(&self) -> bool { + !self.name.is_empty() && self.name == self.default_name + } + pub fn single_pane_tab_name(&self) -> Option<String> { + if !self.single_pane_titles() { + return None; + } + let (_, pane) = self.get_selectable_tiled_content_panes().next()?; + let mut base = if self.tab_name_is_default() && pane.has_explicit_title() { + pane.current_title() + } else { + self.name.clone() + }; + if pane.is_held() && pane.exited() { + match pane.exit_status() { + Some(exit_code) => base.push_str(&format!(" [ EXIT CODE: {} ] ", exit_code)), + None => base.push_str(" [ EXITED ] "), + } + } + Some(base) + } + fn resolve_active_pane_scroll(&self, _client_id: ClientId) -> Option<(usize, usize)> { + if !self.single_pane_titles() { + return None; + } + let (_, pane) = self.get_selectable_tiled_content_panes().next()?; + let (position, length) = pane.scroll_position(); + if position > 0 || length > 0 { + Some((position, length)) + } else { + None + } + } + pub fn emit_active_pane_scroll_if_changed(&mut self) -> Result<()> { + let connected_clients: Vec<ClientId> = + self.connected_clients.borrow().iter().copied().collect(); + let mut plugin_updates = vec![]; + for client_id in connected_clients { + let active_pane_scroll = self.resolve_active_pane_scroll(client_id); + if self.last_active_pane_scroll.get(&client_id) != Some(&active_pane_scroll) { + self.last_active_pane_scroll + .insert(client_id, active_pane_scroll); + plugin_updates.push(( + None, + Some(client_id), + Event::ActivePaneScroll(active_pane_scroll), + )); + } + } + if !plugin_updates.is_empty() { + self.senders + .send_to_plugin(PluginInstruction::Update(plugin_updates)) + .with_context(|| format!("failed to update plugins with active pane scroll"))?; + } + Ok(()) + } pub fn add_client(&mut self, client_id: ClientId, mode_info: Option<ModeInfo>) -> Result<()> { let other_clients_exist_in_tab = { !self.connected_clients.borrow().is_empty() }; if other_clients_exist_in_tab { @@ -1314,6 +1465,7 @@ impl Tab { .map(|c| c.change_to_default_mode()); // TODO: no races? self.connected_clients.borrow_mut().remove(&client_id); self.mouse_help_text_visible.remove(&client_id); + self.mouse_last_pane_id.remove(&client_id); self.last_mouse_activity_time.remove(&client_id); self.set_force_render(); } @@ -3404,6 +3556,10 @@ impl Tab { self.hide_cursor_and_clear_display_as_needed(output); } + self.emit_hint_text_if_changed().with_context(err_context)?; + self.emit_active_pane_scroll_if_changed() + .with_context(err_context)?; + Ok(()) } @@ -3605,7 +3761,7 @@ impl Tab { self.viewport.clone(), self.display_area.clone(), &mut self.tiled_panes, - self.draw_pane_frames, + self.pane_frame_style, ); if let Some(pane_id) = fullscreen_pane_to_restore { if self.tiled_panes.panes_contain(&pane_id) { @@ -4058,7 +4214,7 @@ impl Tab { self.viewport.clone(), self.display_area.clone(), &mut self.tiled_panes, - self.draw_pane_frames, + self.pane_frame_style, ); } pub fn set_mouse_selection_support(&mut self, pane_id: PaneId, selection_support: bool) { @@ -4799,25 +4955,26 @@ impl Tab { let is_flexible_in_stack = p.current_geom().is_stacked() && !p.current_geom().rows.is_fixed(); let is_stacked_under = stacked_pane_ids_under_flexible_pane.contains(&p.pid()); - let geom_to_compare_against = if is_stacked_under && !self.draw_pane_frames { - // these sort of panes are one-liner panes under a flexible pane in a stack when we - // don't draw pane frames - because the whole stack's content is offset to allow - // room for the boundary between panes, they are actually drawn 1 line above where - // they are - let mut geom = p.current_geom(); - geom.y = geom.y.saturating_sub(p.get_content_offset().bottom); - geom - } else if is_flexible_in_stack && !self.draw_pane_frames { - // these sorts of panes are flexible panes inside a stack when we don't draw pane - // frames - because the whole stack's content is offset to give room for the - // boundary between panes, we need to take this offset into account when figuring - // out whether the position is inside them - let mut geom = p.current_geom(); - geom.rows.decrease_inner(p.get_content_offset().bottom); - geom - } else { - p.current_geom() - }; + let geom_to_compare_against = + if is_stacked_under && !self.pane_frame_style.draws_full_frames() { + // these sort of panes are one-liner panes under a flexible pane in a stack when we + // don't draw pane frames - because the whole stack's content is offset to allow + // room for the boundary between panes, they are actually drawn 1 line above where + // they are + let mut geom = p.current_geom(); + geom.y = geom.y.saturating_sub(p.get_content_offset().bottom); + geom + } else if is_flexible_in_stack && !self.pane_frame_style.draws_full_frames() { + // these sorts of panes are flexible panes inside a stack when we don't draw pane + // frames - because the whole stack's content is offset to give room for the + // boundary between panes, we need to take this offset into account when figuring + // out whether the position is inside them + let mut geom = p.current_geom(); + geom.rows.decrease_inner(p.get_content_offset().bottom); + geom + } else { + p.current_geom() + }; geom_to_compare_against.contains(point) }; @@ -4975,6 +5132,7 @@ impl Tab { .with_context(|| format!("failed to set visibility of tab to {visible}"))?; if !visible { self.mouse_hover_pane_id.clear(); + self.plugin_hover_pane_id.clear(); } Ok(()) } @@ -5064,9 +5222,9 @@ impl Tab { && column < viewport.x + viewport.cols) } - pub fn set_pane_frames(&mut self, should_set_pane_frames: bool) { - self.tiled_panes.set_pane_frames(should_set_pane_frames); - self.draw_pane_frames = should_set_pane_frames; + pub fn set_pane_frames(&mut self, pane_frame_style: PaneFrameStyle) { + self.tiled_panes.set_pane_frames(pane_frame_style); + self.pane_frame_style = pane_frame_style; self.set_should_clear_display_before_rendering(); self.set_force_render(); } @@ -5847,6 +6005,8 @@ impl Tab { } pub fn clear_mouse_hover_state(&mut self) { self.mouse_hover_pane_id.clear(); + self.plugin_hover_pane_id.clear(); + self.mouse_last_pane_id.clear(); self.mouse_help_text_visible.clear(); } pub fn update_web_sharing(&mut self, web_sharing: WebSharing) { diff --git a/zellij-server/src/tab/mouse_handler.rs b/zellij-server/src/tab/mouse_handler.rs index 0397a7f4..61718864 100644 --- a/zellij-server/src/tab/mouse_handler.rs +++ b/zellij-server/src/tab/mouse_handler.rs @@ -13,14 +13,23 @@ use crate::ClientId; use super::{Pane, Tab}; fn clear_hover_for_client(tab: &mut Tab, client_id: ClientId) -> bool { + let mut cleared = false; if let Some(prev_pid) = tab.mouse_hover_pane_id.remove(&client_id) { if let Some(pane) = tab.get_pane_with_id_mut(prev_pid) { pane.set_hover_position(None); } - true - } else { - false + cleared = true; } + if let Some(prev_plugin_pid) = tab.plugin_hover_pane_id.remove(&client_id) { + if let Some(pane) = tab.get_pane_with_id(prev_plugin_pid) { + let _ = pane.mouse_event( + &MouseEvent::new_buttonless_motion(Position::new(0, u16::MAX)), + client_id, + ); + } + cleared = true; + } + cleared } #[derive(Debug, Default, Copy, Clone)] @@ -1059,11 +1068,46 @@ impl MouseHandler { fn execute_update_hover( tab: &mut Tab, pane_id: Option<PaneId>, - _position: Option<Position>, + position: Option<Position>, client_id: ClientId, ) -> Result<MouseEffect> { let mut should_render = false; let previous_hover_pane_id = tab.mouse_hover_pane_id.get(&client_id).copied(); + + if tab.mouse_hover_effects { + let previous_plugin_hover_pane_id = tab.plugin_hover_pane_id.get(&client_id).copied(); + let current_plugin_hover_pane_id = match pane_id { + Some(pid) if matches!(pid, PaneId::Plugin(_)) => Some(pid), + _ => None, + }; + if let (Some(pid), Some(position)) = (current_plugin_hover_pane_id, position) { + if let Some(pane) = tab.get_pane_with_id(pid) { + let relative_position = pane.relative_position(&position); + let _ = pane.mouse_event( + &MouseEvent::new_buttonless_motion(relative_position), + client_id, + ); + } + } + if previous_plugin_hover_pane_id != current_plugin_hover_pane_id { + if let Some(previous_pid) = previous_plugin_hover_pane_id { + if let Some(pane) = tab.get_pane_with_id(previous_pid) { + let _ = pane.mouse_event( + &MouseEvent::new_buttonless_motion(Position::new(0, u16::MAX)), + client_id, + ); + } + } + match current_plugin_hover_pane_id { + Some(pid) => { + tab.plugin_hover_pane_id.insert(client_id, pid); + }, + None => { + tab.plugin_hover_pane_id.remove(&client_id); + }, + } + } + } match pane_id { Some(pid) => { if let Some(pane) = tab.get_pane_with_id(pid) { @@ -1073,10 +1117,12 @@ impl MouseHandler { } else if tab.advanced_mouse_actions || !tab.mouse_hover_effects { tab.mouse_hover_pane_id.remove(&client_id); } + tab.mouse_last_pane_id.insert(client_id, pid); should_render = true; } }, None => { + tab.mouse_last_pane_id.remove(&client_id); let removed = tab.mouse_hover_pane_id.remove(&client_id); if removed.is_some() { should_render = true; @@ -1146,19 +1192,23 @@ impl MouseHandler { if event.event_type == MouseEventType::Motion && tab.mouse_hover_effects { tab.last_mouse_activity_time .insert(client_id, Instant::now()); - let was_visible = tab - .mouse_help_text_visible - .get(&client_id) - .copied() - .unwrap_or(false); - tab.mouse_help_text_visible.insert(client_id, true); - if !was_visible { - should_render = true; - } + let entered_pane = tab.mouse_last_pane_id.get(&client_id) != Some(&pane_id); + tab.mouse_last_pane_id.insert(client_id, pane_id); + if entered_pane { + let was_visible = tab + .mouse_help_text_visible + .get(&client_id) + .copied() + .unwrap_or(false); + tab.mouse_help_text_visible.insert(client_id, true); + if !was_visible { + should_render = true; + } - tab.senders - .send_to_background_jobs(BackgroundJob::ClearHelpText { client_id }) - .with_context(err_context)?; + tab.senders + .send_to_background_jobs(BackgroundJob::ClearHelpText { client_id }) + .with_context(err_context)?; + } } } let mouse_effect = if should_render { diff --git a/zellij-server/src/tab/unit/layout_applier_tests.rs b/zellij-server/src/tab/unit/layout_applier_tests.rs index 2d6fd949..33ad8ee4 100644 --- a/zellij-server/src/tab/unit/layout_applier_tests.rs +++ b/zellij-server/src/tab/unit/layout_applier_tests.rs @@ -12,6 +12,7 @@ use std::collections::{HashMap, HashSet}; use std::fmt::Write; use std::path::PathBuf; use std::rc::Rc; +use zellij_utils::input::options::PaneFrameStyle; use interprocess::local_socket::Stream as LocalSocketStream; use zellij_utils::{ @@ -147,7 +148,7 @@ fn create_layout_applier_fixtures( Rc<RefCell<Size>>, TiledPanes, FloatingPanes, - bool, + PaneFrameStyle, Option<PaneId>, Box<dyn ServerOsApi>, bool, @@ -187,7 +188,7 @@ fn create_layout_applier_fixtures( let mode_info = Rc::new(RefCell::new(HashMap::new())); let stacked_resize = Rc::new(RefCell::new(false)); let session_is_mirrored = true; - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let default_mode_info = ModeInfo::default(); let tiled_panes = TiledPanes::new( @@ -269,7 +270,7 @@ fn create_layout_applier_fixtures_with_receivers( Rc<RefCell<Size>>, TiledPanes, FloatingPanes, - bool, + PaneFrameStyle, Option<PaneId>, Box<dyn ServerOsApi>, bool, @@ -317,7 +318,7 @@ fn create_layout_applier_fixtures_with_receivers( let mode_info = Rc::new(RefCell::new(HashMap::new())); let stacked_resize = Rc::new(RefCell::new(false)); let session_is_mirrored = true; - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let default_mode_info = ModeInfo::default(); let tiled_panes = TiledPanes::new( diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap index 8ce91b92..3e3b3084 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__render_stacks_without_pane_frames.snap @@ -1,11 +1,10 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 1134 expression: snapshot --- -00 (C): ─ Pane #1 ────────────────────────────────────────────┼─ Pane #7 ─────────────────────────────────── -01 (C): ─ Pane #9 ────────────────────────────────────────────┤ -02 (C): ─ Pane #10 ───────────────────────────────────────────┤ +00 (C): ─────────────────────── Pane #1 ──────────────────────┼────────────────── Pane #7 ────────────────── +01 (C): ─────────────────────── Pane #9 ──────────────────────┤ +02 (C): ────────────────────── Pane #10 ──────────────────────┤ 03 (C): │ 04 (C): │ 05 (C): │ @@ -21,10 +20,10 @@ expression: snapshot 15 (C): │ 16 (C): │ 17 (C): │ -18 (C): ├─ Pane #8 ─────────────────────────────────── +18 (C): ├────────────────── Pane #8 ────────────────── 19 (C): ─────────────────────────────────────────────────┬────┴───────────────────────────────────────────── -20 (C): ─ Pane #2 ───────────────────────────────────────┼─ Pane #4 ──────────────────────────────────────── -21 (C): ─ Pane #3 ───────────────────────────────────────┼─ Pane #5 ──────────────────────────────────────── +20 (C): ───────────────────── Pane #2 ───────────────────┼───────────────────── Pane #4 ──────────────────── +21 (C): ───────────────────── Pane #3 ───────────────────┼───────────────────── Pane #5 ──────────────────── 22 (C): │ 23 (C): │ 24 (C): │ @@ -42,5 +41,4 @@ expression: snapshot 36 (C): │ 37 (C): │ 38 (C): │ -39 (C): ├─ Pane #6 ──────────────────────────────────────── - +39 (C): ├───────────────────── Pane #6 ──────────────────── diff --git a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap index ee77150c..a9bf60ab 100644 --- a/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap +++ b/zellij-server/src/tab/unit/snapshots/zellij_server__tab__tab_integration_tests__swap_tiled_layout_with_stacked_children_and_no_pane_frames.snap @@ -1,11 +1,10 @@ --- source: zellij-server/src/tab/./unit/tab_integration_tests.rs -assertion_line: 3249 expression: snapshot --- -00 (C): ├─ Pane #2 ────────────────────────────────────────────────── -01 (C): ├─ Pane #3 ────────────────────────────────────────────────── -02 (C): ├─ Pane #4 ────────────────────────────────────────────────── +00 (C): ├────────────────────────── Pane #2 ───────────────────────── +01 (C): ├────────────────────────── Pane #3 ───────────────────────── +02 (C): ├────────────────────────── Pane #4 ───────────────────────── 03 (C): │ 04 (C): │ 05 (C): │ @@ -22,5 +21,4 @@ expression: snapshot 16 (C): │ 17 (C): │ 18 (C): │ -19 (C): │ - +19 (C): │ diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs index c9a7508c..5b623b00 100644 --- a/zellij-server/src/tab/unit/tab_integration_tests.rs +++ b/zellij-server/src/tab/unit/tab_integration_tests.rs @@ -2,6 +2,7 @@ use super::{Output, Tab}; use crate::panes::sixel::SixelImageStore; use crate::screen::CopyOptions; use crate::Arc; +use zellij_utils::input::options::PaneFrameStyle; use crate::{ os_input_output::ServerOsApi, pane_groups::PaneGroups, panes::PaneId, @@ -214,7 +215,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab { let max_panes = None; let mode_info = default_mode; let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -302,7 +303,7 @@ fn create_new_tab_without_pane_frames(size: Size, default_mode: ModeInfo) -> Tab let max_panes = None; let mode_info = default_mode; let style = Style::default(); - let draw_pane_frames = false; + let draw_pane_frames = PaneFrameStyle::None; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -442,7 +443,11 @@ fn create_new_tab_with_swap_layouts( max_panes, style, mode_info, - draw_pane_frames, + if draw_pane_frames { + PaneFrameStyle::Full + } else { + PaneFrameStyle::None + }, auto_layout, connected_clients, session_is_mirrored, @@ -509,7 +514,7 @@ fn create_new_tab_with_os_api( let max_panes = None; let mode_info = default_mode; let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -597,7 +602,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str) let max_panes = None; let mode_info = default_mode; let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -703,7 +708,7 @@ fn create_new_tab_with_mock_pty_writer( let max_panes = None; let mode_info = default_mode; let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -796,7 +801,7 @@ fn create_new_tab_with_sixel_support( let max_panes = None; let mode_info = ModeInfo::default(); let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -3253,7 +3258,7 @@ fn embed_floating_pane_without_pane_frames() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.set_pane_frames(false); + tab.set_pane_frames(PaneFrameStyle::None); tab.toggle_floating_panes(Some(client_id), None, None) .unwrap(); tab.new_pane( @@ -3293,7 +3298,7 @@ fn float_embedded_pane_without_pane_frames() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.set_pane_frames(false); + tab.set_pane_frames(PaneFrameStyle::None); tab.new_pane( new_pane_id, None, @@ -12691,7 +12696,7 @@ fn create_new_tab_with_plugin_receiver( let max_panes = None; let mode_info = default_mode; let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -14513,7 +14518,7 @@ fn create_new_tab_with_server_receiver( max_panes, Style::default(), default_mode, - true, // draw_pane_frames + PaneFrameStyle::Full, true, // auto_layout connected_clients, true, // session_is_mirrored diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs index 4651c0a6..0d18897e 100644 --- a/zellij-server/src/tab/unit/tab_tests.rs +++ b/zellij-server/src/tab/unit/tab_tests.rs @@ -10,6 +10,7 @@ use zellij_utils::channels::{unbounded, Receiver, SenderWithContext}; use zellij_utils::data::{Direction, NewPanePlacement, Resize, ResizeStrategy, WebSharing}; use zellij_utils::errors::prelude::*; use zellij_utils::input::layout::{SplitDirection, SplitSize, TiledPaneLayout}; +use zellij_utils::input::options::PaneFrameStyle; use zellij_utils::ipc::IpcReceiverWithContext; use zellij_utils::pane_size::{Size, SizeInPixels}; @@ -156,7 +157,7 @@ fn create_new_tab(size: Size, stacked_resize: bool) -> Tab { let max_panes = None; let mode_info = ModeInfo::default(); let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -243,7 +244,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab { let max_panes = None; let mode_info = ModeInfo::default(); let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -337,7 +338,7 @@ fn create_new_tab_with_cell_size( let max_panes = None; let mode_info = ModeInfo::default(); let style = Style::default(); - let draw_pane_frames = true; + let draw_pane_frames = PaneFrameStyle::Full; let auto_layout = true; let client_id = 1; let session_is_mirrored = true; @@ -15464,7 +15465,7 @@ fn correctly_resize_frameless_panes_on_pane_close() { let size = Size { cols, rows }; let stacked_resize = true; let mut tab = create_new_tab(size, stacked_resize); - tab.set_pane_frames(false); + tab.set_pane_frames(PaneFrameStyle::None); // a single frameless pane should take up all available space let pane = tab.tiled_panes.panes.get(&PaneId::Terminal(1)).unwrap(); diff --git a/zellij-server/src/ui/hint_text.rs b/zellij-server/src/ui/hint_text.rs new file mode 100644 index 00000000..84a8406d --- /dev/null +++ b/zellij-server/src/ui/hint_text.rs @@ -0,0 +1,303 @@ +use std::collections::BTreeMap; +use unicode_width::UnicodeWidthStr; +use zellij_utils::data::StyledText; + +pub enum HintLevel { + Plain, + Emphasis, + Emphasis2, + Error, + Success, +} + +pub struct HintSegment { + pub text: String, + pub level: HintLevel, +} + +impl HintSegment { + fn plain(text: &str) -> Self { + HintSegment { + text: text.to_string(), + level: HintLevel::Plain, + } + } + fn emphasis(text: &str) -> Self { + HintSegment { + text: text.to_string(), + level: HintLevel::Emphasis, + } + } + fn emphasis_2(text: &str) -> Self { + HintSegment { + text: text.to_string(), + level: HintLevel::Emphasis2, + } + } + fn error(text: &str) -> Self { + HintSegment { + text: text.to_string(), + level: HintLevel::Error, + } + } + fn success(text: &str) -> Self { + HintSegment { + text: text.to_string(), + level: HintLevel::Success, + } + } +} + +#[derive(Copy, Clone)] +pub enum HintExitStatus { + Code(i32), + Exited, +} + +#[derive(Copy, Clone)] +pub enum HintTier { + Full, + Medium, + Minimal, +} + +const ALL_TIERS: [HintTier; 3] = [HintTier::Full, HintTier::Medium, HintTier::Minimal]; + +fn level_index(level: &HintLevel) -> Option<usize> { + match level { + HintLevel::Plain => None, + HintLevel::Emphasis => Some(0), + HintLevel::Emphasis2 => Some(2), + HintLevel::Error => Some(6), + HintLevel::Success => Some(7), + } +} + +pub fn segments_to_styled_text(segments: &[HintSegment]) -> StyledText { + let mut text = String::new(); + let mut indices: Vec<Vec<usize>> = vec![]; + let mut offset = 0; + for segment in segments { + let char_count = segment.text.chars().count(); + if let Some(level) = level_index(&segment.level) { + if indices.len() <= level { + indices.resize(level + 1, vec![]); + } + for position in offset..offset + char_count { + indices[level].push(position); + } + } + text.push_str(&segment.text); + offset += char_count; + } + StyledText { text, indices } +} + +pub fn rerun_segments(is_first_run: bool, tier: HintTier) -> Vec<HintSegment> { + match tier { + HintTier::Full => vec![ + HintSegment::plain(if is_first_run { " <" } else { "<" }), + HintSegment::emphasis("ENTER"), + HintSegment::plain(">"), + HintSegment::plain(if is_first_run { " run, " } else { " re-run, " }), + HintSegment::plain("<"), + HintSegment::emphasis("ESC"), + HintSegment::plain(">"), + HintSegment::plain(" drop to shell, "), + HintSegment::plain("<"), + HintSegment::emphasis("Ctrl-c"), + HintSegment::plain(">"), + HintSegment::plain(" exit "), + ], + HintTier::Medium => vec![ + HintSegment::plain("<"), + HintSegment::emphasis("ENTER"), + HintSegment::plain(">"), + HintSegment::plain(if is_first_run { " run " } else { " re-run " }), + HintSegment::plain("<"), + HintSegment::emphasis("ESC"), + HintSegment::plain(">"), + HintSegment::plain(" shell "), + HintSegment::plain("<"), + HintSegment::emphasis("Ctrl-c"), + HintSegment::plain(">"), + HintSegment::plain(" exit"), + ], + HintTier::Minimal => vec![ + HintSegment::plain("<"), + HintSegment::emphasis("ENTER"), + HintSegment::plain(">"), + HintSegment::plain(if is_first_run { " run" } else { " re-run" }), + ], + } +} + +pub fn exit_code_segments(exit_status: HintExitStatus) -> Vec<HintSegment> { + match exit_status { + HintExitStatus::Code(exit_code) => { + let exit_code_text = format!("{}", exit_code); + let exit_code_segment = if exit_code == 0 { + HintSegment::success(&exit_code_text) + } else { + HintSegment::error(&exit_code_text) + }; + vec![ + HintSegment::plain(" [ "), + HintSegment::plain("EXIT CODE: "), + exit_code_segment, + HintSegment::plain(" ] "), + ] + }, + HintExitStatus::Exited => vec![ + HintSegment::plain(" [ "), + HintSegment::error("EXITED"), + HintSegment::plain(" ] "), + ], + } +} + +pub fn hover_segments(tier: HintTier) -> Vec<HintSegment> { + match tier { + HintTier::Full => vec![ + HintSegment::plain(" "), + HintSegment::emphasis("Alt"), + HintSegment::plain(" <"), + HintSegment::emphasis("Click"), + HintSegment::plain(">"), + HintSegment::plain(" - group,"), + HintSegment::plain(" "), + HintSegment::emphasis("Alt"), + HintSegment::plain(" <"), + HintSegment::emphasis("Right-Click"), + HintSegment::plain(">"), + HintSegment::plain(" - ungroup all "), + ], + HintTier::Medium => vec![ + HintSegment::emphasis("Alt"), + HintSegment::plain(" <"), + HintSegment::emphasis("Click"), + HintSegment::plain("> group, "), + HintSegment::emphasis("Alt"), + HintSegment::plain(" <"), + HintSegment::emphasis("Right-Click"), + HintSegment::plain("> ungroup"), + ], + HintTier::Minimal => vec![ + HintSegment::emphasis("Alt"), + HintSegment::plain(" <"), + HintSegment::emphasis("Click"), + HintSegment::plain("> group"), + ], + } +} + +pub fn hover_hint_variants() -> BTreeMap<usize, StyledText> { + let mut variants = BTreeMap::new(); + for tier in ALL_TIERS { + let styled_text = segments_to_styled_text(&hover_segments(tier)); + variants.insert(styled_text.text.width(), styled_text); + } + variants +} + +pub fn resize_segments(is_floating: bool, tier: HintTier) -> Vec<HintSegment> { + match tier { + HintTier::Full => { + if is_floating { + vec![ + HintSegment::plain(" "), + HintSegment::emphasis_2("Ctrl"), + HintSegment::plain(" <"), + HintSegment::emphasis_2("MouseScroll"), + HintSegment::plain("> or "), + HintSegment::emphasis_2("Ctrl"), + HintSegment::plain(" <"), + HintSegment::emphasis_2("drag borders"), + HintSegment::plain("> to resize "), + ] + } else { + vec![ + HintSegment::plain(" "), + HintSegment::emphasis_2("Ctrl"), + HintSegment::plain(" <"), + HintSegment::emphasis_2("MouseScroll"), + HintSegment::plain("> or <"), + HintSegment::emphasis_2("drag borders"), + HintSegment::plain("> to resize "), + ] + } + }, + HintTier::Medium => { + if is_floating { + vec![ + HintSegment::plain(" <"), + HintSegment::emphasis_2("Ctrl"), + HintSegment::plain(" "), + HintSegment::emphasis_2("MouseScroll"), + HintSegment::plain("/"), + HintSegment::emphasis_2("drag borders"), + HintSegment::plain("> resize "), + ] + } else { + vec![ + HintSegment::plain(" <"), + HintSegment::emphasis_2("Ctrl"), + HintSegment::plain(" "), + HintSegment::emphasis_2("MouseScroll"), + HintSegment::plain(">/<"), + HintSegment::emphasis_2("drag borders"), + HintSegment::plain("> resize "), + ] + } + }, + HintTier::Minimal => { + if is_floating { + vec![ + HintSegment::plain(" <"), + HintSegment::emphasis_2("Ctrl"), + HintSegment::plain(" "), + HintSegment::emphasis_2("MouseScroll"), + HintSegment::plain("/"), + HintSegment::emphasis_2("drag borders"), + HintSegment::plain("> "), + ] + } else { + vec![ + HintSegment::plain(" <"), + HintSegment::emphasis_2("Ctrl"), + HintSegment::plain(" "), + HintSegment::emphasis_2("MouseScroll"), + HintSegment::plain(">/<"), + HintSegment::emphasis_2("drag borders"), + HintSegment::plain("> "), + ] + } + }, + } +} + +pub fn resize_hint_variants(is_floating: bool) -> BTreeMap<usize, StyledText> { + let mut variants = BTreeMap::new(); + for tier in ALL_TIERS { + let styled_text = segments_to_styled_text(&resize_segments(is_floating, tier)); + variants.insert(styled_text.text.width(), styled_text); + } + variants +} + +pub fn held_hint_variants( + is_first_run: bool, + exit_status: Option<HintExitStatus>, +) -> BTreeMap<usize, StyledText> { + let mut variants = BTreeMap::new(); + for tier in ALL_TIERS { + let mut segments = vec![]; + if let Some(exit_status) = exit_status { + segments.extend(exit_code_segments(exit_status)); + } + segments.extend(rerun_segments(is_first_run, tier)); + let styled_text = segments_to_styled_text(&segments); + variants.insert(styled_text.text.width(), styled_text); + } + variants +} diff --git a/zellij-server/src/ui/mod.rs b/zellij-server/src/ui/mod.rs index 1a17e743..1d3ba1f6 100644 --- a/zellij-server/src/ui/mod.rs +++ b/zellij-server/src/ui/mod.rs @@ -1,5 +1,6 @@ pub mod boundaries; pub mod components; +pub mod hint_text; pub mod loading_indication; pub mod pane_boundaries_frame; pub mod pane_contents_and_ui; diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs index a464e4b0..d7abdfd1 100644 --- a/zellij-server/src/ui/pane_boundaries_frame.rs +++ b/zellij-server/src/ui/pane_boundaries_frame.rs @@ -1,6 +1,10 @@ use crate::output::CharacterChunk; use crate::panes::{AnsiCode, RcCharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER}; use crate::ui::boundaries::boundary_type; +use crate::ui::hint_text::{ + exit_code_segments, hover_segments, rerun_segments, HintExitStatus, HintLevel, HintSegment, + HintTier, +}; use crate::ClientId; use zellij_utils::data::{client_id_to_colors, PaletteColor, Style}; use zellij_utils::errors::prelude::*; @@ -60,6 +64,7 @@ pub struct FrameParams { pub other_cursors_exist_in_session: bool, pub pane_is_stacked_under: bool, pub pane_is_stacked_over: bool, + pub pane_is_stacked: bool, pub should_draw_pane_frames: bool, pub pane_is_floating: bool, pub content_offset: Offset, @@ -67,6 +72,7 @@ pub struct FrameParams { pub pane_is_selectable: bool, pub show_help_text: bool, pub highlight_tooltip: Option<String>, + pub omit_title: bool, } #[derive(Default, PartialEq)] @@ -84,6 +90,7 @@ pub struct PaneFrame { is_first_run: bool, pane_is_stacked_over: bool, pane_is_stacked_under: bool, + pane_is_stacked: bool, should_draw_pane_frames: bool, is_pinned: bool, is_floating: bool, @@ -92,6 +99,7 @@ pub struct PaneFrame { is_selectable: bool, show_help_text: bool, highlight_tooltip: Option<String>, + omit_title: bool, } impl PaneFrame { @@ -115,6 +123,7 @@ impl PaneFrame { is_first_run: false, pane_is_stacked_over: frame_params.pane_is_stacked_over, pane_is_stacked_under: frame_params.pane_is_stacked_under, + pane_is_stacked: frame_params.pane_is_stacked, should_draw_pane_frames: frame_params.should_draw_pane_frames, is_pinned: false, is_floating: frame_params.pane_is_floating, @@ -123,6 +132,7 @@ impl PaneFrame { is_selectable: frame_params.pane_is_selectable, show_help_text: frame_params.show_help_text, highlight_tooltip: frame_params.highlight_tooltip, + omit_title: frame_params.omit_title, } } pub fn is_pinned(mut self, is_pinned: bool) -> Self { @@ -386,6 +396,17 @@ impl PaneFrame { } fn render_title_middle(&self, max_length: usize) -> Option<(Vec<TerminalCharacter>, usize)> { // string and length because of color + let renders_exit_status_in_title = self.pane_is_stacked_under + || self.pane_is_stacked_over + || !self.should_draw_pane_frames; + if renders_exit_status_in_title && self.exit_status.is_some() { + let (first_part, first_part_len) = self.first_exited_held_title_part_full(); + return if first_part_len <= max_length { + Some((first_part, first_part_len)) + } else { + None + }; + } if self.is_main_client && self.other_focused_clients.is_empty() && !self.other_cursors_exist_in_session @@ -400,15 +421,6 @@ impl PaneFrame { self.render_my_and_others_focus(max_length) } else if !self.other_focused_clients.is_empty() { self.render_other_focused_users(max_length) - } else if (self.pane_is_stacked_under || self.pane_is_stacked_over) - && self.exit_status.is_some() - { - let (first_part, first_part_len) = self.first_exited_held_title_part_full(); - if first_part_len <= max_length { - Some((first_part, first_part_len)) - } else { - None - } } else { None } @@ -704,12 +716,236 @@ impl PaneFrame { .with_context(|| format!("failed to render title '{}'", self.title)) } fn render_one_line_title(&self) -> Result<Vec<TerminalCharacter>> { - let total_title_length = self.geom.cols.saturating_sub(2); // 2 for the left and right corners + if self.should_draw_pane_frames { + let total_title_length = self.geom.cols.saturating_sub(2); + return self + .render_title_middle(total_title_length) + .map(|(middle, middle_length)| self.title_line_with_middle(middle, &middle_length)) + .or_else(|| Some(self.title_line_without_middle())) + .with_context(|| format!("failed to render title '{}'", self.title)); + } - self.render_title_middle(total_title_length) - .map(|(middle, middle_length)| self.title_line_with_middle(middle, &middle_length)) - .or_else(|| Some(self.title_line_without_middle())) - .with_context(|| format!("failed to render title '{}'", self.title)) + let width = self.geom.cols; + let title = self.bracketed_pane_title(width); + let title_length = title.as_ref().map(|(_, length)| *length).unwrap_or(0); + let side_budget = width.saturating_sub(title_length) / 2; + let focus = self.bracketed_focus_indicator(side_budget); + let focus_length = focus.as_ref().map(|(_, length)| *length).unwrap_or(0); + let scroll = + self.bracketed_scroll_indicator(width.saturating_sub(focus_length + title_length)); + Ok(self.compose_bracketed_title(focus, title, scroll)) + } + fn bracketed_title_part(&self, content: &str) -> (Vec<TerminalCharacter>, usize) { + let text = format!(" [ {} ] ", content); + (foreground_color(&text, self.color), text.width()) + } + fn bracketed_title_part_from_characters( + &self, + mut content: Vec<TerminalCharacter>, + content_length: usize, + ) -> (Vec<TerminalCharacter>, usize) { + let mut part = foreground_color(" [ ", self.color); + part.append(&mut content); + part.append(&mut foreground_color(" ] ", self.color)); + (part, content_length + 6) + } + fn plain_title_part(&self, content: &str) -> (Vec<TerminalCharacter>, usize) { + let text = format!(" {} ", content); + (foreground_color(&text, self.color), text.width()) + } + fn bracketed_pane_title(&self, max_length: usize) -> Option<(Vec<TerminalCharacter>, usize)> { + let title_padding = 2; + if self.title.is_empty() || max_length <= title_padding { + return None; + } + let exit_part = self + .exit_status + .is_some() + .then(|| self.first_exited_held_title_part_full()); + let exit_length = exit_part.as_ref().map(|(_, length)| *length).unwrap_or(0); + let content_max_length = max_length.saturating_sub(title_padding + exit_length); + let content = if self.title.width() <= content_max_length { + self.title.clone() + } else { + let truncation_budget = content_max_length.saturating_sub(1); + let mut truncated = String::new(); + for character in self.title.chars() { + if truncated.width() + character.width().unwrap_or(0) > truncation_budget { + break; + } + truncated.push(character); + } + truncated.push('…'); + truncated + }; + let (mut part, mut length) = self.plain_title_part(&content); + if let Some((mut exit, exit_length)) = exit_part { + part.append(&mut exit); + length += exit_length; + } + Some((part, length)) + } + fn bracketed_scroll_indicator( + &self, + max_length: usize, + ) -> Option<(Vec<TerminalCharacter>, usize)> { + let has_scroll = self.scroll_position.0 > 0 || self.scroll_position.1 > 0; + if !(has_scroll && self.is_selectable) { + return None; + } + let full_indication = format!( + "SCROLL: {}/{}", + self.scroll_position.0, self.scroll_position.1 + ); + let (full_part, full_length) = self.bracketed_title_part(&full_indication); + if full_length <= max_length { + return Some((full_part, full_length)); + } + let short_indication = format!("{}/{}", self.scroll_position.0, self.scroll_position.1); + let (short_part, short_length) = self.bracketed_title_part(&short_indication); + if short_length <= max_length { + return Some((short_part, short_length)); + } + None + } + fn bracketed_focus_indicator( + &self, + max_length: usize, + ) -> Option<(Vec<TerminalCharacter>, usize)> { + if self.is_main_client + && self.other_focused_clients.is_empty() + && !self.other_cursors_exist_in_session + { + None + } else if self.is_main_client + && self.other_focused_clients.is_empty() + && self.other_cursors_exist_in_session + { + let (full_part, full_length) = self.bracketed_title_part("MY FOCUS"); + if full_length <= max_length { + Some((full_part, full_length)) + } else { + let (short_part, short_length) = self.bracketed_title_part("ME"); + (short_length <= max_length).then_some((short_part, short_length)) + } + } else if self.is_main_client && !self.other_focused_clients.is_empty() { + self.bracketed_focused_users("MY FOCUS AND:", "+", max_length) + } else if !self.other_focused_clients.is_empty() { + let full_label = if self.other_focused_clients.len() == 1 { + "FOCUSED USER:" + } else { + "FOCUSED USERS:" + }; + self.bracketed_focused_users(full_label, "U:", max_length) + } else { + None + } + } + fn focused_users_part(&self, label: &str) -> (Vec<TerminalCharacter>, usize) { + let mut content = foreground_color(label, self.color); + let mut content_length = label.width(); + for client_id in &self.other_focused_clients { + content.push(EMPTY_TERMINAL_CHARACTER); + content.append(&mut self.client_cursor(*client_id)); + content_length += 2; + } + self.bracketed_title_part_from_characters(content, content_length) + } + fn focused_users_cursors_part(&self) -> (Vec<TerminalCharacter>, usize) { + let mut content = vec![]; + let mut content_length = 0; + for client_id in &self.other_focused_clients { + if content_length > 0 { + content.push(EMPTY_TERMINAL_CHARACTER); + content_length += 1; + } + content.append(&mut self.client_cursor(*client_id)); + content_length += 1; + } + self.bracketed_title_part_from_characters(content, content_length) + } + fn bracketed_focused_users( + &self, + full_label: &str, + short_label: &str, + max_length: usize, + ) -> Option<(Vec<TerminalCharacter>, usize)> { + let (full_part, full_length) = self.focused_users_part(full_label); + if full_length <= max_length { + return Some((full_part, full_length)); + } + let (short_part, short_length) = self.focused_users_part(short_label); + if short_length <= max_length { + return Some((short_part, short_length)); + } + let (cursors_part, cursors_length) = self.focused_users_cursors_part(); + (cursors_length <= max_length).then_some((cursors_part, cursors_length)) + } + fn compose_bracketed_title( + &self, + left: Option<(Vec<TerminalCharacter>, usize)>, + middle: Option<(Vec<TerminalCharacter>, usize)>, + right: Option<(Vec<TerminalCharacter>, usize)>, + ) -> Vec<TerminalCharacter> { + let width = self.geom.cols; + let left_length = left.as_ref().map(|(_, length)| *length).unwrap_or(0); + let middle_length = middle.as_ref().map(|(_, length)| *length).unwrap_or(0); + let right_length = right.as_ref().map(|(_, length)| *length).unwrap_or(0); + let centered_start = (width / 2) + .saturating_sub(middle_length / 2) + .max(left_length); + let middle_start = if middle.is_some() { + if right_length > 0 { + let scroll_start = width.saturating_sub(right_length); + let centered_end = centered_start + middle_length; + if centered_end > scroll_start { + scroll_start.saturating_sub(middle_length).max(left_length) + } else { + centered_start + } + } else { + centered_start + } + } else { + left_length + }; + let middle_end = if middle.is_some() { + middle_start + middle_length + } else { + left_length + }; + let right_start = width.saturating_sub(right_length).max(middle_end); + let fill_character = if self.pane_is_stacked { + foreground_color(boundary_type::HORIZONTAL, self.color) + .into_iter() + .next() + .unwrap_or(EMPTY_TERMINAL_CHARACTER) + } else { + EMPTY_TERMINAL_CHARACTER + }; + let mut placements: Vec<(usize, Vec<TerminalCharacter>, usize)> = vec![]; + if let Some((characters, length)) = left { + placements.push((0, characters, length)); + } + if let Some((characters, length)) = middle { + placements.push((middle_start, characters, length)); + } + if let Some((characters, length)) = right { + placements.push((right_start, characters, length)); + } + let mut title_line = vec![]; + let mut col = 0; + while col < width { + if let Some(index) = placements.iter().position(|(start, _, _)| *start == col) { + let (_, mut characters, length) = placements.remove(index); + title_line.append(&mut characters); + col += length; + } else { + title_line.push(fill_character.clone()); + col += 1; + } + } + title_line } fn render_highlight_tooltip_undertitle(&self) -> Result<Vec<TerminalCharacter>> { let max_undertitle_length = self.geom.cols.saturating_sub(2); @@ -929,6 +1165,9 @@ impl PaneFrame { pub fn render(&self) -> Result<(Vec<CharacterChunk>, Option<String>)> { let err_context = || "failed to render pane frame"; let mut character_chunks = vec![]; + if self.omit_title { + return Ok((character_chunks, None)); + } if self.geom.rows == 1 || !self.should_draw_pane_frames { // we do this explicitly when not drawing pane frames because this should only happen // if this is a stacked pane with pane frames off (and it doesn't necessarily have only @@ -1038,133 +1277,38 @@ impl PaneFrame { } Ok((character_chunks, None)) } + fn render_hint_segments(&self, segments: &[HintSegment]) -> (Vec<TerminalCharacter>, usize) { + let mut characters = vec![]; + let mut length = 0; + for segment in segments { + let color = match segment.level { + HintLevel::Plain => self.color, + HintLevel::Emphasis => Some(self.style.colors.text_unselected.emphasis_0), + HintLevel::Emphasis2 => Some(self.style.colors.text_unselected.emphasis_2), + HintLevel::Error => Some(self.style.colors.exit_code_error.base), + HintLevel::Success => Some(self.style.colors.exit_code_success.base), + }; + characters.append(&mut foreground_color(&segment.text, color)); + length += segment.text.width(); + } + (characters, length) + } fn first_exited_held_title_part_full(&self) -> (Vec<TerminalCharacter>, usize) { - // (title part, length) match self.exit_status { Some(ExitStatus::Code(exit_code)) => { - let mut first_part = vec![]; - let left_bracket = " [ "; - let exited_text = "EXIT CODE: "; - let exit_code_text = format!("{}", exit_code); - let exit_code_color = if exit_code == 0 { - self.style.colors.exit_code_success.base - } else { - self.style.colors.exit_code_error.base - }; - let right_bracket = " ] "; - first_part.append(&mut foreground_color(left_bracket, self.color)); - first_part.append(&mut foreground_color(exited_text, self.color)); - first_part.append(&mut foreground_color( - &exit_code_text, - Some(exit_code_color), - )); - first_part.append(&mut foreground_color(right_bracket, self.color)); - ( - first_part, - left_bracket.len() - + exited_text.len() - + exit_code_text.len() - + right_bracket.len(), - ) + self.render_hint_segments(&exit_code_segments(HintExitStatus::Code(exit_code))) }, Some(ExitStatus::Exited) => { - let mut first_part = vec![]; - let left_bracket = " [ "; - let exited_text = "EXITED"; - let right_bracket = " ] "; - first_part.append(&mut foreground_color(left_bracket, self.color)); - first_part.append(&mut foreground_color( - exited_text, - Some(self.style.colors.exit_code_error.base), - )); - first_part.append(&mut foreground_color(right_bracket, self.color)); - ( - first_part, - left_bracket.len() + exited_text.len() + right_bracket.len(), - ) + self.render_hint_segments(&exit_code_segments(HintExitStatus::Exited)) }, None => (foreground_color(boundary_type::HORIZONTAL, self.color), 1), } } fn second_held_title_part_full(&self) -> (Vec<TerminalCharacter>, usize) { - // (title part, length) - let mut second_part = vec![]; - let left_enter_bracket = if self.is_first_run { " <" } else { "<" }; - let enter_text = "ENTER"; - let right_enter_bracket = ">"; - let enter_tip = if self.is_first_run { - " run, " - } else { - " re-run, " - }; - - let left_esc_bracket = "<"; - let esc_text = "ESC"; - let right_esc_bracket = ">"; - let esc_tip = " drop to shell, "; - - let left_break_bracket = "<"; - let break_text = "Ctrl-c"; - let right_break_bracket = ">"; - let break_tip = " exit "; - second_part.append(&mut foreground_color(left_enter_bracket, self.color)); - second_part.append(&mut foreground_color( - enter_text, - Some(self.style.colors.text_unselected.emphasis_0), - )); - second_part.append(&mut foreground_color(right_enter_bracket, self.color)); - second_part.append(&mut foreground_color(enter_tip, self.color)); - - second_part.append(&mut foreground_color(left_esc_bracket, self.color)); - second_part.append(&mut foreground_color( - esc_text, - Some(self.style.colors.text_unselected.emphasis_0), - )); - second_part.append(&mut foreground_color(right_esc_bracket, self.color)); - second_part.append(&mut foreground_color(esc_tip, self.color)); - - second_part.append(&mut foreground_color(left_break_bracket, self.color)); - second_part.append(&mut foreground_color( - break_text, - Some(self.style.colors.text_unselected.emphasis_0), - )); - second_part.append(&mut foreground_color(right_break_bracket, self.color)); - second_part.append(&mut foreground_color(break_tip, self.color)); - ( - second_part, - left_enter_bracket.len() - + enter_text.len() - + right_enter_bracket.len() - + enter_tip.len() - + left_esc_bracket.len() - + esc_text.len() - + right_esc_bracket.len() - + esc_tip.len() - + left_break_bracket.len() - + break_text.len() - + right_break_bracket.len() - + break_tip.len(), - ) + self.render_hint_segments(&rerun_segments(self.is_first_run, HintTier::Full)) } fn hover_shortcuts_part_full(&self) -> (Vec<TerminalCharacter>, usize) { - // (title part, length) - let mut hover_shortcuts = vec![]; - let alt_click_text = " Alt <Click>"; - let alt_click_tip = " - group,"; - let alt_right_click_text = " Alt <Right-Click>"; - let alt_right_click_tip = " - ungroup all "; - - hover_shortcuts.append(&mut foreground_color(alt_click_text, self.color)); - hover_shortcuts.append(&mut foreground_color(alt_click_tip, self.color)); - hover_shortcuts.append(&mut foreground_color(alt_right_click_text, self.color)); - hover_shortcuts.append(&mut foreground_color(alt_right_click_tip, self.color)); - ( - hover_shortcuts, - alt_click_text.chars().count() - + alt_click_tip.chars().count() - + alt_right_click_text.chars().count() - + alt_right_click_tip.chars().count(), - ) + self.render_hint_segments(&hover_segments(HintTier::Full)) } fn empty_undertitle(&self, max_undertitle_length: usize) -> Vec<TerminalCharacter> { let mut left_boundary = diff --git a/zellij-server/src/ui/pane_contents_and_ui.rs b/zellij-server/src/ui/pane_contents_and_ui.rs index db7138f5..f2763a9b 100644 --- a/zellij-server/src/ui/pane_contents_and_ui.rs +++ b/zellij-server/src/ui/pane_contents_and_ui.rs @@ -20,6 +20,7 @@ pub struct PaneContentsAndUi<'a> { mouse_is_hovering_over_pane_for_clients: HashSet<ClientId>, current_pane_group: HashMap<ClientId, Vec<PaneId>>, show_help_text: bool, + omit_title: bool, } impl<'a> PaneContentsAndUi<'a> { @@ -36,6 +37,7 @@ impl<'a> PaneContentsAndUi<'a> { mouse_hover_pane_id: &HashMap<ClientId, PaneId>, current_pane_group: HashMap<ClientId, Vec<PaneId>>, show_help_text: bool, + omit_title: bool, ) -> Self { let mut focused_clients: Vec<ClientId> = active_panes .iter() @@ -66,6 +68,7 @@ impl<'a> PaneContentsAndUi<'a> { mouse_is_hovering_over_pane_for_clients, current_pane_group, show_help_text, + omit_title, } } pub fn render_pane_contents_to_multiple_clients( @@ -239,6 +242,7 @@ impl<'a> PaneContentsAndUi<'a> { } else { None }; + let pane_is_stacked = self.pane.current_geom().is_stacked(); let frame_params = if session_is_mirrored { FrameParams { focused_client, @@ -249,6 +253,7 @@ impl<'a> PaneContentsAndUi<'a> { other_cursors_exist_in_session: false, pane_is_stacked_over: self.pane_is_stacked_over, pane_is_stacked_under: self.pane_is_stacked_under, + pane_is_stacked, should_draw_pane_frames: self.should_draw_pane_frames, pane_is_floating, content_offset: self.pane.get_content_offset(), @@ -258,6 +263,7 @@ impl<'a> PaneContentsAndUi<'a> { pane_is_selectable, show_help_text: self.show_help_text, highlight_tooltip: highlight_tooltip.clone(), + omit_title: self.omit_title, } } else { FrameParams { @@ -269,6 +275,7 @@ impl<'a> PaneContentsAndUi<'a> { other_cursors_exist_in_session: self.multiple_users_exist_in_session, pane_is_stacked_over: self.pane_is_stacked_over, pane_is_stacked_under: self.pane_is_stacked_under, + pane_is_stacked, should_draw_pane_frames: self.should_draw_pane_frames, pane_is_floating, content_offset: self.pane.get_content_offset(), @@ -278,6 +285,7 @@ impl<'a> PaneContentsAndUi<'a> { pane_is_selectable, show_help_text: self.show_help_text, highlight_tooltip, + omit_title: self.omit_title, } }; diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 245cac8c..ee46dad3 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -18,7 +18,7 @@ use zellij_utils::input::layout::{ RunPlugin, RunPluginLocation, RunPluginOrAlias, SplitDirection, TiledPaneLayout, }; use zellij_utils::input::mouse::MouseEvent; -use zellij_utils::input::options::Options; +use zellij_utils::input::options::{Options, PaneFrameStyle}; use zellij_utils::ipc::IpcReceiverWithContext; use zellij_utils::pane_size::{Size, SizeInPixels}; use zellij_utils::position::Position; @@ -262,7 +262,7 @@ fn create_new_screen( let max_panes = None; let mut mode_info = ModeInfo::default(); mode_info.session_name = Some("zellij-test".into()); - let draw_pane_frames = false; + let draw_pane_frames = PaneFrameStyle::None; let auto_layout = true; let session_is_mirrored = true; let copy_options = CopyOptions::default(); @@ -693,6 +693,8 @@ impl MockScreen { let os_input = FakeInputOutput::default(); let config_options = Options::default(); + let mut config = Config::default(); + config.options.pane_frame_style = Some(PaneFrameStyle::Full); let main_client_id = 1; std::thread::Builder::new() @@ -734,7 +736,7 @@ impl MockScreen { config_options, session_metadata, last_opened_tab_index: None, - config: Config::default(), + config, advanced_mouse_actions: true, } } @@ -3230,6 +3232,7 @@ pub fn send_cli_new_pane_action_with_default_parameters() { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3284,6 +3287,7 @@ pub fn send_cli_new_pane_action_with_split_direction() { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3338,6 +3342,7 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3403,6 +3408,7 @@ pub fn send_cli_new_pane_action_with_floating_pane_and_coordinates() { floating: true, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -5224,6 +5230,7 @@ pub fn send_cli_new_pane_in_place_with_close_replaced_pane() { floating: false, in_place: true, close_replaced_pane: true, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -5375,7 +5382,7 @@ fn create_new_screen_with_message_capture( let max_panes = None; let mut mode_info = ModeInfo::default(); mode_info.session_name = Some("zellij-test".into()); - let draw_pane_frames = false; + let draw_pane_frames = PaneFrameStyle::None; let auto_layout = true; let session_is_mirrored = true; let copy_options = CopyOptions::default(); @@ -7949,6 +7956,7 @@ pub fn send_cli_new_pane_action_with_tab_id() { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -8010,6 +8018,7 @@ pub fn send_cli_new_floating_pane_action_with_tab_id() { floating: true, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -8119,6 +8128,7 @@ pub fn send_cli_new_pane_action_with_tab_id_and_direction() { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -8179,6 +8189,7 @@ pub fn send_cli_new_pane_action_with_tab_id_and_stacked() { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -8445,7 +8456,7 @@ fn create_new_screen_with_forward_capture(size: Size) -> (Screen, ForwardCapture let max_panes = None; let mut mode_info = ModeInfo::default(); mode_info.session_name = Some("zellij-test".into()); - let draw_pane_frames = false; + let draw_pane_frames = PaneFrameStyle::None; let auto_layout = true; let session_is_mirrored = true; let copy_options = CopyOptions::default(); @@ -9054,7 +9065,7 @@ fn create_new_screen_with_theme_capture(size: Size) -> (Screen, ThemeCapture) { &client_attributes, None, mode_info, - false, + PaneFrameStyle::None, true, true, copy_options, @@ -9533,7 +9544,7 @@ fn create_non_mirrored_screen(size: Size) -> Screen { &client_attributes, None, // max_panes mode_info, - false, // draw_pane_frames + PaneFrameStyle::None, true, // auto_layout false, // session_is_mirrored CopyOptions::default(), diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap index 6274f758..78d55494 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2849 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap index a87d4588..03497d19 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_pane_to_a_new_tab.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3395 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap index 8fc16e07..78d55494 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_floating_plugin_pane_to_a_new_tab-5.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3502 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ tiled_pane ──────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap index 347d93d4..6a14b417 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2739 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap index 2ee1fac4..1a41cccd 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2739 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap index 347d93d4..6a14b417 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab-4.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2739 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap index 765e5426..33a1d24d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_pane_to_a_new_tab.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2739 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_break_free ──────────────────┐┌ pane_to_stay ────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ ││ │ 18 (C): │ ││ │ 19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap index bbcf4b3a..1a41cccd 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2914 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap index 91a3ecd4..1a41cccd 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_break_plugin_pane_to_a_new_tab-5.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3429 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_stay ────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap index bb34d594..6a14b417 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3079 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap index 262029b4..33a1d24d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_left.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3079 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_break_free ──────────────────┐┌ pane_to_stay ────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ ││ │ 18 (C): │ ││ │ 19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap index 32f3248e..6a14b417 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3032 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_break_free ──────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap index 31169db3..33a1d24d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_move_pane_to_a_new_tab_right.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3032 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ pane_to_break_free ──────────────────┐┌ pane_to_stay ────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ ││ │ 18 (C): │ ││ │ 19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap index e4fbe942..7b8c7366 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2852 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap index 3a14dc55..69ea0a2e 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_can_suppress_pane.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2852 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ ││ │ 18 (C): │ ││ │ 19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap index ff7668a0..7b8c7366 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__screen_cannot_break_last_selectable_pane_to_a_new_tab.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2773 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ │ 18 (C): │ │ 19 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap index 4ea0e091..8a6f7e59 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3725 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ P[..]2 ┐─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ │ 08 (C): │ │ │ 09 (C): └────────┘─────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap index 01d4a3ae..f6dec9be 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_change_floating_pane_coordinates_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3725 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ └──────────────────────────────────────┘ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap index a95a55c6..b8ec0590 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2223 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap index 6c5fd6ab..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_pane_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1805 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap index 495842f6..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2459 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap index 9abd2dfc..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2459 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap index d4fce111..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_close_tab_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2118 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap index 1305cf7b..13eb550d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1042 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((41, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap index 74460796..e627107f 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_next_pane_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 939 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((1, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap index ae6be657..13eb550d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1080 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((41, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap index c8861240..e627107f 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_focus_previous_pane_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 968 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((1, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap index a0264d66..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2423 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap index cd63569f..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2423 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap index 1688290e..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_goto_tab_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2037 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap index d03e1da4..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_down_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1397 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap index d38454b4..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_half_page_scroll_up_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1354 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap index 2cbf6cd5..13eb550d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1160 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((41, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap index 7a6fd48a..e627107f 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_or_tab_pane_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1030 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((1, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap index 83bbdbb6..13eb550d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1120 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((41, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap index 208d683f..e627107f 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_focus_pane_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 999 expression: "format!(\"{:?}\", cursor_coordinates)" --- Some((1, 1)) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap index ad657ff1..e6f32591 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1194 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #2 ─────────────────────────────┐┌ Pane #1 ─────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ ││ │ 18 (C): │ ││ │ 19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap index 1c054e3a..69ea0a2e 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_move_pane_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1061 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -23,4 +22,3 @@ expression: "format!(\"{}\", snapshot)" 17 (C): │ ││ │ 18 (C): │ ││ │ 19 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap index fbf000fe..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2346 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap index 05259017..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2366 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap index fdac85da..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_next_tab_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1969 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap index 19f6d030..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_down_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1318 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap index a59f6869..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_page_scroll_up_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1275 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap index a677592e..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2387 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap index 1f0f1907..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2387 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap index b0d42634..793c70c6 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_previous_tab_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2003 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap index 0555f99f..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_to_top_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1565 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap index 94eef91e..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_scroll_up_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1147 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap index 8b57c658..b4649346 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_stack_panes_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 3687 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────┐┌ Pane #2 ─────┐┌ Pane #3 ─────┐┌ Pane #4 ─────┐┌ Pane #5 ─────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ ││ ││ ││ │ 08 (C): │ ││ ││ ││ ││ │ 09 (C): └──────────────┘└──────────────┘└──────────────┘└──────────────┘└──────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap index 0eaddd57..13c2a287 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2609 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ └──────────────────────────────────────┘ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap index 70970461..b8ec0590 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2186 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap index 0eaddd57..13c2a287 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes-4.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2609 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ └──────────────────────────────────────┘ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap index b7d2d258..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_floating_panes.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1775 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap index a5049d6c..7b763850 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1739 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap index a18e57fb..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_full_screen_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1427 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap index ca19a162..13c2a287 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-2.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2569 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #2 ─────────────────────────────────────────────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ └──────────────────────────────────────┘ │ 08 (C): │ │ 09 (C): └──────────────────────────────────────────────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap index 5a16d92e..85c2d9ae 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float-3.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2583 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #2 ─────────────────────────────┐┌ Pane #1 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap index 626bca74..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_embed_or_float.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1737 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap index 5d8c103b..6fdc8cca 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action-2.snap @@ -1,9 +1,8 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1776 expression: "format!(\"{}\", snapshot)" --- -00 (C): │ +00 (C): Pane #1 │ Pane #2 01 (C): │ 02 (C): │ 03 (C): │ @@ -12,5 +11,4 @@ expression: "format!(\"{}\", snapshot)" 06 (C): │ 07 (C): │ 08 (C): │ -09 (C): │ - +09 (C): │ diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap index e8307ea9..a54fd73c 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_toggle_pane_frames_action.snap @@ -1,6 +1,5 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1457 expression: "format!(\"{}\", snapshot)" --- 00 (C): ┌ Pane #1 ─────────────────────────────┐┌ Pane #2 ─────────────────────────────┐ @@ -13,4 +12,3 @@ expression: "format!(\"{}\", snapshot)" 07 (C): │ ││ │ 08 (C): │ ││ │ 09 (C): └──────────────────────────────────────┘└──────────────────────────────────────┘ - diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index 54431151..00be00bf 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -1300,6 +1300,13 @@ pub fn toggle_pane_frames() { unsafe { host_run_plugin_command() }; } +pub fn set_pane_frame_style(pane_frame_style: PaneFrameStyle) { + let plugin_command = PluginCommand::SetPaneFrameStyle(pane_frame_style); + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Embed the currently focused pane (make it stop floating) or turn it to a float pane if it is not pub fn toggle_pane_embed_or_eject() { let plugin_command = PluginCommand::TogglePaneEmbedOrEject; @@ -1323,6 +1330,20 @@ pub fn close_focus() { unsafe { host_run_plugin_command() }; } +pub fn new_pane() { + let plugin_command = PluginCommand::NewPane; + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + +pub fn toggle_floating_panes(tab_id: Option<u64>) { + let plugin_command = PluginCommand::ToggleFloatingPanes { tab_id }; + let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); + object_to_stdout(&protobuf_plugin_command.encode_to_vec()); + unsafe { host_run_plugin_command() }; +} + /// Turn the `STDIN` synchronization of the current tab on or off pub fn toggle_active_tab_sync() { let plugin_command = PluginCommand::ToggleActiveTabSync; diff --git a/zellij-tile/src/ui_components/text.rs b/zellij-tile/src/ui_components/text.rs index fe813fb3..ddfbc0e8 100644 --- a/zellij-tile/src/ui_components/text.rs +++ b/zellij-tile/src/ui_components/text.rs @@ -1,5 +1,6 @@ use std::ops::Bound; use std::ops::RangeBounds; +use zellij_utils::data::StyledText; #[derive(Debug, Default, Clone)] pub struct Text { @@ -9,6 +10,17 @@ pub struct Text { indices: Vec<Vec<usize>>, } +impl From<StyledText> for Text { + fn from(styled_text: StyledText) -> Self { + Text { + text: styled_text.text, + selected: false, + opaque: false, + indices: styled_text.indices, + } + } +} + impl Text { pub fn new<S: AsRef<str>>(content: S) -> Self where diff --git a/zellij-utils/assets/plugins/about.wasm b/zellij-utils/assets/plugins/about.wasm Binary files differindex 020b3970..b36db1c4 100755 --- a/zellij-utils/assets/plugins/about.wasm +++ b/zellij-utils/assets/plugins/about.wasm diff --git a/zellij-utils/assets/plugins/compact-bar.wasm b/zellij-utils/assets/plugins/compact-bar.wasm Binary files differindex 98b6939c..58b5f638 100755 --- a/zellij-utils/assets/plugins/compact-bar.wasm +++ b/zellij-utils/assets/plugins/compact-bar.wasm diff --git a/zellij-utils/assets/plugins/configuration.wasm b/zellij-utils/assets/plugins/configuration.wasm Binary files differindex 60ba05c7..cf12f093 100755 --- a/zellij-utils/assets/plugins/configuration.wasm +++ b/zellij-utils/assets/plugins/configuration.wasm diff --git a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm Binary files differindex 5dd2d0a6..0877d78a 100755 --- a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm +++ b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm diff --git a/zellij-utils/assets/plugins/layout-manager.wasm b/zellij-utils/assets/plugins/layout-manager.wasm Binary files differindex 610b4bcb..d41686c5 100755 --- a/zellij-utils/assets/plugins/layout-manager.wasm +++ b/zellij-utils/assets/plugins/layout-manager.wasm diff --git a/zellij-utils/assets/plugins/link.wasm b/zellij-utils/assets/plugins/link.wasm Binary files differindex c04c3791..dc5b14ec 100755 --- a/zellij-utils/assets/plugins/link.wasm +++ b/zellij-utils/assets/plugins/link.wasm diff --git a/zellij-utils/assets/plugins/mobile.wasm b/zellij-utils/assets/plugins/mobile.wasm Binary files differindex d31d600e..65ae6f64 100755 --- a/zellij-utils/assets/plugins/mobile.wasm +++ b/zellij-utils/assets/plugins/mobile.wasm diff --git a/zellij-utils/assets/plugins/multiple-select.wasm b/zellij-utils/assets/plugins/multiple-select.wasm Binary files differindex 925c5101..9ed820ed 100755 --- a/zellij-utils/assets/plugins/multiple-select.wasm +++ b/zellij-utils/assets/plugins/multiple-select.wasm diff --git a/zellij-utils/assets/plugins/plugin-manager.wasm b/zellij-utils/assets/plugins/plugin-manager.wasm Binary files differindex da2bc87e..b761818a 100755 --- a/zellij-utils/assets/plugins/plugin-manager.wasm +++ b/zellij-utils/assets/plugins/plugin-manager.wasm diff --git a/zellij-utils/assets/plugins/session-manager.wasm b/zellij-utils/assets/plugins/session-manager.wasm Binary files differindex 20719005..03c8e421 100755 --- a/zellij-utils/assets/plugins/session-manager.wasm +++ b/zellij-utils/assets/plugins/session-manager.wasm diff --git a/zellij-utils/assets/plugins/share.wasm b/zellij-utils/assets/plugins/share.wasm Binary files differindex 28403157..53622d68 100755 --- a/zellij-utils/assets/plugins/share.wasm +++ b/zellij-utils/assets/plugins/share.wasm diff --git a/zellij-utils/assets/plugins/status-bar.wasm b/zellij-utils/assets/plugins/status-bar.wasm Binary files differindex aaddeeb1..c70dff5d 100755 --- a/zellij-utils/assets/plugins/status-bar.wasm +++ b/zellij-utils/assets/plugins/status-bar.wasm diff --git a/zellij-utils/assets/plugins/strider.wasm b/zellij-utils/assets/plugins/strider.wasm Binary files differindex 2ea2f96e..8e0ad467 100755 --- a/zellij-utils/assets/plugins/strider.wasm +++ b/zellij-utils/assets/plugins/strider.wasm diff --git a/zellij-utils/assets/plugins/tab-bar.wasm b/zellij-utils/assets/plugins/tab-bar.wasm Binary files differindex 7f63366e..2a1bb455 100755 --- a/zellij-utils/assets/plugins/tab-bar.wasm +++ b/zellij-utils/assets/plugins/tab-bar.wasm diff --git a/zellij-utils/assets/prost/api.action.rs b/zellij-utils/assets/prost/api.action.rs index 31325096..a703c9f0 100644 --- a/zellij-utils/assets/prost/api.action.rs +++ b/zellij-utils/assets/prost/api.action.rs @@ -302,7 +302,7 @@ pub struct OverrideLayoutPayload { pub struct Action { #[prost(enumeration="ActionName", tag="1")] pub name: i32, - #[prost(oneof="action::OptionalPayload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60")] + #[prost(oneof="action::OptionalPayload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61")] pub optional_payload: ::core::option::Option<action::OptionalPayload>, } /// Nested message and enum types in `Action`. @@ -422,10 +422,18 @@ pub mod action { HideFloatingPanesPayload(super::HideFloatingPanesPayload), #[prost(message, tag="60")] AreFloatingPanesVisiblePayload(super::AreFloatingPanesVisiblePayload), + #[prost(message, tag="61")] + SetPaneFrameStylePayload(super::SetPaneFrameStylePayload), } } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct SetPaneFrameStylePayload { + #[prost(enumeration="super::pane_frame_style::PaneFrameStyle", tag="1")] + pub pane_frame_style: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct CliPipePayload { #[prost(string, optional, tag="1")] pub name: ::core::option::Option<::prost::alloc::string::String>, @@ -1125,6 +1133,7 @@ pub enum ActionName { SetLightTheme = 102, ToggleTheme = 103, FocusLastPane = 104, + SetPaneFrameStyle = 105, } impl ActionName { /// String value of the enum field names used in the ProtoBuf definition. @@ -1235,6 +1244,7 @@ impl ActionName { ActionName::SetLightTheme => "SetLightTheme", ActionName::ToggleTheme => "ToggleTheme", ActionName::FocusLastPane => "FocusLastPane", + ActionName::SetPaneFrameStyle => "SetPaneFrameStyle", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -1342,6 +1352,7 @@ impl ActionName { "SetLightTheme" => Some(Self::SetLightTheme), "ToggleTheme" => Some(Self::ToggleTheme), "FocusLastPane" => Some(Self::FocusLastPane), + "SetPaneFrameStyle" => Some(Self::SetPaneFrameStyle), _ => None, } } diff --git a/zellij-utils/assets/prost/api.event.rs b/zellij-utils/assets/prost/api.event.rs index eadb9394..8f050da7 100644 --- a/zellij-utils/assets/prost/api.event.rs +++ b/zellij-utils/assets/prost/api.event.rs @@ -9,7 +9,7 @@ pub struct EventNameList { pub struct Event { #[prost(enumeration="EventType", tag="1")] pub name: i32, - #[prost(oneof="event::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41")] + #[prost(oneof="event::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43")] pub payload: ::core::option::Option<event::Payload>, } /// Nested message and enum types in `Event`. @@ -97,10 +97,42 @@ pub mod event { HostTerminalThemeChangedPayload(super::HostTerminalThemeChangedPayload), #[prost(message, tag="41")] SoftKeyboardVisibilityChangedPayload(super::SoftKeyboardVisibilityChangedPayload), + #[prost(message, tag="42")] + HintTextPayload(super::HintTextPayload), + #[prost(message, tag="43")] + ActivePaneScrollPayload(super::ActivePaneScrollPayload), } } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct HintTextPayload { + #[prost(map="uint32, message", tag="1")] + pub hint_text: ::std::collections::HashMap<u32, StyledText>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ActivePaneScrollPayload { + #[prost(uint32, optional, tag="1")] + pub position: ::core::option::Option<u32>, + #[prost(uint32, optional, tag="2")] + pub length: ::core::option::Option<u32>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StyledText { + #[prost(string, tag="1")] + pub text: ::prost::alloc::string::String, + #[prost(message, repeated, tag="2")] + pub indices: ::prost::alloc::vec::Vec<StyledTextIndices>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StyledTextIndices { + #[prost(uint32, repeated, tag="1")] + pub indices: ::prost::alloc::vec::Vec<u32>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct HostTerminalThemeChangedPayload { #[prost(enumeration="HostTerminalThemeIndication", tag="1")] pub mode: i32, @@ -669,6 +701,8 @@ pub struct ModeUpdatePayload { pub web_server_port: ::core::option::Option<u32>, #[prost(bool, optional, tag="15")] pub web_server_capability: ::core::option::Option<bool>, + #[prost(enumeration="PaneFrameStyle", optional, tag="16")] + pub pane_frame_style: ::core::option::Option<i32>, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -850,6 +884,8 @@ pub enum EventType { CommandChanged = 45, HostTerminalThemeChanged = 46, SoftKeyboardVisibilityChanged = 47, + HintText = 48, + ActivePaneScroll = 49, } impl EventType { /// String value of the enum field names used in the ProtoBuf definition. @@ -905,6 +941,8 @@ impl EventType { EventType::CommandChanged => "CommandChanged", EventType::HostTerminalThemeChanged => "HostTerminalThemeChanged", EventType::SoftKeyboardVisibilityChanged => "SoftKeyboardVisibilityChanged", + EventType::HintText => "HintText", + EventType::ActivePaneScroll => "ActivePaneScroll", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -957,6 +995,8 @@ impl EventType { "CommandChanged" => Some(Self::CommandChanged), "HostTerminalThemeChanged" => Some(Self::HostTerminalThemeChanged), "SoftKeyboardVisibilityChanged" => Some(Self::SoftKeyboardVisibilityChanged), + "HintText" => Some(Self::HintText), + "ActivePaneScroll" => Some(Self::ActivePaneScroll), _ => None, } } @@ -1148,3 +1188,32 @@ impl WebSharing { } } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum PaneFrameStyle { + Full = 0, + Titles = 1, + None = 2, +} +impl PaneFrameStyle { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + PaneFrameStyle::Full => "Full", + PaneFrameStyle::Titles => "Titles", + PaneFrameStyle::None => "None", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option<Self> { + match value { + "Full" => Some(Self::Full), + "Titles" => Some(Self::Titles), + "None" => Some(Self::None), + _ => None, + } + } +} diff --git a/zellij-utils/assets/prost/api.pane_frame_style.rs b/zellij-utils/assets/prost/api.pane_frame_style.rs new file mode 100644 index 00000000..a39ff161 --- /dev/null +++ b/zellij-utils/assets/prost/api.pane_frame_style.rs @@ -0,0 +1,29 @@ +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum PaneFrameStyle { + Full = 0, + Titles = 1, + None = 2, +} +impl PaneFrameStyle { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + PaneFrameStyle::Full => "Full", + PaneFrameStyle::Titles => "Titles", + PaneFrameStyle::None => "None", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option<Self> { + match value { + "Full" => Some(Self::Full), + "Titles" => Some(Self::Titles), + "None" => Some(Self::None), + _ => None, + } + } +} diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs index 4cef814a..676361b2 100644 --- a/zellij-utils/assets/prost/api.plugin_command.rs +++ b/zellij-utils/assets/prost/api.plugin_command.rs @@ -3,7 +3,7 @@ pub struct PluginCommand { #[prost(enumeration="CommandName", tag="1")] pub name: i32, - #[prost(oneof="plugin_command::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 167, 168, 169")] + #[prost(oneof="plugin_command::Payload", tags="2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 167, 168, 169, 170, 171")] pub payload: ::core::option::Option<plugin_command::Payload>, } /// Nested message and enum types in `PluginCommand`. @@ -319,10 +319,26 @@ pub mod plugin_command { NewTabUnfocusedPayload(super::NewTabUnfocusedPayload), #[prost(message, tag="169")] NewTiledPaneInTabPayload(super::NewTiledPaneInTabPayload), + #[prost(message, tag="170")] + SetPaneFrameStylePayload(super::SetPaneFrameStylePayload), + #[prost(message, tag="171")] + ToggleFloatingPanesPayload(super::ToggleFloatingPanesPayload), } } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct SetPaneFrameStylePayload { + #[prost(enumeration="super::pane_frame_style::PaneFrameStyle", tag="1")] + pub pane_frame_style: i32, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ToggleFloatingPanesPayload { + #[prost(uint64, optional, tag="1")] + pub tab_id: ::core::option::Option<u64>, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct NewTabPayload { #[prost(string, optional, tag="1")] pub name: ::core::option::Option<::prost::alloc::string::String>, @@ -2230,6 +2246,9 @@ pub enum CommandName { NewTiledPaneInTab = 221, ExitMobileMode = 222, FocusLastPane = 223, + SetPaneFrameStyle = 224, + ToggleFloatingPanes = 225, + NewPane = 226, } impl CommandName { /// String value of the enum field names used in the ProtoBuf definition. @@ -2439,6 +2458,9 @@ impl CommandName { CommandName::NewTiledPaneInTab => "NewTiledPaneInTab", CommandName::ExitMobileMode => "ExitMobileMode", CommandName::FocusLastPane => "FocusLastPane", + CommandName::SetPaneFrameStyle => "SetPaneFrameStyle", + CommandName::ToggleFloatingPanes => "ToggleFloatingPanes", + CommandName::NewPane => "NewPane", } } /// Creates an enum from field names used in the ProtoBuf definition. @@ -2645,6 +2667,9 @@ impl CommandName { "NewTiledPaneInTab" => Some(Self::NewTiledPaneInTab), "ExitMobileMode" => Some(Self::ExitMobileMode), "FocusLastPane" => Some(Self::FocusLastPane), + "SetPaneFrameStyle" => Some(Self::SetPaneFrameStyle), + "ToggleFloatingPanes" => Some(Self::ToggleFloatingPanes), + "NewPane" => Some(Self::NewPane), _ => None, } } diff --git a/zellij-utils/assets/prost/generated_plugin_api.rs b/zellij-utils/assets/prost/generated_plugin_api.rs index ee70c470..fcea0e0a 100644 --- a/zellij-utils/assets/prost/generated_plugin_api.rs +++ b/zellij-utils/assets/prost/generated_plugin_api.rs @@ -20,6 +20,9 @@ pub mod api { pub mod message { include!("api.message.rs"); } + pub mod pane_frame_style { + include!("api.pane_frame_style.rs"); + } pub mod pipe_message { include!("api.pipe_message.rs"); } diff --git a/zellij-utils/assets/prost_ipc/client_server_contract.rs b/zellij-utils/assets/prost_ipc/client_server_contract.rs index e08496e7..3dada2ac 100644 --- a/zellij-utils/assets/prost_ipc/client_server_contract.rs +++ b/zellij-utils/assets/prost_ipc/client_server_contract.rs @@ -119,7 +119,7 @@ pub struct RgbColor { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Action { - #[prost(oneof="action::ActionType", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141")] + #[prost(oneof="action::ActionType", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142")] pub action_type: ::core::option::Option<action::ActionType>, } /// Nested message and enum types in `Action`. @@ -411,6 +411,8 @@ pub mod action { ToggleMobileMode(super::ToggleMobileModeAction), #[prost(message, tag="141")] FocusLastPane(super::FocusLastPaneAction), + #[prost(message, tag="142")] + SetPaneFrameStyle(super::SetPaneFrameStyleAction), } } // Action message definitions (all 92 variants) @@ -500,6 +502,12 @@ pub struct TogglePaneFramesAction { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] +pub struct SetPaneFrameStyleAction { + #[prost(string, tag="1")] + pub style: ::prost::alloc::string::String, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct ToggleActiveSyncTabAction { } #[allow(clippy::derive_partial_eq_without_eq)] @@ -1971,6 +1979,8 @@ pub struct Options { pub mobile_threshold_cols: ::core::option::Option<u32>, #[prost(uint32, optional, tag="50")] pub mobile_threshold_rows: ::core::option::Option<u32>, + #[prost(string, optional, tag="51")] + pub pane_frame_style: ::core::option::Option<::prost::alloc::string::String>, } /// Pane-targeting action messages #[allow(clippy::derive_partial_eq_without_eq)] diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index a00c4d05..ee2b6da1 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -2,7 +2,10 @@ use crate::data::{Direction, InputMode, Resize, UnblockCondition}; use crate::setup::Setup; use crate::{ consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV}, - input::{layout::PluginUserConfiguration, options::Options}, + input::{ + layout::PluginUserConfiguration, + options::{Options, PaneFrameStyle}, + }, }; use clap::{ArgEnum, Args, Parser, Subcommand}; use serde::{Deserialize, Serialize}; @@ -884,6 +887,10 @@ pub enum CliAction { }, /// Toggle frames around panes in the UI TogglePaneFrames, + SetPaneFrameStyle { + #[clap(arg_enum, value_parser)] + style: PaneFrameStyle, + }, /// Toggle between sending text commands to all panes on the current tab and normal mode. ToggleActiveSyncTab { /// Target a specific tab by ID @@ -934,6 +941,16 @@ pub enum CliAction { )] close_replaced_pane: bool, + /// The pane to replace when opening in place, eg. terminal_1, plugin_2 or 3 (only + /// effective with --in-place; defaults to the focused pane) + #[clap( + long, + value_parser, + requires("in-place"), + conflicts_with("near-current-pane") + )] + pane_id: Option<String>, + /// Name of the new pane #[clap(short, long, value_parser)] name: Option<String>, diff --git a/zellij-utils/src/client_server_contract/common_types.proto b/zellij-utils/src/client_server_contract/common_types.proto index 718cc279..6a7809c8 100644 --- a/zellij-utils/src/client_server_contract/common_types.proto +++ b/zellij-utils/src/client_server_contract/common_types.proto @@ -279,6 +279,7 @@ message Action { ToggleThemeAction toggle_theme = 139; ToggleMobileModeAction toggle_mobile_mode = 140; FocusLastPaneAction focus_last_pane = 141; + SetPaneFrameStyleAction set_pane_frame_style = 142; } } @@ -307,6 +308,9 @@ message HalfPageScrollUpAction {} message HalfPageScrollDownAction {} message ToggleFocusFullscreenAction {} message TogglePaneFramesAction {} +message SetPaneFrameStyleAction { + string style = 1; +} message ToggleActiveSyncTabAction {} message TogglePaneEmbedOrFloatingAction {} message ToggleFloatingPanesAction {} @@ -1183,6 +1187,7 @@ message Options { optional MobileLayout mobile_layout = 48; optional uint32 mobile_threshold_cols = 49; optional uint32 mobile_threshold_rows = 50; + optional string pane_frame_style = 51; } enum OnForceClose { diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index c11f777f..758e2ab3 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -5,6 +5,7 @@ use crate::input::keybinds::Keybinds; use crate::input::layout::{ Layout, PercentOrFixed, Run, RunPlugin, RunPluginLocation, RunPluginOrAlias, }; +pub use crate::input::options::PaneFrameStyle; use crate::pane_size::{PaneGeom, Size}; use crate::position::Position; use crate::shared::{colors as default_colors, eightbit_to_rgb}; @@ -938,6 +939,12 @@ impl From<Metadata> for FileMetadata { } } +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct StyledText { + pub text: String, + pub indices: Vec<Vec<usize>>, +} + /// These events can be subscribed to with subscribe method exported by `zellij-tile`. /// Once subscribed to, they will trigger the `update` method of the `ZellijPlugin` trait. #[derive(Debug, Clone, PartialEq, EnumDiscriminants, Display, Serialize, Deserialize)] @@ -1031,6 +1038,8 @@ pub enum Event { /// The host terminal indicated its color palette theme mode (CSI 2031 / DSR 997). HostTerminalThemeChanged(HostTerminalThemeMode), SoftKeyboardVisibilityChanged(bool), + HintText(BTreeMap<usize, StyledText>), + ActivePaneScroll(Option<(usize, usize)>), } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -1741,6 +1750,7 @@ pub struct ModeInfo { pub web_server_ip: Option<IpAddr>, pub web_server_port: Option<u16>, pub web_server_capability: Option<bool>, + pub pane_frame_style: Option<PaneFrameStyle>, } impl ModeInfo { @@ -3378,6 +3388,10 @@ pub enum PluginCommand { NewTiledPaneInTab { tab_position: usize, }, + ToggleFloatingPanes { + tab_id: Option<u64>, + }, + NewPane, GoToNextTab, GoToPreviousTab, Resize(Resize), @@ -3403,6 +3417,7 @@ pub enum PluginCommand { PageScrollDown, ToggleFocusFullscreen, TogglePaneFrames, + SetPaneFrameStyle(PaneFrameStyle), TogglePaneEmbedOrEject, UndoRenamePane, CloseFocus, diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index c9e8e25f..8ffe0907 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -282,6 +282,7 @@ pub enum ScreenContext { ToggleActiveSyncTab, ToggleActiveTerminalFullscreen, TogglePaneFrames, + SetPaneFrameStyle, SetSelectable, ShowPluginCursor, SetInvisibleBorders, @@ -466,6 +467,7 @@ pub enum ScreenContext { MoveTabWithTabId, PluginSubscribedToAnsiPaneContents, UpdateBackgroundPluginSubscriptions, + ClearHintTextCache, BroadcastModeUpdate, EnterMobileMode, ExitMobileMode, diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 40158b8b..757e99e4 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -14,7 +14,7 @@ use crate::data::{FloatingPaneCoordinates, InputMode}; use crate::home::{find_default_config_dir, get_layout_dir}; use crate::input::config::{Config, ConfigError, KdlError}; use crate::input::mouse::MouseEvent; -use crate::input::options::OnForceClose; +use crate::input::options::{OnForceClose, PaneFrameStyle}; use miette::{NamedSource, Report}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -218,6 +218,7 @@ pub enum Action { ToggleFocusFullscreen, /// Toggle frames around panes in the UI TogglePaneFrames, + SetPaneFrameStyle(PaneFrameStyle), /// Toggle between sending text commands to all panes on the current tab and normal mode. ToggleActiveSyncTab, /// Open a new pane in the specified direction (relative to focus). @@ -1007,6 +1008,7 @@ impl Action { None => Ok(vec![Action::ToggleFocusFullscreen]), }, CliAction::TogglePaneFrames => Ok(vec![Action::TogglePaneFrames]), + CliAction::SetPaneFrameStyle { style } => Ok(vec![Action::SetPaneFrameStyle(style)]), CliAction::ToggleActiveSyncTab { tab_id } => match tab_id { Some(id) => Ok(vec![Action::ToggleActiveSyncTabByTabId { id: id as u64 }]), None => Ok(vec![Action::ToggleActiveSyncTab]), @@ -1019,6 +1021,7 @@ impl Action { floating, in_place, close_replaced_pane, + pane_id, name, close_on_exit, start_suspended, @@ -1039,6 +1042,18 @@ impl Action { borderless, tab_id, } => { + let pane_id_to_replace = match pane_id { + Some(pane_id_str) => match PaneId::from_str(&pane_id_str) { + Ok(parsed_pane_id) => Some(parsed_pane_id), + Err(_e) => { + return Err(format!( + "Malformed pane id: {}, expecting either a bare integer (eg. 1), a terminal pane id (eg. terminal_1) or a plugin pane id (eg. plugin_1)", + pane_id_str + )) + }, + }, + None => None, + }; let current_dir = get_current_dir(); // cwd should only be specified in a plugin alias if it was explicitly given to us, // otherwise the current_dir might override a cwd defined in the alias itself @@ -1087,7 +1102,7 @@ impl Action { )) } else if in_place { NewPanePlacement::InPlace { - pane_id_to_replace: None, + pane_id_to_replace, close_replaced_pane, borderless, } @@ -1197,7 +1212,7 @@ impl Action { command: Some(run_command_action), pane_name: name, near_current_pane, - pane_id_to_replace: None, // TODO: support this + pane_id_to_replace, close_replaced_pane, tab_id, }]) @@ -1234,7 +1249,7 @@ impl Action { command: None, pane_name: name, near_current_pane, - pane_id_to_replace: None, // TODO: support this + pane_id_to_replace, close_replaced_pane, tab_id, }]) @@ -3575,6 +3590,7 @@ mod tests { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3617,6 +3633,7 @@ mod tests { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3650,6 +3667,87 @@ mod tests { } #[test] + fn test_new_in_place_pane_with_pane_id_to_replace() { + let cli_action = CliAction::NewPane { + direction: None, + command: vec![], + plugin: None, + cwd: None, + floating: false, + in_place: true, + close_replaced_pane: true, + pane_id: Some("terminal_4".to_string()), + name: None, + close_on_exit: false, + start_suspended: false, + configuration: None, + skip_plugin_cache: false, + x: None, + y: None, + width: None, + height: None, + pinned: None, + stacked: false, + blocking: false, + block_until_exit_success: false, + block_until_exit_failure: false, + block_until_exit: false, + unblock_condition: None, + near_current_pane: false, + borderless: None, + tab_id: None, + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_ok()); + let actions = result.unwrap(); + assert_eq!(actions.len(), 1); + match &actions[0] { + Action::NewInPlacePane { + pane_id_to_replace, .. + } => { + assert_eq!(*pane_id_to_replace, Some(PaneId::Terminal(4))); + }, + _ => panic!("Expected NewInPlacePane action"), + } + } + + #[test] + fn test_new_in_place_pane_with_malformed_pane_id() { + let cli_action = CliAction::NewPane { + direction: None, + command: vec![], + plugin: None, + cwd: None, + floating: false, + in_place: true, + close_replaced_pane: false, + pane_id: Some("not_a_pane".to_string()), + name: None, + close_on_exit: false, + start_suspended: false, + configuration: None, + skip_plugin_cache: false, + x: None, + y: None, + width: None, + height: None, + pinned: None, + stacked: false, + blocking: false, + block_until_exit_success: false, + block_until_exit_failure: false, + block_until_exit: false, + unblock_condition: None, + near_current_pane: false, + borderless: None, + tab_id: None, + }; + let result = Action::actions_from_cli(cli_action, Box::new(|| PathBuf::from("/tmp")), None); + assert!(result.is_err()); + assert!(result.unwrap_err().contains("Malformed pane id")); + } + + #[test] fn test_new_pane_floating_with_tab_id() { let cli_action = CliAction::NewPane { direction: None, @@ -3659,6 +3757,7 @@ mod tests { floating: true, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3701,6 +3800,7 @@ mod tests { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3743,6 +3843,7 @@ mod tests { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3847,6 +3948,7 @@ mod tests { floating: false, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, @@ -3889,6 +3991,7 @@ mod tests { floating: true, in_place: false, close_replaced_pane: false, + pane_id: None, name: None, close_on_exit: false, start_suspended: false, diff --git a/zellij-utils/src/input/mod.rs b/zellij-utils/src/input/mod.rs index c103e580..0934287e 100644 --- a/zellij-utils/src/input/mod.rs +++ b/zellij-utils/src/input/mod.rs @@ -54,6 +54,7 @@ mod not_wasm { web_server_ip: None, web_server_port: None, web_server_capability: None, + pane_frame_style: None, } } diff --git a/zellij-utils/src/input/options.rs b/zellij-utils/src/input/options.rs index 8f91cb47..a1cfdd67 100644 --- a/zellij-utils/src/input/options.rs +++ b/zellij-utils/src/input/options.rs @@ -93,6 +93,56 @@ impl FromStr for OnForceClose { } } +#[derive(ArgEnum, Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum PaneFrameStyle { + Full, + Titles, + None, +} + +impl Default for PaneFrameStyle { + fn default() -> Self { + PaneFrameStyle::Titles + } +} + +impl PaneFrameStyle { + pub fn draws_full_frames(&self) -> bool { + matches!(self, PaneFrameStyle::Full) + } + + pub fn draws_titles(&self) -> bool { + matches!(self, PaneFrameStyle::Titles) + } + + pub fn from_options(options: &Options) -> Self { + if options.pane_frames == Some(false) { + return PaneFrameStyle::None; + } + match options.pane_frame_style { + Some(PaneFrameStyle::Full) => PaneFrameStyle::Full, + _ => PaneFrameStyle::Titles, + } + } +} + +impl FromStr for PaneFrameStyle { + type Err = Box<dyn std::error::Error>; + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s.trim().to_lowercase().as_str() { + "full" => Ok(PaneFrameStyle::Full), + "titles" => Ok(PaneFrameStyle::Titles), + "none" => Ok(PaneFrameStyle::None), + e => Err(format!( + "Unknown pane frame style: '{}' (expected 'full', 'titles' or 'none')", + e + ) + .into()), + } + } +} + #[derive(Clone, Default, Debug, PartialEq, Deserialize, Serialize, Args)] /// Options that can be set either through the config file, /// or cli flags - cli flags should take precedence over the config file @@ -146,6 +196,9 @@ pub struct Options { #[serde(default)] /// Set display of the pane frames (true or false) pub pane_frames: Option<bool>, + #[clap(long, arg_enum, hide_possible_values = true, value_parser)] + #[serde(default)] + pub pane_frame_style: Option<PaneFrameStyle>, #[clap(long, value_parser)] #[serde(default)] /// Mirror session when multiple users are connected (true or false) @@ -393,6 +446,7 @@ impl Options { pub fn merge(&self, other: Options) -> Options { let mouse_mode = other.mouse_mode.or(self.mouse_mode); let pane_frames = other.pane_frames.or(self.pane_frames); + let pane_frame_style = other.pane_frame_style.or(self.pane_frame_style); let auto_layout = other.auto_layout.or(self.auto_layout); let mirror_session = other.mirror_session.or(self.mirror_session); let simplified_ui = other.simplified_ui.or(self.simplified_ui); @@ -475,6 +529,7 @@ impl Options { theme_dir, mouse_mode, pane_frames, + pane_frame_style, mirror_session, on_force_close, scroll_buffer_size, @@ -534,6 +589,7 @@ impl Options { let simplified_ui = merge_bool(other.simplified_ui, self.simplified_ui); let mouse_mode = merge_bool(other.mouse_mode, self.mouse_mode); let pane_frames = merge_bool(other.pane_frames, self.pane_frames); + let pane_frame_style = other.pane_frame_style.or(self.pane_frame_style); let auto_layout = merge_bool(other.auto_layout, self.auto_layout); let mirror_session = merge_bool(other.mirror_session, self.mirror_session); let session_serialization = @@ -616,6 +672,7 @@ impl Options { theme_dir, mouse_mode, pane_frames, + pane_frame_style, mirror_session, on_force_close, scroll_buffer_size, @@ -675,6 +732,27 @@ mod tests { const TALL_NARROW: (usize, usize) = (40, 200); const LARGE: (usize, usize) = (200, 200); + #[test] + fn pane_frame_style_from_str_accepts_all_variants() { + assert_eq!( + "full".parse::<PaneFrameStyle>().unwrap(), + PaneFrameStyle::Full + ); + assert_eq!( + "titles".parse::<PaneFrameStyle>().unwrap(), + PaneFrameStyle::Titles + ); + assert_eq!( + "none".parse::<PaneFrameStyle>().unwrap(), + PaneFrameStyle::None + ); + assert_eq!( + "NONE".parse::<PaneFrameStyle>().unwrap(), + PaneFrameStyle::None + ); + assert!("bogus".parse::<PaneFrameStyle>().is_err()); + } + fn route( layout: MobileLayoutConfiguration, is_web: bool, diff --git a/zellij-utils/src/ipc/protobuf_conversion.rs b/zellij-utils/src/ipc/protobuf_conversion.rs index c4941676..f1ad8118 100644 --- a/zellij-utils/src/ipc/protobuf_conversion.rs +++ b/zellij-utils/src/ipc/protobuf_conversion.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use crate::{ client_server_contract::client_server_contract::{ client_to_server_msg, server_to_client_msg, ActionMsg, AttachClientMsg, @@ -766,6 +768,11 @@ impl From<crate::input::options::Options> }), mobile_threshold_cols: options.mobile_threshold_cols.map(|v| v as u32), mobile_threshold_rows: options.mobile_threshold_rows.map(|v| v as u32), + pane_frame_style: options.pane_frame_style.map(|s| match s { + crate::input::options::PaneFrameStyle::Full => "full".to_owned(), + crate::input::options::PaneFrameStyle::Titles => "titles".to_owned(), + crate::input::options::PaneFrameStyle::None => "none".to_owned(), + }), } } } @@ -798,6 +805,12 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Options> theme_dir: options.theme_dir.map(std::path::PathBuf::from), mouse_mode: options.mouse_mode, pane_frames: options.pane_frames, + pane_frame_style: options.pane_frame_style.as_deref().and_then(|s| match s { + "full" => Some(crate::input::options::PaneFrameStyle::Full), + "titles" => Some(crate::input::options::PaneFrameStyle::Titles), + "none" => Some(crate::input::options::PaneFrameStyle::None), + _ => None, + }), mirror_session: options.mirror_session, on_force_close: options .on_force_close @@ -999,6 +1012,7 @@ impl From<crate::input::actions::Action> SetLightThemeAction, SetPaneBorderlessAction, SetPaneColorAction, + SetPaneFrameStyleAction, ShowFloatingPanesAction, SkipConfirmAction, StackPanesAction, @@ -1177,6 +1191,16 @@ impl From<crate::input::actions::Action> crate::input::actions::Action::TogglePaneFrames => { ActionType::TogglePaneFrames(TogglePaneFramesAction {}) }, + crate::input::actions::Action::SetPaneFrameStyle(style) => { + let style = match style { + crate::input::options::PaneFrameStyle::Full => "full", + crate::input::options::PaneFrameStyle::Titles => "titles", + crate::input::options::PaneFrameStyle::None => "none", + }; + ActionType::SetPaneFrameStyle(SetPaneFrameStyleAction { + style: style.to_owned(), + }) + }, crate::input::actions::Action::ToggleActiveSyncTab => { ActionType::ToggleActiveSyncTab(ToggleActiveSyncTabAction {}) }, @@ -2037,6 +2061,13 @@ impl TryFrom<crate::client_server_contract::client_server_contract::Action> Ok(crate::input::actions::Action::ToggleFocusFullscreen) }, ActionType::TogglePaneFrames(_) => Ok(crate::input::actions::Action::TogglePaneFrames), + ActionType::SetPaneFrameStyle(set_pane_frame_style_action) => { + let style = crate::input::options::PaneFrameStyle::from_str( + &set_pane_frame_style_action.style, + ) + .map_err(|e| anyhow!("{}", e))?; + Ok(crate::input::actions::Action::SetPaneFrameStyle(style)) + }, ActionType::ToggleActiveSyncTab(_) => { Ok(crate::input::actions::Action::ToggleActiveSyncTab) }, diff --git a/zellij-utils/src/ipc/tests/roundtrip_tests.rs b/zellij-utils/src/ipc/tests/roundtrip_tests.rs index 280805ab..8ea01a5f 100644 --- a/zellij-utils/src/ipc/tests/roundtrip_tests.rs +++ b/zellij-utils/src/ipc/tests/roundtrip_tests.rs @@ -13,7 +13,9 @@ use crate::input::layout::{ TiledPaneLayout, }; use crate::input::mouse::{MouseEvent, MouseEventType}; -use crate::input::options::{Clipboard, MobileLayoutConfiguration, OnForceClose, Options}; +use crate::input::options::{ + Clipboard, MobileLayoutConfiguration, OnForceClose, Options, PaneFrameStyle, +}; use crate::ipc::{ ClientToServerMsg, ColorRegister, ExitReason, PaneReference, PixelDimensions, ResizeCause, ServerToClientMsg, @@ -444,6 +446,7 @@ fn test_client_messages() { theme_dir: Some(PathBuf::from("theme_dir")), mouse_mode: Some(true), pane_frames: Some(true), + pane_frame_style: Some(PaneFrameStyle::Full), mirror_session: Some(true), on_force_close: Some(OnForceClose::Quit), scroll_buffer_size: Some(100000), @@ -3536,6 +3539,24 @@ fn test_client_messages() { client_id: Some(100), is_cli_client: true, }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::SetPaneFrameStyle(PaneFrameStyle::Full), + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::SetPaneFrameStyle(PaneFrameStyle::Titles), + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); + test_client_roundtrip!(ClientToServerMsg::Action { + action: Action::SetPaneFrameStyle(PaneFrameStyle::None), + terminal_id: Some(1), + client_id: Some(100), + is_cli_client: true, + }); test_client_roundtrip!(ClientToServerMsg::ForwardedReplyFromHost { token: 0, reply_bytes: vec![], diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index 14695f68..42ce65c5 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -12,7 +12,7 @@ use crate::input::keybinds::Keybinds; use crate::input::layout::{ Layout, PercentOrFixed, PluginUserConfiguration, RunPlugin, RunPluginOrAlias, TabLayoutInfo, }; -use crate::input::options::{Clipboard, OnForceClose, Options}; +use crate::input::options::{Clipboard, OnForceClose, Options, PaneFrameStyle}; use crate::input::permission::{GrantedPermission, PermissionCache}; use crate::input::plugins::PluginAliases; use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig}; @@ -455,6 +455,16 @@ impl Action { ) -> Result<Self, ConfigError> { match action_name { "WriteChars" => Ok(Action::WriteChars { chars: string }), + "SetPaneFrameStyle" => { + let style = PaneFrameStyle::from_str(string.as_str()).map_err(|e| { + ConfigError::new_kdl_error( + format!("{}", e), + action_node.span().offset(), + action_node.span().len(), + ) + })?; + Ok(Action::SetPaneFrameStyle(style)) + }, "SwitchToMode" => match InputMode::from_str(string.as_str()) { Ok(input_mode) => Ok(Action::SwitchToMode { input_mode }), Err(_e) => { @@ -734,6 +744,16 @@ impl Action { Action::HalfPageScrollDown => Some(KdlNode::new("HalfPageScrollDown")), Action::ToggleFocusFullscreen => Some(KdlNode::new("ToggleFocusFullscreen")), Action::TogglePaneFrames => Some(KdlNode::new("TogglePaneFrames")), + Action::SetPaneFrameStyle(style) => { + let mut node = KdlNode::new("SetPaneFrameStyle"); + let style = match style { + PaneFrameStyle::Full => "full", + PaneFrameStyle::Titles => "titles", + PaneFrameStyle::None => "none", + }; + node.push(style); + Some(node) + }, Action::ToggleActiveSyncTab => Some(KdlNode::new("ToggleActiveSyncTab")), Action::NewPane { direction, @@ -1652,6 +1672,11 @@ impl TryFrom<(&KdlNode, &Options)> for Action { action_arguments, kdl_action ), + "SetPaneFrameStyle" => parse_kdl_action_char_or_string_arguments!( + action_name, + action_arguments, + kdl_action + ), "Search" => parse_kdl_action_char_or_string_arguments!( action_name, action_arguments, @@ -2683,6 +2708,16 @@ impl Options { .map(|(string, _entry)| PathBuf::from(string)); let pane_frames = kdl_property_first_arg_as_bool_or_error!(kdl_options, "pane_frames").map(|(v, _)| v); + let pane_frame_style = + match kdl_property_first_arg_as_string_or_error!(kdl_options, "pane_frame_style") { + Some((string, entry)) => Some(PaneFrameStyle::from_str(string).map_err(|_| { + kdl_parsing_error!( + format!("Invalid value for pane_frame_style: '{}'", string), + entry + ) + })?), + None => None, + }; let auto_layout = kdl_property_first_arg_as_bool_or_error!(kdl_options, "auto_layout").map(|(v, _)| v); let theme = kdl_property_first_arg_as_string_or_error!(kdl_options, "theme") @@ -2881,6 +2916,7 @@ impl Options { theme_dir, mouse_mode, pane_frames, + pane_frame_style, mirror_session, on_force_close, scroll_buffer_size, @@ -3295,6 +3331,44 @@ impl Options { None } } + fn pane_frame_style_to_kdl(&self, add_comments: bool) -> Option<KdlNode> { + let comment_text = format!( + "{}\n{}\n{}\n{}\n{}\n{}", + " ", + "// Set the pane frame style when pane_frames is enabled", + "// Options:", + "// - full", + "// - titles (default)", + "// ", + ); + + let style_as_str = |style: &PaneFrameStyle| -> &'static str { + match style { + PaneFrameStyle::Full => "full", + PaneFrameStyle::Titles => "titles", + PaneFrameStyle::None => "none", + } + }; + + let create_node = |node_value: &str| -> KdlNode { + let mut node = KdlNode::new("pane_frame_style"); + node.push(node_value.to_owned()); + node + }; + if let Some(pane_frame_style) = &self.pane_frame_style { + let mut node = create_node(style_as_str(pane_frame_style)); + if add_comments { + node.set_leading(format!("{}\n", comment_text)); + } + Some(node) + } else if add_comments { + let mut node = create_node("titles"); + node.set_leading(format!("{}\n// ", comment_text)); + Some(node) + } else { + None + } + } fn mirror_session_to_kdl(&self, add_comments: bool) -> Option<KdlNode> { let comment_text = format!( "{}\n{}\n{}\n{}\n{}\n{}\n{}", @@ -4419,6 +4493,9 @@ impl Options { if let Some(pane_frames) = self.pane_frames_to_kdl(add_comments) { nodes.push(pane_frames); } + if let Some(pane_frame_style) = self.pane_frame_style_to_kdl(add_comments) { + nodes.push(pane_frame_style); + } if let Some(mirror_session) = self.mirror_session_to_kdl(add_comments) { nodes.push(mirror_session); } diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap index 5dbede33..2d0063ce 100644 --- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap +++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap @@ -359,6 +359,13 @@ web_client { // // pane_frames false +// Set the pane frame style when pane_frames is enabled +// Options: +// - full +// - titles (default) +// +// pane_frame_style "titles" + // When attaching to an existing session with other users, // should the session be mirrored (true) // or should each user have their own cursor (false) diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap index 347a2074..a69641fe 100644 --- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap +++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__config_options_to_string_with_comments.snap @@ -77,6 +77,13 @@ mouse_mode false // pane_frames false +// Set the pane frame style when pane_frames is enabled +// Options: +// - full +// - titles (default) +// +// pane_frame_style "titles" + // When attaching to an existing session with other users, // should the session be mirrored (true) // or should each user have their own cursor (false) diff --git a/zellij-utils/src/plugin_api/action.proto b/zellij-utils/src/plugin_api/action.proto index 68c859b8..f9370961 100644 --- a/zellij-utils/src/plugin_api/action.proto +++ b/zellij-utils/src/plugin_api/action.proto @@ -2,6 +2,7 @@ syntax = "proto3"; import "input_mode.proto"; import "resize.proto"; +import "pane_frame_style.proto"; package api.action; @@ -245,9 +246,14 @@ message Action { ShowFloatingPanesPayload show_floating_panes_payload = 58; HideFloatingPanesPayload hide_floating_panes_payload = 59; AreFloatingPanesVisiblePayload are_floating_panes_visible_payload = 60; + SetPaneFrameStylePayload set_pane_frame_style_payload = 61; } } +message SetPaneFrameStylePayload { + pane_frame_style.PaneFrameStyle pane_frame_style = 1; +} + message CliPipePayload { optional string name = 1; string payload = 2; @@ -494,6 +500,7 @@ enum ActionName { SetLightTheme = 102; ToggleTheme = 103; FocusLastPane = 104; + SetPaneFrameStyle = 105; } message Position { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index f4e35d84..209bff3f 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -58,6 +58,7 @@ pub use super::generated_api::api::{ ScrollAtPayload, SearchDirection as ProtobufSearchDirection, SearchOption as ProtobufSearchOption, + SetPaneFrameStylePayload, ShowFloatingPanesPayload, SplitDirection as ProtobufSplitDirection, SplitSize as ProtobufSplitSize, @@ -74,6 +75,7 @@ pub use super::generated_api::api::{ WritePayload, }, input_mode::InputMode as ProtobufInputMode, + pane_frame_style::PaneFrameStyle as ProtobufPaneFrameStyle, resize::{Resize as ProtobufResize, ResizeDirection as ProtobufResizeDirection}, }; use crate::data::{ @@ -300,6 +302,17 @@ impl TryFrom<ProtobufAction> for Action { Some(_) => Err("TogglePaneFrames should not have a payload"), None => Ok(Action::TogglePaneFrames), }, + Some(ProtobufActionName::SetPaneFrameStyle) => match protobuf_action.optional_payload { + Some(OptionalPayload::SetPaneFrameStylePayload(payload)) => { + match ProtobufPaneFrameStyle::from_i32(payload.pane_frame_style) { + Some(protobuf_pane_frame_style) => Ok(Action::SetPaneFrameStyle( + protobuf_pane_frame_style.try_into()?, + )), + None => Err("Malformed payload for Action::SetPaneFrameStyle"), + } + }, + _ => Err("Wrong payload for Action::SetPaneFrameStyle"), + }, Some(ProtobufActionName::ToggleActiveSyncTab) => { match protobuf_action.optional_payload { Some(_) => Err("ToggleActiveSyncTab should not have a payload"), @@ -1301,6 +1314,15 @@ impl TryFrom<Action> for ProtobufAction { name: ProtobufActionName::TogglePaneFrames as i32, optional_payload: None, }), + Action::SetPaneFrameStyle(pane_frame_style) => Ok(ProtobufAction { + name: ProtobufActionName::SetPaneFrameStyle as i32, + optional_payload: Some(OptionalPayload::SetPaneFrameStylePayload( + SetPaneFrameStylePayload { + pane_frame_style: ProtobufPaneFrameStyle::try_from(pane_frame_style)? + as i32, + }, + )), + }), Action::ToggleActiveSyncTab => Ok(ProtobufAction { name: ProtobufActionName::ToggleActiveSyncTab as i32, optional_payload: None, @@ -3235,3 +3257,23 @@ impl TryFrom<SwapFloatingLayout> for ProtobufSwapFloatingLayout { }) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::input::options::PaneFrameStyle; + + #[test] + fn set_pane_frame_style_action_protobuf_round_trip() { + for style in [ + PaneFrameStyle::Full, + PaneFrameStyle::Titles, + PaneFrameStyle::None, + ] { + let original = Action::SetPaneFrameStyle(style); + let protobuf: ProtobufAction = original.clone().try_into().expect("encode"); + let decoded: Action = protobuf.try_into().expect("decode"); + assert_eq!(original, decoded); + } + } +} diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto index 2567c657..d3148edf 100644 --- a/zellij-utils/src/plugin_api/event.proto +++ b/zellij-utils/src/plugin_api/event.proto @@ -70,6 +70,8 @@ enum EventType { CommandChanged = 45; HostTerminalThemeChanged = 46; SoftKeyboardVisibilityChanged = 47; + HintText = 48; + ActivePaneScroll = 49; } message EventNameList { @@ -119,9 +121,29 @@ message Event { CommandChangedPayload command_changed_payload = 39; HostTerminalThemeChangedPayload host_terminal_theme_changed_payload = 40; SoftKeyboardVisibilityChangedPayload soft_keyboard_visibility_changed_payload = 41; + HintTextPayload hint_text_payload = 42; + ActivePaneScrollPayload active_pane_scroll_payload = 43; } } +message HintTextPayload { + map<uint32, StyledText> hint_text = 1; +} + +message ActivePaneScrollPayload { + optional uint32 position = 1; + optional uint32 length = 2; +} + +message StyledText { + string text = 1; + repeated StyledTextIndices indices = 2; +} + +message StyledTextIndices { + repeated uint32 indices = 1; +} + message HostTerminalThemeChangedPayload { HostTerminalThemeIndication mode = 1; } @@ -488,6 +510,7 @@ message ModeUpdatePayload { optional string web_server_ip = 13; optional uint32 web_server_port = 14; optional bool web_server_capability = 15; + optional PaneFrameStyle pane_frame_style = 16; } enum WebSharing { @@ -496,6 +519,12 @@ enum WebSharing { Disabled = 2; } +enum PaneFrameStyle { + Full = 0; + Titles = 1; + None = 2; +} + message InputModeKeybinds { input_mode.InputMode mode = 1; repeated KeyBind key_bind = 2; diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs index 5ba106d0..190552d4 100644 --- a/zellij-utils/src/plugin_api/event.rs +++ b/zellij-utils/src/plugin_api/event.rs @@ -4,6 +4,7 @@ pub use super::generated_api::api::{ event::Payload as ProtobufEventPayload, layout_parsing_error::ErrorType as ProtobufLayoutParsingErrorType, pane_scrollback_response, ActionCompletePayload as ProtobufActionCompletePayload, + ActivePaneScrollPayload as ProtobufActivePaneScrollPayload, AvailableLayoutInfoPayload as ProtobufAvailableLayoutInfoPayload, ClientInfo as ProtobufClientInfo, ClientPaneHistory as ProtobufClientPaneHistory, ClientTabHistory as ProtobufClientTabHistory, @@ -11,6 +12,7 @@ pub use super::generated_api::api::{ CopyDestination as ProtobufCopyDestination, CwdChangedPayload as ProtobufCwdChangedPayload, Event as ProtobufEvent, EventNameList as ProtobufEventNameList, EventType as ProtobufEventType, FileMetadata as ProtobufFileMetadata, + HintTextPayload as ProtobufHintTextPayload, HostTerminalThemeChangedPayload as ProtobufHostTerminalThemeChangedPayload, HostTerminalThemeIndication as ProtobufHostTerminalThemeIndication, InputModeKeybinds as ProtobufInputModeKeybinds, KdlError as ProtobufKdlError, @@ -19,14 +21,16 @@ pub use super::generated_api::api::{ LayoutParsingError as ProtobufLayoutParsingError, LayoutWithError as ProtobufLayoutWithError, ModeUpdatePayload as ProtobufModeUpdatePayload, PaneContents as ProtobufPaneContents, PaneContentsEntry as ProtobufPaneContentsEntry, - PaneId as ProtobufPaneId, PaneInfo as ProtobufPaneInfo, - PaneManifest as ProtobufPaneManifest, PaneMetadata as ProtobufPaneMetadata, + PaneFrameStyle as ProtobufPaneFrameStyle, PaneId as ProtobufPaneId, + PaneInfo as ProtobufPaneInfo, PaneManifest as ProtobufPaneManifest, + PaneMetadata as ProtobufPaneMetadata, PaneRenderReportPayload as ProtobufPaneRenderReportPayload, PaneScrollbackResponse as ProtobufPaneScrollbackResponse, PaneType as ProtobufPaneType, PluginConfigurationChangedPayload as ProtobufPluginConfigurationChangedPayload, PluginInfo as ProtobufPluginInfo, ResurrectableSession as ProtobufResurrectableSession, SelectedText as ProtobufSelectedText, SessionManifest as ProtobufSessionManifest, SoftKeyboardVisibilityChangedPayload as ProtobufSoftKeyboardVisibilityChangedPayload, + StyledText as ProtobufStyledText, StyledTextIndices as ProtobufStyledTextIndices, SyntaxError as ProtobufSyntaxError, TabInfo as ProtobufTabInfo, TabMetadata as ProtobufTabMetadata, UserActionPayload as ProtobufUserActionPayload, WebServerStatusPayload as ProtobufWebServerStatusPayload, WebSharing as ProtobufWebSharing, @@ -41,8 +45,8 @@ use crate::data::{ ClientId, ClientInfo, CopyDestination, Event, EventType, FileMetadata, HostTerminalThemeMode, InputMode, KeyWithModifier, LayoutInfo, LayoutMetadata, ModeInfo, Mouse, PaneContents, PaneId, PaneInfo, PaneManifest, PaneMetadata, PaneScrollbackResponse, PermissionStatus, - PluginCapabilities, PluginInfo, SelectedText, SessionInfo, Style, TabInfo, TabMetadata, - WebServerStatus, WebSharing, + PluginCapabilities, PluginInfo, SelectedText, SessionInfo, Style, StyledText, TabInfo, + TabMetadata, WebServerStatus, WebSharing, }; use crate::errors::prelude::*; @@ -597,6 +601,28 @@ impl TryFrom<ProtobufEvent> for Event { _ => Err("Malformed payload for SoftKeyboardVisibilityChanged Event"), } }, + Some(ProtobufEventType::HintText) => match protobuf_event.payload { + Some(ProtobufEventPayload::HintTextPayload(p)) => { + let mut hint_text = BTreeMap::new(); + for (width, styled_text) in p.hint_text { + hint_text.insert(width as usize, StyledText::from(styled_text)); + } + Ok(Event::HintText(hint_text)) + }, + _ => Err("Malformed payload for HintText Event"), + }, + Some(ProtobufEventType::ActivePaneScroll) => match protobuf_event.payload { + Some(ProtobufEventPayload::ActivePaneScrollPayload(p)) => { + let scroll = match (p.position, p.length) { + (Some(position), Some(length)) => { + Some((position as usize, length as usize)) + }, + _ => None, + }; + Ok(Event::ActivePaneScroll(scroll)) + }, + _ => Err("Malformed payload for ActivePaneScroll Event"), + }, None => Err("Unknown Protobuf Event"), } } @@ -1147,6 +1173,35 @@ impl TryFrom<Event> for ProtobufEvent { )), }) }, + Event::HintText(hint_text) => { + let mut proto_hint_text = HashMap::new(); + for (width, styled_text) in hint_text { + proto_hint_text.insert(width as u32, ProtobufStyledText::from(styled_text)); + } + let payload = ProtobufHintTextPayload { + hint_text: proto_hint_text, + }; + Ok(ProtobufEvent { + name: ProtobufEventType::HintText as i32, + payload: Some(event::Payload::HintTextPayload(payload)), + }) + }, + Event::ActivePaneScroll(scroll) => { + let payload = match scroll { + Some((position, length)) => ProtobufActivePaneScrollPayload { + position: Some(position as u32), + length: Some(length as u32), + }, + None => ProtobufActivePaneScrollPayload { + position: None, + length: None, + }, + }; + Ok(ProtobufEvent { + name: ProtobufEventType::ActivePaneScroll as i32, + payload: Some(event::Payload::ActivePaneScrollPayload(payload)), + }) + }, Event::InitialKeybinds(keybinds) => { let mut protobuf_keybinds: Vec<ProtobufInputModeKeybinds> = vec![]; for (input_mode, input_mode_keybinds) in keybinds { @@ -1960,6 +2015,11 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo { let web_server_capability = protobuf_mode_update_payload.web_server_capability; + let pane_frame_style = protobuf_mode_update_payload + .pane_frame_style + .and_then(|p| ProtobufPaneFrameStyle::from_i32(p)) + .map(|p| p.into()); + let mode_info = ModeInfo { mode: current_mode, keybinds, @@ -1976,6 +2036,7 @@ impl TryFrom<ProtobufModeUpdatePayload> for ModeInfo { web_server_ip, web_server_port, web_server_capability, + pane_frame_style, }; Ok(mode_info) } @@ -2000,6 +2061,10 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload { let web_server_ip = mode_info.web_server_ip.map(|i| format!("{}", i)); let web_server_port = mode_info.web_server_port.map(|p| p as u32); let web_server_capability = mode_info.web_server_capability; + let pane_frame_style = mode_info.pane_frame_style.map(|p| { + let protobuf_pane_frame_style: ProtobufPaneFrameStyle = p.into(); + protobuf_pane_frame_style as i32 + }); let mut protobuf_input_mode_keybinds: Vec<ProtobufInputModeKeybinds> = vec![]; for (input_mode, input_mode_keybinds) in mode_info.keybinds { let mode: ProtobufInputMode = input_mode.try_into()?; @@ -2040,6 +2105,7 @@ impl TryFrom<ModeInfo> for ProtobufModeUpdatePayload { web_server_ip, web_server_port, web_server_capability, + pane_frame_style, }) } } @@ -2127,6 +2193,8 @@ impl TryFrom<ProtobufEventType> for EventType { ProtobufEventType::SoftKeyboardVisibilityChanged => { EventType::SoftKeyboardVisibilityChanged }, + ProtobufEventType::HintText => EventType::HintText, + ProtobufEventType::ActivePaneScroll => EventType::ActivePaneScroll, }) } } @@ -2184,10 +2252,40 @@ impl TryFrom<EventType> for ProtobufEventType { EventType::SoftKeyboardVisibilityChanged => { ProtobufEventType::SoftKeyboardVisibilityChanged }, + EventType::HintText => ProtobufEventType::HintText, + EventType::ActivePaneScroll => ProtobufEventType::ActivePaneScroll, }) } } +impl From<StyledText> for ProtobufStyledText { + fn from(styled_text: StyledText) -> Self { + ProtobufStyledText { + text: styled_text.text, + indices: styled_text + .indices + .into_iter() + .map(|inner| ProtobufStyledTextIndices { + indices: inner.into_iter().map(|i| i as u32).collect(), + }) + .collect(), + } + } +} + +impl From<ProtobufStyledText> for StyledText { + fn from(styled_text: ProtobufStyledText) -> Self { + StyledText { + text: styled_text.text, + indices: styled_text + .indices + .into_iter() + .map(|inner| inner.indices.into_iter().map(|i| i as usize).collect()) + .collect(), + } + } +} + impl From<HostTerminalThemeMode> for ProtobufHostTerminalThemeIndication { fn from(mode: HostTerminalThemeMode) -> Self { match mode { @@ -2361,6 +2459,7 @@ fn serialize_mode_update_event_with_non_default_values() { web_server_ip: IpAddr::from_str("127.0.0.1").ok(), web_server_port: Some(8082), web_server_capability: Some(true), + pane_frame_style: Some(crate::input::options::PaneFrameStyle::Titles), }); let protobuf_event: ProtobufEvent = mode_update_event.clone().try_into().unwrap(); let serialized_protobuf_event = protobuf_event.encode_to_vec(); @@ -2463,6 +2562,55 @@ fn serialize_pane_update_event() { } #[test] +fn serialize_hint_text_event() { + use prost::Message; + let hint_text_event = Event::HintText(BTreeMap::from([ + ( + 10, + StyledText { + text: "group".to_owned(), + indices: vec![vec![0]], + }, + ), + ( + 42, + StyledText { + text: "resize".to_owned(), + indices: vec![vec![0, 1], vec![3]], + }, + ), + ])); + let protobuf_event: ProtobufEvent = hint_text_event.clone().try_into().unwrap(); + let serialized_protobuf_event = protobuf_event.encode_to_vec(); + let deserialized_protobuf_event: ProtobufEvent = + Message::decode(serialized_protobuf_event.as_slice()).unwrap(); + let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap(); + assert_eq!( + hint_text_event, deserialized_event, + "Event properly serialized/deserialized without change" + ); +} + +#[test] +fn serialize_active_pane_scroll_event() { + use prost::Message; + for active_pane_scroll_event in [ + Event::ActivePaneScroll(Some((3, 12))), + Event::ActivePaneScroll(None), + ] { + let protobuf_event: ProtobufEvent = active_pane_scroll_event.clone().try_into().unwrap(); + let serialized_protobuf_event = protobuf_event.encode_to_vec(); + let deserialized_protobuf_event: ProtobufEvent = + Message::decode(serialized_protobuf_event.as_slice()).unwrap(); + let deserialized_event: Event = deserialized_protobuf_event.try_into().unwrap(); + assert_eq!( + active_pane_scroll_event, deserialized_event, + "Event properly serialized/deserialized without change" + ); + } +} + +#[test] fn serialize_key_event() { use crate::data::BareKey; use prost::Message; @@ -2946,6 +3094,26 @@ impl Into<WebSharing> for ProtobufWebSharing { } } +impl Into<ProtobufPaneFrameStyle> for crate::input::options::PaneFrameStyle { + fn into(self) -> ProtobufPaneFrameStyle { + match self { + crate::input::options::PaneFrameStyle::Full => ProtobufPaneFrameStyle::Full, + crate::input::options::PaneFrameStyle::Titles => ProtobufPaneFrameStyle::Titles, + crate::input::options::PaneFrameStyle::None => ProtobufPaneFrameStyle::None, + } + } +} + +impl Into<crate::input::options::PaneFrameStyle> for ProtobufPaneFrameStyle { + fn into(self) -> crate::input::options::PaneFrameStyle { + match self { + ProtobufPaneFrameStyle::Full => crate::input::options::PaneFrameStyle::Full, + ProtobufPaneFrameStyle::Titles => crate::input::options::PaneFrameStyle::Titles, + ProtobufPaneFrameStyle::None => crate::input::options::PaneFrameStyle::None, + } + } +} + impl TryFrom<WebServerStatus> for ProtobufWebServerStatusPayload { type Error = &'static str; fn try_from(web_server_status: WebServerStatus) -> Result<Self, &'static str> { diff --git a/zellij-utils/src/plugin_api/mod.rs b/zellij-utils/src/plugin_api/mod.rs index 0e26485e..918ad4ae 100644 --- a/zellij-utils/src/plugin_api/mod.rs +++ b/zellij-utils/src/plugin_api/mod.rs @@ -5,6 +5,7 @@ pub mod file; pub mod input_mode; pub mod key; pub mod message; +pub mod pane_frame_style; pub mod pipe_message; pub mod plugin_command; pub mod plugin_ids; diff --git a/zellij-utils/src/plugin_api/pane_frame_style.proto b/zellij-utils/src/plugin_api/pane_frame_style.proto new file mode 100644 index 00000000..0acd8bee --- /dev/null +++ b/zellij-utils/src/plugin_api/pane_frame_style.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package api.pane_frame_style; + +enum PaneFrameStyle { + Full = 0; + Titles = 1; + None = 2; +} diff --git a/zellij-utils/src/plugin_api/pane_frame_style.rs b/zellij-utils/src/plugin_api/pane_frame_style.rs new file mode 100644 index 00000000..392f2e89 --- /dev/null +++ b/zellij-utils/src/plugin_api/pane_frame_style.rs @@ -0,0 +1,49 @@ +pub use super::generated_api::api::pane_frame_style::PaneFrameStyle as ProtobufPaneFrameStyle; +use crate::input::options::PaneFrameStyle; + +use std::convert::TryFrom; + +impl TryFrom<ProtobufPaneFrameStyle> for PaneFrameStyle { + type Error = &'static str; + fn try_from(protobuf_pane_frame_style: ProtobufPaneFrameStyle) -> Result<Self, &'static str> { + match protobuf_pane_frame_style { + ProtobufPaneFrameStyle::Full => Ok(PaneFrameStyle::Full), + ProtobufPaneFrameStyle::Titles => Ok(PaneFrameStyle::Titles), + ProtobufPaneFrameStyle::None => Ok(PaneFrameStyle::None), + } + } +} + +impl TryFrom<PaneFrameStyle> for ProtobufPaneFrameStyle { + type Error = &'static str; + fn try_from(pane_frame_style: PaneFrameStyle) -> Result<Self, &'static str> { + Ok(match pane_frame_style { + PaneFrameStyle::Full => ProtobufPaneFrameStyle::Full, + PaneFrameStyle::Titles => ProtobufPaneFrameStyle::Titles, + PaneFrameStyle::None => ProtobufPaneFrameStyle::None, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn pane_frame_style_roundtrips_through_protobuf() { + for style in [ + PaneFrameStyle::Full, + PaneFrameStyle::Titles, + PaneFrameStyle::None, + ] { + let protobuf: ProtobufPaneFrameStyle = style.try_into().unwrap(); + let roundtripped: PaneFrameStyle = protobuf.try_into().unwrap(); + assert_eq!(style, roundtripped); + } + } + + #[test] + fn unknown_pane_frame_style_value_is_rejected() { + assert!(ProtobufPaneFrameStyle::from_i32(99).is_none()); + } +} diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index 82f4d835..8d31727d 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -9,6 +9,7 @@ import "resize.proto"; import "plugin_permission.proto"; import "input_mode.proto"; import "key.proto"; +import "pane_frame_style.proto"; package api.plugin_command; @@ -214,6 +215,9 @@ enum CommandName { NewTiledPaneInTab = 221; ExitMobileMode = 222; FocusLastPane = 223; + SetPaneFrameStyle = 224; + ToggleFloatingPanes = 225; + NewPane = 226; } message PluginCommand { @@ -373,9 +377,19 @@ message PluginCommand { PaneId set_shadow_focus_payload = 167; NewTabUnfocusedPayload new_tab_unfocused_payload = 168; NewTiledPaneInTabPayload new_tiled_pane_in_tab_payload = 169; + SetPaneFrameStylePayload set_pane_frame_style_payload = 170; + ToggleFloatingPanesPayload toggle_floating_panes_payload = 171; } } +message SetPaneFrameStylePayload { + pane_frame_style.PaneFrameStyle pane_frame_style = 1; +} + +message ToggleFloatingPanesPayload { + optional uint64 tab_id = 1; +} + message NewTabPayload { optional string name = 1; optional string cwd = 2; diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index 546c3586..38c42565 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -6,6 +6,7 @@ pub use super::generated_api::api::{ SessionManifest as ProtobufSessionManifest, }, input_mode::InputMode as ProtobufInputMode, + pane_frame_style::PaneFrameStyle as ProtobufPaneFrameStyle, plugin_command::{ break_panes_to_new_tab_response, break_panes_to_tab_with_id_response, break_panes_to_tab_with_index_response, delete_layout_response, dump_layout_response, @@ -120,16 +121,18 @@ pub use super::generated_api::api::{ SaveSessionResponse as ProtobufSaveSessionResponse, ScrollDownInPaneIdPayload, ScrollToBottomInPaneIdPayload, ScrollToTopInPaneIdPayload, ScrollUpInPaneIdPayload, SessionListSnapshot as ProtobufSessionListSnapshot, SetFloatingPanePinnedPayload, - SetPaneBorderlessPayload, SetPaneColorPayload, SetPaneRegexHighlightsPayload, - SetSelfMouseSelectionSupportPayload, + SetPaneBorderlessPayload, SetPaneColorPayload, + SetPaneFrameStylePayload as ProtobufSetPaneFrameStylePayload, + SetPaneRegexHighlightsPayload, SetSelfMouseSelectionSupportPayload, SetSoftKeyboardPayload as ProtobufSetSoftKeyboardPayload, SetTabFitPayload as ProtobufSetTabFitPayload, SetTimeoutPayload, ShowCursorPayload, ShowFloatingPanesPayload as ProtobufShowFloatingPanesPayload, ShowFloatingPanesResponse as ProtobufShowFloatingPanesResponse, ShowPaneWithIdPayload, Size as ProtobufSize, StackPanesPayload, SubscribePayload, SwitchSessionPayload, - SwitchTabToIdPayload, SwitchTabToPayload, TogglePaneBorderlessPayload, - TogglePaneEmbedOrEjectForPaneIdPayload, TogglePaneIdFullscreenPayload, UnsubscribePayload, - WebRequestPayload, WriteCharsToPaneIdPayload, WriteToPaneIdPayload, + SwitchTabToIdPayload, SwitchTabToPayload, ToggleFloatingPanesPayload, + TogglePaneBorderlessPayload, TogglePaneEmbedOrEjectForPaneIdPayload, + TogglePaneIdFullscreenPayload, UnsubscribePayload, WebRequestPayload, + WriteCharsToPaneIdPayload, WriteToPaneIdPayload, }, plugin_permission::PermissionType as ProtobufPermissionType, resize::ResizeAction as ProtobufResizeAction, @@ -940,6 +943,20 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { }, _ => Err("Mismatched payload for NewTiledPaneInTab"), }, + Some(CommandName::ToggleFloatingPanes) => match protobuf_plugin_command.payload { + Some(Payload::ToggleFloatingPanesPayload(payload)) => { + Ok(PluginCommand::ToggleFloatingPanes { + tab_id: payload.tab_id, + }) + }, + _ => Ok(PluginCommand::ToggleFloatingPanes { tab_id: None }), + }, + Some(CommandName::NewPane) => { + if protobuf_plugin_command.payload.is_some() { + return Err("NewPane should not have a payload"); + } + Ok(PluginCommand::NewPane) + }, Some(CommandName::GoToNextTab) => { if protobuf_plugin_command.payload.is_some() { return Err("GoToNextTab should not have a payload"); @@ -1099,6 +1116,17 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand { } Ok(PluginCommand::TogglePaneFrames) }, + Some(CommandName::SetPaneFrameStyle) => match protobuf_plugin_command.payload { + Some(Payload::SetPaneFrameStylePayload(payload)) => { + match ProtobufPaneFrameStyle::from_i32(payload.pane_frame_style) { + Some(protobuf_pane_frame_style) => Ok(PluginCommand::SetPaneFrameStyle( + protobuf_pane_frame_style.try_into()?, + )), + None => Err("Malformed SetPaneFrameStyle payload"), + } + }, + _ => Err("Mismatched payload for SetPaneFrameStyle"), + }, Some(CommandName::TogglePaneEmbedOrEject) => { if protobuf_plugin_command.payload.is_some() { return Err("TogglePaneEmbedOrEject should not have a payload"); @@ -2983,6 +3011,16 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { }, )), }), + PluginCommand::ToggleFloatingPanes { tab_id } => Ok(ProtobufPluginCommand { + name: CommandName::ToggleFloatingPanes as i32, + payload: Some(Payload::ToggleFloatingPanesPayload( + ToggleFloatingPanesPayload { tab_id }, + )), + }), + PluginCommand::NewPane => Ok(ProtobufPluginCommand { + name: CommandName::NewPane as i32, + payload: None, + }), PluginCommand::GoToNextTab => Ok(ProtobufPluginCommand { name: CommandName::GoToNextTab as i32, payload: None, @@ -3093,6 +3131,15 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand { name: CommandName::TogglePaneFrames as i32, payload: None, }), + PluginCommand::SetPaneFrameStyle(pane_frame_style) => Ok(ProtobufPluginCommand { + name: CommandName::SetPaneFrameStyle as i32, + payload: Some(Payload::SetPaneFrameStylePayload( + ProtobufSetPaneFrameStylePayload { + pane_frame_style: ProtobufPaneFrameStyle::try_from(pane_frame_style)? + as i32, + }, + )), + }), PluginCommand::TogglePaneEmbedOrEject => Ok(ProtobufPluginCommand { name: CommandName::TogglePaneEmbedOrEject as i32, payload: None, @@ -5265,4 +5312,57 @@ mod tests { other => panic!("expected SetTabFit, got {:?}", other), } } + + #[test] + fn set_pane_frame_style_protobuf_round_trip() { + use crate::input::options::PaneFrameStyle; + for style in [ + PaneFrameStyle::Full, + PaneFrameStyle::Titles, + PaneFrameStyle::None, + ] { + let original = PluginCommand::SetPaneFrameStyle(style); + let protobuf: ProtobufPluginCommand = original.try_into().expect("encode"); + let decoded: PluginCommand = protobuf.try_into().expect("decode"); + match decoded { + PluginCommand::SetPaneFrameStyle(decoded_style) => { + assert_eq!(decoded_style, style) + }, + other => panic!("expected SetPaneFrameStyle, got {:?}", other), + } + } + } + + #[test] + fn new_pane_protobuf_round_trip() { + let original = PluginCommand::NewPane; + let protobuf: ProtobufPluginCommand = original.try_into().expect("encode"); + let decoded: PluginCommand = protobuf.try_into().expect("decode"); + match decoded { + PluginCommand::NewPane => {}, + other => panic!("expected NewPane, got {:?}", other), + } + } + + #[test] + fn toggle_floating_panes_focused_tab_protobuf_round_trip() { + let original = PluginCommand::ToggleFloatingPanes { tab_id: None }; + let protobuf: ProtobufPluginCommand = original.try_into().expect("encode"); + let decoded: PluginCommand = protobuf.try_into().expect("decode"); + match decoded { + PluginCommand::ToggleFloatingPanes { tab_id } => assert_eq!(tab_id, None), + other => panic!("expected ToggleFloatingPanes, got {:?}", other), + } + } + + #[test] + fn toggle_floating_panes_with_tab_id_protobuf_round_trip() { + let original = PluginCommand::ToggleFloatingPanes { tab_id: Some(2) }; + let protobuf: ProtobufPluginCommand = original.try_into().expect("encode"); + let decoded: PluginCommand = protobuf.try_into().expect("decode"); + match decoded { + PluginCommand::ToggleFloatingPanes { tab_id } => assert_eq!(tab_id, Some(2)), + other => panic!("expected ToggleFloatingPanes, got {:?}", other), + } + } } diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap index 0d51e89b..4d16821f 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_config_options.snap @@ -17,6 +17,7 @@ Options { theme_dir: None, mouse_mode: None, pane_frames: None, + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap index 1b0c154a..d8378848 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__cli_arguments_override_layout_options.snap @@ -17,6 +17,7 @@ Options { pane_frames: Some( true, ), + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap index 08b89aac..79a656a5 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments-3.snap @@ -15,6 +15,7 @@ Options { theme_dir: None, mouse_mode: None, pane_frames: None, + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap index a8a144a8..2f8c1964 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap @@ -5993,6 +5993,7 @@ Config { theme_dir: None, mouse_mode: None, pane_frames: None, + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap index 4792ab0c..e4a22a82 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap @@ -5993,6 +5993,7 @@ Config { theme_dir: None, mouse_mode: None, pane_frames: None, + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap index 8f5baed6..f703371c 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_keybinds_override_config_keybinds.snap @@ -102,6 +102,7 @@ Config { theme_dir: None, mouse_mode: None, pane_frames: None, + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap index 40822e6e..0830a4b6 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_options_override_config_options.snap @@ -17,6 +17,7 @@ Options { pane_frames: Some( false, ), + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap index 2cb1c9af..e8e1b3ee 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap @@ -5993,6 +5993,7 @@ Config { theme_dir: None, mouse_mode: None, pane_frames: None, + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, diff --git a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap index 431c8fc4..ff3a4fda 100644 --- a/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap +++ b/zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap @@ -5993,6 +5993,7 @@ Config { theme_dir: None, mouse_mode: None, pane_frames: None, + pane_frame_style: None, mirror_session: None, on_force_close: None, scroll_buffer_size: None, |
