diff options
| author | Aram Drevekenin <aram@poor.dev> | 2025-06-03 17:15:32 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-03 17:15:32 +0200 |
| commit | a9f8bbcd197c8d14832fc1ab1fbe4d4111a2014d (patch) | |
| tree | 6d354fdd36cf534d73e0cb81a7cacd3fedc1ebb9 /default-plugins/compact-bar/src | |
| parent | docs(changelog): theme fixes (diff) | |
| download | sl0ppij-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
Diffstat (limited to 'default-plugins/compact-bar/src')
| -rw-r--r-- | default-plugins/compact-bar/src/line.rs | 300 | ||||
| -rw-r--r-- | default-plugins/compact-bar/src/main.rs | 27 |
2 files changed, 10 insertions, 317 deletions
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 |
