aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-06-03 17:15:32 +0200
committerGitHub <noreply@github.com>2025-06-03 17:15:32 +0200
commita9f8bbcd197c8d14832fc1ab1fbe4d4111a2014d (patch)
tree6d354fdd36cf534d73e0cb81a7cacd3fedc1ebb9
parentdocs(changelog): theme fixes (diff)
downloadsl0ppij-a9f8bbcd197c8d14832fc1ab1fbe4d4111a2014d.tar.gz
sl0ppij-a9f8bbcd197c8d14832fc1ab1fbe4d4111a2014d.tar.xz
sl0ppij-a9f8bbcd197c8d14832fc1ab1fbe4d4111a2014d.zip
feat(ux): improve multiple select (#4221)
* intercept/clear-intercept key APIs * allow opening a pinned unfocused floating pane * rework plugin * improve some apis * fix tests * tests for pane groups * more exact placement and tests * plugin command permission and cleanup * improve some multiselect ux * improve plugin ui * remove old status indicator * allow moving plugin out of the way * style(fmt): rustfmt * update plugins * remove old keybinding * cleanups * fix: only rename pane if needed * changelog and some cleanups * style(fmt): rustfmt
-rw-r--r--CHANGELOG.md2
-rw-r--r--default-plugins/compact-bar/src/line.rs300
-rw-r--r--default-plugins/compact-bar/src/main.rs27
-rw-r--r--default-plugins/configuration/src/presets.rs24
-rw-r--r--default-plugins/multiple-select/src/main.rs770
-rw-r--r--default-plugins/multiple-select/src/state.rs634
-rw-r--r--default-plugins/multiple-select/src/ui.rs873
-rw-r--r--default-plugins/status-bar/src/main.rs26
-rw-r--r--default-plugins/status-bar/src/one_line_ui.rs252
-rw-r--r--example/config.kdl6
-rw-r--r--zellij-server/src/lib.rs1
-rw-r--r--zellij-server/src/pane_groups.rs469
-rw-r--r--zellij-server/src/panes/floating_panes/mod.rs16
-rw-r--r--zellij-server/src/panes/tiled_panes/mod.rs3
-rw-r--r--zellij-server/src/plugins/mod.rs15
-rw-r--r--zellij-server/src/plugins/plugin_loader.rs1
-rw-r--r--zellij-server/src/plugins/plugin_map.rs4
-rw-r--r--zellij-server/src/plugins/unit/plugin_tests.rs216
-rw-r--r--zellij-server/src/plugins/wasm_bridge.rs11
-rw-r--r--zellij-server/src/plugins/zellij_exports.rs33
-rw-r--r--zellij-server/src/pty.rs10
-rw-r--r--zellij-server/src/screen.rs98
-rw-r--r--zellij-server/src/tab/mod.rs75
-rw-r--r--zellij-server/src/tab/unit/tab_integration_tests.rs449
-rw-r--r--zellij-server/src/tab/unit/tab_tests.rs127
-rw-r--r--zellij-server/src/ui/pane_boundaries_frame.rs7
-rw-r--r--zellij-server/src/ui/pane_contents_and_ui.rs3
-rw-r--r--zellij-server/src/unit/screen_tests.rs70
-rw-r--r--zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap2
-rw-r--r--zellij-tile/src/shim.rs14
-rw-r--r--zellij-tile/src/ui_components/text.rs38
-rw-r--r--zellij-utils/assets/config/default.kdl6
-rwxr-xr-xzellij-utils/assets/plugins/about.wasmbin1224909 -> 1227248 bytes
-rwxr-xr-xzellij-utils/assets/plugins/compact-bar.wasmbin1241648 -> 1159630 bytes
-rwxr-xr-xzellij-utils/assets/plugins/configuration.wasmbin1288450 -> 1288854 bytes
-rwxr-xr-xzellij-utils/assets/plugins/fixture-plugin-for-tests.wasmbin1202789 -> 1205401 bytes
-rwxr-xr-xzellij-utils/assets/plugins/multiple-select.wasmbin1195843 -> 1197535 bytes
-rwxr-xr-xzellij-utils/assets/plugins/plugin-manager.wasmbin1179478 -> 1179872 bytes
-rwxr-xr-xzellij-utils/assets/plugins/session-manager.wasmbin1245393 -> 1248313 bytes
-rwxr-xr-xzellij-utils/assets/plugins/status-bar.wasmbin1428180 -> 1412225 bytes
-rwxr-xr-xzellij-utils/assets/plugins/strider.wasmbin1272028 -> 1273119 bytes
-rwxr-xr-xzellij-utils/assets/plugins/tab-bar.wasmbin1222521 -> 1225384 bytes
-rw-r--r--zellij-utils/assets/prost/api.event.rs7
-rw-r--r--zellij-utils/assets/prost/api.plugin_command.rs6
-rw-r--r--zellij-utils/assets/prost/api.plugin_permission.rs3
-rw-r--r--zellij-utils/src/data.rs5
-rw-r--r--zellij-utils/src/errors.rs2
-rw-r--r--zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap6
-rw-r--r--zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string_with_comments.snap6
-rw-r--r--zellij-utils/src/plugin_api/event.proto2
-rw-r--r--zellij-utils/src/plugin_api/event.rs12
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.proto2
-rw-r--r--zellij-utils/src/plugin_api/plugin_command.rs16
-rw-r--r--zellij-utils/src/plugin_api/plugin_permission.proto1
-rw-r--r--zellij-utils/src/plugin_api/plugin_permission.rs2
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__default_config_with_no_cli_arguments.snap377
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_env_vars_override_config_env_vars.snap377
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_themes_override_config_themes.snap377
-rw-r--r--zellij-utils/src/snapshots/zellij_utils__setup__setup_test__layout_ui_config_overrides_config_ui_config.snap377
59 files changed, 2190 insertions, 3970 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6c22301d..a3b6e220 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## [Unreleased]
-* feat: multiple select and bulk pane actions (https://github.com/zellij-org/zellij/pull/4169 and https://github.com/zellij-org/zellij/pull/4171)
+* feat: multiple select and bulk pane actions (https://github.com/zellij-org/zellij/pull/4169 and https://github.com/zellij-org/zellij/pull/4171 and https://github.com/zellij-org/zellij/pull/4221)
## [0.42.2] - 2025-04-15
* refactor(terminal): track scroll_region as tuple rather than Option (https://github.com/zellij-org/zellij/pull/4082)
diff --git a/default-plugins/compact-bar/src/line.rs b/default-plugins/compact-bar/src/line.rs
index 43431446..5d50d527 100644
--- a/default-plugins/compact-bar/src/line.rs
+++ b/default-plugins/compact-bar/src/line.rs
@@ -2,7 +2,6 @@ use ansi_term::ANSIStrings;
use unicode_width::UnicodeWidthStr;
use crate::{LinePart, ARROW_SEPARATOR};
-use zellij_tile::prelude::actions::Action;
use zellij_tile::prelude::*;
use zellij_tile_utils::style;
@@ -252,8 +251,6 @@ pub fn tab_line(
mode: InputMode,
active_swap_layout_name: &Option<String>,
is_swap_layout_dirty: bool,
- mode_info: &ModeInfo,
- grouped_pane_count: Option<usize>,
) -> Vec<LinePart> {
let mut tabs_after_active = all_tabs.split_off(active_tab_index);
let mut tabs_before_active = all_tabs;
@@ -289,21 +286,15 @@ pub fn tab_line(
if current_title_len < cols {
let mut remaining_space = cols - current_title_len;
let remaining_bg = palette.text_unselected.background;
- let right_side_component = match grouped_pane_count {
- Some(grouped_pane_count) => {
- render_group_controls(mode_info, grouped_pane_count, remaining_space)
- },
- None => swap_layout_status(
- remaining_space,
- active_swap_layout_name,
- is_swap_layout_dirty,
- mode,
- &palette,
- tab_separator(capabilities),
- ),
- };
- if let Some(right_side_component) = right_side_component {
- remaining_space -= right_side_component.len;
+ if let Some(swap_layout_status) = swap_layout_status(
+ remaining_space,
+ active_swap_layout_name,
+ is_swap_layout_dirty,
+ mode,
+ &palette,
+ tab_separator(capabilities),
+ ) {
+ remaining_space -= swap_layout_status.len;
let mut buffer = String::new();
for _ in 0..remaining_space {
buffer.push_str(&style!(remaining_bg, remaining_bg).paint(" ").to_string());
@@ -313,7 +304,7 @@ pub fn tab_line(
len: remaining_space,
tab_index: None,
});
- prefix.push(right_side_component);
+ prefix.push(swap_layout_status);
}
}
@@ -382,274 +373,3 @@ fn swap_layout_status(
None => None,
}
}
-
-fn render_group_controls(
- help: &ModeInfo,
- grouped_pane_count: usize,
- max_len: usize,
-) -> Option<LinePart> {
- let currently_marking_group = help.currently_marking_pane_group.unwrap_or(false);
- let keymap = help.get_mode_keybinds();
- let (common_modifiers, multiple_select_key, pane_group_toggle_key, group_mark_toggle_key) = {
- let multiple_select_key = multiple_select_key(&keymap);
- let pane_group_toggle_key = single_action_key(&keymap, &[Action::TogglePaneInGroup]);
- let group_mark_toggle_key = single_action_key(&keymap, &[Action::ToggleGroupMarking]);
- let common_modifiers = get_common_modifiers(
- vec![
- multiple_select_key.iter().next(),
- pane_group_toggle_key.iter().next(),
- group_mark_toggle_key.iter().next(),
- ]
- .into_iter()
- .filter_map(|k| k)
- .collect(),
- );
- let multiple_select_key: Vec<KeyWithModifier> = multiple_select_key
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- let pane_group_toggle_key: Vec<KeyWithModifier> = pane_group_toggle_key
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- let group_mark_toggle_key: Vec<KeyWithModifier> = group_mark_toggle_key
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- (
- common_modifiers,
- multiple_select_key,
- pane_group_toggle_key,
- group_mark_toggle_key,
- )
- };
- let multiple_select_key = multiple_select_key
- .iter()
- .next()
- .map(|key| format!("{}", key))
- .unwrap_or("UNBOUND".to_owned());
- let pane_group_toggle_key = pane_group_toggle_key
- .iter()
- .next()
- .map(|key| format!("{}", key))
- .unwrap_or("UNBOUND".to_owned());
- let group_mark_toggle_key = group_mark_toggle_key
- .iter()
- .next()
- .map(|key| format!("{}", key))
- .unwrap_or("UNBOUND".to_owned());
- let background = help.style.colors.text_unselected.background;
- let foreground = help.style.colors.text_unselected.base;
- let superkey_prefix_style = style!(foreground, background).bold();
- let common_modifier_text = if common_modifiers.is_empty() {
- "".to_owned()
- } else {
- format!(
- "{} + ",
- common_modifiers
- .iter()
- .map(|c| c.to_string())
- .collect::<Vec<_>>()
- .join("-")
- )
- };
-
- // full
- let full_selected_panes_text = if common_modifier_text.is_empty() {
- format!("{} SELECTED PANES", grouped_pane_count)
- } else {
- format!("{} SELECTED PANES |", grouped_pane_count)
- };
- let full_group_actions_text = format!("<{}> Group Actions", &multiple_select_key);
- let full_toggle_group_text = format!("<{}> Toggle Group", &pane_group_toggle_key);
- let full_group_mark_toggle_text = format!("<{}> Follow Focus", &group_mark_toggle_key);
- let ribbon_paddings_len = 12;
- let full_controls_line_len = full_selected_panes_text.chars().count()
- + 1
- + common_modifier_text.chars().count()
- + full_group_actions_text.chars().count()
- + full_toggle_group_text.chars().count()
- + full_group_mark_toggle_text.chars().count()
- + ribbon_paddings_len
- + 1; // 1 for the end padding
-
- // medium
- let medium_selected_panes_text = if common_modifier_text.is_empty() {
- format!("{} SELECTED", grouped_pane_count)
- } else {
- format!("{} SELECTED |", grouped_pane_count)
- };
- let medium_group_actions_text = format!("<{}> Actions", &multiple_select_key);
- let medium_toggle_group_text = format!("<{}> Toggle", &pane_group_toggle_key);
- let medium_group_mark_toggle_text = format!("<{}> Follow", &group_mark_toggle_key);
- let ribbon_paddings_len = 12;
- let medium_controls_line_len = medium_selected_panes_text.chars().count()
- + 1
- + common_modifier_text.chars().count()
- + medium_group_actions_text.chars().count()
- + medium_toggle_group_text.chars().count()
- + medium_group_mark_toggle_text.chars().count()
- + ribbon_paddings_len
- + 1; // 1 for the end padding
-
- // short
- let short_selected_panes_text = if common_modifier_text.is_empty() {
- format!("{} SELECTED", grouped_pane_count)
- } else {
- format!("{} SELECTED |", grouped_pane_count)
- };
- let short_group_actions_text = format!("<{}>", &multiple_select_key);
- let short_toggle_group_text = format!("<{}>", &pane_group_toggle_key);
- let short_group_mark_toggle_text = format!("<{}>", &group_mark_toggle_key);
- let color_emphasis_range_end = if common_modifier_text.is_empty() {
- 0
- } else {
- 2
- };
- let ribbon_paddings_len = 12;
- let short_controls_line_len = short_selected_panes_text.chars().count()
- + 1
- + common_modifier_text.chars().count()
- + short_group_actions_text.chars().count()
- + short_toggle_group_text.chars().count()
- + short_group_mark_toggle_text.chars().count()
- + ribbon_paddings_len
- + 1; // 1 for the end padding
-
- let (
- selected_panes_text,
- group_actions_text,
- toggle_group_text,
- group_mark_toggle_text,
- controls_line_len,
- ) = if max_len >= full_controls_line_len {
- (
- full_selected_panes_text,
- full_group_actions_text,
- full_toggle_group_text,
- full_group_mark_toggle_text,
- full_controls_line_len,
- )
- } else if max_len >= medium_controls_line_len {
- (
- medium_selected_panes_text,
- medium_group_actions_text,
- medium_toggle_group_text,
- medium_group_mark_toggle_text,
- medium_controls_line_len,
- )
- } else if max_len >= short_controls_line_len {
- (
- short_selected_panes_text,
- short_group_actions_text,
- short_toggle_group_text,
- short_group_mark_toggle_text,
- short_controls_line_len,
- )
- } else {
- return None;
- };
- let selected_panes = serialize_text(
- &Text::new(&selected_panes_text)
- .color_range(
- 3,
- ..selected_panes_text
- .chars()
- .count()
- .saturating_sub(color_emphasis_range_end),
- )
- .opaque(),
- );
- let group_actions_ribbon = serialize_ribbon(
- &Text::new(&group_actions_text).color_range(0, 1..=multiple_select_key.chars().count()),
- );
- let toggle_group_ribbon = serialize_ribbon(
- &Text::new(&toggle_group_text).color_range(0, 1..=pane_group_toggle_key.chars().count()),
- );
- let mut group_mark_toggle_ribbon = Text::new(&group_mark_toggle_text)
- .color_range(0, 1..=group_mark_toggle_key.chars().count());
- if currently_marking_group {
- group_mark_toggle_ribbon = group_mark_toggle_ribbon.selected();
- }
- let group_mark_toggle_ribbon = serialize_ribbon(&group_mark_toggle_ribbon);
- let controls_line = if common_modifiers.is_empty() {
- format!(
- "{} {}{}{}",
- selected_panes, group_actions_ribbon, toggle_group_ribbon, group_mark_toggle_ribbon
- )
- } else {
- let common_modifier =
- serialize_text(&Text::new(&common_modifier_text).color_range(0, ..).opaque());
- format!(
- "{} {}{}{}{}",
- selected_panes,
- common_modifier,
- group_actions_ribbon,
- toggle_group_ribbon,
- group_mark_toggle_ribbon
- )
- };
- let remaining_space = max_len.saturating_sub(controls_line_len);
- let mut padding = String::new();
- let mut padding_len = 0;
- for _ in 0..remaining_space {
- padding.push_str(&ANSIStrings(&[superkey_prefix_style.paint(" ")]).to_string());
- padding_len += 1;
- }
- Some(LinePart {
- part: format!("{}{}", padding, controls_line),
- len: controls_line_len + padding_len,
- tab_index: None,
- })
-}
-
-fn multiple_select_key(keymap: &[(KeyWithModifier, Vec<Action>)]) -> Vec<KeyWithModifier> {
- let mut matching = keymap.iter().find_map(|(key, acvec)| {
- let has_match = acvec
- .iter()
- .find(|a| a.launches_plugin("zellij:multiple-select")) // TODO: make this an alias
- .is_some();
- if has_match {
- Some(key.clone())
- } else {
- None
- }
- });
- if let Some(matching) = matching.take() {
- vec![matching]
- } else {
- vec![]
- }
-}
-
-fn single_action_key(
- keymap: &[(KeyWithModifier, Vec<Action>)],
- action: &[Action],
-) -> Vec<KeyWithModifier> {
- let mut matching = keymap.iter().find_map(|(key, acvec)| {
- if acvec.iter().next() == action.iter().next() {
- Some(key.clone())
- } else {
- None
- }
- });
- if let Some(matching) = matching.take() {
- vec![matching]
- } else {
- vec![]
- }
-}
-
-fn get_common_modifiers(mut keyvec: Vec<&KeyWithModifier>) -> Vec<KeyModifier> {
- if keyvec.is_empty() {
- return vec![];
- }
- let mut common_modifiers = keyvec.pop().unwrap().key_modifiers.clone();
- for key in keyvec {
- common_modifiers = common_modifiers
- .intersection(&key.key_modifiers)
- .cloned()
- .collect();
- }
- common_modifiers.into_iter().collect()
-}
diff --git a/default-plugins/compact-bar/src/main.rs b/default-plugins/compact-bar/src/main.rs
index d4a43ab8..91924211 100644
--- a/default-plugins/compact-bar/src/main.rs
+++ b/default-plugins/compact-bar/src/main.rs
@@ -26,8 +26,6 @@ struct State {
tab_line: Vec<LinePart>,
text_copy_destination: Option<CopyDestination>,
display_system_clipboard_failure: bool,
- own_client_id: Option<ClientId>,
- grouped_panes_count: Option<usize>,
}
static ARROW_SEPARATOR: &str = "";
@@ -46,7 +44,6 @@ impl ZellijPlugin for State {
EventType::SystemClipboardFailure,
EventType::PaneUpdate,
]);
- self.own_client_id = Some(get_plugin_ids().client_id);
}
fn update(&mut self, event: Event) -> bool {
@@ -112,28 +109,6 @@ impl ZellijPlugin for State {
self.text_copy_destination = None;
self.display_system_clipboard_failure = false;
},
- Event::PaneUpdate(pane_manifest) => {
- if let Some(own_client_id) = self.own_client_id {
- let mut grouped_panes_count = 0;
- for (_tab_index, pane_infos) in pane_manifest.panes {
- for pane_info in pane_infos {
- let is_in_pane_group =
- pane_info.index_in_pane_group.get(&own_client_id).is_some();
- if is_in_pane_group {
- grouped_panes_count += 1;
- }
- }
- }
- if Some(grouped_panes_count) != self.grouped_panes_count {
- if grouped_panes_count == 0 {
- self.grouped_panes_count = None;
- } else {
- self.grouped_panes_count = Some(grouped_panes_count);
- }
- should_render = true;
- }
- }
- },
_ => {
eprintln!("Got unrecognized event: {:?}", event);
},
@@ -207,8 +182,6 @@ impl ZellijPlugin for State {
self.mode_info.mode,
&active_swap_layout_name,
is_swap_layout_dirty,
- &self.mode_info,
- self.grouped_panes_count,
);
let output = self
.tab_line
diff --git a/default-plugins/configuration/src/presets.rs b/default-plugins/configuration/src/presets.rs
index 54713635..abe26afc 100644
--- a/default-plugins/configuration/src/presets.rs
+++ b/default-plugins/configuration/src/presets.rs
@@ -168,12 +168,6 @@ keybinds clear-defaults=true {{
bind "{secondary_modifier} -" {{ Resize "Decrease"; }}
bind "{secondary_modifier} [" {{ PreviousSwapLayout; }}
bind "{secondary_modifier} ]" {{ NextSwapLayout; }}
- bind "{secondary_modifier} m" {{
- LaunchOrFocusPlugin "zellij:multiple-select" {{
- floating true
- move_to_focused_tab true
- }}
- }}
bind "{secondary_modifier} p" {{ TogglePaneInGroup; }}
bind "{secondary_modifier} Shift p" {{ ToggleGroupMarking; }}
}}
@@ -400,12 +394,6 @@ keybinds clear-defaults=true {{
bind "{secondary_modifier} -" {{ Resize "Decrease"; }}
bind "{secondary_modifier} [" {{ PreviousSwapLayout; }}
bind "{secondary_modifier} ]" {{ NextSwapLayout; }}
- bind "{secondary_modifier} m" {{
- LaunchOrFocusPlugin "zellij:multiple-select" {{
- floating true
- move_to_focused_tab true
- }}
- }}
bind "{secondary_modifier} p" {{ TogglePaneInGroup; }}
bind "{secondary_modifier} Shift p" {{ ToggleGroupMarking; }}
}}
@@ -611,12 +599,6 @@ keybinds clear-defaults=true {{
bind "{secondary_modifier} -" {{ Resize "Decrease"; }}
bind "{secondary_modifier} [" {{ PreviousSwapLayout; }}
bind "{secondary_modifier} ]" {{ NextSwapLayout; }}
- bind "{secondary_modifier} m" {{
- LaunchOrFocusPlugin "zellij:multiple-select" {{
- floating true
- move_to_focused_tab true
- }}
- }}
bind "{secondary_modifier} p" {{ TogglePaneInGroup; }}
bind "{secondary_modifier} Shift p" {{ ToggleGroupMarking; }}
}}
@@ -1182,12 +1164,6 @@ keybinds clear-defaults=true {{
bind "{secondary_modifier} -" {{ Resize "Decrease"; }}
bind "{secondary_modifier} [" {{ PreviousSwapLayout; }}
bind "{secondary_modifier} ]" {{ NextSwapLayout; }}
- bind "{secondary_modifier} m" {{
- LaunchOrFocusPlugin "zellij:multiple-select" {{
- floating true
- move_to_focused_tab true
- }}
- }}
bind "{secondary_modifier} p" {{ TogglePaneInGroup; }}
bind "{secondary_modifier} Shift p" {{ ToggleGroupMarking; }}
}}
diff --git a/default-plugins/multiple-select/src/main.rs b/default-plugins/multiple-select/src/main.rs
index 773fd6fb..6bcd9b9b 100644
--- a/default-plugins/multiple-select/src/main.rs
+++ b/default-plugins/multiple-select/src/main.rs
@@ -1,9 +1,6 @@
-pub mod state;
-pub mod ui;
-
-use state::{MarkedIndex, VisibilityAndFocus};
use std::collections::BTreeMap;
-use ui::PaneItem;
+use std::time::Instant;
+use zellij_tile::prelude::actions::Action;
use zellij_tile::prelude::*;
#[derive(Debug, Default)]
@@ -12,13 +9,17 @@ pub struct App {
own_client_id: Option<ClientId>,
own_tab_index: Option<usize>,
total_tabs_in_session: Option<usize>,
- search_string: String,
- previous_search_string: String, // used eg. for the new tab title when breaking panes
- left_side_panes: Vec<PaneItem>,
- right_side_panes: Vec<PaneItem>,
- search_results: Option<Vec<PaneItem>>,
- visibility_and_focus: VisibilityAndFocus,
- marked_index: Option<MarkedIndex>,
+ grouped_panes: Vec<PaneId>,
+ grouped_panes_count: usize,
+ mode_info: ModeInfo,
+ closing: bool,
+ highlighted_at: Option<Instant>,
+ baseline_ui_width: usize,
+ current_rows: usize,
+ current_cols: usize,
+ display_area_rows: usize,
+ display_area_cols: usize,
+ alternate_coordinates: bool,
}
register_plugin!(App);
@@ -27,186 +28,597 @@ impl ZellijPlugin for App {
fn load(&mut self, _configuration: BTreeMap<String, String>) {
subscribe(&[
EventType::Key,
- EventType::Mouse,
+ EventType::InterceptedKeyPress,
EventType::ModeUpdate,
- EventType::RunCommandResult,
- EventType::TabUpdate,
EventType::PaneUpdate,
- EventType::FailedToWriteConfigToDisk,
- EventType::ConfigWasWrittenToDisk,
- EventType::BeforeClose,
+ EventType::TabUpdate,
+ EventType::Timer,
]);
+
let plugin_ids = get_plugin_ids();
self.own_plugin_id = Some(plugin_ids.plugin_id);
self.own_client_id = Some(plugin_ids.client_id);
- rename_plugin_pane(plugin_ids.plugin_id, "Multiple Select");
+
+ intercept_key_presses();
+ set_selectable(false);
}
+
fn update(&mut self, event: Event) -> bool {
- let mut should_render = false;
+ if self.closing {
+ return false;
+ }
match event {
- Event::PaneUpdate(pane_manifest) => {
- self.react_to_zellij_state_update(pane_manifest);
- should_render = true;
- },
- Event::Key(key) => {
- match key.bare_key {
- BareKey::Tab if key.has_no_modifiers() => {
- self.visibility_and_focus.toggle_focus();
- self.marked_index = None;
- self.update_highlighted_panes();
- should_render = true;
- },
- BareKey::Char(character)
- if key.has_no_modifiers()
- && self.visibility_and_focus.left_side_is_focused()
- && self.marked_index.is_none() =>
- {
- self.search_string.push(character);
- self.update_search_results();
- should_render = true;
- },
- BareKey::Backspace
- if key.has_no_modifiers()
- && self.visibility_and_focus.left_side_is_focused()
- && self.marked_index.is_none() =>
- {
- self.search_string.pop();
- self.update_search_results();
- should_render = true;
- },
- BareKey::Enter if key.has_no_modifiers() => {
- if self.visibility_and_focus.left_side_is_focused() {
- if let Some(marked_index) = self.marked_index.take() {
- let keep_left_side_focused = false;
- self.group_panes(marked_index, keep_left_side_focused);
- } else {
- match self.search_results.take() {
- Some(search_results) => {
- self.group_search_results(search_results)
- },
- None => self.group_all_panes(),
- }
- self.handle_left_side_emptied();
- }
- }
- should_render = true;
- },
- BareKey::Right
- if key.has_no_modifiers()
- && self.visibility_and_focus.left_side_is_focused() =>
- {
- if let Some(marked_index) = self.marked_index.take() {
- let keep_left_side_focused = true;
- self.group_panes(marked_index, keep_left_side_focused);
- should_render = true;
- }
- },
- BareKey::Left
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- if self.visibility_and_focus.right_side_is_focused() {
- if let Some(marked_index) = self.marked_index.take() {
- self.ungroup_panes(marked_index);
- should_render = true;
- }
- }
- },
- BareKey::Char('c') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
- if self.visibility_and_focus.right_side_is_focused() {
- // this means we're in the selection panes part and we want to clear
- // them
- self.ungroup_all_panes();
- } else if self.visibility_and_focus.left_side_is_focused() {
- if self.marked_index.is_some() {
- self.marked_index = None;
- self.update_highlighted_panes();
- } else {
- self.ungroup_all_panes_and_close_self();
- }
- }
- should_render = true;
- },
- BareKey::Down if key.has_no_modifiers() => {
- self.move_marked_index_down();
- should_render = true;
- },
- BareKey::Up if key.has_no_modifiers() => {
- self.move_marked_index_up();
- should_render = true;
- },
- BareKey::Char(' ') if key.has_no_modifiers() && self.marked_index.is_some() => {
- self.mark_entry();
- should_render = true;
- },
- BareKey::Char('b')
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- self.break_grouped_panes_to_new_tab();
- },
- BareKey::Char('s')
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- self.stack_grouped_panes();
- },
- BareKey::Char('f')
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- self.float_grouped_panes();
- },
- BareKey::Char('e')
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- self.embed_grouped_panes();
- },
- BareKey::Char('r')
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- self.break_grouped_panes_right();
- },
- BareKey::Char('l')
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- self.break_grouped_panes_left();
- },
- BareKey::Char('c')
- if key.has_no_modifiers()
- && self.visibility_and_focus.right_side_is_focused() =>
- {
- self.close_grouped_panes();
- },
- _ => {},
- }
- },
- Event::BeforeClose => {
- self.unhighlight_all_panes();
- },
- _ => {},
+ Event::ModeUpdate(mode_info) => self.handle_mode_update(mode_info),
+ Event::PaneUpdate(pane_manifest) => self.handle_pane_update(pane_manifest),
+ Event::TabUpdate(tab_infos) => self.handle_tab_update(tab_infos),
+ Event::InterceptedKeyPress(key) => self.handle_key_press(key),
+ Event::Timer(_) => self.handle_timer(),
+ _ => false,
}
- should_render
}
+
fn render(&mut self, rows: usize, cols: usize) {
- self.render_close_shortcut(cols);
- self.render_tab_shortcut(cols, rows);
- match self.visibility_and_focus {
- VisibilityAndFocus::OnlyLeftSideVisible => self.render_left_side(rows, cols, true),
- VisibilityAndFocus::OnlyRightSideVisible => self.render_right_side(rows, cols, true),
- VisibilityAndFocus::BothSidesVisibleLeftSideFocused => {
- self.render_left_side(rows, cols, true);
- self.render_right_side(rows, cols, false);
- },
- VisibilityAndFocus::BothSidesVisibleRightSideFocused => {
- self.render_left_side(rows, cols, false);
- self.render_right_side(rows, cols, true);
+ self.update_current_size(rows, cols);
+ let ui_width = self.calculate_ui_width();
+ self.update_baseline_ui_width(ui_width);
+ let base_x = cols.saturating_sub(self.baseline_ui_width) / 2;
+ let base_y = rows.saturating_sub(8) / 2;
+ self.render_header(base_x, base_y);
+ self.render_shortcuts(base_x, base_y + 2);
+ self.render_controls(base_x, base_y + 7);
+ }
+}
+
+impl App {
+ fn update_current_size(&mut self, new_rows: usize, new_cols: usize) {
+ let size_changed = new_rows != self.current_rows || new_cols != self.current_cols;
+ self.current_rows = new_rows;
+ self.current_cols = new_cols;
+ if size_changed {
+ self.baseline_ui_width = 0;
+ }
+ }
+ fn update_baseline_ui_width(&mut self, current_ui_width: usize) {
+ if current_ui_width > self.baseline_ui_width {
+ self.baseline_ui_width = current_ui_width;
+ }
+ }
+
+ fn calculate_ui_width(&self) -> usize {
+ let controls_width = group_controls_length(&self.mode_info);
+
+ let header_width = Self::header_text().0.len();
+ let shortcuts_max_width = Self::shortcuts_max_width();
+
+ std::cmp::max(
+ controls_width,
+ std::cmp::max(header_width, shortcuts_max_width),
+ )
+ }
+
+ fn header_text() -> (&'static str, Text) {
+ let header_text = "<ESC> - cancel, <TAB> - move";
+ let header_text_component = Text::new(header_text)
+ .color_substring(3, "<ESC>")
+ .color_substring(3, "<TAB>");
+ (header_text, header_text_component)
+ }
+
+ fn shortcuts_max_width() -> usize {
+ std::cmp::max(
+ std::cmp::max(
+ Self::group_actions_text().0.len(),
+ Self::shortcuts_line1_text().0.len(),
+ ),
+ std::cmp::max(
+ Self::shortcuts_line2_text().0.len(),
+ Self::shortcuts_line3_text().0.len(),
+ ),
+ )
+ }
+
+ fn group_actions_text() -> (&'static str, Text) {
+ let text = "GROUP ACTIONS";
+ let component = Text::new(text).color_all(2);
+ (text, component)
+ }
+
+ fn shortcuts_line1_text() -> (&'static str, Text) {
+ let text = "<b> - break out, <s> - stack, <c> - close";
+ let component = Text::new(text)
+ .color_substring(3, "<b>")
+ .color_substring(3, "<s>")
+ .color_substring(3, "<c>");
+ (text, component)
+ }
+
+ fn shortcuts_line2_text() -> (&'static str, Text) {
+ let text = "<r> - break right, <l> - break left";
+ let component = Text::new(text)
+ .color_substring(3, "<r>")
+ .color_substring(3, "<l>");
+ (text, component)
+ }
+
+ fn shortcuts_line3_text() -> (&'static str, Text) {
+ let text = "<e> - embed, <f> - float";
+ let component = Text::new(text)
+ .color_substring(3, "<e>")
+ .color_substring(3, "<f>");
+ (text, component)
+ }
+
+ fn handle_mode_update(&mut self, mode_info: ModeInfo) -> bool {
+ if self.mode_info != mode_info {
+ self.mode_info = mode_info;
+ let ui_width = self.calculate_ui_width();
+ self.update_baseline_ui_width(ui_width);
+ true
+ } else {
+ false
+ }
+ }
+
+ fn handle_pane_update(&mut self, pane_manifest: PaneManifest) -> bool {
+ let Some(own_client_id) = self.own_client_id else {
+ return false;
+ };
+
+ self.update_grouped_panes(&pane_manifest, own_client_id);
+ self.update_tab_info(&pane_manifest);
+ self.total_tabs_in_session = Some(pane_manifest.panes.keys().count());
+
+ true
+ }
+
+ fn handle_tab_update(&mut self, tab_infos: Vec<TabInfo>) -> bool {
+ for tab in tab_infos {
+ if tab.active {
+ self.display_area_rows = tab.display_area_rows;
+ self.display_area_cols = tab.display_area_columns;
+ break;
+ }
+ }
+
+ false
+ }
+
+ fn update_grouped_panes(&mut self, pane_manifest: &PaneManifest, own_client_id: ClientId) {
+ self.grouped_panes.clear();
+ let mut count = 0;
+
+ for (_tab_index, pane_infos) in &pane_manifest.panes {
+ for pane_info in pane_infos {
+ if pane_info.index_in_pane_group.get(&own_client_id).is_some() {
+ let pane_id = if pane_info.is_plugin {
+ PaneId::Plugin(pane_info.id)
+ } else {
+ PaneId::Terminal(pane_info.id)
+ };
+ self.grouped_panes.push(pane_id);
+ count += 1;
+ }
+ }
+ }
+ if count == 0 {
+ self.close_self();
+ }
+
+ let previous_count = self.grouped_panes_count;
+ self.grouped_panes_count = count;
+ if let Some(own_plugin_id) = self.own_plugin_id {
+ let title = if count == 1 {
+ "SELECTED PANE"
+ } else {
+ "SELECTED PANES"
+ };
+ if previous_count != count {
+ rename_plugin_pane(own_plugin_id, format!("{} {}", count, title));
+ }
+ if previous_count != 0 && count != 0 && previous_count != count {
+ if self.doherty_threshold_elapsed_since_highlight() {
+ self.highlighted_at = Some(Instant::now());
+ highlight_and_unhighlight_panes(vec![PaneId::Plugin(own_plugin_id)], vec![]);
+ set_timeout(0.4);
+ }
+ }
+ }
+ }
+
+ fn doherty_threshold_elapsed_since_highlight(&self) -> bool {
+ self.highlighted_at
+ .map(|h| h.elapsed() >= std::time::Duration::from_millis(400))
+ .unwrap_or(true)
+ }
+
+ fn update_tab_info(&mut self, pane_manifest: &PaneManifest) {
+ for (tab_index, pane_infos) in &pane_manifest.panes {
+ for pane_info in pane_infos {
+ if pane_info.is_plugin && Some(pane_info.id) == self.own_plugin_id {
+ self.own_tab_index = Some(*tab_index);
+ return;
+ }
+ }
+ }
+ }
+
+ fn handle_key_press(&mut self, key: KeyWithModifier) -> bool {
+ if !key.has_no_modifiers() {
+ return false;
+ }
+
+ match key.bare_key {
+ BareKey::Char('b') => self.break_grouped_panes_to_new_tab(),
+ BareKey::Char('s') => self.stack_grouped_panes(),
+ BareKey::Char('f') => self.float_grouped_panes(),
+ BareKey::Char('e') => self.embed_grouped_panes(),
+ BareKey::Char('r') => self.break_grouped_panes_right(),
+ BareKey::Char('l') => self.break_grouped_panes_left(),
+ BareKey::Char('c') => self.close_grouped_panes(),
+ BareKey::Tab => self.next_coordinates(),
+ BareKey::Esc => {
+ self.ungroup_panes_in_zellij(&self.grouped_panes.clone());
+ self.close_self();
},
+ _ => return false,
+ }
+ false
+ }
+ fn handle_timer(&mut self) -> bool {
+ if let Some(own_plugin_id) = self.own_plugin_id {
+ if self.doherty_threshold_elapsed_since_highlight() {
+ highlight_and_unhighlight_panes(vec![], vec![PaneId::Plugin(own_plugin_id)]);
+ }
+ }
+ false
+ }
+
+ fn render_header(&self, base_x: usize, base_y: usize) {
+ let header_text = Self::header_text();
+
+ print_text_with_coordinates(header_text.1, base_x, base_y, None, None);
+ }
+
+ fn render_shortcuts(&self, base_x: usize, base_y: usize) {
+ let mut running_y = base_y;
+ print_text_with_coordinates(Self::group_actions_text().1, base_x, running_y, None, None);
+ running_y += 1;
+
+ print_text_with_coordinates(
+ Self::shortcuts_line1_text().1,
+ base_x,
+ running_y,
+ None,
+ None,
+ );
+ running_y += 1;
+
+ print_text_with_coordinates(
+ Self::shortcuts_line2_text().1,
+ base_x,
+ running_y,
+ None,
+ None,
+ );
+ running_y += 1;
+
+ print_text_with_coordinates(
+ Self::shortcuts_line3_text().1,
+ base_x,
+ running_y,
+ None,
+ None,
+ );
+ }
+
+ fn render_controls(&self, base_x: usize, base_y: usize) {
+ render_group_controls(&self.mode_info, base_x, base_y);
+ }
+
+ fn execute_action_and_close<F>(&mut self, action: F)
+ where
+ F: FnOnce(&[PaneId]),
+ {
+ let pane_ids = self.grouped_panes.clone();
+ action(&pane_ids);
+ self.close_self();
+ }
+
+ pub fn break_grouped_panes_to_new_tab(&mut self) {
+ self.execute_action_and_close(|pane_ids| {
+ break_panes_to_new_tab(pane_ids, None, true);
+ });
+ self.ungroup_panes_in_zellij(&self.grouped_panes.clone());
+ }
+
+ pub fn stack_grouped_panes(&mut self) {
+ self.execute_action_and_close(|pane_ids| {
+ stack_panes(pane_ids.to_vec());
+ });
+ self.ungroup_panes_in_zellij(&self.grouped_panes.clone());
+ }
+
+ pub fn float_grouped_panes(&mut self) {
+ self.execute_action_and_close(|pane_ids| {
+ float_multiple_panes(pane_ids.to_vec());
+ });
+ self.ungroup_panes_in_zellij(&self.grouped_panes.clone());
+ }
+
+ pub fn embed_grouped_panes(&mut self) {
+ self.execute_action_and_close(|pane_ids| {
+ embed_multiple_panes(pane_ids.to_vec());
+ });
+ self.ungroup_panes_in_zellij(&self.grouped_panes.clone());
+ }
+
+ pub fn break_grouped_panes_right(&mut self) {
+ let Some(own_tab_index) = self.own_tab_index else {
+ return;
+ };
+
+ let pane_ids = self.grouped_panes.clone();
+
+ if Some(own_tab_index + 1) < self.total_tabs_in_session {
+ break_panes_to_tab_with_index(&pane_ids, own_tab_index + 1, true);
+ } else {
+ break_panes_to_new_tab(&pane_ids, None, true);
+ }
+
+ self.close_self();
+ }
+
+ pub fn break_grouped_panes_left(&mut self) {
+ let Some(own_tab_index) = self.own_tab_index else {
+ return;
+ };
+
+ let pane_ids = self.grouped_panes.clone();
+
+ if own_tab_index > 0 {
+ break_panes_to_tab_with_index(&pane_ids, own_tab_index - 1, true);
+ } else {
+ break_panes_to_new_tab(&pane_ids, None, true);
+ }
+
+ self.close_self();
+ }
+
+ pub fn close_grouped_panes(&mut self) {
+ self.execute_action_and_close(|pane_ids| {
+ close_multiple_panes(pane_ids.to_vec());
+ });
+ }
+
+ pub fn ungroup_panes_in_zellij(&mut self, pane_ids: &[PaneId]) {
+ group_and_ungroup_panes(vec![], pane_ids.to_vec());
+ }
+ pub fn close_self(&mut self) {
+ self.closing = true;
+ close_self();
+ }
+ pub fn next_coordinates(&mut self) {
+ let width_30_percent = (self.display_area_cols as f64 * 0.3) as usize;
+ let height_30_percent = (self.display_area_rows as f64 * 0.3) as usize;
+ let width = std::cmp::max(width_30_percent, 48);
+ let height = std::cmp::max(height_30_percent, 10);
+ let y_position = self.display_area_rows.saturating_sub(height + 2);
+ if let Some(own_plugin_id) = self.own_plugin_id {
+ if self.alternate_coordinates {
+ let x_position = 2;
+ let Some(next_coordinates) = FloatingPaneCoordinates::new(
+ Some(format!("{}", x_position)),
+ Some(format!("{}", y_position)),
+ Some(format!("{}", width)),
+ Some(format!("{}", height)),
+ Some(true),
+ ) else {
+ return;
+ };
+ change_floating_panes_coordinates(vec![(
+ PaneId::Plugin(own_plugin_id),
+ next_coordinates,
+ )]);
+ self.alternate_coordinates = false;
+ } else {
+ let x_position = self
+ .display_area_cols
+ .saturating_sub(width)
+ .saturating_sub(2);
+ let Some(next_coordinates) = FloatingPaneCoordinates::new(
+ Some(format!("{}", x_position)),
+ Some(format!("{}", y_position)),
+ Some(format!("{}", width)),
+ Some(format!("{}", height)),
+ Some(true),
+ ) else {
+ return;
+ };
+ change_floating_panes_coordinates(vec![(
+ PaneId::Plugin(own_plugin_id),
+ next_coordinates,
+ )]);
+ self.alternate_coordinates = true;
+ }
}
- self.render_focus_boundary(rows, cols);
- self.render_help_line(rows, cols);
}
}
+
+fn render_group_controls(mode_info: &ModeInfo, base_x: usize, base_y: usize) {
+ let keymap = mode_info.get_mode_keybinds();
+ let (common_modifiers, pane_group_key, group_mark_key) = extract_key_bindings(&keymap);
+
+ let pane_group_bound = pane_group_key != "UNBOUND";
+ let group_mark_bound = group_mark_key != "UNBOUND";
+
+ if !pane_group_bound && !group_mark_bound {
+ return;
+ }
+
+ render_common_modifiers(&common_modifiers, base_x, base_y);
+
+ let mut next_x = base_x + render_common_modifiers(&common_modifiers, base_x, base_y);
+
+ if pane_group_bound {
+ next_x = render_toggle_group_ribbon(&pane_group_key, next_x, base_y);
+ }
+
+ if group_mark_bound {
+ render_follow_focus_ribbon(&group_mark_key, next_x, base_y, mode_info);
+ }
+}
+
+fn group_controls_length(mode_info: &ModeInfo) -> usize {
+ let keymap = mode_info.get_mode_keybinds();
+ let (common_modifiers, pane_group_key, group_mark_key) = extract_key_bindings(&keymap);
+
+ let pane_group_bound = pane_group_key != "UNBOUND";
+ let group_mark_bound = group_mark_key != "UNBOUND";
+
+ let mut length = 0;
+
+ if !common_modifiers.is_empty() {
+ let modifiers_text = format!(
+ "{} + ",
+ common_modifiers
+ .iter()
+ .map(|m| m.to_string())
+ .collect::<Vec<_>>()
+ .join(" ")
+ );
+ length += modifiers_text.chars().count();
+ }
+
+ if pane_group_bound {
+ let toggle_text = format!("<{}> Toggle", pane_group_key);
+ length += toggle_text.chars().count() + 4;
+ }
+
+ if group_mark_bound {
+ let follow_text = format!("<{}> Follow Focus", group_mark_key);
+ length += follow_text.chars().count() + 4;
+ }
+
+ length
+}
+
+fn extract_key_bindings(
+ keymap: &[(KeyWithModifier, Vec<Action>)],
+) -> (Vec<KeyModifier>, String, String) {
+ let pane_group_keys = get_key_for_action(keymap, &[Action::TogglePaneInGroup]);
+ let group_mark_keys = get_key_for_action(keymap, &[Action::ToggleGroupMarking]);
+
+ let key_refs: Vec<&KeyWithModifier> = [pane_group_keys.first(), group_mark_keys.first()]
+ .into_iter()
+ .flatten()
+ .collect();
+
+ let common_modifiers = get_common_modifiers(key_refs);
+
+ let pane_group_key = format_key_without_modifiers(&pane_group_keys, &common_modifiers);
+ let group_mark_key = format_key_without_modifiers(&group_mark_keys, &common_modifiers);
+
+ (common_modifiers, pane_group_key, group_mark_key)
+}
+
+fn format_key_without_modifiers(
+ keys: &[KeyWithModifier],
+ common_modifiers: &[KeyModifier],
+) -> String {
+ keys.first()
+ .map(|key| format!("{}", key.strip_common_modifiers(&common_modifiers.to_vec())))
+ .unwrap_or_else(|| "UNBOUND".to_string())
+}
+
+fn render_common_modifiers(
+ common_modifiers: &[KeyModifier],
+ base_x: usize,
+ base_y: usize,
+) -> usize {
+ if !common_modifiers.is_empty() {
+ let modifiers_text = format!(
+ "{} + ",
+ common_modifiers
+ .iter()
+ .map(|m| m.to_string())
+ .collect::<Vec<_>>()
+ .join(" ")
+ );
+
+ print_text_with_coordinates(
+ Text::new(&modifiers_text).color_all(0),
+ base_x,
+ base_y,
+ None,
+ None,
+ );
+
+ modifiers_text.chars().count()
+ } else {
+ 0
+ }
+}
+
+fn get_key_for_action(
+ keymap: &[(KeyWithModifier, Vec<Action>)],
+ target_action: &[Action],
+) -> Vec<KeyWithModifier> {
+ keymap
+ .iter()
+ .find_map(|(key, actions)| {
+ if actions.first() == target_action.first() {
+ Some(key.clone())
+ } else {
+ None
+ }
+ })
+ .map(|key| vec![key])
+ .unwrap_or_default()
+}
+
+fn get_common_modifiers(keys: Vec<&KeyWithModifier>) -> Vec<KeyModifier> {
+ if keys.is_empty() {
+ return vec![];
+ }
+
+ let mut common = keys[0].key_modifiers.clone();
+
+ for key in keys.iter().skip(1) {
+ common = common.intersection(&key.key_modifiers).cloned().collect();
+ }
+
+ common.into_iter().collect()
+}
+
+fn render_follow_focus_ribbon(
+ group_mark_key: &str,
+ x_position: usize,
+ base_y: usize,
+ mode_info: &ModeInfo,
+) {
+ let follow_text = format!("<{}> Follow Focus", group_mark_key);
+ let key_highlight = format!("{}", group_mark_key);
+
+ let mut ribbon = Text::new(&follow_text).color_substring(0, &key_highlight);
+
+ if mode_info.currently_marking_pane_group.unwrap_or(false) {
+ ribbon = ribbon.selected();
+ }
+
+ print_ribbon_with_coordinates(ribbon, x_position, base_y, None, None);
+}
+
+fn render_toggle_group_ribbon(pane_group_key: &str, base_x: usize, base_y: usize) -> usize {
+ let toggle_text = format!("<{}> Toggle", pane_group_key);
+ let key_highlight = format!("{}", pane_group_key);
+
+ print_ribbon_with_coordinates(
+ Text::new(&toggle_text).color_substring(0, &key_highlight),
+ base_x,
+ base_y,
+ None,
+ None,
+ );
+
+ base_x + toggle_text.len() + 4
+}
diff --git a/default-plugins/multiple-select/src/state.rs b/default-plugins/multiple-select/src/state.rs
deleted file mode 100644
index 3bf863f8..00000000
--- a/default-plugins/multiple-select/src/state.rs
+++ /dev/null
@@ -1,634 +0,0 @@
-use crate::{ui::PaneItem, App};
-use std::collections::{BTreeMap, BTreeSet, HashSet};
-
-use fuzzy_matcher::skim::SkimMatcherV2;
-use fuzzy_matcher::FuzzyMatcher;
-
-use zellij_tile::prelude::*;
-
-#[derive(Debug, Default)]
-pub struct MarkedIndex {
- pub main_index: usize,
- pub additional_indices: HashSet<usize>,
-}
-
-impl MarkedIndex {
- pub fn new(main_index: usize) -> Self {
- MarkedIndex {
- main_index,
- additional_indices: HashSet::new(),
- }
- }
-}
-
-impl MarkedIndex {
- pub fn toggle_additional_mark(&mut self) {
- if self.additional_indices.contains(&self.main_index) {
- self.additional_indices.retain(|a| a != &self.main_index);
- } else {
- self.additional_indices.insert(self.main_index);
- }
- }
-}
-
-#[derive(Debug)]
-pub enum VisibilityAndFocus {
- OnlyLeftSideVisible,
- OnlyRightSideVisible,
- BothSidesVisibleLeftSideFocused,
- BothSidesVisibleRightSideFocused,
-}
-
-impl Default for VisibilityAndFocus {
- fn default() -> Self {
- VisibilityAndFocus::OnlyLeftSideVisible
- }
-}
-
-impl VisibilityAndFocus {
- pub fn only_left_side_is_focused(&self) -> bool {
- match self {
- VisibilityAndFocus::OnlyLeftSideVisible => true,
- _ => false,
- }
- }
- pub fn left_side_is_focused(&self) -> bool {
- match self {
- VisibilityAndFocus::OnlyLeftSideVisible
- | VisibilityAndFocus::BothSidesVisibleLeftSideFocused => true,
- _ => false,
- }
- }
- pub fn right_side_is_focused(&self) -> bool {
- match self {
- VisibilityAndFocus::OnlyRightSideVisible
- | VisibilityAndFocus::BothSidesVisibleRightSideFocused => true,
- _ => false,
- }
- }
- pub fn hide_left_side(&mut self) {
- *self = VisibilityAndFocus::OnlyRightSideVisible
- }
- pub fn hide_right_side(&mut self) {
- *self = VisibilityAndFocus::OnlyLeftSideVisible
- }
- pub fn focus_right_side(&mut self) {
- *self = VisibilityAndFocus::BothSidesVisibleRightSideFocused
- }
- pub fn toggle_focus(&mut self) {
- match self {
- VisibilityAndFocus::BothSidesVisibleLeftSideFocused => {
- *self = VisibilityAndFocus::BothSidesVisibleRightSideFocused
- },
- VisibilityAndFocus::BothSidesVisibleRightSideFocused => {
- *self = VisibilityAndFocus::BothSidesVisibleLeftSideFocused
- },
- VisibilityAndFocus::OnlyLeftSideVisible => {
- *self = VisibilityAndFocus::BothSidesVisibleRightSideFocused
- },
- VisibilityAndFocus::OnlyRightSideVisible => {
- *self = VisibilityAndFocus::BothSidesVisibleLeftSideFocused
- },
- }
- }
- pub fn show_both_sides(&mut self) {
- match self {
- VisibilityAndFocus::OnlyLeftSideVisible => {
- *self = VisibilityAndFocus::BothSidesVisibleLeftSideFocused
- },
- VisibilityAndFocus::OnlyRightSideVisible => {
- *self = VisibilityAndFocus::BothSidesVisibleRightSideFocused
- },
- VisibilityAndFocus::BothSidesVisibleLeftSideFocused
- | VisibilityAndFocus::BothSidesVisibleRightSideFocused => {
- // no-op
- },
- }
- }
-}
-
-impl App {
- pub fn react_to_zellij_state_update(&mut self, pane_manifest: PaneManifest) {
- let is_first_update = self.right_side_panes.is_empty() && self.left_side_panes.is_empty();
- let panes_on_the_left_before = self.left_side_panes.len();
- let panes_on_the_right_before = self.right_side_panes.len();
- self.update_tab_info(&pane_manifest);
- self.update_panes(pane_manifest);
- if is_first_update && !self.right_side_panes.is_empty() {
- // in this case, the plugin was started with an existing group
- // most likely, the user wants to perform operations just on this group, so we
- // only show the group, giving the option to add more panes
- self.visibility_and_focus.hide_left_side();
- }
- let pane_count_changed = (panes_on_the_left_before != self.left_side_panes.len())
- || (panes_on_the_right_before != self.right_side_panes.len());
- if !is_first_update && pane_count_changed {
- let has_panes_on_the_right = !self.right_side_panes.is_empty();
- let has_panes_on_the_left = !self.left_side_panes.is_empty();
- if has_panes_on_the_right && has_panes_on_the_left {
- self.visibility_and_focus.show_both_sides();
- } else if has_panes_on_the_right {
- self.visibility_and_focus.hide_left_side();
- } else if has_panes_on_the_left {
- self.visibility_and_focus.hide_right_side();
- }
- }
- }
- pub fn update_panes(&mut self, pane_manifest: PaneManifest) {
- let mut all_panes = BTreeMap::new();
- for (_tab_index, pane_infos) in pane_manifest.panes {
- for pane_info in pane_infos {
- if pane_info.is_selectable {
- if pane_info.is_plugin {
- all_panes.insert(PaneId::Plugin(pane_info.id), pane_info);
- } else {
- all_panes.insert(PaneId::Terminal(pane_info.id), pane_info);
- }
- }
- }
- }
- self.left_side_panes
- .retain(|p| all_panes.contains_key(&p.id));
- self.right_side_panes
- .retain(|p| all_panes.contains_key(&p.id));
- let mut new_selected_panes: BTreeMap<usize, PaneItem> = BTreeMap::new(); // usize -> index_in_pane_group
- for (pane_id, pane) in all_panes.into_iter() {
- let is_known = self
- .left_side_panes
- .iter()
- .find(|p| p.id == pane_id)
- .is_some()
- || self
- .right_side_panes
- .iter()
- .find(|p| p.id == pane_id)
- .is_some();
- let index_in_pane_group = self
- .own_client_id
- .and_then(|own_client_id| pane.index_in_pane_group.get(&own_client_id));
- let is_grouped_for_own_client_id = index_in_pane_group.is_some();
- if !is_known {
- if is_grouped_for_own_client_id {
- if let Some(index_in_pane_group) = index_in_pane_group {
- // we do this rather than adding them directly to right_side_panes so that
- // we can make sure they're in the same order as the group is so that
- // things like stacking order will do the right thing
- new_selected_panes.insert(
- *index_in_pane_group,
- PaneItem {
- text: pane.title,
- id: pane_id,
- color_indices: vec![],
- },
- );
- }
- } else {
- self.left_side_panes.push(PaneItem {
- text: pane.title,
- id: pane_id,
- color_indices: vec![],
- });
- }
- } else {
- if is_grouped_for_own_client_id {
- if let Some(position) =
- self.left_side_panes.iter().position(|p| p.id == pane_id)
- {
- // pane was added to a pane group outside the plugin (eg. with mouse selection)
- let mut pane = self.left_side_panes.remove(position);
- pane.clear();
- self.right_side_panes.push(pane);
- }
- } else {
- if let Some(position) =
- self.right_side_panes.iter().position(|p| p.id == pane_id)
- {
- // pane was removed from a pane group outside the plugin (eg. with mouse selection)
- let mut pane = self.right_side_panes.remove(position);
- pane.clear();
- self.left_side_panes.push(pane);
- }
- }
- }
- }
- for (_index_in_pane_group, pane_item) in new_selected_panes.into_iter() {
- self.right_side_panes.push(pane_item);
- }
- }
- pub fn update_tab_info(&mut self, pane_manifest: &PaneManifest) {
- for (tab_index, pane_infos) in &pane_manifest.panes {
- for pane_info in pane_infos {
- if pane_info.is_plugin && Some(pane_info.id) == self.own_plugin_id {
- self.own_tab_index = Some(*tab_index);
- }
- }
- }
- self.total_tabs_in_session = Some(pane_manifest.panes.keys().count());
- }
- pub fn update_search_results(&mut self) {
- let mut matches = vec![];
- let matcher = SkimMatcherV2::default().use_cache(true);
- for pane_item in &self.left_side_panes {
- if let Some((score, indices)) =
- matcher.fuzzy_indices(&pane_item.text, &self.search_string)
- {
- let mut pane_item = pane_item.clone();
- pane_item.color_indices = indices;
- matches.push((score, pane_item));
- }
- }
- matches.sort_by(|(a_score, _a), (b_score, _b)| b_score.cmp(&a_score));
- if self.search_string.is_empty() {
- self.search_results = None;
- } else {
- self.search_results = Some(
- matches
- .into_iter()
- .map(|(_s, pane_item)| pane_item)
- .collect(),
- );
- }
- }
- pub fn group_panes_in_zellij(&mut self, pane_ids: Vec<PaneId>) {
- group_and_ungroup_panes(pane_ids, vec![]);
- }
- pub fn ungroup_panes_in_zellij(&mut self, pane_ids: Vec<PaneId>) {
- group_and_ungroup_panes(vec![], pane_ids);
- }
- pub fn update_highlighted_panes(&self) {
- let mut pane_ids_to_highlight = vec![];
- let mut pane_ids_to_unhighlight = vec![];
- if let Some(marked_index) = &self.marked_index {
- if self.visibility_and_focus.left_side_is_focused() {
- if let Some(main_index_pane_id) = self
- .search_results
- .as_ref()
- .and_then(|s| s.get(marked_index.main_index))
- .or_else(|| self.left_side_panes.get(marked_index.main_index))
- .map(|p| p.id)
- {
- pane_ids_to_highlight.push(main_index_pane_id);
- }
- for index in &marked_index.additional_indices {
- if let Some(pane_id) = self
- .search_results
- .as_ref()
- .and_then(|s| s.get(*index))
- .or_else(|| self.left_side_panes.get(*index))
- .map(|p| p.id)
- {
- pane_ids_to_highlight.push(pane_id);
- }
- }
- } else {
- if let Some(main_index_pane_id) = self
- .right_side_panes
- .get(marked_index.main_index)
- .map(|p| p.id)
- {
- pane_ids_to_highlight.push(main_index_pane_id);
- }
- for index in &marked_index.additional_indices {
- if let Some(pane_id) = self.right_side_panes.get(*index).map(|p| p.id) {
- pane_ids_to_highlight.push(pane_id);
- }
- }
- }
- }
- for pane in &self.left_side_panes {
- if !pane_ids_to_highlight.contains(&pane.id) {
- pane_ids_to_unhighlight.push(pane.id);
- }
- }
- for pane in &self.right_side_panes {
- if !pane_ids_to_highlight.contains(&pane.id) {
- pane_ids_to_unhighlight.push(pane.id);
- }
- }
- highlight_and_unhighlight_panes(pane_ids_to_highlight, pane_ids_to_unhighlight);
- }
- pub fn unhighlight_all_panes(&mut self) {
- let mut pane_ids_to_unhighlight = HashSet::new();
- for pane_item in &self.left_side_panes {
- pane_ids_to_unhighlight.insert(pane_item.id);
- }
- for pane_item in &self.right_side_panes {
- pane_ids_to_unhighlight.insert(pane_item.id);
- }
- highlight_and_unhighlight_panes(vec![], pane_ids_to_unhighlight.into_iter().collect());
- }
- pub fn ungroup_all_panes(&mut self) {
- let mut unselected_panes = vec![];
- for pane_item in self.right_side_panes.iter_mut() {
- pane_item.clear();
- unselected_panes.push(pane_item.id);
- }
- self.left_side_panes.append(&mut self.right_side_panes);
- self.ungroup_panes_in_zellij(unselected_panes);
- self.visibility_and_focus.hide_right_side();
- self.marked_index = None;
- }
- pub fn ungroup_all_panes_and_close_self(&mut self) {
- let mut pane_ids_to_ungroup = HashSet::new();
- for pane_item in &self.left_side_panes {
- pane_ids_to_ungroup.insert(pane_item.id);
- }
- for pane_item in &self.right_side_panes {
- pane_ids_to_ungroup.insert(pane_item.id);
- }
- group_and_ungroup_panes(vec![], pane_ids_to_ungroup.into_iter().collect());
- close_self();
- }
- pub fn group_panes(&mut self, mut marked_index: MarkedIndex, keep_left_side_focused: bool) {
- let mut all_selected_indices: BTreeSet<usize> =
- marked_index.additional_indices.drain().collect();
- all_selected_indices.insert(marked_index.main_index);
-
- // reverse so that the indices will remain consistent while
- // removing
- let mut selected_panes = vec![];
- for index in all_selected_indices.iter().rev() {
- let index = self
- .search_results
- .as_mut()
- .and_then(|search_results| {
- if search_results.len() > *index {
- Some(search_results.remove(*index))
- } else {
- None
- }
- })
- .and_then(|selected_search_result| {
- self.left_side_panes
- .iter()
- .position(|p| p.id == selected_search_result.id)
- })
- .unwrap_or(*index);
- if self.left_side_panes.len() > index {
- let selected_pane = self.left_side_panes.remove(index);
- selected_panes.push(selected_pane);
- }
- }
- let pane_ids_to_make_selected: Vec<PaneId> = selected_panes.iter().map(|p| p.id).collect();
- self.right_side_panes
- .append(&mut selected_panes.into_iter().rev().collect());
-
- let displayed_list_len = match self.search_results.as_ref() {
- Some(search_results) => search_results.len(),
- None => self.left_side_panes.len(),
- };
-
- if displayed_list_len == 0 {
- self.handle_left_side_emptied();
- } else if keep_left_side_focused {
- if marked_index.main_index > displayed_list_len.saturating_sub(1) {
- self.marked_index = Some(MarkedIndex::new(displayed_list_len.saturating_sub(1)));
- } else {
- self.marked_index = Some(marked_index);
- }
- self.visibility_and_focus.show_both_sides();
- } else {
- self.visibility_and_focus.focus_right_side();
- }
-
- self.group_panes_in_zellij(pane_ids_to_make_selected);
- self.update_highlighted_panes();
- }
- pub fn ungroup_panes(&mut self, mut marked_index: MarkedIndex) {
- let mut all_selected_indices: BTreeSet<usize> =
- marked_index.additional_indices.drain().collect();
- all_selected_indices.insert(marked_index.main_index);
-
- // reverse so that the indices will remain consistent while
- // removing
- let mut selected_panes = vec![];
- for index in all_selected_indices.iter().rev() {
- if self.right_side_panes.len() > *index {
- let mut selected_pane = self.right_side_panes.remove(*index);
- selected_pane.clear();
- selected_panes.push(selected_pane);
- }
- }
- self.ungroup_panes_in_zellij(selected_panes.iter().map(|p| p.id).collect());
- self.left_side_panes
- .append(&mut selected_panes.into_iter().rev().collect());
-
- if self.right_side_panes.is_empty() {
- self.marked_index = None;
- self.visibility_and_focus.hide_right_side();
- } else if marked_index.main_index > self.right_side_panes.len().saturating_sub(1) {
- self.marked_index = Some(MarkedIndex::new(
- self.right_side_panes.len().saturating_sub(1),
- ));
- self.visibility_and_focus.show_both_sides();
- } else {
- self.marked_index = Some(marked_index);
- self.visibility_and_focus.show_both_sides();
- }
- self.update_highlighted_panes();
- }
- pub fn group_search_results(&mut self, search_results: Vec<PaneItem>) {
- let mut pane_ids_to_make_selected = vec![];
- for search_result in search_results {
- let pane_id = search_result.id;
- pane_ids_to_make_selected.push(pane_id);
- self.left_side_panes.retain(|p| p.id != pane_id);
- self.right_side_panes.push(search_result);
- }
- self.group_panes_in_zellij(pane_ids_to_make_selected);
- }
- pub fn group_all_panes(&mut self) {
- let pane_ids_to_make_selected: Vec<PaneId> =
- self.left_side_panes.iter().map(|p| p.id).collect();
- self.right_side_panes.append(&mut self.left_side_panes);
- self.group_panes_in_zellij(pane_ids_to_make_selected);
- }
- pub fn handle_left_side_emptied(&mut self) {
- self.visibility_and_focus.hide_left_side();
- self.previous_search_string = self.search_string.drain(..).collect();
- self.marked_index = None;
- self.search_results = None;
- self.update_highlighted_panes();
- }
- pub fn move_marked_index_down(&mut self) {
- match self.marked_index.as_mut() {
- Some(marked_index) => {
- let is_searching = self.search_results.is_some();
- let search_result_count =
- self.search_results.as_ref().map(|s| s.len()).unwrap_or(0);
- if self.visibility_and_focus.left_side_is_focused()
- && is_searching
- && marked_index.main_index == search_result_count.saturating_sub(1)
- {
- marked_index.main_index = 0;
- } else if self.visibility_and_focus.left_side_is_focused()
- && !is_searching
- && marked_index.main_index == self.left_side_panes.len().saturating_sub(1)
- {
- marked_index.main_index = 0;
- } else if self.visibility_and_focus.right_side_is_focused()
- && marked_index.main_index == self.right_side_panes.len().saturating_sub(1)
- {
- marked_index.main_index = 0;
- } else {
- marked_index.main_index += 1
- }
- },
- None => {
- if self.visibility_and_focus.left_side_is_focused() {
- let is_searching = self.search_results.is_some();
- let has_search_results = self
- .search_results
- .as_ref()
- .map(|s| !s.is_empty())
- .unwrap_or(false);
- if is_searching && has_search_results {
- self.marked_index = Some(MarkedIndex::new(0));
- } else if !is_searching && !self.left_side_panes.is_empty() {
- self.marked_index = Some(MarkedIndex::new(0));
- }
- } else if self.visibility_and_focus.right_side_is_focused()
- && !self.right_side_panes.is_empty()
- {
- self.marked_index = Some(MarkedIndex::new(0));
- }
- },
- }
- self.update_highlighted_panes();
- }
- pub fn move_marked_index_up(&mut self) {
- match self.marked_index.as_mut() {
- Some(marked_index) => {
- if self.visibility_and_focus.left_side_is_focused() && marked_index.main_index == 0
- {
- if let Some(search_result_count) = self.search_results.as_ref().map(|s| s.len())
- {
- marked_index.main_index = search_result_count.saturating_sub(1);
- } else {
- marked_index.main_index = self.left_side_panes.len().saturating_sub(1);
- }
- } else if self.visibility_and_focus.right_side_is_focused()
- && marked_index.main_index == 0
- {
- marked_index.main_index = self.right_side_panes.len().saturating_sub(1);
- } else {
- marked_index.main_index = marked_index.main_index.saturating_sub(1);
- }
- },
- None => {
- if self.visibility_and_focus.left_side_is_focused() {
- let is_searching = self.search_results.is_some();
- let has_search_results = self
- .search_results
- .as_ref()
- .map(|s| !s.is_empty())
- .unwrap_or(false);
- if is_searching && has_search_results {
- let search_results_count =
- self.search_results.as_ref().map(|s| s.len()).unwrap_or(0);
- self.marked_index =
- Some(MarkedIndex::new(search_results_count.saturating_sub(1)));
- } else if !is_searching && !self.left_side_panes.is_empty() {
- self.marked_index = Some(MarkedIndex::new(
- self.left_side_panes.len().saturating_sub(1),
- ));
- }
- } else if self.visibility_and_focus.right_side_is_focused()
- && !self.right_side_panes.is_empty()
- {
- self.marked_index = Some(MarkedIndex::new(
- self.right_side_panes.len().saturating_sub(1),
- ));
- }
- },
- }
- self.update_highlighted_panes();
- }
- pub fn mark_entry(&mut self) {
- if let Some(marked_index) = self.marked_index.as_mut() {
- marked_index.toggle_additional_mark();
- self.update_highlighted_panes();
- }
- }
- pub fn break_grouped_panes_to_new_tab(&mut self) {
- let pane_ids_to_break_to_new_tab: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- let title_for_new_tab = if !self.previous_search_string.is_empty() {
- Some(self.previous_search_string.clone())
- } else {
- None
- };
- break_panes_to_new_tab(&pane_ids_to_break_to_new_tab, title_for_new_tab, true);
- self.ungroup_panes_in_zellij(pane_ids_to_break_to_new_tab);
- close_self();
- }
- pub fn stack_grouped_panes(&mut self) {
- let pane_ids_to_stack: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- stack_panes(pane_ids_to_stack.clone());
- self.ungroup_panes_in_zellij(pane_ids_to_stack);
- close_self();
- }
- pub fn float_grouped_panes(&mut self) {
- let pane_ids_to_float: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- float_multiple_panes(pane_ids_to_float.clone());
- self.ungroup_panes_in_zellij(pane_ids_to_float);
- close_self();
- }
- pub fn embed_grouped_panes(&mut self) {
- let pane_ids_to_embed: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- embed_multiple_panes(pane_ids_to_embed.clone());
- self.ungroup_panes_in_zellij(pane_ids_to_embed);
- close_self();
- }
- pub fn break_grouped_panes_right(&mut self) {
- if let Some(own_tab_index) = self.own_tab_index {
- if Some(own_tab_index + 1) < self.total_tabs_in_session {
- let pane_ids_to_break_right: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- break_panes_to_tab_with_index(&pane_ids_to_break_right, own_tab_index + 1, true);
- } else {
- let pane_ids_to_break_to_new_tab: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- let title_for_new_tab = if !self.previous_search_string.is_empty() {
- Some(self.previous_search_string.clone())
- } else {
- None
- };
- break_panes_to_new_tab(&pane_ids_to_break_to_new_tab, title_for_new_tab, true);
- }
- close_self();
- }
- }
- pub fn break_grouped_panes_left(&mut self) {
- if let Some(own_tab_index) = self.own_tab_index {
- if own_tab_index > 0 {
- let pane_ids_to_break_left: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- break_panes_to_tab_with_index(
- &pane_ids_to_break_left,
- own_tab_index.saturating_sub(1),
- true,
- );
- } else {
- let pane_ids_to_break_to_new_tab: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- let title_for_new_tab = if !self.previous_search_string.is_empty() {
- Some(self.previous_search_string.clone())
- } else {
- None
- };
- break_panes_to_new_tab(&pane_ids_to_break_to_new_tab, title_for_new_tab, true);
- }
- close_self();
- }
- }
- pub fn close_grouped_panes(&mut self) {
- let pane_ids_to_close: Vec<PaneId> =
- self.right_side_panes.drain(..).map(|p| p.id).collect();
- close_multiple_panes(pane_ids_to_close);
- close_self();
- }
-}
diff --git a/default-plugins/multiple-select/src/ui.rs b/default-plugins/multiple-select/src/ui.rs
deleted file mode 100644
index 0c74b0fe..00000000
--- a/default-plugins/multiple-select/src/ui.rs
+++ /dev/null
@@ -1,873 +0,0 @@
-use crate::{App, VisibilityAndFocus};
-use zellij_tile::prelude::*;
-
-const TOP_LEFT_CORNER_CHARACTER: &'static str = "┌";
-const TOP_RIGHT_CORNER_CHARACTER: &'static str = "┐";
-const BOTTOM_LEFT_CORNER_CHARACTER: &'static str = "└";
-const BOTTOM_RIGHT_CORNER_CHARACTER: &'static str = "┘";
-const BOUNDARY_CHARACTER: &'static str = "│";
-const HORIZONTAL_BOUNDARY_CHARACTER: &'static str = "─";
-
-#[derive(Debug, Clone)]
-pub struct PaneItem {
- pub text: String,
- pub id: PaneId,
- pub color_indices: Vec<usize>,
-}
-
-impl PaneItem {
- pub fn clear(&mut self) {
- self.color_indices.clear();
- }
- pub fn render(&self, max_width_for_item: usize) -> NestedListItem {
- let pane_item_text_len = self.text.chars().count();
- if pane_item_text_len <= max_width_for_item {
- NestedListItem::new(&self.text)
- .color_range(0, ..)
- .color_indices(3, self.color_indices.iter().copied().collect())
- } else {
- let length_of_each_half = max_width_for_item.saturating_sub(3) / 2;
- let first_half: String = self.text.chars().take(length_of_each_half).collect();
- let second_half: String = self
- .text
- .chars()
- .rev()
- .take(length_of_each_half)
- .collect::<Vec<_>>()
- .iter()
- .rev()
- .collect();
- let second_half_start_index = pane_item_text_len.saturating_sub(length_of_each_half);
- let adjusted_indices: Vec<usize> = self
- .color_indices
- .iter()
- .filter_map(|i| {
- if i < &length_of_each_half {
- Some(*i)
- } else if i >= &second_half_start_index {
- Some(i.saturating_sub(second_half_start_index) + length_of_each_half + 3)
- //3 for the bulletin
- } else {
- None
- }
- })
- .collect();
- NestedListItem::new(format!("{}...{}", first_half, second_half))
- .color_range(0, ..)
- .color_indices(3, adjusted_indices)
- }
- }
-}
-
-// rendering code
-impl App {
- pub fn render_close_shortcut(&self, cols: usize) {
- let should_render_close_shortcut =
- self.visibility_and_focus.left_side_is_focused() && self.marked_index.is_none();
- if should_render_close_shortcut {
- let x_coordinates_right_padding =
- if self.visibility_and_focus.only_left_side_is_focused() {
- 5
- } else {
- 1
- };
- let ctrl_c_shortcut_text = "<Ctrl c> - Close";
- let ctrl_c_shortcut = Text::new(ctrl_c_shortcut_text).color_range(3, ..=7);
- print_text_with_coordinates(
- ctrl_c_shortcut,
- cols.saturating_sub(ctrl_c_shortcut_text.chars().count())
- .saturating_sub(x_coordinates_right_padding),
- 0,
- None,
- None,
- );
- }
- }
- pub fn render_tab_shortcut(&self, cols: usize, rows: usize) {
- match self.visibility_and_focus {
- VisibilityAndFocus::BothSidesVisibleRightSideFocused => {
- let side_width = self.calculate_side_width(cols);
- let tab_shortcut = Text::new("<TAB> - select more panes").color_range(3, ..=4);
- print_text_with_coordinates(
- tab_shortcut,
- side_width + 6,
- rows.saturating_sub(2),
- None,
- None,
- );
- },
- VisibilityAndFocus::BothSidesVisibleLeftSideFocused => {
- let side_width = self.calculate_side_width(cols);
- let tab_shortcut_text = "<TAB> - browse selected panes";
- let tab_shortcut = Text::new(tab_shortcut_text).color_range(3, ..=4);
- print_text_with_coordinates(
- tab_shortcut,
- side_width.saturating_sub(tab_shortcut_text.chars().count() + 1),
- rows.saturating_sub(2),
- None,
- None,
- );
- },
- VisibilityAndFocus::OnlyRightSideVisible => {
- let tab_shortcut = Text::new("<TAB> - select more panes").color_range(3, ..=4);
- print_text_with_coordinates(tab_shortcut, 4, rows.saturating_sub(2), None, None);
- },
- VisibilityAndFocus::OnlyLeftSideVisible => {
- // not visible
- },
- };
- }
- pub fn render_left_side(&self, rows: usize, cols: usize, is_focused: bool) {
- let title_y = 0;
- let left_side_base_x = 1;
- let list_y = 2;
- let side_width = self.calculate_side_width(cols);
- let max_left_list_height = rows.saturating_sub(8);
- let (
- extra_pane_count_on_top_left,
- extra_pane_count_on_bottom_left,
- extra_selected_item_count_on_top_left,
- extra_selected_item_count_on_bottom_left,
- left_side_panes,
- ) = self.left_side_panes_list(side_width, max_left_list_height);
- let (filter_prompt_text, filter_prompt) = self.filter_panes_prompt();
- let filter = self.filter(side_width.saturating_sub(filter_prompt_text.chars().count() + 1));
- let (
- _enter_select_panes_text,
- enter_select_panes,
- space_shortcut_text,
- space_shortcut,
- _escape_shortcut_text,
- escape_shortcut,
- ) = self.left_side_controls(side_width);
- print_text_with_coordinates(filter_prompt, left_side_base_x, title_y, None, None);
- if is_focused {
- print_text_with_coordinates(
- filter,
- left_side_base_x + filter_prompt_text.chars().count(),
- title_y,
- None,
- None,
- );
- }
- print_nested_list_with_coordinates(
- left_side_panes.clone(),
- left_side_base_x,
- list_y,
- Some(side_width),
- None,
- );
- if is_focused {
- if let Some(marked_index) = self.marked_index.as_ref().map(|i| i.main_index) {
- print_text_with_coordinates(
- Text::new(">").color_range(3, ..).selected(),
- left_side_base_x + 1,
- (list_y + marked_index).saturating_sub(extra_pane_count_on_top_left),
- None,
- None,
- );
- }
- }
- if extra_pane_count_on_top_left > 0 {
- self.print_extra_pane_count(
- extra_pane_count_on_top_left,
- extra_selected_item_count_on_top_left,
- list_y.saturating_sub(1),
- left_side_base_x,
- side_width,
- );
- }
- if extra_pane_count_on_bottom_left > 0 {
- self.print_extra_pane_count(
- extra_pane_count_on_bottom_left,
- extra_selected_item_count_on_bottom_left,
- list_y + left_side_panes.len(),
- left_side_base_x,
- side_width,
- );
- }
- if is_focused && !left_side_panes.is_empty() {
- let controls_x = 1;
- print_text_with_coordinates(
- enter_select_panes,
- controls_x,
- list_y + left_side_panes.len() + 1,
- None,
- None,
- );
- if self.marked_index.is_some() {
- print_text_with_coordinates(
- space_shortcut.clone(),
- controls_x,
- list_y + left_side_panes.len() + 2,
- None,
- None,
- );
- print_text_with_coordinates(
- escape_shortcut.clone(),
- controls_x + space_shortcut_text.chars().count() + 1,
- list_y + left_side_panes.len() + 2,
- None,
- None,
- );
- }
- }
- }
- pub fn render_right_side(&self, rows: usize, cols: usize, is_focused: bool) {
- let side_width = self.calculate_side_width(cols);
- let right_side_base_x = match self.visibility_and_focus {
- VisibilityAndFocus::OnlyLeftSideVisible | VisibilityAndFocus::OnlyRightSideVisible => 1,
- VisibilityAndFocus::BothSidesVisibleLeftSideFocused
- | VisibilityAndFocus::BothSidesVisibleRightSideFocused => side_width + 4,
- };
- let title_y = 0;
- let list_y: usize = 2;
- let max_right_list_height = rows.saturating_sub(11);
- let selected_prompt = self.selected_panes_title();
- let (
- extra_pane_count_on_top_right,
- extra_pane_count_on_bottom_right,
- extra_selected_item_count_on_top_right,
- extra_selected_item_count_on_bottom_right,
- right_side_panes,
- ) = self.right_side_panes_list(side_width, max_right_list_height);
- let right_side_pane_count = right_side_panes.len();
- let (
- right_side_controls_1,
- right_side_controls_2,
- right_side_controls_3,
- right_side_controls_4,
- ) = self.right_side_controls(side_width);
- if extra_pane_count_on_top_right > 0 {
- self.print_extra_pane_count(
- extra_pane_count_on_top_right,
- extra_selected_item_count_on_top_right,
- list_y.saturating_sub(1),
- right_side_base_x,
- side_width,
- );
- }
- if extra_pane_count_on_bottom_right > 0 {
- self.print_extra_pane_count(
- extra_pane_count_on_bottom_right,
- extra_selected_item_count_on_bottom_right,
- list_y + right_side_panes.len(),
- right_side_base_x,
- side_width,
- );
- }
- print_text_with_coordinates(selected_prompt, right_side_base_x + 3, title_y, None, None);
- print_nested_list_with_coordinates(
- right_side_panes,
- right_side_base_x,
- list_y,
- Some(side_width),
- None,
- );
- if is_focused {
- if let Some(marked_index) = self.marked_index.as_ref().map(|i| i.main_index) {
- print_text_with_coordinates(
- Text::new(">").color_range(3, ..).selected(),
- right_side_base_x + 1,
- (list_y + marked_index).saturating_sub(extra_pane_count_on_top_right),
- None,
- None,
- );
- }
- }
- if is_focused && !self.right_side_panes.is_empty() {
- print_text_with_coordinates(
- right_side_controls_1,
- right_side_base_x + 1,
- list_y + right_side_pane_count + 1,
- None,
- None,
- );
- print_text_with_coordinates(
- right_side_controls_2,
- right_side_base_x + 1,
- list_y + right_side_pane_count + 3,
- None,
- None,
- );
- print_text_with_coordinates(
- right_side_controls_3,
- right_side_base_x + 1,
- list_y + right_side_pane_count + 4,
- None,
- None,
- );
- print_text_with_coordinates(
- right_side_controls_4,
- right_side_base_x + 1,
- list_y + right_side_pane_count + 5,
- None,
- None,
- );
- }
- }
- pub fn render_help_line(&self, rows: usize, cols: usize) {
- let help_line_text = match self.visibility_and_focus {
- VisibilityAndFocus::OnlyLeftSideVisible => {
- let full_help_line = "Help: Select one or more panes to group for bulk operations";
- let short_help_line = "Help: Select panes to group";
- if cols >= full_help_line.chars().count() {
- full_help_line
- } else {
- short_help_line
- }
- },
- VisibilityAndFocus::OnlyRightSideVisible => {
- let full_help_line = "Help: Perform bulk operations on all selected panes";
- let short_help_line = "Help: Perform bulk operations";
- if cols >= full_help_line.chars().count() {
- full_help_line
- } else {
- short_help_line
- }
- },
- _ => {
- let full_help_line =
- "Help: Select panes on the left, then perform operations on the right.";
- let short_help_line = "Help: Group panes for bulk operations";
- if cols >= full_help_line.chars().count() {
- full_help_line
- } else {
- short_help_line
- }
- },
- };
- let help_line = Text::new(help_line_text);
- print_text_with_coordinates(help_line, 0, rows, None, None);
- }
- pub fn render_focus_boundary(&self, rows: usize, cols: usize) {
- let side_width = self.calculate_side_width(cols);
- let x = match self.visibility_and_focus {
- VisibilityAndFocus::OnlyRightSideVisible => 0,
- VisibilityAndFocus::BothSidesVisibleLeftSideFocused
- | VisibilityAndFocus::BothSidesVisibleRightSideFocused
- | VisibilityAndFocus::OnlyLeftSideVisible => side_width + 2,
- };
- let y = 0;
- let height = rows.saturating_sub(2);
- for i in y..=height {
- if i == y && self.visibility_and_focus.left_side_is_focused() {
- print_text_with_coordinates(
- Text::new(TOP_RIGHT_CORNER_CHARACTER),
- x,
- i,
- None,
- None,
- );
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x.saturating_sub(1),
- i,
- None,
- None,
- );
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x.saturating_sub(2),
- i,
- None,
- None,
- );
- } else if i == y && !self.visibility_and_focus.left_side_is_focused() {
- print_text_with_coordinates(Text::new(TOP_LEFT_CORNER_CHARACTER), x, i, None, None);
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x + 1,
- i,
- None,
- None,
- );
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x + 2,
- i,
- None,
- None,
- );
- } else if i == height && self.visibility_and_focus.left_side_is_focused() {
- print_text_with_coordinates(
- Text::new(BOTTOM_RIGHT_CORNER_CHARACTER),
- x,
- i,
- None,
- None,
- );
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x.saturating_sub(1),
- i,
- None,
- None,
- );
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x.saturating_sub(2),
- i,
- None,
- None,
- );
- } else if i == height && !self.visibility_and_focus.left_side_is_focused() {
- print_text_with_coordinates(
- Text::new(BOTTOM_LEFT_CORNER_CHARACTER),
- x,
- i,
- None,
- None,
- );
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x + 1,
- i,
- None,
- None,
- );
- print_text_with_coordinates(
- Text::new(HORIZONTAL_BOUNDARY_CHARACTER),
- x + 2,
- i,
- None,
- None,
- );
- } else {
- print_text_with_coordinates(Text::new(BOUNDARY_CHARACTER), x, i, None, None);
- }
- }
- }
- pub fn calculate_side_width(&self, cols: usize) -> usize {
- match self.visibility_and_focus {
- VisibilityAndFocus::OnlyLeftSideVisible | VisibilityAndFocus::OnlyRightSideVisible => {
- cols.saturating_sub(4)
- },
- VisibilityAndFocus::BothSidesVisibleLeftSideFocused
- | VisibilityAndFocus::BothSidesVisibleRightSideFocused => (cols / 2).saturating_sub(3),
- }
- }
-}
-
-// ui components
-impl App {
- fn filter_panes_prompt(&self) -> (&'static str, Text) {
- let search_prompt_text = if self.search_string.is_empty() {
- "ALL PANES "
- } else {
- "FILTER: "
- };
- let search_prompt = if self.visibility_and_focus.left_side_is_focused() {
- Text::new(&search_prompt_text).color_range(2, ..)
- } else {
- Text::new(&search_prompt_text)
- };
- (search_prompt_text, search_prompt)
- }
- fn filter(&self, max_width: usize) -> Text {
- let search_string_text = if self.marked_index.is_none() && self.search_string.is_empty() {
- let full = "[Type filter term...]";
- let short = "[...]";
- if max_width >= full.chars().count() {
- full.to_owned()
- } else {
- short.to_owned()
- }
- } else if self.marked_index.is_none() && !self.search_string.is_empty() {
- if max_width >= self.search_string.chars().count() + 1 {
- format!("{}_", self.search_string)
- } else {
- let truncated: String = self
- .search_string
- .chars()
- .rev()
- .take(max_width.saturating_sub(4))
- .collect::<Vec<_>>()
- .iter()
- .rev()
- .collect();
- format!("...{}_", truncated)
- }
- } else if self.marked_index.is_some() && !self.search_string.is_empty() {
- if max_width >= self.search_string.chars().count() {
- format!("{}", self.search_string)
- } else {
- let truncated: String = self
- .search_string
- .chars()
- .rev()
- .take(max_width.saturating_sub(4))
- .collect::<Vec<_>>()
- .iter()
- .rev()
- .collect();
- format!("...{}", truncated)
- }
- } else {
- format!("")
- };
- Text::new(&search_string_text).color_range(3, ..)
- }
- fn left_side_panes_list(
- &self,
- max_width: usize,
- max_list_height: usize,
- ) -> (usize, usize, usize, usize, Vec<NestedListItem>) {
- // returns: extra_pane_count_on_top, extra_pane_count_on_bottom,
- // extra_selected_item_count_on_top, extra_selected_item_count_on_bottom, list
- let mut left_side_panes = vec![];
- let pane_items_on_the_left = self
- .search_results
- .as_ref()
- .unwrap_or_else(|| &self.left_side_panes);
- let max_width_for_item = max_width.saturating_sub(3); // 3 for the list bulletin
- let item_count = pane_items_on_the_left.iter().count();
- let first_item_index = if self.visibility_and_focus.left_side_is_focused() {
- self.marked_index
- .as_ref()
- .map(|s| s.main_index.saturating_sub(max_list_height / 2))
- .unwrap_or(0)
- } else {
- 0
- };
- let last_item_index = std::cmp::min(
- (max_list_height + first_item_index).saturating_sub(1),
- item_count.saturating_sub(1),
- );
- for (i, pane_item) in pane_items_on_the_left
- .iter()
- .enumerate()
- .skip(first_item_index)
- {
- if i > last_item_index {
- break;
- }
- let mut item = pane_item.render(max_width_for_item);
- if Some(i) == self.marked_index.as_ref().map(|s| s.main_index)
- && self.visibility_and_focus.left_side_is_focused()
- {
- item = item.selected();
- if self
- .marked_index
- .as_ref()
- .map(|s| s.additional_indices.contains(&i))
- .unwrap_or(false)
- {
- item = item.selected().color_range(1, ..);
- }
- } else if self
- .marked_index
- .as_ref()
- .map(|s| s.additional_indices.contains(&i))
- .unwrap_or(false)
- && self.visibility_and_focus.left_side_is_focused()
- {
- item = item.selected();
- }
- left_side_panes.push(item);
- }
- let extra_panes_on_top = first_item_index;
- let extra_panes_on_bottom = item_count.saturating_sub(last_item_index + 1);
- let extra_selected_item_count_on_top = if self.visibility_and_focus.left_side_is_focused() {
- self.marked_index
- .as_ref()
- .map(|s| {
- s.additional_indices
- .iter()
- .filter(|a| a < &&first_item_index)
- .count()
- })
- .unwrap_or(0)
- } else {
- 0
- };
- let extra_selected_item_count_on_bottom =
- if self.visibility_and_focus.left_side_is_focused() {
- self.marked_index
- .as_ref()
- .map(|s| {
- s.additional_indices
- .iter()
- .filter(|a| a > &&last_item_index)
- .count()
- })
- .unwrap_or(0)
- } else {
- 0
- };
- (
- extra_panes_on_top,
- extra_panes_on_bottom,
- extra_selected_item_count_on_top,
- extra_selected_item_count_on_bottom,
- left_side_panes,
- )
- }
- fn left_side_controls(
- &self,
- max_width: usize,
- ) -> (&'static str, Text, &'static str, Text, &'static str, Text) {
- // returns three components and their text
- let (enter_select_panes_text, enter_select_panes) = if self.marked_index.is_some() {
- let enter_select_panes_text_full = "<ENTER> - select, <↓↑→> - navigate";
- let enter_select_panes_text_short = "<ENTER> / <↓↑→>...";
- if max_width >= enter_select_panes_text_full.chars().count() {
- let enter_select_panes_full = Text::new(enter_select_panes_text_full)
- .color_range(3, ..=6)
- .color_range(3, 18..=22);
- (enter_select_panes_text_full, enter_select_panes_full)
- } else {
- let enter_select_panes_short = Text::new(enter_select_panes_text_short)
- .color_range(3, ..=6)
- .color_range(3, 10..=14);
- (enter_select_panes_text_short, enter_select_panes_short)
- }
- } else {
- let enter_select_panes_text_full = "<ENTER> - select all, <↓↑> - navigate";
- let enter_select_panes_text_short = "<ENTER> / <↓↑>...";
- if max_width >= enter_select_panes_text_full.chars().count() {
- let enter_select_panes_full = Text::new(enter_select_panes_text_full)
- .color_range(3, ..=6)
- .color_range(3, 21..=25);
- (enter_select_panes_text_full, enter_select_panes_full)
- } else {
- let enter_select_panes_short = Text::new(enter_select_panes_text_short)
- .color_range(3, ..=6)
- .color_range(3, 10..=13);
- (enter_select_panes_text_short, enter_select_panes_short)
- }
- };
- let space_shortcut_text_full = "<SPACE> - mark many,";
- let space_shortcut_text_short = "<SPACE> /";
- if self.marked_index.is_some() {
- let escape_shortcut_text_full = "<Ctrl c> - remove marks";
- let escape_shortcut_text_short = "<Ctrl c>...";
- let (escape_shortcut, space_shortcut, escape_shortcut_text, space_shortcut_text) =
- if max_width
- >= space_shortcut_text_full.chars().count()
- + escape_shortcut_text_full.chars().count()
- {
- (
- Text::new(escape_shortcut_text_full).color_range(3, ..=7),
- Text::new(space_shortcut_text_full).color_range(3, ..=6),
- escape_shortcut_text_full,
- space_shortcut_text_full,
- )
- } else {
- (
- Text::new(escape_shortcut_text_short).color_range(3, ..=7),
- Text::new(space_shortcut_text_short).color_range(3, ..=6),
- escape_shortcut_text_short,
- space_shortcut_text_short,
- )
- };
- (
- enter_select_panes_text,
- enter_select_panes,
- space_shortcut_text,
- space_shortcut,
- escape_shortcut_text,
- escape_shortcut,
- )
- } else {
- let escape_shortcut_text = if self.right_side_panes.is_empty() {
- "<Ctrl c> - Close"
- } else {
- ""
- };
- let escape_shortcut = Text::new(escape_shortcut_text).color_range(3, ..=7);
- let space_shortcut = Text::new(space_shortcut_text_full).color_range(3, ..=6);
- (
- enter_select_panes_text,
- enter_select_panes,
- space_shortcut_text_full,
- space_shortcut,
- escape_shortcut_text,
- escape_shortcut,
- )
- }
- }
- fn selected_panes_title(&self) -> Text {
- let selected_prompt_text = "SELECTED PANES: ";
- let selected_prompt = if self.visibility_and_focus.left_side_is_focused() {
- Text::new(selected_prompt_text)
- } else {
- Text::new(selected_prompt_text).color_range(2, ..)
- };
- selected_prompt
- }
- fn right_side_panes_list(
- &self,
- max_width: usize,
- max_list_height: usize,
- ) -> (usize, usize, usize, usize, Vec<NestedListItem>) {
- // returns: extra_pane_count_on_top, extra_pane_count_on_bottom,
- // extra_selected_item_count_on_top, extra_selected_item_count_on_bottom, list
- let mut right_side_panes = vec![];
- let item_count = self.right_side_panes.iter().count();
- let first_item_index = if self.visibility_and_focus.left_side_is_focused() {
- 0
- } else {
- self.marked_index
- .as_ref()
- .map(|s| s.main_index.saturating_sub(max_list_height / 2))
- .unwrap_or(0)
- };
- let last_item_index = std::cmp::min(
- (max_list_height + first_item_index).saturating_sub(1),
- item_count.saturating_sub(1),
- );
-
- let max_width_for_item = max_width.saturating_sub(3); // 3 for the list bulletin
- for (i, pane_item) in self
- .right_side_panes
- .iter()
- .enumerate()
- .skip(first_item_index)
- {
- if i > last_item_index {
- break;
- }
- let mut item = pane_item.render(max_width_for_item);
- if &Some(i) == &self.marked_index.as_ref().map(|s| s.main_index)
- && self.visibility_and_focus.right_side_is_focused()
- {
- item = item.selected();
- if self
- .marked_index
- .as_ref()
- .map(|s| s.additional_indices.contains(&i))
- .unwrap_or(false)
- {
- item = item.selected().color_range(1, ..);
- }
- } else if self
- .marked_index
- .as_ref()
- .map(|s| s.additional_indices.contains(&i))
- .unwrap_or(false)
- && self.visibility_and_focus.right_side_is_focused()
- {
- item = item.selected();
- }
- right_side_panes.push(item);
- }
-
- let extra_panes_on_top = first_item_index;
- let extra_panes_on_bottom = self
- .right_side_panes
- .iter()
- .len()
- .saturating_sub(last_item_index + 1);
- let extra_selected_item_count_on_top = if self.visibility_and_focus.left_side_is_focused() {
- 0
- } else {
- self.marked_index
- .as_ref()
- .map(|s| {
- s.additional_indices
- .iter()
- .filter(|a| a < &&first_item_index)
- .count()
- })
- .unwrap_or(0)
- };
- let extra_selected_item_count_on_bottom =
- if self.visibility_and_focus.left_side_is_focused() {
- 0
- } else {
- self.marked_index
- .as_ref()
- .map(|s| {
- s.additional_indices
- .iter()
- .filter(|a| a > &&last_item_index)
- .count()
- })
- .unwrap_or(0)
- };
- (
- extra_panes_on_top,
- extra_panes_on_bottom,
- extra_selected_item_count_on_top,
- extra_selected_item_count_on_bottom,
- right_side_panes,
- )
- }
- fn right_side_controls(&self, cols: usize) -> (Text, Text, Text, Text) {
- let right_side_controls_text_1_full = "<←↓↑> - navigate, <Ctrl c> - clear";
- let right_side_controls_text_1_short = "<←↓↑>/<Ctrl c>...";
- let right_side_controls_1 = if cols >= right_side_controls_text_1_full.chars().count() {
- Text::new(right_side_controls_text_1_full)
- .color_range(3, ..=4)
- .color_range(3, 18..=25)
- } else {
- Text::new(right_side_controls_text_1_short)
- .color_range(3, ..=4)
- .color_range(3, 6..=13)
- };
- let right_side_controls_text_2_full = "<b> - break out, <s> - stack, <c> - close";
- let right_side_controls_text_2_short = "<b>/<s>/<c>...";
- let right_side_controls_2 = if cols >= right_side_controls_text_2_full.chars().count() {
- Text::new(right_side_controls_text_2_full)
- .color_range(3, ..=2)
- .color_range(3, 17..=19)
- .color_range(3, 30..=32)
- } else {
- Text::new(right_side_controls_text_2_short)
- .color_range(3, ..=2)
- .color_range(3, 4..=6)
- .color_range(3, 8..=10)
- };
- let right_side_controls_text_3_full = "<r> - break right, <l> - break left";
- let right_side_controls_text_3_short = "<r>/<l>...";
- let right_side_controls_3 = if cols >= right_side_controls_text_3_full.chars().count() {
- Text::new(right_side_controls_text_3_full)
- .color_range(3, ..=2)
- .color_range(3, 19..=21)
- } else {
- Text::new(right_side_controls_text_3_short)
- .color_range(3, ..=2)
- .color_range(3, 4..=6)
- };
- let right_side_controls_text_4_full = "<e> - embed, <f> - float";
- let right_side_controls_text_4_short = "<e>/<f>...";
- let right_side_controls_4 = if cols >= right_side_controls_text_4_full.chars().count() {
- Text::new(right_side_controls_text_4_full)
- .color_range(3, ..=2)
- .color_range(3, 13..=15)
- } else {
- Text::new(right_side_controls_text_4_short)
- .color_range(3, ..=2)
- .color_range(3, 4..=6)
- };
- (
- right_side_controls_1,
- right_side_controls_2,
- right_side_controls_3,
- right_side_controls_4,
- )
- }
- fn print_extra_pane_count(
- &self,
- count: usize,
- selected_count: usize,
- y: usize,
- list_x: usize,
- list_width: usize,
- ) {
- let extra_count_text = if selected_count > 0 {
- format!("[+{} ({} selected)]", count, selected_count)
- } else {
- format!("[+{}]", count)
- };
- let extra_count = Text::new(&extra_count_text).color_range(1, ..);
- print_text_with_coordinates(
- extra_count,
- (list_x + list_width).saturating_sub(extra_count_text.chars().count()),
- y,
- None,
- None,
- );
- }
-}
diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs
index dd5d54c5..5bc54da0 100644
--- a/default-plugins/status-bar/src/main.rs
+++ b/default-plugins/status-bar/src/main.rs
@@ -39,8 +39,6 @@ struct State {
display_system_clipboard_failure: bool,
classic_ui: bool,
base_mode_is_locked: bool,
- own_client_id: Option<ClientId>,
- grouped_panes_count: Option<usize>,
}
register_plugin!(State);
@@ -199,7 +197,6 @@ impl ZellijPlugin for State {
.get("classic")
.map(|c| c == "true")
.unwrap_or(false);
- self.own_client_id = Some(get_plugin_ids().client_id);
set_selectable(false);
subscribe(&[
EventType::ModeUpdate,
@@ -227,28 +224,6 @@ impl ZellijPlugin for State {
}
self.tabs = tabs;
},
- Event::PaneUpdate(pane_manifest) => {
- if let Some(own_client_id) = self.own_client_id {
- let mut grouped_panes_count = 0;
- for (_tab_index, pane_infos) in pane_manifest.panes {
- for pane_info in pane_infos {
- let is_in_pane_group =
- pane_info.index_in_pane_group.get(&own_client_id).is_some();
- if is_in_pane_group {
- grouped_panes_count += 1;
- }
- }
- }
- if Some(grouped_panes_count) != self.grouped_panes_count {
- if grouped_panes_count == 0 {
- self.grouped_panes_count = None;
- } else {
- self.grouped_panes_count = Some(grouped_panes_count);
- }
- should_render = true;
- }
- }
- },
Event::CopyToClipboard(copy_destination) => {
match self.text_copy_destination {
Some(text_copy_destination) => {
@@ -306,7 +281,6 @@ impl ZellijPlugin for State {
self.base_mode_is_locked,
self.text_copy_destination,
self.display_system_clipboard_failure,
- self.grouped_panes_count,
),
fill_bg,
);
diff --git a/default-plugins/status-bar/src/one_line_ui.rs b/default-plugins/status-bar/src/one_line_ui.rs
index f6b88491..5abf67b6 100644
--- a/default-plugins/status-bar/src/one_line_ui.rs
+++ b/default-plugins/status-bar/src/one_line_ui.rs
@@ -6,7 +6,7 @@ use ansi_term::{
use std::collections::HashMap;
use zellij_tile::prelude::actions::Action;
use zellij_tile::prelude::*;
-use zellij_tile_utils::{palette_match, style};
+use zellij_tile_utils::palette_match;
use crate::first_line::{to_char, KeyAction, KeyMode, KeyShortcut};
use crate::second_line::{system_clipboard_error, text_copied_hint};
@@ -22,7 +22,6 @@ pub fn one_line_ui(
base_mode_is_locked: bool,
text_copied_to_clipboard_destination: Option<CopyDestination>,
clipboard_failure: bool,
- grouped_pane_count: Option<usize>,
) -> LinePart {
if let Some(text_copied_to_clipboard_destination) = text_copied_to_clipboard_destination {
return text_copied_hint(text_copied_to_clipboard_destination);
@@ -36,18 +35,11 @@ pub fn one_line_ui(
*max_len = max_len.saturating_sub(line_part.len);
};
- let currently_marking_pane_group = help.currently_marking_pane_group.unwrap_or(false);
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 => match grouped_pane_count {
- Some(grouped_pane_count) => {
- render_group_controls(help, grouped_pane_count, max_len)
- },
- None if currently_marking_pane_group => render_group_controls(help, 0, max_len),
- None => render_secondary_info(help, tab_info, max_len),
- }
- .map(|secondary_info| append(&secondary_info, &mut max_len)),
+ 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))
@@ -664,225 +656,6 @@ fn render_common_modifiers(
line_part_to_render.len += prefix_text.chars().count() + separator.chars().count();
}
-fn render_group_controls(
- help: &ModeInfo,
- grouped_pane_count: usize,
- max_len: usize,
-) -> Option<LinePart> {
- let currently_marking_group = help.currently_marking_pane_group.unwrap_or(false);
- let keymap = help.get_mode_keybinds();
- let (common_modifiers, multiple_select_key, pane_group_toggle_key, group_mark_toggle_key) = {
- let multiple_select_key = multiple_select_key(&keymap);
- let pane_group_toggle_key = single_action_key(&keymap, &[Action::TogglePaneInGroup]);
- let group_mark_toggle_key = single_action_key(&keymap, &[Action::ToggleGroupMarking]);
- let common_modifiers = get_common_modifiers(
- vec![
- multiple_select_key.iter().next(),
- pane_group_toggle_key.iter().next(),
- group_mark_toggle_key.iter().next(),
- ]
- .into_iter()
- .filter_map(|k| k)
- .collect(),
- );
- let multiple_select_key: Vec<KeyWithModifier> = multiple_select_key
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- let pane_group_toggle_key: Vec<KeyWithModifier> = pane_group_toggle_key
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- let group_mark_toggle_key: Vec<KeyWithModifier> = group_mark_toggle_key
- .iter()
- .map(|k| k.strip_common_modifiers(&common_modifiers))
- .collect();
- (
- common_modifiers,
- multiple_select_key,
- pane_group_toggle_key,
- group_mark_toggle_key,
- )
- };
- let multiple_select_key = multiple_select_key
- .iter()
- .next()
- .map(|key| format!("{}", key))
- .unwrap_or("UNBOUND".to_owned());
- let pane_group_toggle_key = pane_group_toggle_key
- .iter()
- .next()
- .map(|key| format!("{}", key))
- .unwrap_or("UNBOUND".to_owned());
- let group_mark_toggle_key = group_mark_toggle_key
- .iter()
- .next()
- .map(|key| format!("{}", key))
- .unwrap_or("UNBOUND".to_owned());
- let background = help.style.colors.text_unselected.background;
- let foreground = help.style.colors.text_unselected.base;
- let superkey_prefix_style = style!(foreground, background).bold();
- let common_modifier_text = if common_modifiers.is_empty() {
- "".to_owned()
- } else {
- format!(
- "{} + ",
- common_modifiers
- .iter()
- .map(|c| c.to_string())
- .collect::<Vec<_>>()
- .join("-")
- )
- };
-
- // full
- let full_selected_panes_text = if common_modifier_text.is_empty() {
- format!("{} SELECTED PANES", grouped_pane_count)
- } else {
- format!("{} SELECTED PANES |", grouped_pane_count)
- };
- let full_group_actions_text = format!("<{}> Group Actions", &multiple_select_key);
- let full_toggle_group_text = format!("<{}> Toggle Group", &pane_group_toggle_key);
- let full_group_mark_toggle_text = format!("<{}> Follow Focus", &group_mark_toggle_key);
- let ribbon_paddings_len = 12;
- let full_controls_line_len = full_selected_panes_text.chars().count()
- + 1
- + common_modifier_text.chars().count()
- + full_group_actions_text.chars().count()
- + full_toggle_group_text.chars().count()
- + full_group_mark_toggle_text.chars().count()
- + ribbon_paddings_len
- + 1; // 1 for the end padding
-
- // medium
- let medium_selected_panes_text = if common_modifier_text.is_empty() {
- format!("{} SELECTED", grouped_pane_count)
- } else {
- format!("{} SELECTED |", grouped_pane_count)
- };
- let medium_group_actions_text = format!("<{}> Actions", &multiple_select_key);
- let medium_toggle_group_text = format!("<{}> Toggle", &pane_group_toggle_key);
- let medium_group_mark_toggle_text = format!("<{}> Follow", &group_mark_toggle_key);
- let ribbon_paddings_len = 12;
- let medium_controls_line_len = medium_selected_panes_text.chars().count()
- + 1
- + common_modifier_text.chars().count()
- + medium_group_actions_text.chars().count()
- + medium_toggle_group_text.chars().count()
- + medium_group_mark_toggle_text.chars().count()
- + ribbon_paddings_len
- + 1; // 1 for the end padding
-
- // short
- let short_selected_panes_text = if common_modifier_text.is_empty() {
- format!("{} SELECTED", grouped_pane_count)
- } else {
- format!("{} SELECTED |", grouped_pane_count)
- };
- let short_group_actions_text = format!("<{}>", &multiple_select_key);
- let short_toggle_group_text = format!("<{}>", &pane_group_toggle_key);
- let short_group_mark_toggle_text = format!("<{}>", &group_mark_toggle_key);
- let color_emphasis_range_end = if common_modifier_text.is_empty() {
- 0
- } else {
- 2
- };
- let ribbon_paddings_len = 12;
- let short_controls_line_len = short_selected_panes_text.chars().count()
- + 1
- + common_modifier_text.chars().count()
- + short_group_actions_text.chars().count()
- + short_toggle_group_text.chars().count()
- + short_group_mark_toggle_text.chars().count()
- + ribbon_paddings_len
- + 1; // 1 for the end padding
-
- let (
- selected_panes_text,
- group_actions_text,
- toggle_group_text,
- group_mark_toggle_text,
- controls_line_len,
- ) = if max_len >= full_controls_line_len {
- (
- full_selected_panes_text,
- full_group_actions_text,
- full_toggle_group_text,
- full_group_mark_toggle_text,
- full_controls_line_len,
- )
- } else if max_len >= medium_controls_line_len {
- (
- medium_selected_panes_text,
- medium_group_actions_text,
- medium_toggle_group_text,
- medium_group_mark_toggle_text,
- medium_controls_line_len,
- )
- } else if max_len >= short_controls_line_len {
- (
- short_selected_panes_text,
- short_group_actions_text,
- short_toggle_group_text,
- short_group_mark_toggle_text,
- short_controls_line_len,
- )
- } else {
- return None;
- };
- let selected_panes = serialize_text(
- &Text::new(&selected_panes_text)
- .color_range(
- 3,
- ..selected_panes_text
- .chars()
- .count()
- .saturating_sub(color_emphasis_range_end),
- )
- .opaque(),
- );
- let group_actions_ribbon = serialize_ribbon(
- &Text::new(&group_actions_text).color_range(0, 1..=multiple_select_key.chars().count()),
- );
- let toggle_group_ribbon = serialize_ribbon(
- &Text::new(&toggle_group_text).color_range(0, 1..=pane_group_toggle_key.chars().count()),
- );
- let mut group_mark_toggle_ribbon = Text::new(&group_mark_toggle_text)
- .color_range(0, 1..=group_mark_toggle_key.chars().count());
- if currently_marking_group {
- group_mark_toggle_ribbon = group_mark_toggle_ribbon.selected();
- }
- let group_mark_toggle_ribbon = serialize_ribbon(&group_mark_toggle_ribbon);
- let controls_line = if common_modifiers.is_empty() {
- format!(
- "{} {}{}{}",
- selected_panes, group_actions_ribbon, toggle_group_ribbon, group_mark_toggle_ribbon
- )
- } else {
- let common_modifier =
- serialize_text(&Text::new(&common_modifier_text).color_range(0, ..).opaque());
- format!(
- "{} {}{}{}{}",
- selected_panes,
- common_modifier,
- group_actions_ribbon,
- toggle_group_ribbon,
- group_mark_toggle_ribbon
- )
- };
- let remaining_space = max_len.saturating_sub(controls_line_len);
- let mut padding = String::new();
- let mut padding_len = 0;
- for _ in 0..remaining_space {
- padding.push_str(&ANSIStrings(&[superkey_prefix_style.paint(" ")]).to_string());
- padding_len += 1;
- }
- Some(LinePart {
- part: format!("{}{}", padding, controls_line),
- len: controls_line_len + padding_len,
- })
-}
-
fn render_secondary_info(
help: &ModeInfo,
tab_info: Option<&TabInfo>,
@@ -1745,25 +1518,6 @@ fn configuration_key(keymap: &[(KeyWithModifier, Vec<Action>)]) -> Vec<KeyWithMo
}
}
-fn multiple_select_key(keymap: &[(KeyWithModifier, Vec<Action>)]) -> Vec<KeyWithModifier> {
- let mut matching = keymap.iter().find_map(|(key, acvec)| {
- let has_match = acvec
- .iter()
- .find(|a| a.launches_plugin("zellij:multiple-select")) // TODO: make this an alias
- .is_some();
- if has_match {
- Some(key.clone())
- } else {
- None
- }
- });
- if let Some(matching) = matching.take() {
- vec![matching]
- } else {
- vec![]
- }
-}
-
fn style_key_with_modifier(keyvec: &[KeyWithModifier], color_index: Option<usize>) -> LinePart {
if keyvec.is_empty() {
return LinePart::default();
diff --git a/example/config.kdl b/example/config.kdl
index 92fbda49..44f56a8f 100644
--- a/example/config.kdl
+++ b/example/config.kdl
@@ -138,12 +138,6 @@ keybinds {
bind "Alt k" "Alt Up" { MoveFocus "Up"; }
bind "Alt =" "Alt +" { Resize "Increase"; }
bind "Alt -" { Resize "Decrease"; }
- bind "Alt m" {
- LaunchOrFocusPlugin "zellij:multiple-select" {
- floating true
- move_to_focused_tab true
- }
- }
bind "Alt p" { TogglePaneInGroup; }
bind "Alt Shift p" { ToggleGroupMarking; }
}
diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs
index cc551273..3e89ea65 100644
--- a/zellij-server/src/lib.rs
+++ b/zellij-server/src/lib.rs
@@ -5,6 +5,7 @@ pub mod tab;
mod background_jobs;
mod logging_pipe;
+mod pane_groups;
mod plugins;
mod pty;
mod pty_writer;
diff --git a/zellij-server/src/pane_groups.rs b/zellij-server/src/pane_groups.rs
new file mode 100644
index 00000000..6cf68eed
--- /dev/null
+++ b/zellij-server/src/pane_groups.rs
@@ -0,0 +1,469 @@
+use std::collections::{HashMap, HashSet};
+
+use zellij_utils::data::FloatingPaneCoordinates;
+use zellij_utils::input::layout::{RunPluginOrAlias, SplitSize};
+use zellij_utils::pane_size::Size;
+
+use crate::{panes::PaneId, pty::PtyInstruction, thread_bus::ThreadSenders, ClientId};
+
+pub struct PaneGroups {
+ panes_in_group: HashMap<ClientId, Vec<PaneId>>,
+ senders: ThreadSenders,
+}
+
+impl std::fmt::Debug for PaneGroups {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("PaneGroups")
+ .field("panes_in_group", &self.panes_in_group)
+ .finish_non_exhaustive()
+ }
+}
+
+impl PaneGroups {
+ pub fn new(senders: ThreadSenders) -> Self {
+ PaneGroups {
+ panes_in_group: HashMap::new(),
+ senders,
+ }
+ }
+ pub fn clone_inner(&self) -> HashMap<ClientId, Vec<PaneId>> {
+ self.panes_in_group.clone()
+ }
+ pub fn get_client_pane_group(&self, client_id: &ClientId) -> HashSet<PaneId> {
+ self.panes_in_group
+ .get(client_id)
+ .map(|p| p.iter().copied().collect())
+ .unwrap_or_else(|| HashSet::new())
+ }
+ pub fn clear_pane_group(&mut self, client_id: &ClientId) {
+ self.panes_in_group.get_mut(client_id).map(|p| p.clear());
+ }
+ pub fn toggle_pane_id_in_group(
+ &mut self,
+ pane_id: PaneId,
+ screen_size: Size,
+ client_id: &ClientId,
+ ) {
+ let previous_groups = self.clone_inner();
+ let client_pane_group = self
+ .panes_in_group
+ .entry(*client_id)
+ .or_insert_with(|| vec![]);
+ if client_pane_group.contains(&pane_id) {
+ client_pane_group.retain(|p| p != &pane_id);
+ } else {
+ client_pane_group.push(pane_id);
+ };
+ if self.should_launch_plugin(&previous_groups, client_id) {
+ self.launch_plugin(screen_size, client_id);
+ }
+ }
+ pub fn add_pane_id_to_group(
+ &mut self,
+ pane_id: PaneId,
+ screen_size: Size,
+ client_id: &ClientId,
+ ) {
+ let previous_groups = self.clone_inner();
+ let client_pane_group = self
+ .panes_in_group
+ .entry(*client_id)
+ .or_insert_with(|| vec![]);
+ if !client_pane_group.contains(&pane_id) {
+ client_pane_group.push(pane_id);
+ }
+ if self.should_launch_plugin(&previous_groups, client_id) {
+ self.launch_plugin(screen_size, client_id);
+ }
+ }
+ pub fn group_and_ungroup_panes(
+ &mut self,
+ mut pane_ids_to_group: Vec<PaneId>,
+ pane_ids_to_ungroup: Vec<PaneId>,
+ screen_size: Size,
+ client_id: &ClientId,
+ ) {
+ let previous_groups = self.clone_inner();
+ let client_pane_group = self
+ .panes_in_group
+ .entry(*client_id)
+ .or_insert_with(|| vec![]);
+ client_pane_group.append(&mut pane_ids_to_group);
+ client_pane_group.retain(|p| !pane_ids_to_ungroup.contains(p));
+ if self.should_launch_plugin(&previous_groups, client_id) {
+ self.launch_plugin(screen_size, client_id);
+ }
+ }
+ pub fn override_groups_with(&mut self, new_pane_groups: HashMap<ClientId, Vec<PaneId>>) {
+ self.panes_in_group = new_pane_groups;
+ }
+ fn should_launch_plugin(
+ &self,
+ previous_groups: &HashMap<ClientId, Vec<PaneId>>,
+ client_id: &ClientId,
+ ) -> bool {
+ let mut should_launch = false;
+ for (client_id, previous_panes) in previous_groups {
+ let previous_panes_has_panes = !previous_panes.is_empty();
+ let current_panes_has_panes = self
+ .panes_in_group
+ .get(&client_id)
+ .map(|g| !g.is_empty())
+ .unwrap_or(false);
+ if !previous_panes_has_panes && current_panes_has_panes {
+ should_launch = true;
+ }
+ }
+ should_launch || previous_groups.get(&client_id).is_none()
+ }
+ fn launch_plugin(&self, screen_size: Size, client_id: &ClientId) {
+ if let Ok(run_plugin) =
+ RunPluginOrAlias::from_url("zellij:multiple-select", &None, None, None)
+ {
+ let tab_index = 1;
+ let size = Size::default();
+ let should_float = Some(true);
+ let should_be_opened_in_place = false;
+ let pane_title = None;
+ let skip_cache = false;
+ let cwd = None;
+ let should_focus_plugin = Some(false);
+ let width_30_percent = (screen_size.cols as f64 * 0.3) as usize;
+ let height_30_percent = (screen_size.rows as f64 * 0.3) as usize;
+ let width = std::cmp::max(width_30_percent, 48);
+ let height = std::cmp::max(height_30_percent, 10);
+ let y_position = screen_size.rows.saturating_sub(height + 2);
+ let floating_pane_coordinates = FloatingPaneCoordinates {
+ x: Some(SplitSize::Fixed(2)),
+ y: Some(SplitSize::Fixed(y_position)),
+ width: Some(SplitSize::Fixed(width)),
+ height: Some(SplitSize::Fixed(height)),
+ pinned: Some(true),
+ };
+ let _ = self.senders.send_to_pty(PtyInstruction::FillPluginCwd(
+ should_float,
+ should_be_opened_in_place,
+ pane_title,
+ run_plugin,
+ tab_index,
+ None,
+ *client_id,
+ size,
+ skip_cache,
+ cwd,
+ should_focus_plugin,
+ Some(floating_pane_coordinates),
+ ));
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::collections::HashMap;
+
+ fn create_mock_senders() -> ThreadSenders {
+ let mut mock = ThreadSenders::default();
+ mock.should_silently_fail = true;
+ mock
+ }
+
+ fn create_test_pane_groups() -> PaneGroups {
+ PaneGroups::new(create_mock_senders())
+ }
+
+ fn create_test_screen_size() -> Size {
+ Size { rows: 24, cols: 80 }
+ }
+
+ #[test]
+ fn new_creates_empty_pane_groups() {
+ let pane_groups = create_test_pane_groups();
+ assert!(pane_groups.panes_in_group.is_empty());
+ }
+
+ #[test]
+ fn clone_inner_returns_copy_of_internal_map() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let pane_id = PaneId::Terminal(10);
+ let screen_size = create_test_screen_size();
+
+ pane_groups.add_pane_id_to_group(pane_id, screen_size, &client_id);
+ let cloned = pane_groups.clone_inner();
+
+ assert_eq!(cloned.len(), 1);
+ assert!(cloned.contains_key(&client_id));
+ assert_eq!(cloned[&client_id], vec![pane_id]);
+ }
+
+ #[test]
+ fn get_client_pane_group_returns_empty_set_for_nonexistent_client() {
+ let pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 999;
+
+ let result = pane_groups.get_client_pane_group(&client_id);
+ assert!(result.is_empty());
+ }
+
+ #[test]
+ fn get_client_pane_group_returns_correct_panes() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let pane_ids = vec![
+ PaneId::Terminal(10),
+ PaneId::Plugin(20),
+ PaneId::Terminal(30),
+ ];
+ let screen_size = create_test_screen_size();
+
+ for pane_id in &pane_ids {
+ pane_groups.add_pane_id_to_group(*pane_id, screen_size, &client_id);
+ }
+
+ let result = pane_groups.get_client_pane_group(&client_id);
+ assert_eq!(result.len(), 3);
+ for pane_id in pane_ids {
+ assert!(result.contains(&pane_id));
+ }
+ }
+
+ #[test]
+ fn clear_pane_group_clears_existing_group() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let pane_ids = vec![
+ PaneId::Terminal(10),
+ PaneId::Plugin(20),
+ PaneId::Terminal(30),
+ ];
+ let screen_size = create_test_screen_size();
+
+ for pane_id in pane_ids {
+ pane_groups.add_pane_id_to_group(pane_id, screen_size, &client_id);
+ }
+
+ assert!(!pane_groups.get_client_pane_group(&client_id).is_empty());
+
+ pane_groups.clear_pane_group(&client_id);
+
+ assert!(pane_groups.get_client_pane_group(&client_id).is_empty());
+ }
+
+ #[test]
+ fn clear_pane_group_handles_nonexistent_client() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 999;
+
+ pane_groups.clear_pane_group(&client_id);
+ assert!(pane_groups.get_client_pane_group(&client_id).is_empty());
+ }
+
+ #[test]
+ fn toggle_pane_id_adds_new_pane() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let pane_id = PaneId::Terminal(10);
+ let screen_size = create_test_screen_size();
+
+ pane_groups.toggle_pane_id_in_group(pane_id, screen_size, &client_id);
+
+ let result = pane_groups.get_client_pane_group(&client_id);
+ assert!(result.contains(&pane_id));
+ }
+
+ #[test]
+ fn toggle_pane_id_removes_existing_pane() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let pane_id = PaneId::Plugin(10);
+ let screen_size = create_test_screen_size();
+
+ pane_groups.add_pane_id_to_group(pane_id, screen_size, &client_id);
+ assert!(pane_groups
+ .get_client_pane_group(&client_id)
+ .contains(&pane_id));
+
+ pane_groups.toggle_pane_id_in_group(pane_id, screen_size, &client_id);
+ assert!(!pane_groups
+ .get_client_pane_group(&client_id)
+ .contains(&pane_id));
+ }
+
+ #[test]
+ fn add_pane_id_to_group_adds_new_pane() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let pane_id = PaneId::Terminal(10);
+ let screen_size = create_test_screen_size();
+
+ pane_groups.add_pane_id_to_group(pane_id, screen_size, &client_id);
+
+ let result = pane_groups.get_client_pane_group(&client_id);
+ assert!(result.contains(&pane_id));
+ }
+
+ #[test]
+ fn add_pane_id_to_group_does_not_duplicate() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let pane_id = PaneId::Plugin(10);
+ let screen_size = create_test_screen_size();
+
+ pane_groups.add_pane_id_to_group(pane_id, screen_size, &client_id);
+ pane_groups.add_pane_id_to_group(pane_id, screen_size, &client_id);
+
+ let result = pane_groups.get_client_pane_group(&client_id);
+ assert_eq!(result.len(), 1);
+ assert!(result.contains(&pane_id));
+ }
+
+ #[test]
+ fn group_and_ungroup_panes_adds_and_removes_correctly() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let screen_size = create_test_screen_size();
+
+ let initial_panes = vec![PaneId::Terminal(1), PaneId::Plugin(2), PaneId::Terminal(3)];
+ for pane_id in &initial_panes {
+ pane_groups.add_pane_id_to_group(*pane_id, screen_size, &client_id);
+ }
+
+ let panes_to_add = vec![PaneId::Plugin(4), PaneId::Terminal(5)];
+ let panes_to_remove = vec![PaneId::Plugin(2), PaneId::Terminal(3)];
+
+ pane_groups.group_and_ungroup_panes(panes_to_add, panes_to_remove, screen_size, &client_id);
+
+ let result = pane_groups.get_client_pane_group(&client_id);
+
+ assert!(result.contains(&PaneId::Terminal(1)));
+ assert!(result.contains(&PaneId::Plugin(4)));
+ assert!(result.contains(&PaneId::Terminal(5)));
+ assert!(!result.contains(&PaneId::Plugin(2)));
+ assert!(!result.contains(&PaneId::Terminal(3)));
+ assert_eq!(result.len(), 3);
+ }
+
+ #[test]
+ fn override_groups_with_replaces_all_groups() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id1: ClientId = 1;
+ let client_id2: ClientId = 2;
+ let screen_size = create_test_screen_size();
+
+ pane_groups.add_pane_id_to_group(PaneId::Terminal(10), screen_size, &client_id1);
+
+ let mut new_groups = HashMap::new();
+ new_groups.insert(client_id2, vec![PaneId::Plugin(20), PaneId::Terminal(30)]);
+
+ pane_groups.override_groups_with(new_groups);
+
+ assert!(pane_groups.get_client_pane_group(&client_id1).is_empty());
+
+ let result = pane_groups.get_client_pane_group(&client_id2);
+ assert!(result.contains(&PaneId::Plugin(20)));
+ assert!(result.contains(&PaneId::Terminal(30)));
+ assert_eq!(result.len(), 2);
+ }
+
+ #[test]
+ fn multiple_clients_independent_groups() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id1: ClientId = 1;
+ let client_id2: ClientId = 2;
+ let screen_size = create_test_screen_size();
+
+ pane_groups.add_pane_id_to_group(PaneId::Terminal(10), screen_size, &client_id1);
+ pane_groups.add_pane_id_to_group(PaneId::Plugin(20), screen_size, &client_id2);
+
+ let group1 = pane_groups.get_client_pane_group(&client_id1);
+ let group2 = pane_groups.get_client_pane_group(&client_id2);
+
+ assert!(group1.contains(&PaneId::Terminal(10)));
+ assert!(!group1.contains(&PaneId::Plugin(20)));
+
+ assert!(group2.contains(&PaneId::Plugin(20)));
+ assert!(!group2.contains(&PaneId::Terminal(10)));
+ }
+
+ #[test]
+ fn pane_id_variants_work_correctly() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let screen_size = create_test_screen_size();
+
+ let terminal_pane = PaneId::Terminal(100);
+ let plugin_pane = PaneId::Plugin(200);
+
+ pane_groups.add_pane_id_to_group(terminal_pane, screen_size, &client_id);
+ pane_groups.add_pane_id_to_group(plugin_pane, screen_size, &client_id);
+
+ let result = pane_groups.get_client_pane_group(&client_id);
+ assert!(result.contains(&terminal_pane));
+ assert!(result.contains(&plugin_pane));
+ assert_eq!(result.len(), 2);
+
+ let another_terminal = PaneId::Terminal(200);
+ assert!(!result.contains(&another_terminal));
+ }
+
+ #[test]
+ fn should_launch_plugin_returns_true_when_first_pane_added() {
+ let pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let previous_groups = HashMap::new();
+
+ assert!(pane_groups.should_launch_plugin(&previous_groups, &client_id));
+ }
+
+ #[test]
+ fn should_launch_plugin_returns_true_when_empty_to_non_empty() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let screen_size = create_test_screen_size();
+
+ let mut previous_groups = HashMap::new();
+ previous_groups.insert(client_id, vec![]);
+
+ pane_groups.add_pane_id_to_group(PaneId::Terminal(10), screen_size, &client_id);
+
+ assert!(pane_groups.should_launch_plugin(&previous_groups, &client_id));
+ }
+
+ #[test]
+ fn should_launch_plugin_returns_false_when_non_empty_to_non_empty() {
+ let mut pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+ let screen_size = create_test_screen_size();
+
+ pane_groups.add_pane_id_to_group(PaneId::Terminal(10), screen_size, &client_id);
+ let previous_groups = pane_groups.clone_inner();
+
+ pane_groups.add_pane_id_to_group(PaneId::Plugin(20), screen_size, &client_id);
+
+ assert!(!pane_groups.should_launch_plugin(&previous_groups, &client_id));
+ }
+
+ #[test]
+ fn should_launch_plugin_returns_false_when_non_empty_to_empty() {
+ let pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+
+ let mut previous_groups = HashMap::new();
+ previous_groups.insert(client_id, vec![PaneId::Terminal(10)]);
+
+ assert!(!pane_groups.should_launch_plugin(&previous_groups, &client_id));
+ }
+
+ #[test]
+ fn should_launch_plugin_returns_false_when_empty_to_empty() {
+ let pane_groups = create_test_pane_groups();
+ let client_id: ClientId = 1;
+
+ let mut previous_groups = HashMap::new();
+ previous_groups.insert(client_id, vec![]);
+
+ assert!(!pane_groups.should_launch_plugin(&previous_groups, &client_id));
+ }
+}
diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs
index 4913ee51..e360b642 100644
--- a/zellij-server/src/panes/floating_panes/mod.rs
+++ b/zellij-server/src/panes/floating_panes/mod.rs
@@ -316,6 +316,20 @@ impl FloatingPanes {
pub fn last_floating_pane_id(&self) -> Option<PaneId> {
self.panes.keys().last().copied()
}
+ pub fn last_selectable_floating_pane_id(&self) -> Option<PaneId> {
+ self.panes
+ .iter()
+ .filter(|(_p_id, p)| p.selectable())
+ .last()
+ .map(|(p_id, _p)| *p_id)
+ }
+ pub fn has_selectable_panes(&self) -> bool {
+ self.panes
+ .iter()
+ .filter(|(_p_id, p)| p.selectable())
+ .last()
+ .is_some()
+ }
pub fn first_active_floating_pane_id(&self) -> Option<PaneId> {
self.active_panes.values().next().copied()
}
@@ -388,6 +402,7 @@ impl FloatingPanes {
let multiple_users_exist_in_session =
{ self.connected_clients_in_app.borrow().len() > 1 };
active_panes.retain(|c_id, _| self.connected_clients.borrow().contains(c_id));
+ let pane_is_selectable = pane.selectable();
let mut pane_contents_and_ui = PaneContentsAndUi::new(
pane,
output,
@@ -415,6 +430,7 @@ impl FloatingPanes {
client_mode,
self.session_is_mirrored,
is_floating,
+ pane_is_selectable,
)
.with_context(err_context)?;
if let PaneId::Plugin(..) = kind {
diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs
index 9ec50fb0..be8bdb6e 100644
--- a/zellij-server/src/panes/tiled_panes/mod.rs
+++ b/zellij-server/src/panes/tiled_panes/mod.rs
@@ -967,6 +967,7 @@ impl TiledPanes {
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();
+ let pane_is_selectable = pane.selectable();
let mut pane_contents_and_ui = PaneContentsAndUi::new(
pane,
output,
@@ -1004,6 +1005,7 @@ impl TiledPanes {
client_mode,
self.session_is_mirrored,
is_floating,
+ pane_is_selectable,
)
.with_context(err_context)?;
} else if pane_is_stacked {
@@ -1015,6 +1017,7 @@ impl TiledPanes {
client_mode,
self.session_is_mirrored,
is_floating,
+ pane_is_selectable,
)
.with_context(err_context)?;
// we also need to render its boundaries as normal
diff --git a/zellij-server/src/plugins/mod.rs b/zellij-server/src/plugins/mod.rs
index d7cb07d2..ec13df38 100644
--- a/zellij-server/src/plugins/mod.rs
+++ b/zellij-server/src/plugins/mod.rs
@@ -25,8 +25,8 @@ use wasm_bridge::WasmBridge;
use async_std::{channel, future::timeout, task};
use zellij_utils::{
data::{
- ClientInfo, Event, EventType, InputMode, MessageToPlugin, PermissionStatus, PermissionType,
- PipeMessage, PipeSource, PluginCapabilities,
+ ClientInfo, Event, EventType, FloatingPaneCoordinates, InputMode, MessageToPlugin,
+ PermissionStatus, PermissionType, PipeMessage, PipeSource, PluginCapabilities,
},
errors::{prelude::*, ContextType, PluginContext},
input::{
@@ -55,6 +55,8 @@ pub enum PluginInstruction {
Size,
Option<PathBuf>, // cwd
bool, // skip cache
+ Option<bool>, // should focus plugin
+ Option<FloatingPaneCoordinates>,
),
LoadBackgroundPlugin(RunPluginOrAlias, ClientId),
Update(Vec<(Option<PluginId>, Option<ClientId>, Event)>), // Focused plugin / broadcast, client_id, event data
@@ -281,6 +283,8 @@ pub(crate) fn plugin_thread_main(
size,
cwd,
skip_cache,
+ should_focus_plugin,
+ floating_pane_coordinates,
) => {
run_plugin_or_alias.populate_run_plugin_if_needed(&plugin_aliases);
let cwd = run_plugin_or_alias.get_initial_cwd().or(cwd);
@@ -306,6 +310,8 @@ pub(crate) fn plugin_thread_main(
pane_id_to_replace,
cwd,
start_suppressed,
+ floating_pane_coordinates,
+ should_focus_plugin,
Some(client_id),
)));
},
@@ -378,6 +384,8 @@ pub(crate) fn plugin_thread_main(
None,
start_suppressed,
None,
+ None,
+ None,
),
));
},
@@ -1070,7 +1078,8 @@ fn load_background_plugin(
pane_id_to_replace,
cwd,
start_suppressed,
- // None,
+ None,
+ None,
Some(client_id),
)));
},
diff --git a/zellij-server/src/plugins/plugin_loader.rs b/zellij-server/src/plugins/plugin_loader.rs
index 1dbe020e..4d8a4542 100644
--- a/zellij-server/src/plugins/plugin_loader.rs
+++ b/zellij-server/src/plugins/plugin_loader.rs
@@ -868,6 +868,7 @@ impl<'a> PluginLoader<'a> {
default_mode: self.default_mode.clone(),
subscriptions: Arc::new(Mutex::new(HashSet::new())),
keybinds: self.keybinds.clone(),
+ intercepting_key_presses: false,
stdin_pipe,
stdout_pipe,
};
diff --git a/zellij-server/src/plugins/plugin_map.rs b/zellij-server/src/plugins/plugin_map.rs
index 62020f4c..a92c291a 100644
--- a/zellij-server/src/plugins/plugin_map.rs
+++ b/zellij-server/src/plugins/plugin_map.rs
@@ -313,6 +313,7 @@ pub struct PluginEnv {
pub stdin_pipe: Arc<Mutex<VecDeque<u8>>>,
pub stdout_pipe: Arc<Mutex<VecDeque<u8>>>,
pub keybinds: Keybinds,
+ pub intercepting_key_presses: bool,
}
#[derive(Clone)]
@@ -457,4 +458,7 @@ impl RunningPlugin {
pub fn update_default_shell(&mut self, default_shell: Option<TerminalAction>) {
self.store.data_mut().default_shell = default_shell;
}
+ pub fn intercepting_key_presses(&self) -> bool {
+ self.store.data().intercepting_key_presses
+ }
}
diff --git a/zellij-server/src/plugins/unit/plugin_tests.rs b/zellij-server/src/plugins/unit/plugin_tests.rs
index 60f850cc..276461d9 100644
--- a/zellij-server/src/plugins/unit/plugin_tests.rs
+++ b/zellij-server/src/plugins/unit/plugin_tests.rs
@@ -714,6 +714,8 @@ pub fn load_new_plugin_from_hd() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -794,6 +796,8 @@ pub fn load_new_plugin_with_plugin_alias() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -870,6 +874,8 @@ pub fn plugin_workers() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
// we send a SystemClipboardFailure to trigger the custom handler in the fixture plugin that
@@ -950,6 +956,8 @@ pub fn plugin_workers_persist_state() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
// we send a SystemClipboardFailure to trigger the custom handler in the fixture plugin that
@@ -1040,6 +1048,8 @@ pub fn can_subscribe_to_hd_events() {
size,
None,
false,
+ None,
+ None,
));
// extra long time because we only start the fs watcher on plugin load
std::thread::sleep(std::time::Duration::from_millis(5000));
@@ -1118,6 +1128,8 @@ pub fn switch_to_mode_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1190,6 +1202,8 @@ pub fn switch_to_mode_plugin_command_permission_denied() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1262,6 +1276,8 @@ pub fn new_tabs_with_layout_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1348,6 +1364,8 @@ pub fn new_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1420,6 +1438,8 @@ pub fn go_to_next_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1491,6 +1511,8 @@ pub fn go_to_previous_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1562,6 +1584,8 @@ pub fn resize_focused_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1633,6 +1657,8 @@ pub fn resize_focused_pane_with_direction_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1704,6 +1730,8 @@ pub fn focus_next_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1775,6 +1803,8 @@ pub fn focus_previous_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1846,6 +1876,8 @@ pub fn move_focus_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1917,6 +1949,8 @@ pub fn move_focus_or_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -1988,6 +2022,8 @@ pub fn edit_scrollback_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2059,6 +2095,8 @@ pub fn write_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2130,6 +2168,8 @@ pub fn write_chars_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2201,6 +2241,8 @@ pub fn toggle_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2272,6 +2314,8 @@ pub fn move_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2343,6 +2387,8 @@ pub fn move_pane_with_direction_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2415,6 +2461,8 @@ pub fn clear_screen_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2487,6 +2535,8 @@ pub fn scroll_up_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2558,6 +2608,8 @@ pub fn scroll_down_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2629,6 +2681,8 @@ pub fn scroll_to_top_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2700,6 +2754,8 @@ pub fn scroll_to_bottom_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2771,6 +2827,8 @@ pub fn page_scroll_up_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2842,6 +2900,8 @@ pub fn page_scroll_down_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2913,6 +2973,8 @@ pub fn toggle_focus_fullscreen_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -2984,6 +3046,8 @@ pub fn toggle_pane_frames_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3055,6 +3119,8 @@ pub fn toggle_pane_embed_or_eject_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3126,6 +3192,8 @@ pub fn undo_rename_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3197,6 +3265,8 @@ pub fn close_focus_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3268,6 +3338,8 @@ pub fn toggle_active_tab_sync_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3339,6 +3411,8 @@ pub fn close_focused_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3410,6 +3484,8 @@ pub fn undo_rename_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3481,6 +3557,8 @@ pub fn previous_swap_layout_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3552,6 +3630,8 @@ pub fn next_swap_layout_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3623,6 +3703,8 @@ pub fn go_to_tab_name_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3694,6 +3776,8 @@ pub fn focus_or_create_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3765,6 +3849,8 @@ pub fn go_to_tab() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3836,6 +3922,8 @@ pub fn start_or_reload_plugin() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3914,6 +4002,8 @@ pub fn quit_zellij_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -3992,6 +4082,8 @@ pub fn detach_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4070,6 +4162,8 @@ pub fn open_file_floating_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4152,6 +4246,8 @@ pub fn open_file_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4235,6 +4331,8 @@ pub fn open_file_with_line_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4317,6 +4415,8 @@ pub fn open_file_with_line_floating_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4399,6 +4499,8 @@ pub fn open_terminal_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4477,6 +4579,8 @@ pub fn open_terminal_floating_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4555,6 +4659,8 @@ pub fn open_command_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4633,6 +4739,8 @@ pub fn open_command_pane_floating_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4704,6 +4812,8 @@ pub fn switch_to_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4775,6 +4885,8 @@ pub fn hide_self_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4845,6 +4957,8 @@ pub fn show_self_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4916,6 +5030,8 @@ pub fn close_terminal_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -4987,6 +5103,8 @@ pub fn close_plugin_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5058,6 +5176,8 @@ pub fn focus_terminal_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5129,6 +5249,8 @@ pub fn focus_plugin_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5200,6 +5322,8 @@ pub fn rename_terminal_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5271,6 +5395,8 @@ pub fn rename_plugin_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5342,6 +5468,8 @@ pub fn rename_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5422,6 +5550,8 @@ pub fn send_configuration_to_plugins() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5490,6 +5620,8 @@ pub fn request_plugin_permissions() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5582,6 +5714,8 @@ pub fn granted_permission_request_result() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5673,6 +5807,8 @@ pub fn denied_permission_request_result() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5744,6 +5880,8 @@ pub fn run_command_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5822,6 +5960,8 @@ pub fn run_command_with_env_vars_and_cwd_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5900,6 +6040,8 @@ pub fn web_request_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -5971,6 +6113,8 @@ pub fn unblock_input_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6053,6 +6197,8 @@ pub fn block_input_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
// extra long time because we only start the fs watcher on plugin load
std::thread::sleep(std::time::Duration::from_millis(5000));
@@ -6143,6 +6289,8 @@ pub fn pipe_output_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6226,6 +6374,8 @@ pub fn pipe_message_to_plugin_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::CliPipe {
@@ -6320,6 +6470,8 @@ pub fn switch_session_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6401,6 +6553,8 @@ pub fn switch_session_with_layout_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6482,6 +6636,8 @@ pub fn switch_session_with_layout_and_cwd_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6563,6 +6719,8 @@ pub fn disconnect_other_clients_plugins_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6644,6 +6802,8 @@ pub fn reconfigure_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6729,6 +6889,8 @@ pub fn run_plugin_in_specific_cwd() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -6803,6 +6965,8 @@ pub fn hide_pane_with_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -6874,6 +7038,8 @@ pub fn show_pane_with_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -6952,6 +7118,8 @@ pub fn open_command_pane_background_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7027,6 +7195,8 @@ pub fn rerun_command_pane_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7098,6 +7268,8 @@ pub fn resize_pane_with_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7169,6 +7341,8 @@ pub fn edit_scrollback_for_pane_with_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7240,6 +7414,8 @@ pub fn write_to_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7311,6 +7487,8 @@ pub fn write_chars_to_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7382,6 +7560,8 @@ pub fn move_pane_with_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7453,6 +7633,8 @@ pub fn move_pane_with_pane_id_in_direction_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7524,6 +7706,8 @@ pub fn clear_screen_for_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7595,6 +7779,8 @@ pub fn scroll_up_in_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7666,6 +7852,8 @@ pub fn scroll_down_in_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7737,6 +7925,8 @@ pub fn scroll_to_top_in_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7808,6 +7998,8 @@ pub fn scroll_to_bottom_in_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7879,6 +8071,8 @@ pub fn page_scroll_up_in_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -7950,6 +8144,8 @@ pub fn page_scroll_down_in_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8021,6 +8217,8 @@ pub fn toggle_pane_id_fullscreen_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8092,6 +8290,8 @@ pub fn toggle_pane_embed_or_eject_for_pane_id_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8163,6 +8363,8 @@ pub fn close_tab_with_index_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8234,6 +8436,8 @@ pub fn break_panes_to_new_tab_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8305,6 +8509,8 @@ pub fn break_panes_to_tab_with_index_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8376,6 +8582,8 @@ pub fn reload_plugin_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8447,6 +8655,8 @@ pub fn load_new_plugin_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8525,6 +8735,8 @@ pub fn rebind_keys_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
@@ -8599,6 +8811,8 @@ pub fn list_clients_plugin_command() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(500));
let _ = plugin_thread_sender.send(PluginInstruction::Update(vec![(
@@ -8670,6 +8884,8 @@ pub fn before_close_plugin_event() {
size,
None,
false,
+ None,
+ None,
));
std::thread::sleep(std::time::Duration::from_millis(5000));
// here we send an unload to plugin id 0 (the first plugin id, presumably this plugin)
diff --git a/zellij-server/src/plugins/wasm_bridge.rs b/zellij-server/src/plugins/wasm_bridge.rs
index d01a24e7..00b30aa1 100644
--- a/zellij-server/src/plugins/wasm_bridge.rs
+++ b/zellij-server/src/plugins/wasm_bridge.rs
@@ -324,6 +324,15 @@ impl WasmBridge {
for (_worker_name, worker_sender) in workers {
drop(worker_sender.send(MessageToWorker::Exit));
}
+ {
+ // if the plugin was intercepting key presses and for some reason did not clear
+ // this state, we make sure to do it ourselves so that the user will not get stuck
+ if running_plugin.lock().unwrap().intercepting_key_presses() {
+ let _ = self
+ .senders
+ .send_to_screen(ScreenInstruction::ClearKeyPressesIntercepts(client_id));
+ }
+ }
let subscriptions = subscriptions.lock().unwrap();
if subscriptions.contains(&EventType::BeforeClose) {
let mut running_plugin = running_plugin.lock().unwrap();
@@ -1436,6 +1445,8 @@ impl WasmBridge {
pane_id_to_replace,
cwd,
start_suppressed,
+ None,
+ None,
Some(client_id),
)));
vec![(plugin_id, Some(client_id))]
diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs
index f8dad922..ffc3fce9 100644
--- a/zellij-server/src/plugins/zellij_exports.rs
+++ b/zellij-server/src/plugins/zellij_exports.rs
@@ -73,9 +73,10 @@ pub fn zellij_exports(linker: &mut Linker<PluginEnv>) {
.unwrap();
}
-fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
- let env = caller.data();
- let err_context = || format!("failed to run plugin command {}", env.name());
+fn host_run_plugin_command(mut caller: Caller<'_, PluginEnv>) {
+ let mut env = caller.data_mut();
+ let plugin_command = env.name();
+ let err_context = || format!("failed to run plugin command {}", plugin_command);
wasi_read_bytes(env)
.and_then(|bytes| {
let command: ProtobufPluginCommand = ProtobufPluginCommand::decode(bytes.as_slice())?;
@@ -455,6 +456,10 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
PluginCommand::EmbedMultiplePanes(pane_ids) => {
embed_multiple_panes(env, pane_ids.into_iter().map(|p| p.into()).collect())
},
+ PluginCommand::InterceptKeyPresses => intercept_key_presses(&mut env),
+ PluginCommand::ClearKeyPressesIntercepts => {
+ clear_key_presses_intercepts(&mut env)
+ },
},
(PermissionStatus::Denied, permission) => {
log::error!(
@@ -2163,6 +2168,8 @@ fn load_new_plugin(
size,
cwd,
skip_cache,
+ None,
+ None,
));
},
Err(e) => {
@@ -2231,6 +2238,23 @@ fn embed_multiple_panes(env: &PluginEnv, pane_ids: Vec<PaneId>) {
));
}
+fn intercept_key_presses(env: &mut PluginEnv) {
+ env.intercepting_key_presses = true;
+ let _ = env
+ .senders
+ .send_to_screen(ScreenInstruction::InterceptKeyPresses(
+ env.plugin_id,
+ env.client_id,
+ ));
+}
+
+fn clear_key_presses_intercepts(env: &mut PluginEnv) {
+ env.intercepting_key_presses = false;
+ let _ = env
+ .senders
+ .send_to_screen(ScreenInstruction::ClearKeyPressesIntercepts(env.client_id));
+}
+
// Custom panic handler for plugins.
//
// This is called when a panic occurs in a plugin. Since most panics will likely originate in the
@@ -2409,6 +2433,9 @@ fn check_command_permission(
PermissionType::Reconfigure
},
PluginCommand::ChangeHostFolder(..) => PermissionType::FullHdAccess,
+ PluginCommand::InterceptKeyPresses | PluginCommand::ClearKeyPressesIntercepts => {
+ PermissionType::InterceptInput
+ },
_ => return (PermissionStatus::Granted, None),
};
diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs
index 450f0b0b..e0abff49 100644
--- a/zellij-server/src/pty.rs
+++ b/zellij-server/src/pty.rs
@@ -97,6 +97,7 @@ pub enum PtyInstruction {
Size,
bool, // skip cache
Option<PathBuf>, // if Some, will not fill cwd but just forward the message
+ Option<bool>, // should focus plugin
Option<FloatingPaneCoordinates>,
),
ListClientsMetadata(SessionLayoutMetadata, ClientId),
@@ -771,6 +772,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
size,
skip_cache,
cwd,
+ should_focus_plugin,
floating_pane_coordinates,
) => {
pty.fill_plugin_cwd(
@@ -784,6 +786,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
size,
skip_cache,
cwd,
+ should_focus_plugin,
floating_pane_coordinates,
)?;
},
@@ -1527,9 +1530,8 @@ impl Pty {
size: Size,
skip_cache: bool,
cwd: Option<PathBuf>,
- // left here for historical and potential future reasons since we might change the ordering
- // of the pipeline between threads and end up needing to forward this
- _floating_pane_coordinates: Option<FloatingPaneCoordinates>,
+ should_focus_plugin: Option<bool>,
+ floating_pane_coordinates: Option<FloatingPaneCoordinates>,
) -> Result<()> {
let get_focused_cwd = || {
self.active_panes
@@ -1563,6 +1565,8 @@ impl Pty {
size,
cwd,
skip_cache,
+ should_focus_plugin,
+ floating_pane_coordinates,
))?;
Ok(())
}
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs
index be7e7d7d..64c8836e 100644
--- a/zellij-server/src/screen.rs
+++ b/zellij-server/src/screen.rs
@@ -9,8 +9,8 @@ use std::time::Duration;
use log::{debug, warn};
use zellij_utils::data::{
- Direction, KeyWithModifier, PaneManifest, PluginPermission, Resize, ResizeStrategy,
- SessionInfo, Styling,
+ Direction, FloatingPaneCoordinates, KeyWithModifier, PaneManifest, PluginPermission, Resize,
+ ResizeStrategy, SessionInfo, Styling,
};
use zellij_utils::errors::prelude::*;
use zellij_utils::input::command::RunCommand;
@@ -32,6 +32,7 @@ use zellij_utils::{
use crate::background_jobs::BackgroundJob;
use crate::os_input_output::ResizeCache;
+use crate::pane_groups::PaneGroups;
use crate::panes::alacritty_functions::xparse_color;
use crate::panes::terminal_character::AnsiCode;
use crate::session_layout_metadata::{PaneLayoutMetadata, SessionLayoutMetadata};
@@ -51,10 +52,7 @@ use crate::{
ClientId, ServerInstruction,
};
use zellij_utils::{
- data::{
- Event, FloatingPaneCoordinates, InputMode, ModeInfo, Palette, PaletteColor,
- PluginCapabilities, Style, TabInfo,
- },
+ data::{Event, InputMode, ModeInfo, Palette, PaletteColor, PluginCapabilities, Style, TabInfo},
errors::{ContextType, ScreenContext},
input::get_mode_info,
ipc::{ClientAttributes, PixelDimensions, ServerToClientMsg},
@@ -305,6 +303,8 @@ pub enum ScreenInstruction {
Option<PaneId>,
Option<PathBuf>, // cwd
bool, // start suppressed
+ Option<FloatingPaneCoordinates>,
+ Option<bool>, // should focus plugin
Option<ClientId>,
),
UpdatePluginLoadingStage(u32, LoadingIndication), // u32 - plugin_id
@@ -415,6 +415,8 @@ pub enum ScreenInstruction {
EmbedMultiplePanes(Vec<PaneId>, ClientId),
TogglePaneInGroup(ClientId),
ToggleGroupMarking(ClientId),
+ InterceptKeyPresses(PluginId, ClientId),
+ ClearKeyPressesIntercepts(ClientId),
}
impl From<&ScreenInstruction> for ScreenContext {
@@ -636,6 +638,10 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::EmbedMultiplePanes(..) => ScreenContext::EmbedMultiplePanes,
ScreenInstruction::TogglePaneInGroup(..) => ScreenContext::TogglePaneInGroup,
ScreenInstruction::ToggleGroupMarking(..) => ScreenContext::ToggleGroupMarking,
+ ScreenInstruction::InterceptKeyPresses(..) => ScreenContext::InterceptKeyPresses,
+ ScreenInstruction::ClearKeyPressesIntercepts(..) => {
+ ScreenContext::ClearKeyPressesIntercepts
+ },
}
}
}
@@ -717,7 +723,7 @@ pub(crate) struct Screen {
default_layout_name: Option<String>,
explicitly_disable_kitty_keyboard_protocol: bool,
default_editor: Option<PathBuf>,
- current_pane_group: Rc<RefCell<HashMap<ClientId, Vec<PaneId>>>>,
+ current_pane_group: Rc<RefCell<PaneGroups>>,
advanced_mouse_actions: bool,
currently_marking_pane_group: Rc<RefCell<HashMap<ClientId, bool>>>,
}
@@ -753,6 +759,7 @@ impl Screen {
let mut session_infos_on_machine = BTreeMap::new();
let resurrectable_sessions = BTreeMap::new();
session_infos_on_machine.insert(session_name.clone(), session_info);
+ let current_pane_group = PaneGroups::new(bus.senders.clone());
Screen {
bus,
max_panes,
@@ -790,7 +797,7 @@ impl Screen {
layout_dir,
explicitly_disable_kitty_keyboard_protocol,
default_editor,
- current_pane_group: Rc::new(RefCell::new(HashMap::new())),
+ current_pane_group: Rc::new(RefCell::new(current_pane_group)),
currently_marking_pane_group: Rc::new(RefCell::new(HashMap::new())),
advanced_mouse_actions,
}
@@ -2897,15 +2904,12 @@ impl Screen {
fn get_client_pane_group(&self, client_id: &ClientId) -> HashSet<PaneId> {
self.current_pane_group
.borrow()
- .get(client_id)
- .map(|p| p.iter().copied().collect())
- .unwrap_or_else(|| HashSet::new())
+ .get_client_pane_group(client_id)
}
fn clear_pane_group(&mut self, client_id: &ClientId) {
self.current_pane_group
.borrow_mut()
- .get_mut(client_id)
- .map(|p| p.clear());
+ .clear_pane_group(client_id);
self.currently_marking_pane_group
.borrow_mut()
.remove(client_id);
@@ -2913,22 +2917,14 @@ impl Screen {
fn toggle_pane_id_in_group(&mut self, pane_id: PaneId, client_id: &ClientId) {
{
let mut pane_groups = self.current_pane_group.borrow_mut();
- let client_pane_group = pane_groups.entry(*client_id).or_insert_with(|| vec![]);
- if client_pane_group.contains(&pane_id) {
- client_pane_group.retain(|p| p != &pane_id);
- } else {
- client_pane_group.push(pane_id);
- };
+ pane_groups.toggle_pane_id_in_group(pane_id, self.size, client_id);
}
self.retain_only_existing_panes_in_pane_groups();
}
fn add_pane_id_to_group(&mut self, pane_id: PaneId, client_id: &ClientId) {
{
let mut pane_groups = self.current_pane_group.borrow_mut();
- let client_pane_group = pane_groups.entry(*client_id).or_insert_with(|| vec![]);
- if !client_pane_group.contains(&pane_id) {
- client_pane_group.push(pane_id);
- }
+ pane_groups.add_pane_id_to_group(pane_id, self.size, client_id);
}
self.retain_only_existing_panes_in_pane_groups();
}
@@ -2956,17 +2952,18 @@ impl Screen {
fn group_and_ungroup_panes(
&mut self,
- mut pane_ids_to_group: Vec<PaneId>,
+ pane_ids_to_group: Vec<PaneId>,
pane_ids_to_ungroup: Vec<PaneId>,
client_id: ClientId,
) {
{
let mut current_pane_group = self.current_pane_group.borrow_mut();
- let client_pane_group = current_pane_group
- .entry(client_id)
- .or_insert_with(|| vec![]);
- client_pane_group.append(&mut pane_ids_to_group);
- client_pane_group.retain(|p| !pane_ids_to_ungroup.contains(p));
+ current_pane_group.group_and_ungroup_panes(
+ pane_ids_to_group,
+ pane_ids_to_ungroup,
+ self.size,
+ &client_id,
+ );
}
self.retain_only_existing_panes_in_pane_groups();
let _ = self.log_and_report_session_state();
@@ -2974,7 +2971,7 @@ impl Screen {
fn retain_only_existing_panes_in_pane_groups(&mut self) {
let clients_with_empty_group = {
let mut clients_with_empty_group = vec![];
- let mut current_pane_group = self.current_pane_group.borrow_mut();
+ let mut current_pane_group = { self.current_pane_group.borrow().clone_inner() };
for (client_id, panes_in_group) in current_pane_group.iter_mut() {
let all_tabs = self.get_tabs();
panes_in_group.retain(|p_id| {
@@ -2991,6 +2988,9 @@ impl Screen {
clients_with_empty_group.push(*client_id)
}
}
+ self.current_pane_group
+ .borrow_mut()
+ .override_groups_with(current_pane_group);
clients_with_empty_group
};
for client_id in &clients_with_empty_group {
@@ -3114,6 +3114,7 @@ pub(crate) fn screen_thread_main(
let mut pending_events_waiting_for_tab: Vec<ScreenInstruction> = vec![];
let mut pending_events_waiting_for_client: Vec<ScreenInstruction> = vec![];
let mut plugin_loading_message_cache = HashMap::new();
+ let mut keybind_intercepts = HashMap::new();
loop {
let (event, mut err_ctx) = screen
.bus
@@ -3178,6 +3179,7 @@ pub(crate) fn screen_thread_main(
invoked_with,
floating_pane_coordinates,
start_suppressed,
+ true,
Some(client_id)
)
}, ?);
@@ -3204,6 +3206,7 @@ pub(crate) fn screen_thread_main(
invoked_with,
floating_pane_coordinates,
start_suppressed,
+ true,
None,
)?;
if let Some(hold_for_command) = hold_for_command {
@@ -3226,6 +3229,7 @@ pub(crate) fn screen_thread_main(
invoked_with,
floating_pane_coordinates,
start_suppressed,
+ true,
None,
)?;
if let Some(hold_for_command) = hold_for_command {
@@ -3361,6 +3365,19 @@ pub(crate) fn screen_thread_main(
is_kitty_keyboard_protocol,
client_id,
) => {
+ if let Some(plugin_id) = keybind_intercepts.get(&client_id) {
+ if let Some(key_with_modifier) = key_with_modifier {
+ let _ = screen
+ .bus
+ .senders
+ .send_to_plugin(PluginInstruction::Update(vec![(
+ Some(*plugin_id),
+ Some(client_id),
+ Event::InterceptedKeyPress(key_with_modifier),
+ )]));
+ continue;
+ }
+ }
let mut state_changed = false;
active_tab_and_connected_client_id!(
screen,
@@ -4322,6 +4339,7 @@ pub(crate) fn screen_thread_main(
skip_cache,
cwd,
None,
+ None,
))?;
},
ScreenInstruction::NewFloatingPluginPane(
@@ -4350,6 +4368,7 @@ pub(crate) fn screen_thread_main(
size,
skip_cache,
cwd,
+ None,
floating_pane_coordinates,
))?;
},
@@ -4385,6 +4404,7 @@ pub(crate) fn screen_thread_main(
skip_cache,
None,
None,
+ None,
))?;
},
None => {
@@ -4419,6 +4439,8 @@ pub(crate) fn screen_thread_main(
pane_id_to_replace,
cwd,
start_suppressed,
+ floating_pane_coordinates,
+ should_focus_plugin,
client_id,
) => {
if screen.active_tab_indices.is_empty() && tab_index.is_none() {
@@ -4432,6 +4454,8 @@ pub(crate) fn screen_thread_main(
pane_id_to_replace,
cwd,
start_suppressed,
+ floating_pane_coordinates,
+ should_focus_plugin,
client_id,
));
continue;
@@ -4480,8 +4504,9 @@ pub(crate) fn screen_thread_main(
Some(pane_title),
should_float,
Some(run_plugin),
- None,
+ floating_pane_coordinates,
start_suppressed,
+ should_focus_plugin.unwrap_or(true),
Some(client_id),
)
}, ?);
@@ -4495,6 +4520,7 @@ pub(crate) fn screen_thread_main(
Some(run_plugin),
None,
start_suppressed,
+ should_focus_plugin.unwrap_or(true),
None,
)?;
} else {
@@ -4571,6 +4597,7 @@ pub(crate) fn screen_thread_main(
skip_cache,
None,
None,
+ None,
))?;
},
None => {
@@ -4618,6 +4645,7 @@ pub(crate) fn screen_thread_main(
skip_cache,
None,
None,
+ None,
))?;
}
},
@@ -4654,6 +4682,7 @@ pub(crate) fn screen_thread_main(
skip_cache,
cwd,
None,
+ None,
))?;
},
None => {
@@ -4691,6 +4720,7 @@ pub(crate) fn screen_thread_main(
skip_cache,
cwd,
None,
+ None,
))?;
},
None => {
@@ -5271,6 +5301,12 @@ pub(crate) fn screen_thread_main(
}
let _ = screen.log_and_report_session_state();
},
+ ScreenInstruction::InterceptKeyPresses(plugin_id, client_id) => {
+ keybind_intercepts.insert(client_id, plugin_id);
+ },
+ ScreenInstruction::ClearKeyPressesIntercepts(client_id) => {
+ keybind_intercepts.remove(&client_id);
+ },
}
}
Ok(())
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs
index e3a36ae5..12376817 100644
--- a/zellij-server/src/tab/mod.rs
+++ b/zellij-server/src/tab/mod.rs
@@ -22,6 +22,7 @@ use zellij_utils::position::Position;
use zellij_utils::position::{Column, Line};
use crate::background_jobs::BackgroundJob;
+use crate::pane_groups::PaneGroups;
use crate::pty_writer::PtyWriteInstruction;
use crate::screen::CopyOptions;
use crate::ui::{loading_indication::LoadingIndication, pane_boundaries_frame::FrameParams};
@@ -262,7 +263,7 @@ pub(crate) struct Tab {
styled_underlines: bool,
explicitly_disable_kitty_keyboard_protocol: bool,
mouse_hover_pane_id: HashMap<ClientId, PaneId>,
- current_pane_group: Rc<RefCell<HashMap<ClientId, Vec<PaneId>>>>,
+ current_pane_group: Rc<RefCell<PaneGroups>>,
advanced_mouse_actions: bool,
currently_marking_pane_group: Rc<RefCell<HashMap<ClientId, bool>>>,
}
@@ -675,7 +676,7 @@ impl Tab {
styled_underlines: bool,
explicitly_disable_kitty_keyboard_protocol: bool,
default_editor: Option<PathBuf>,
- current_pane_group: Rc<RefCell<HashMap<ClientId, Vec<PaneId>>>>,
+ current_pane_group: Rc<RefCell<PaneGroups>>,
currently_marking_pane_group: Rc<RefCell<HashMap<ClientId, bool>>>,
advanced_mouse_actions: bool,
) -> Self {
@@ -1187,17 +1188,17 @@ impl Tab {
self.set_force_render();
} else {
self.show_floating_panes();
- match self.floating_panes.last_floating_pane_id() {
- Some(first_floating_pane_id) => match client_id {
+ match self.floating_panes.last_selectable_floating_pane_id() {
+ Some(last_selectable_floating_pane_id) => match client_id {
Some(client_id) => {
if !self.floating_panes.active_panes_contain(&client_id) {
self.floating_panes
- .focus_pane(first_floating_pane_id, client_id);
+ .focus_pane(last_selectable_floating_pane_id, client_id);
}
},
None => {
self.floating_panes
- .focus_pane_for_all_clients(first_floating_pane_id);
+ .focus_pane_for_all_clients(last_selectable_floating_pane_id);
},
},
None => {
@@ -1234,14 +1235,17 @@ impl Tab {
invoked_with: Option<Run>,
floating_pane_coordinates: Option<FloatingPaneCoordinates>,
start_suppressed: bool,
+ should_focus_pane: bool,
client_id: Option<ClientId>,
) -> Result<()> {
let err_context = || format!("failed to create new pane with id {pid:?}");
- match should_float {
- Some(true) => self.show_floating_panes(),
- Some(false) => self.hide_floating_panes(),
- None => {},
- };
+ if should_focus_pane {
+ match should_float {
+ Some(true) => self.show_floating_panes(),
+ Some(false) => self.hide_floating_panes(),
+ None => {},
+ };
+ }
self.close_down_to_max_terminals()
.with_context(err_context)?;
let mut new_pane = match pid {
@@ -1316,10 +1320,26 @@ impl Tab {
self.suppressed_panes
.insert(pid, (is_scrollback_editor, new_pane));
Ok(())
- } else if self.floating_panes.panes_are_visible() {
- self.add_floating_pane(new_pane, pid, floating_pane_coordinates, true)
+ } else if should_focus_pane {
+ if self.floating_panes.panes_are_visible() {
+ self.add_floating_pane(new_pane, pid, floating_pane_coordinates, true)
+ } else {
+ self.add_tiled_pane(new_pane, pid, client_id)
+ }
} else {
- self.add_tiled_pane(new_pane, pid, client_id)
+ match should_float {
+ Some(true) => {
+ self.add_floating_pane(new_pane, pid, floating_pane_coordinates, false)
+ },
+ Some(false) => self.add_tiled_pane(new_pane, pid, client_id),
+ None => {
+ if self.floating_panes.panes_are_visible() {
+ self.add_floating_pane(new_pane, pid, floating_pane_coordinates, false)
+ } else {
+ self.add_tiled_pane(new_pane, pid, client_id)
+ }
+ },
+ }
}
}
pub fn replace_active_pane_with_editor_pane(
@@ -2277,7 +2297,7 @@ impl Tab {
);
let current_pane_group: HashMap<ClientId, Vec<PaneId>> =
- { self.current_pane_group.borrow().clone() };
+ { self.current_pane_group.borrow().clone_inner() };
self.tiled_panes
.render(
output,
@@ -2851,6 +2871,8 @@ impl Tab {
// is opened
self.tiled_panes.move_clients_out_of_pane(id);
}
+ } else if let Some(pane) = self.floating_panes.get_pane_mut(id) {
+ pane.set_selectable(selectable);
}
// we do this here because if there is a non-selectable pane on the edge, we consider it
// outside the viewport (a ui-pane, eg. the status-bar and tab-bar) and need to adjust for it
@@ -2877,7 +2899,7 @@ impl Tab {
if self.floating_panes.panes_contain(&id) {
let _closed_pane = self.floating_panes.remove_pane(id);
self.floating_panes.move_clients_out_of_pane(id);
- if !self.floating_panes.has_panes() {
+ if !self.floating_panes.has_selectable_panes() {
self.swap_layouts.reset_floating_damage();
self.hide_floating_panes();
}
@@ -3663,10 +3685,9 @@ impl Tab {
let err_context =
|| format!("failed to handle mouse event {event:?} for client {client_id}");
if !self.floating_panes.panes_are_visible() {
- let search_selectable = false;
if let Ok(Some(pane_id)) = self
.floating_panes
- .get_pinned_pane_id_at(&event.position, search_selectable)
+ .get_pinned_pane_id_at(&event.position, true)
{
// here, the floating panes are not visible, but there is a pinned pane (always
// visible) that has been clicked on - so we make the entire surface visible and
@@ -3674,6 +3695,15 @@ impl Tab {
self.show_floating_panes();
self.floating_panes.focus_pane(pane_id, client_id);
return Ok(MouseEffect::state_changed());
+ } else if let Ok(Some(_pane_id)) = self
+ .floating_panes
+ .get_pinned_pane_id_at(&event.position, false)
+ {
+ // here, the floating panes are not visible, but there is a pinned pane (always
+ // visible) that has been clicked on - this pane however is not selectable
+ // (we know this because we passed "false" to get_pinned_pane_id_at)
+ // so we don't do anything
+ return Ok(MouseEffect::default());
}
}
let active_pane_id_before_click = self
@@ -3924,8 +3954,13 @@ impl Tab {
self.mouse_hover_pane_id.remove(&client_id);
} else {
let pane_id = pane.pid();
- if self.advanced_mouse_actions {
+ // if the pane is not selectable, we don't want to create a hover effect over it
+ // we do however want to remove the hover effect from other panes
+ let pane_is_selectable = pane.selectable();
+ if self.advanced_mouse_actions && pane_is_selectable {
self.mouse_hover_pane_id.insert(client_id, pane_id);
+ } else if self.advanced_mouse_actions {
+ self.mouse_hover_pane_id.remove(&client_id);
}
}
};
@@ -4467,7 +4502,7 @@ impl Tab {
}
pub fn pane_infos(&self) -> Vec<PaneInfo> {
let mut pane_info = vec![];
- let current_pane_group = { self.current_pane_group.borrow().clone() };
+ let current_pane_group = { self.current_pane_group.borrow().clone_inner() };
let mut tiled_pane_info = self.tiled_panes.pane_info(&current_pane_group);
let mut floating_pane_info = self.floating_panes.pane_info(&current_pane_group);
pane_info.append(&mut tiled_pane_info);
diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs
index acbe04c1..824325a9 100644
--- a/zellij-server/src/tab/unit/tab_integration_tests.rs
+++ b/zellij-server/src/tab/unit/tab_integration_tests.rs
@@ -5,6 +5,7 @@ use crate::Arc;
use crate::{
os_input_output::{AsyncReader, Pid, ServerOsApi},
+ pane_groups::PaneGroups,
panes::PaneId,
plugins::PluginInstruction,
thread_bus::ThreadSenders,
@@ -224,7 +225,7 @@ fn create_new_tab(size: Size, default_mode: ModeInfo) -> Tab {
let copy_options = CopyOptions::default();
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
- let current_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -298,7 +299,7 @@ fn create_new_tab_without_pane_frames(size: Size, default_mode: ModeInfo) -> Tab
let copy_options = CopyOptions::default();
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
- let current_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -387,7 +388,7 @@ fn create_new_tab_with_swap_layouts(
let copy_options = CopyOptions::default();
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
- let current_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -477,7 +478,7 @@ fn create_new_tab_with_os_api(
let copy_options = CopyOptions::default();
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
- let current_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -553,7 +554,7 @@ fn create_new_tab_with_layout(size: Size, default_mode: ModeInfo, layout: &str)
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
let layout = Layout::from_str(layout, "layout_file_name".into(), None, None).unwrap();
let (tab_layout, floating_panes_layout) = layout.new_tab();
- let current_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -643,7 +644,7 @@ fn create_new_tab_with_mock_pty_writer(
let copy_options = CopyOptions::default();
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
- let current_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -724,7 +725,7 @@ fn create_new_tab_with_sixel_support(
let terminal_emulator_colors = Rc::new(RefCell::new(Palette::default()));
let copy_options = CopyOptions::default();
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
- let current_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -912,6 +913,7 @@ fn increase_tiled_pane_sizes_with_stacked_resizes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -965,6 +967,7 @@ fn increase_tiled_pane_sizes_with_stacked_resizes_into_uneven_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1027,6 +1030,7 @@ fn split_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1067,6 +1071,7 @@ fn split_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1109,6 +1114,7 @@ fn render_stacks_without_pane_frames() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1129,6 +1135,7 @@ fn render_stacks_without_pane_frames() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1143,6 +1150,7 @@ fn render_stacks_without_pane_frames() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1157,6 +1165,7 @@ fn render_stacks_without_pane_frames() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1193,8 +1202,17 @@ fn dump_screen() {
..Default::default()
});
let new_pane_id = PaneId::Terminal(2);
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(2, Vec::from("scratch".as_bytes()))
.unwrap();
let file = "/tmp/log.sh";
@@ -1221,8 +1239,17 @@ fn clear_screen() {
..Default::default()
});
let new_pane_id = PaneId::Terminal(2);
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(2, Vec::from("scratch".as_bytes()))
.unwrap();
let file = "/tmp/log-clear-screen.sh";
@@ -1247,8 +1274,17 @@ fn new_floating_pane() {
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
@@ -1275,8 +1311,17 @@ fn floating_panes_persist_across_toggles() {
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
// here we send bytes to the pane when it's not visible to make sure they're still handled and
// we see them once we toggle the panes back
@@ -1307,8 +1352,17 @@ fn toggle_floating_panes_off() {
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
@@ -1336,8 +1390,17 @@ fn toggle_floating_panes_on() {
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
@@ -1377,6 +1440,7 @@ fn five_new_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1387,6 +1451,7 @@ fn five_new_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1397,6 +1462,7 @@ fn five_new_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1407,6 +1473,7 @@ fn five_new_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1417,6 +1484,7 @@ fn five_new_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1461,6 +1529,7 @@ fn increase_floating_pane_size() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1499,6 +1568,7 @@ fn decrease_floating_pane_size() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1537,6 +1607,7 @@ fn resize_floating_pane_left() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1578,6 +1649,7 @@ fn resize_floating_pane_right() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1619,6 +1691,7 @@ fn resize_floating_pane_up() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1660,6 +1733,7 @@ fn resize_floating_pane_down() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1705,6 +1779,7 @@ fn move_floating_pane_focus_left() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1715,6 +1790,7 @@ fn move_floating_pane_focus_left() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1725,6 +1801,7 @@ fn move_floating_pane_focus_left() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1735,6 +1812,7 @@ fn move_floating_pane_focus_left() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1745,6 +1823,7 @@ fn move_floating_pane_focus_left() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1800,6 +1879,7 @@ fn move_floating_pane_focus_right() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1810,6 +1890,7 @@ fn move_floating_pane_focus_right() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1820,6 +1901,7 @@ fn move_floating_pane_focus_right() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1830,6 +1912,7 @@ fn move_floating_pane_focus_right() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1840,6 +1923,7 @@ fn move_floating_pane_focus_right() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1896,6 +1980,7 @@ fn move_floating_pane_focus_up() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1906,6 +1991,7 @@ fn move_floating_pane_focus_up() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1916,6 +2002,7 @@ fn move_floating_pane_focus_up() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1926,6 +2013,7 @@ fn move_floating_pane_focus_up() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1936,6 +2024,7 @@ fn move_floating_pane_focus_up() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1991,6 +2080,7 @@ fn move_floating_pane_focus_down() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2001,6 +2091,7 @@ fn move_floating_pane_focus_down() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2011,6 +2102,7 @@ fn move_floating_pane_focus_down() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2021,6 +2113,7 @@ fn move_floating_pane_focus_down() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2031,6 +2124,7 @@ fn move_floating_pane_focus_down() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2087,6 +2181,7 @@ fn move_floating_pane_focus_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2097,6 +2192,7 @@ fn move_floating_pane_focus_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2107,6 +2203,7 @@ fn move_floating_pane_focus_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2117,6 +2214,7 @@ fn move_floating_pane_focus_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2127,6 +2225,7 @@ fn move_floating_pane_focus_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2191,6 +2290,7 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2201,6 +2301,7 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2211,6 +2312,7 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2221,6 +2323,7 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2231,6 +2334,7 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2295,6 +2399,7 @@ fn drag_pane_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2305,6 +2410,7 @@ fn drag_pane_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2315,6 +2421,7 @@ fn drag_pane_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2325,6 +2432,7 @@ fn drag_pane_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2335,6 +2443,7 @@ fn drag_pane_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2399,6 +2508,7 @@ fn mark_text_inside_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2409,6 +2519,7 @@ fn mark_text_inside_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2419,6 +2530,7 @@ fn mark_text_inside_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2429,6 +2541,7 @@ fn mark_text_inside_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2439,6 +2552,7 @@ fn mark_text_inside_floating_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2511,6 +2625,7 @@ fn resize_tab_with_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2521,6 +2636,7 @@ fn resize_tab_with_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2531,6 +2647,7 @@ fn resize_tab_with_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2541,6 +2658,7 @@ fn resize_tab_with_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2551,6 +2669,7 @@ fn resize_tab_with_floating_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2605,6 +2724,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2615,6 +2735,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2625,6 +2746,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2635,6 +2757,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2645,6 +2768,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2695,6 +2819,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2705,6 +2830,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2715,6 +2841,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2725,6 +2852,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2735,6 +2863,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -2779,8 +2908,17 @@ fn embed_floating_pane() {
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
@@ -2807,8 +2945,17 @@ fn float_embedded_pane() {
let mut tab = create_new_tab(size, ModeInfo::default());
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am an embedded pane".as_bytes()),
@@ -2837,8 +2984,17 @@ fn embed_floating_pane_without_pane_frames() {
let mut output = Output::default();
tab.set_pane_frames(false);
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am scratch terminal".as_bytes()),
@@ -2866,8 +3022,17 @@ fn float_embedded_pane_without_pane_frames() {
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
tab.set_pane_frames(false);
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am an embedded pane".as_bytes()),
@@ -2969,8 +3134,17 @@ fn rename_floating_pane() {
let mut tab = create_new_tab(size, ModeInfo::default());
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.handle_pty_bytes(
2,
Vec::from("\n\n\n I am a floating pane".as_bytes()),
@@ -3065,8 +3239,17 @@ fn move_floating_pane_with_sixel_image() {
let mut output = Output::new(sixel_image_store.clone(), character_cell_size, true);
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
let fixture = read_fixture("sixel-image-500px.six");
tab.handle_pty_bytes(2, fixture).unwrap();
tab.handle_mouse_event(
@@ -3109,8 +3292,17 @@ fn floating_pane_above_sixel_image() {
let mut output = Output::new(sixel_image_store.clone(), character_cell_size, true);
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
let fixture = read_fixture("sixel-image-500px.six");
tab.handle_pty_bytes(1, fixture).unwrap();
tab.handle_mouse_event(
@@ -3173,8 +3365,17 @@ fn suppress_floating_pane() {
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id)
.unwrap();
tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes()))
@@ -3229,8 +3430,17 @@ fn close_suppressing_floating_pane() {
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id)
.unwrap();
tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes()))
@@ -3289,8 +3499,17 @@ fn suppress_floating_pane_embed_it_and_close_it() {
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id)
.unwrap();
tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes()))
@@ -3351,8 +3570,17 @@ fn resize_whole_tab_while_floting_pane_is_suppressed() {
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id)
.unwrap();
tab.handle_pty_bytes(3, Vec::from("\n\n\nI am an editor pane".as_bytes()))
@@ -3453,8 +3681,17 @@ fn enter_search_floating_pane() {
let new_pane_id = PaneId::Terminal(2);
let mut output = Output::default();
tab.toggle_floating_panes(Some(client_id), None).unwrap();
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(client_id))
- .unwrap();
+ tab.new_pane(
+ new_pane_id,
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(client_id),
+ )
+ .unwrap();
let pane_content = read_fixture("grid_copy");
tab.handle_pty_bytes(2, pane_content).unwrap();
@@ -4227,6 +4464,7 @@ fn move_pane_focus_sends_tty_csi_event() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4270,6 +4508,7 @@ fn move_floating_pane_focus_sends_tty_csi_event() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4280,6 +4519,7 @@ fn move_floating_pane_focus_sends_tty_csi_event() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4329,6 +4569,7 @@ fn toggle_floating_panes_on_sends_tty_csi_event() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4339,6 +4580,7 @@ fn toggle_floating_panes_on_sends_tty_csi_event() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4389,6 +4631,7 @@ fn toggle_floating_panes_off_sends_tty_csi_event() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4399,6 +4642,7 @@ fn toggle_floating_panes_off_sends_tty_csi_event() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4469,6 +4713,7 @@ fn can_swap_tiled_layout_at_runtime() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4534,6 +4779,7 @@ fn can_swap_floating_layout_at_runtime() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4544,6 +4790,7 @@ fn can_swap_floating_layout_at_runtime() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4605,6 +4852,7 @@ fn swapping_layouts_after_resize_snaps_to_current_layout() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4665,6 +4913,7 @@ fn swap_tiled_layout_with_stacked_children() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4675,6 +4924,7 @@ fn swap_tiled_layout_with_stacked_children() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4685,6 +4935,7 @@ fn swap_tiled_layout_with_stacked_children() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4738,6 +4989,7 @@ fn swap_tiled_layout_with_only_stacked_children() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4748,6 +5000,7 @@ fn swap_tiled_layout_with_only_stacked_children() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4758,6 +5011,7 @@ fn swap_tiled_layout_with_only_stacked_children() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4814,6 +5068,7 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4824,6 +5079,7 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4834,6 +5090,7 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4890,6 +5147,7 @@ fn move_focus_up_with_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4900,6 +5158,7 @@ fn move_focus_up_with_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4910,6 +5169,7 @@ fn move_focus_up_with_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4968,6 +5228,7 @@ fn move_focus_down_with_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4978,6 +5239,7 @@ fn move_focus_down_with_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -4988,6 +5250,7 @@ fn move_focus_down_with_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5048,6 +5311,7 @@ fn move_focus_right_into_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5119,6 +5383,7 @@ fn move_focus_left_into_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5192,6 +5457,7 @@ fn move_focus_up_into_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5266,6 +5532,7 @@ fn move_focus_down_into_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5336,6 +5603,7 @@ fn close_main_stacked_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5346,6 +5614,7 @@ fn close_main_stacked_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5356,6 +5625,7 @@ fn close_main_stacked_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5415,6 +5685,7 @@ fn close_main_stacked_pane_in_mid_stack() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5425,6 +5696,7 @@ fn close_main_stacked_pane_in_mid_stack() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5435,6 +5707,7 @@ fn close_main_stacked_pane_in_mid_stack() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5445,6 +5718,7 @@ fn close_main_stacked_pane_in_mid_stack() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5455,6 +5729,7 @@ fn close_main_stacked_pane_in_mid_stack() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5517,6 +5792,7 @@ fn close_one_liner_stacked_pane_below_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5527,6 +5803,7 @@ fn close_one_liner_stacked_pane_below_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5537,6 +5814,7 @@ fn close_one_liner_stacked_pane_below_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5547,6 +5825,7 @@ fn close_one_liner_stacked_pane_below_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5557,6 +5836,7 @@ fn close_one_liner_stacked_pane_below_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5620,6 +5900,7 @@ fn close_one_liner_stacked_pane_above_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5630,6 +5911,7 @@ fn close_one_liner_stacked_pane_above_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5640,6 +5922,7 @@ fn close_one_liner_stacked_pane_above_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5650,6 +5933,7 @@ fn close_one_liner_stacked_pane_above_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5660,6 +5944,7 @@ fn close_one_liner_stacked_pane_above_main_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5722,6 +6007,7 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5732,6 +6018,7 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5742,6 +6029,7 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5752,6 +6040,7 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5762,6 +6051,7 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5828,6 +6118,7 @@ fn can_increase_size_of_main_pane_in_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5838,6 +6129,7 @@ fn can_increase_size_of_main_pane_in_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5848,6 +6140,7 @@ fn can_increase_size_of_main_pane_in_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5858,6 +6151,7 @@ fn can_increase_size_of_main_pane_in_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5868,6 +6162,7 @@ fn can_increase_size_of_main_pane_in_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5934,6 +6229,7 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5944,6 +6240,7 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5954,6 +6251,7 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5964,6 +6262,7 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -5974,6 +6273,7 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6035,6 +6335,7 @@ fn can_increase_size_into_pane_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6045,6 +6346,7 @@ fn can_increase_size_into_pane_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6055,6 +6357,7 @@ fn can_increase_size_into_pane_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6065,6 +6368,7 @@ fn can_increase_size_into_pane_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6075,6 +6379,7 @@ fn can_increase_size_into_pane_stack_horizontally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6140,6 +6445,7 @@ fn can_increase_size_into_pane_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6150,6 +6456,7 @@ fn can_increase_size_into_pane_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6160,6 +6467,7 @@ fn can_increase_size_into_pane_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6170,6 +6478,7 @@ fn can_increase_size_into_pane_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6180,6 +6489,7 @@ fn can_increase_size_into_pane_stack_vertically() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6248,6 +6558,7 @@ fn can_increase_size_into_pane_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6258,6 +6569,7 @@ fn can_increase_size_into_pane_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6268,6 +6580,7 @@ fn can_increase_size_into_pane_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6278,6 +6591,7 @@ fn can_increase_size_into_pane_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6288,6 +6602,7 @@ fn can_increase_size_into_pane_stack_non_directionally() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6348,6 +6663,7 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6358,6 +6674,7 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6368,6 +6685,7 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6378,6 +6696,7 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6388,6 +6707,7 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6450,6 +6770,7 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6460,6 +6781,7 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6470,6 +6792,7 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6480,6 +6803,7 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6490,6 +6814,7 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6557,6 +6882,7 @@ fn cannot_decrease_stack_size_beyond_minimum_height() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6567,6 +6893,7 @@ fn cannot_decrease_stack_size_beyond_minimum_height() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6577,6 +6904,7 @@ fn cannot_decrease_stack_size_beyond_minimum_height() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6587,6 +6915,7 @@ fn cannot_decrease_stack_size_beyond_minimum_height() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6597,6 +6926,7 @@ fn cannot_decrease_stack_size_beyond_minimum_height() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6664,6 +6994,7 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6674,6 +7005,7 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6684,6 +7016,7 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6694,6 +7027,7 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6704,6 +7038,7 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6768,6 +7103,7 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6778,6 +7114,7 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6788,6 +7125,7 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6798,6 +7136,7 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6808,6 +7147,7 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6877,6 +7217,7 @@ fn close_stacked_pane_with_previously_focused_other_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6887,6 +7228,7 @@ fn close_stacked_pane_with_previously_focused_other_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6897,6 +7239,7 @@ fn close_stacked_pane_with_previously_focused_other_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6907,6 +7250,7 @@ fn close_stacked_pane_with_previously_focused_other_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6917,6 +7261,7 @@ fn close_stacked_pane_with_previously_focused_other_pane() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -6992,6 +7337,7 @@ fn close_pane_near_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7002,6 +7348,7 @@ fn close_pane_near_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7012,6 +7359,7 @@ fn close_pane_near_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7022,6 +7370,7 @@ fn close_pane_near_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7032,6 +7381,7 @@ fn close_pane_near_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7098,6 +7448,7 @@ fn focus_next_pane_expands_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7108,6 +7459,7 @@ fn focus_next_pane_expands_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7118,6 +7470,7 @@ fn focus_next_pane_expands_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7128,6 +7481,7 @@ fn focus_next_pane_expands_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7138,6 +7492,7 @@ fn focus_next_pane_expands_stacked_panes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7200,6 +7555,7 @@ fn stacked_panes_can_become_fullscreen() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7210,6 +7566,7 @@ fn stacked_panes_can_become_fullscreen() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7220,6 +7577,7 @@ fn stacked_panes_can_become_fullscreen() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7230,6 +7588,7 @@ fn stacked_panes_can_become_fullscreen() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7240,6 +7599,7 @@ fn stacked_panes_can_become_fullscreen() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7898,6 +8258,7 @@ fn new_pane_in_auto_layout() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -7968,6 +8329,7 @@ fn new_pane_in_stacked_resizes() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -8919,6 +9281,7 @@ fn new_floating_pane_in_auto_layout() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs
index f80b870b..67115118 100644
--- a/zellij-server/src/tab/unit/tab_tests.rs
+++ b/zellij-server/src/tab/unit/tab_tests.rs
@@ -1,4 +1,5 @@
use super::Tab;
+use crate::pane_groups::PaneGroups;
use crate::panes::sixel::SixelImageStore;
use crate::screen::CopyOptions;
use crate::{
@@ -165,7 +166,7 @@ fn create_new_tab(size: Size, stacked_resize: bool) -> Tab {
let copy_options = CopyOptions::default();
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
- let current_pane_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_pane_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -238,7 +239,7 @@ fn create_new_tab_with_layout(size: Size, layout: TiledPaneLayout) -> Tab {
let copy_options = CopyOptions::default();
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
- let current_pane_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_pane_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -317,7 +318,7 @@ fn create_new_tab_with_cell_size(
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
let stacked_resize = Rc::new(RefCell::new(true));
- let current_pane_group = Rc::new(RefCell::new(HashMap::new()));
+ let current_pane_group = Rc::new(RefCell::new(PaneGroups::new(ThreadSenders::default())));
let currently_marking_pane_group = Rc::new(RefCell::new(HashMap::new()));
let debug = false;
let arrow_fonts = true;
@@ -602,7 +603,7 @@ fn split_largest_pane() {
let mut tab = create_new_tab(size, stacked_resize);
for i in 2..5 {
let new_pane_id = PaneId::Terminal(i);
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(1))
+ tab.new_pane(new_pane_id, None, None, None, None, false, true, Some(1))
.unwrap();
}
assert_eq!(tab.tiled_panes.panes.len(), 4, "The tab has four panes");
@@ -811,8 +812,17 @@ pub fn cannot_split_largest_pane_when_there_is_no_room() {
let size = Size { cols: 8, rows: 4 };
let stacked_resize = true;
let mut tab = create_new_tab(size, stacked_resize);
- tab.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
- .unwrap();
+ tab.new_pane(
+ PaneId::Terminal(2),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
+ .unwrap();
assert_eq!(
tab.tiled_panes.panes.len(),
1,
@@ -856,7 +866,7 @@ pub fn toggle_focused_pane_fullscreen() {
let mut tab = create_new_tab(size, stacked_resize);
for i in 2..5 {
let new_pane_id = PaneId::Terminal(i);
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(1))
+ tab.new_pane(new_pane_id, None, None, None, None, false, true, Some(1))
.unwrap();
}
tab.toggle_active_pane_fullscreen(1);
@@ -932,7 +942,7 @@ pub fn toggle_focused_pane_fullscreen_with_stacked_resizes() {
let mut tab = create_new_tab(size, stacked_resize);
for i in 2..5 {
let new_pane_id = PaneId::Terminal(i);
- tab.new_pane(new_pane_id, None, None, None, None, false, Some(1))
+ tab.new_pane(new_pane_id, None, None, None, None, false, true, Some(1))
.unwrap();
}
tab.toggle_active_pane_fullscreen(1);
@@ -1008,16 +1018,52 @@ fn switch_to_next_pane_fullscreen() {
let mut active_tab = create_new_tab(size, stacked_resize);
active_tab
- .new_pane(PaneId::Terminal(1), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(1),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab
- .new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(2),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab
- .new_pane(PaneId::Terminal(3), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(3),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab
- .new_pane(PaneId::Terminal(4), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(4),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab.toggle_active_pane_fullscreen(1);
@@ -1049,16 +1095,52 @@ fn switch_to_prev_pane_fullscreen() {
//testing four consecutive switches in fullscreen mode
active_tab
- .new_pane(PaneId::Terminal(1), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(1),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab
- .new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(2),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab
- .new_pane(PaneId::Terminal(3), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(3),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab
- .new_pane(PaneId::Terminal(4), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(4),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab.toggle_active_pane_fullscreen(1);
// order is now 1 2 3 4
@@ -14650,8 +14732,17 @@ fn correctly_resize_frameless_panes_on_pane_close() {
let content_size = (pane.get_content_columns(), pane.get_content_rows());
assert_eq!(content_size, (cols, rows));
- tab.new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
- .unwrap();
+ tab.new_pane(
+ PaneId::Terminal(2),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
+ .unwrap();
tab.close_pane(PaneId::Terminal(2), true);
// the size should be the same after adding and then removing a pane
diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs
index 35979bd4..2b0d02eb 100644
--- a/zellij-server/src/ui/pane_boundaries_frame.rs
+++ b/zellij-server/src/ui/pane_boundaries_frame.rs
@@ -64,6 +64,7 @@ pub struct FrameParams {
pub pane_is_floating: bool,
pub content_offset: Offset,
pub mouse_is_hovering_over_pane: bool,
+ pub pane_is_selectable: bool,
}
#[derive(Default, PartialEq)]
@@ -86,6 +87,7 @@ pub struct PaneFrame {
is_floating: bool,
content_offset: Offset,
mouse_is_hovering_over_pane: bool,
+ is_selectable: bool,
}
impl PaneFrame {
@@ -114,6 +116,7 @@ impl PaneFrame {
is_floating: frame_params.pane_is_floating,
content_offset: frame_params.content_offset,
mouse_is_hovering_over_pane: frame_params.mouse_is_hovering_over_pane,
+ is_selectable: frame_params.pane_is_selectable,
}
}
pub fn is_pinned(mut self, is_pinned: bool) -> Self {
@@ -167,7 +170,7 @@ impl PaneFrame {
// string and length because of color
let has_scroll = self.scroll_position.0 > 0 || self.scroll_position.1 > 0;
if has_scroll {
- let pin_indication = if self.is_floating {
+ let pin_indication = if self.is_floating && self.is_selectable {
self.render_pinned_indication(max_length)
} else {
None
@@ -192,7 +195,7 @@ impl PaneFrame {
(None, Some(scroll_indication)) => Some(scroll_indication),
_ => None,
}
- } else if self.is_floating {
+ } else if self.is_floating && self.is_selectable {
self.render_pinned_indication(max_length)
} else {
None
diff --git a/zellij-server/src/ui/pane_contents_and_ui.rs b/zellij-server/src/ui/pane_contents_and_ui.rs
index d3d99f0e..c17a9b66 100644
--- a/zellij-server/src/ui/pane_contents_and_ui.rs
+++ b/zellij-server/src/ui/pane_contents_and_ui.rs
@@ -207,6 +207,7 @@ impl<'a> PaneContentsAndUi<'a> {
client_mode: InputMode,
session_is_mirrored: bool,
pane_is_floating: bool,
+ pane_is_selectable: bool,
) -> Result<()> {
let err_context = || format!("failed to render pane frame for client {client_id}");
@@ -243,6 +244,7 @@ impl<'a> PaneContentsAndUi<'a> {
mouse_is_hovering_over_pane: self
.mouse_is_hovering_over_pane_for_clients
.contains(&client_id),
+ pane_is_selectable,
}
} else {
FrameParams {
@@ -260,6 +262,7 @@ impl<'a> PaneContentsAndUi<'a> {
mouse_is_hovering_over_pane: self
.mouse_is_hovering_over_pane_for_clients
.contains(&client_id),
+ pane_is_selectable,
}
};
diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs
index 9e744097..e2b28ed3 100644
--- a/zellij-server/src/unit/screen_tests.rs
+++ b/zellij-server/src/unit/screen_tests.rs
@@ -1194,7 +1194,16 @@ fn switch_to_tab_with_fullscreen() {
{
let active_tab = screen.get_active_tab_mut(1).unwrap();
active_tab
- .new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(2),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab.toggle_active_pane_fullscreen(1);
}
@@ -1309,7 +1318,16 @@ fn attach_after_first_tab_closed() {
{
let active_tab = screen.get_active_tab_mut(1).unwrap();
active_tab
- .new_pane(PaneId::Terminal(2), None, None, None, None, false, Some(1))
+ .new_pane(
+ PaneId::Terminal(2),
+ None,
+ None,
+ None,
+ None,
+ false,
+ true,
+ Some(1),
+ )
.unwrap();
active_tab.toggle_active_pane_fullscreen(1);
}
@@ -1345,6 +1363,7 @@ fn open_new_floating_pane_with_custom_coordinates() {
pinned: None,
}),
false,
+ true,
Some(1),
)
.unwrap();
@@ -1380,6 +1399,7 @@ fn open_new_floating_pane_with_custom_coordinates_exceeding_viewport() {
pinned: None,
}),
false,
+ true,
Some(1),
)
.unwrap();
@@ -1478,7 +1498,11 @@ fn group_panes_with_mouse() {
);
assert_eq!(
- screen.current_pane_group.borrow().get(&client_id),
+ screen
+ .current_pane_group
+ .borrow()
+ .clone_inner()
+ .get(&client_id),
Some(&vec![PaneId::Terminal(2)]),
"Pane Id added to client's pane group"
);
@@ -1489,7 +1513,11 @@ fn group_panes_with_mouse() {
);
assert_eq!(
- screen.current_pane_group.borrow().get(&client_id),
+ screen
+ .current_pane_group
+ .borrow()
+ .clone_inner()
+ .get(&client_id),
Some(&vec![]),
"Pane Id removed from client's pane group"
);
@@ -1509,7 +1537,11 @@ fn group_panes_with_keyboard() {
let _ = screen.toggle_pane_in_group(client_id);
assert_eq!(
- screen.current_pane_group.borrow().get(&client_id),
+ screen
+ .current_pane_group
+ .borrow()
+ .clone_inner()
+ .get(&client_id),
Some(&vec![PaneId::Terminal(2)]),
"Pane Id added to client's pane group"
);
@@ -1517,7 +1549,11 @@ fn group_panes_with_keyboard() {
let _ = screen.toggle_pane_in_group(client_id);
assert_eq!(
- screen.current_pane_group.borrow().get(&client_id),
+ screen
+ .current_pane_group
+ .borrow()
+ .clone_inner()
+ .get(&client_id),
Some(&vec![]),
"Pane Id removed from client's pane group"
);
@@ -1546,6 +1582,7 @@ fn group_panes_following_focus() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1560,7 +1597,11 @@ fn group_panes_following_focus() {
.unwrap();
screen.add_active_pane_to_group_if_marking(&client_id);
assert_eq!(
- screen.current_pane_group.borrow().get(&client_id),
+ screen
+ .current_pane_group
+ .borrow()
+ .clone_inner()
+ .get(&client_id),
Some(&vec![PaneId::Terminal(4), PaneId::Terminal(3)]),
"Pane Id of focused pane and newly focused pane above added to pane group"
);
@@ -1573,7 +1614,7 @@ fn group_panes_following_focus() {
.move_focus_up(client_id)
.unwrap();
let _ = screen.add_active_pane_to_group_if_marking(&client_id);
- assert_eq!(screen.current_pane_group.borrow().get(&client_id), Some(&vec![PaneId::Terminal(4), PaneId::Terminal(3)]), "Pane Id of newly focused pane not added to group after the group marking was toggled off");
+ assert_eq!(screen.current_pane_group.borrow().clone_inner().get(&client_id), Some(&vec![PaneId::Terminal(4), PaneId::Terminal(3)]), "Pane Id of newly focused pane not added to group after the group marking was toggled off");
}
}
@@ -1600,6 +1641,7 @@ fn break_group_with_mouse() {
None,
None,
false,
+ true,
Some(client_id),
)
.unwrap();
@@ -1620,7 +1662,11 @@ fn break_group_with_mouse() {
.unwrap();
screen.add_active_pane_to_group_if_marking(&client_id);
assert_eq!(
- screen.current_pane_group.borrow().get(&client_id),
+ screen
+ .current_pane_group
+ .borrow()
+ .clone_inner()
+ .get(&client_id),
Some(&vec![
PaneId::Terminal(4),
PaneId::Terminal(3),
@@ -1635,7 +1681,11 @@ fn break_group_with_mouse() {
client_id,
);
assert_eq!(
- screen.current_pane_group.borrow().get(&client_id),
+ screen
+ .current_pane_group
+ .borrow()
+ .clone_inner()
+ .get(&client_id),
Some(&vec![]),
"Group cleared by mouse event"
);
diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap
index cd58c620..e4b7c405 100644
--- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap
+++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap
@@ -1,6 +1,5 @@
---
source: zellij-server/src/./unit/screen_tests.rs
-assertion_line: 2983
expression: "format!(\"{:#?}\", pty_fill_plugin_cwd_instruction)"
---
Some(
@@ -32,5 +31,6 @@ Some(
false,
None,
None,
+ None,
),
)
diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs
index db6ea180..d67768f1 100644
--- a/zellij-tile/src/shim.rs
+++ b/zellij-tile/src/shim.rs
@@ -1313,6 +1313,20 @@ pub fn embed_multiple_panes(pane_ids: Vec<PaneId>) {
unsafe { host_run_plugin_command() };
}
+pub fn intercept_key_presses() {
+ let plugin_command = PluginCommand::InterceptKeyPresses;
+ 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 clear_key_presses_intercepts() {
+ let plugin_command = PluginCommand::ClearKeyPressesIntercepts;
+ let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
+ object_to_stdout(&protobuf_plugin_command.encode_to_vec());
+ unsafe { host_run_plugin_command() };
+}
+
// Utility Functions
#[allow(unused)]
diff --git a/zellij-tile/src/ui_components/text.rs b/zellij-tile/src/ui_components/text.rs
index 228b8975..787125b5 100644
--- a/zellij-tile/src/ui_components/text.rs
+++ b/zellij-tile/src/ui_components/text.rs
@@ -54,6 +54,44 @@ impl Text {
.map(|i| i.append(&mut indices.into_iter().collect()));
self
}
+ pub fn color_substring<S: AsRef<str>>(mut self, index_level: usize, substr: S) -> Self {
+ let substr = substr.as_ref();
+ let mut start = 0;
+
+ while let Some(pos) = self.text[start..].find(substr) {
+ let abs_pos = start + pos;
+ self = self.color_range(index_level, abs_pos..abs_pos + substr.len());
+ start = abs_pos + substr.len();
+ }
+
+ self
+ }
+
+ pub fn color_all(self, index_level: usize) -> Self {
+ self.color_range(index_level, ..)
+ }
+
+ pub fn color_nth_substring<S: AsRef<str>>(
+ self,
+ index_level: usize,
+ substr: S,
+ occurrence_index: usize,
+ ) -> Self {
+ let substr = substr.as_ref();
+ let mut start = 0;
+ let mut count = 0;
+
+ while let Some(pos) = self.text[start..].find(substr) {
+ if count == occurrence_index {
+ let abs_pos = start + pos;
+ return self.color_range(index_level, abs_pos..abs_pos + substr.len());
+ }
+ count += 1;
+ start = start + pos + substr.len();
+ }
+
+ self
+ }
fn pad_indices(&mut self, index_level: usize) {
if self.indices.get(index_level).is_none() {
for _ in self.indices.len()..=index_level {
diff --git a/zellij-utils/assets/config/default.kdl b/zellij-utils/assets/config/default.kdl
index bdfedc86..722d9eff 100644
--- a/zellij-utils/assets/config/default.kdl
+++ b/zellij-utils/assets/config/default.kdl
@@ -181,12 +181,6 @@ keybinds {
bind "Alt -" { Resize "Decrease"; }
bind "Alt [" { PreviousSwapLayout; }
bind "Alt ]" { NextSwapLayout; }
- bind "Alt m" {
- LaunchOrFocusPlugin "zellij:multiple-select" {
- floating true
- move_to_focused_tab true
- }
- }
bind "Alt p" { TogglePaneInGroup; }
bind "Alt Shift p" { ToggleGroupMarking; }
}
diff --git a/zellij-utils/assets/plugins/about.wasm b/zellij-utils/assets/plugins/about.wasm
index c7355f84..07ac7021 100755
--- a/zellij-utils/assets/plugins/about.wasm
+++ b/zellij-utils/assets/plugins/about.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/compact-bar.wasm b/zellij-utils/assets/plugins/compact-bar.wasm
index fab6fbac..3918af37 100755
--- a/zellij-utils/assets/plugins/compact-bar.wasm
+++ b/zellij-utils/assets/plugins/compact-bar.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/configuration.wasm b/zellij-utils/assets/plugins/configuration.wasm
index 0fd47e93..a2aa03fe 100755
--- a/zellij-utils/assets/plugins/configuration.wasm
+++ b/zellij-utils/assets/plugins/configuration.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm
index e3135dea..be0bd88a 100755
--- a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm
+++ b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/multiple-select.wasm b/zellij-utils/assets/plugins/multiple-select.wasm
index c3b73e96..584569c2 100755
--- a/zellij-utils/assets/plugins/multiple-select.wasm
+++ b/zellij-utils/assets/plugins/multiple-select.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/plugin-manager.wasm b/zellij-utils/assets/plugins/plugin-manager.wasm
index 87617d79..3817aa9e 100755
--- a/zellij-utils/assets/plugins/plugin-manager.wasm
+++ b/zellij-utils/assets/plugins/plugin-manager.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/session-manager.wasm b/zellij-utils/assets/plugins/session-manager.wasm
index fb2ac62b..17cd792c 100755
--- a/zellij-utils/assets/plugins/session-manager.wasm
+++ b/zellij-utils/assets/plugins/session-manager.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/status-bar.wasm b/zellij-utils/assets/plugins/status-bar.wasm
index 4465559e..fefe06ba 100755
--- a/zellij-utils/assets/plugins/status-bar.wasm
+++ b/zellij-utils/assets/plugins/status-bar.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/strider.wasm b/zellij-utils/assets/plugins/strider.wasm
index 5e57d392..ae11f8e0 100755
--- a/zellij-utils/assets/plugins/strider.wasm
+++ b/zellij-utils/assets/plugins/strider.wasm
Binary files differ
diff --git a/zellij-utils/assets/plugins/tab-bar.wasm b/zellij-utils/assets/plugins/tab-bar.wasm
index 07ba9f24..5f1e2c9f 100755
--- a/zellij-utils/assets/plugins/tab-bar.wasm
+++ b/zellij-utils/assets/plugins/tab-bar.wasm
Binary files differ
diff --git a/zellij-utils/assets/prost/api.event.rs b/zellij-utils/assets/prost/api.event.rs
index 258dba41..7ec6e076 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")]
+ #[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")]
pub payload: ::core::option::Option<event::Payload>,
}
/// Nested message and enum types in `Event`.
@@ -67,6 +67,8 @@ pub mod event {
FailedToChangeHostFolderPayload(super::FailedToChangeHostFolderPayload),
#[prost(message, tag="26")]
PastedTextPayload(super::PastedTextPayload),
+ #[prost(message, tag="27")]
+ InterceptedKeyPayload(super::super::key::Key),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
@@ -530,6 +532,7 @@ pub enum EventType {
PastedText = 29,
ConfigWasWrittenToDisk = 30,
BeforeClose = 31,
+ InterceptedKeyPress = 32,
}
impl EventType {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -570,6 +573,7 @@ impl EventType {
EventType::PastedText => "PastedText",
EventType::ConfigWasWrittenToDisk => "ConfigWasWrittenToDisk",
EventType::BeforeClose => "BeforeClose",
+ EventType::InterceptedKeyPress => "InterceptedKeyPress",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -607,6 +611,7 @@ impl EventType {
"PastedText" => Some(Self::PastedText),
"ConfigWasWrittenToDisk" => Some(Self::ConfigWasWrittenToDisk),
"BeforeClose" => Some(Self::BeforeClose),
+ "InterceptedKeyPress" => Some(Self::InterceptedKeyPress),
_ => None,
}
}
diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs
index b7dd7a20..5bdccac9 100644
--- a/zellij-utils/assets/prost/api.plugin_command.rs
+++ b/zellij-utils/assets/prost/api.plugin_command.rs
@@ -919,6 +919,8 @@ pub enum CommandName {
CloseMultiplePanes = 129,
FloatMultiplePanes = 130,
EmbedMultiplePanes = 131,
+ InterceptKeyPresses = 132,
+ ClearKeyPressesIntercepts = 133,
}
impl CommandName {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -1059,6 +1061,8 @@ impl CommandName {
CommandName::CloseMultiplePanes => "CloseMultiplePanes",
CommandName::FloatMultiplePanes => "FloatMultiplePanes",
CommandName::EmbedMultiplePanes => "EmbedMultiplePanes",
+ CommandName::InterceptKeyPresses => "InterceptKeyPresses",
+ CommandName::ClearKeyPressesIntercepts => "ClearKeyPressesIntercepts",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -1196,6 +1200,8 @@ impl CommandName {
"CloseMultiplePanes" => Some(Self::CloseMultiplePanes),
"FloatMultiplePanes" => Some(Self::FloatMultiplePanes),
"EmbedMultiplePanes" => Some(Self::EmbedMultiplePanes),
+ "InterceptKeyPresses" => Some(Self::InterceptKeyPresses),
+ "ClearKeyPressesIntercepts" => Some(Self::ClearKeyPressesIntercepts),
_ => None,
}
}
diff --git a/zellij-utils/assets/prost/api.plugin_permission.rs b/zellij-utils/assets/prost/api.plugin_permission.rs
index 27eba0d4..4e837373 100644
--- a/zellij-utils/assets/prost/api.plugin_permission.rs
+++ b/zellij-utils/assets/prost/api.plugin_permission.rs
@@ -12,6 +12,7 @@ pub enum PermissionType {
MessageAndLaunchOtherPlugins = 8,
Reconfigure = 9,
FullHdAccess = 10,
+ InterceptInput = 11,
}
impl PermissionType {
/// String value of the enum field names used in the ProtoBuf definition.
@@ -31,6 +32,7 @@ impl PermissionType {
PermissionType::MessageAndLaunchOtherPlugins => "MessageAndLaunchOtherPlugins",
PermissionType::Reconfigure => "Reconfigure",
PermissionType::FullHdAccess => "FullHdAccess",
+ PermissionType::InterceptInput => "InterceptInput",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
@@ -47,6 +49,7 @@ impl PermissionType {
"MessageAndLaunchOtherPlugins" => Some(Self::MessageAndLaunchOtherPlugins),
"Reconfigure" => Some(Self::Reconfigure),
"FullHdAccess" => Some(Self::FullHdAccess),
+ "InterceptInput" => Some(Self::InterceptInput),
_ => None,
}
}
diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs
index 3e888a63..2cceeab8 100644
--- a/zellij-utils/src/data.rs
+++ b/zellij-utils/src/data.rs
@@ -938,6 +938,7 @@ pub enum Event {
PastedText(String),
ConfigWasWrittenToDisk,
BeforeClose,
+ InterceptedKeyPress(KeyWithModifier),
}
#[derive(
@@ -969,6 +970,7 @@ pub enum Permission {
MessageAndLaunchOtherPlugins,
Reconfigure,
FullHdAccess,
+ InterceptInput,
}
impl PermissionType {
@@ -991,6 +993,7 @@ impl PermissionType {
},
PermissionType::Reconfigure => "Change Zellij runtime configuration".to_owned(),
PermissionType::FullHdAccess => "Full access to the hard-drive".to_owned(),
+ PermissionType::InterceptInput => "Intercept Input (keyboard & mouse)".to_owned(),
}
}
}
@@ -2323,4 +2326,6 @@ pub enum PluginCommand {
CloseMultiplePanes(Vec<PaneId>),
FloatMultiplePanes(Vec<PaneId>),
EmbedMultiplePanes(Vec<PaneId>),
+ InterceptKeyPresses,
+ ClearKeyPressesIntercepts,
}
diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs
index cf417ad4..dbc9ba60 100644
--- a/zellij-utils/src/errors.rs
+++ b/zellij-utils/src/errors.rs
@@ -382,6 +382,8 @@ pub enum ScreenContext {
EmbedMultiplePanes,
TogglePaneInGroup,
ToggleGroupMarking,
+ InterceptKeyPresses,
+ ClearKeyPressesIntercepts,
}
/// Stack call representations corresponding to the different types of [`PtyInstruction`]s.
diff --git a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap
index 0a78ce71..e3b5eaa4 100644
--- a/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap
+++ b/zellij-utils/src/kdl/snapshots/zellij_utils__kdl__bare_config_from_default_assets_to_string.snap
@@ -146,12 +146,6 @@ keybinds clear-defaults=true {
bind "Alt j" { MoveFocus "down"; }
bind "Alt k" { MoveFocus "up"; }
bind "Alt l" { MoveFocusOrTab "right"; }
- bind "Alt m" {
- LaunchOrFocusPlugin "zellij:multiple-select" {
- floating true
- move_to_focused_tab true
- }
- }
bind "Alt n" { NewPane; }
bind "Alt o" { MoveTab "right"; }
bind "Alt p" { TogglePaneInGroup; }
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 81ca2f2d..c7295555 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
@@ -146,12 +146,6 @@ keybinds clear-defaults=true {
bind "Alt j" { MoveFocus "down"; }
bind "Alt k" { MoveFocus "up"; }
bind "Alt l" { MoveFocusOrTab "right"; }
- bind "Alt m" {
- LaunchOrFocusPlugin "zellij:multiple-select" {
- floating true
- move_to_focused_tab true
- }
- }
bind "Alt n" { NewPane; }
bind "Alt o" { MoveTab "right"; }
bind "Alt p" { TogglePaneInGroup; }
diff --git a/zellij-utils/src/plugin_api/event.proto b/zellij-utils/src/plugin_api/event.proto
index 9b0e4d2f..760aee0b 100644
--- a/zellij-utils/src/plugin_api/event.proto
+++ b/zellij-utils/src/plugin_api/event.proto
@@ -55,6 +55,7 @@ enum EventType {
PastedText = 29;
ConfigWasWrittenToDisk = 30;
BeforeClose = 31;
+ InterceptedKeyPress = 32;
}
message EventNameList {
@@ -89,6 +90,7 @@ message Event {
HostFolderChangedPayload host_folder_changed_payload = 24;
FailedToChangeHostFolderPayload failed_to_change_host_folder_payload = 25;
PastedTextPayload pasted_text_payload = 26;
+ key.Key intercepted_key_payload = 27;
}
}
diff --git a/zellij-utils/src/plugin_api/event.rs b/zellij-utils/src/plugin_api/event.rs
index 88c55827..a853e12d 100644
--- a/zellij-utils/src/plugin_api/event.rs
+++ b/zellij-utils/src/plugin_api/event.rs
@@ -363,6 +363,12 @@ impl TryFrom<ProtobufEvent> for Event {
None => Ok(Event::BeforeClose),
_ => Err("Malformed payload for the BeforeClose Event"),
},
+ Some(ProtobufEventType::InterceptedKeyPress) => match protobuf_event.payload {
+ Some(ProtobufEventPayload::KeyPayload(protobuf_key)) => {
+ Ok(Event::InterceptedKeyPress(protobuf_key.try_into()?))
+ },
+ _ => Err("Malformed payload for the InterceptedKeyPress Event"),
+ },
None => Err("Unknown Protobuf Event"),
}
}
@@ -741,6 +747,10 @@ impl TryFrom<Event> for ProtobufEvent {
name: ProtobufEventType::BeforeClose as i32,
payload: None,
}),
+ Event::InterceptedKeyPress(key) => Ok(ProtobufEvent {
+ name: ProtobufEventType::InterceptedKeyPress as i32,
+ payload: Some(event::Payload::KeyPayload(key.try_into()?)),
+ }),
}
}
}
@@ -1376,6 +1386,7 @@ impl TryFrom<ProtobufEventType> for EventType {
ProtobufEventType::PastedText => EventType::PastedText,
ProtobufEventType::ConfigWasWrittenToDisk => EventType::ConfigWasWrittenToDisk,
ProtobufEventType::BeforeClose => EventType::BeforeClose,
+ ProtobufEventType::InterceptedKeyPress => EventType::InterceptedKeyPress,
})
}
}
@@ -1416,6 +1427,7 @@ impl TryFrom<EventType> for ProtobufEventType {
EventType::PastedText => ProtobufEventType::PastedText,
EventType::ConfigWasWrittenToDisk => ProtobufEventType::ConfigWasWrittenToDisk,
EventType::BeforeClose => ProtobufEventType::BeforeClose,
+ EventType::InterceptedKeyPress => ProtobufEventType::InterceptedKeyPress,
})
}
}
diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto
index 3a63b0c8..621b5de6 100644
--- a/zellij-utils/src/plugin_api/plugin_command.proto
+++ b/zellij-utils/src/plugin_api/plugin_command.proto
@@ -145,6 +145,8 @@ enum CommandName {
CloseMultiplePanes = 129;
FloatMultiplePanes = 130;
EmbedMultiplePanes = 131;
+ InterceptKeyPresses = 132;
+ ClearKeyPressesIntercepts = 133;
}
message PluginCommand {
diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs
index 833d6270..08a9545e 100644
--- a/zellij-utils/src/plugin_api/plugin_command.rs
+++ b/zellij-utils/src/plugin_api/plugin_command.rs
@@ -1614,6 +1614,14 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
},
_ => Err("Mismatched payload for EmbedMultiplePanes"),
},
+ Some(CommandName::InterceptKeyPresses) => match protobuf_plugin_command.payload {
+ Some(_) => Err("InterceptKeyPresses should have no payload, found a payload"),
+ None => Ok(PluginCommand::InterceptKeyPresses),
+ },
+ Some(CommandName::ClearKeyPressesIntercepts) => match protobuf_plugin_command.payload {
+ Some(_) => Err("ClearKeyPressesIntercepts should have no payload, found a payload"),
+ None => Ok(PluginCommand::ClearKeyPressesIntercepts),
+ },
None => Err("Unrecognized plugin command"),
}
}
@@ -2684,6 +2692,14 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
},
)),
}),
+ PluginCommand::InterceptKeyPresses => Ok(ProtobufPluginCommand {
+ name: CommandName::InterceptKeyPresses as i32,
+ payload: None,
+ }),
+ PluginCommand::ClearKeyPressesIntercepts => Ok(ProtobufPluginCommand {
+ name: CommandName::ClearKeyPressesIntercepts as i32,
+ payload: None,
+ }),
}
}
}
diff --git a/zellij-utils/src/plugin_api/plugin_permission.proto b/zellij-utils/src/plugin_api/plugin_permission.proto
index 4f1f90f9..72c5b0f9 100644
--- a/zellij-utils/src/plugin_api/plugin_permission.proto
+++ b/zellij-utils/src/plugin_api/plugin_permission.proto
@@ -14,4 +14,5 @@ enum PermissionType {
MessageAndLaunchOtherPlugins = 8;
Reconfigure = 9;
FullHdAccess = 10;
+ InterceptInput = 11;
}
diff --git a/zellij-utils/src/plugin_api/plugin_permission.rs b/zellij-utils/src/plugin_api/plugin_permission.rs
index 5b6a831f..ad64b499 100644
--- a/zellij-utils/src/plugin_api/plugin_permission.rs
+++ b/zellij-utils/src/plugin_api/plugin_permission.rs
@@ -26,6 +26,7 @@ impl TryFrom<ProtobufPermissionType> for PermissionType {
},
ProtobufPermissionType::Reconfigure => Ok(PermissionType::Reconfigure),
ProtobufPermissionType::FullHdAccess => Ok(PermissionType::FullHdAccess),
+ ProtobufPermissionType::InterceptInput => Ok(PermissionType::InterceptInput),
}
}
}
@@ -53,6 +54,7 @@ impl TryFrom<PermissionType> for ProtobufPermissionType {
},
PermissionType::Reconfigure => Ok(ProtobufPermissionType::Reconfigure),
PermissionType::FullHdAccess => Ok(ProtobufPermissionType::FullHdAccess),
+ PermissionType::InterceptInput => Ok(ProtobufPermissionType::InterceptInput),
}
}
}
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 ca465e22..8a09cae9 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
@@ -212,35 +212,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -760,35 +731,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -1266,35 +1208,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -1914,35 +1827,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -2452,35 +2336,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -2856,35 +2711,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -3332,35 +3158,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -3761,35 +3558,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4143,35 +3911,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4579,35 +4318,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -5092,35 +4802,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -5487,35 +5168,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -6047,35 +5699,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
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 3af974e0..e4ac2827 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
@@ -212,35 +212,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -760,35 +731,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -1266,35 +1208,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -1914,35 +1827,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -2452,35 +2336,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -2856,35 +2711,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -3332,35 +3158,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -3761,35 +3558,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4143,35 +3911,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4579,35 +4318,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -5092,35 +4802,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -5487,35 +5168,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -6047,35 +5699,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
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 5281896f..0f330251 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
@@ -212,35 +212,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -760,35 +731,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -1266,35 +1208,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -1914,35 +1827,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -2452,35 +2336,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -2856,35 +2711,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -3332,35 +3158,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -3761,35 +3558,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4143,35 +3911,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4579,35 +4318,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -5092,35 +4802,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -5487,35 +5168,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -6047,35 +5699,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
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 a56b840e..263c68ee 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
@@ -212,35 +212,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -760,35 +731,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -1266,35 +1208,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -1914,35 +1827,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -2452,35 +2336,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -2856,35 +2711,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -3332,35 +3158,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -3761,35 +3558,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4143,35 +3911,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -4579,35 +4318,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -5092,35 +4802,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},
@@ -5487,35 +5168,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {
@@ -6047,35 +5699,6 @@ Config {
],
KeyWithModifier {
bare_key: Char(
- 'm',
- ),
- key_modifiers: {
- Alt,
- },
- }: [
- LaunchOrFocusPlugin(
- RunPlugin(
- RunPlugin {
- _allow_exec_host_cmd: false,
- location: Zellij(
- PluginTag(
- "multiple-select",
- ),
- ),
- configuration: PluginUserConfiguration(
- {},
- ),
- initial_cwd: None,
- },
- ),
- true,
- true,
- false,
- false,
- ),
- ],
- KeyWithModifier {
- bare_key: Char(
'n',
),
key_modifiers: {},