diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-06-29 18:10:59 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-06-29 18:10:59 +0200 |
| commit | 245f5141c9bb7eb91f003efac4defc94470243fd (patch) | |
| tree | 52ae6d003366f97e41c8a1450602aef63c8fdca2 /default-plugins/tab-bar/src/line.rs | |
| parent | feat: reload config on theme change (#5135) (diff) | |
| download | sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.tar.gz sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.tar.xz sl0ppij-245f5141c9bb7eb91f003efac4defc94470243fd.zip | |
Title frames (#5318)
* initial implementation
* improve single line title design
* hint text plugin infra
* add proto regen task
* display alt text in status bar
* don't display text with full frames
* style alt hover text
* fix + style control own pane hover
* make multiplayer indications responsive
* update snapshots
* plugin api
* single pane as tab
* better scroll styling
* fix tests
* tab-bar plus hover
* plugin surface tests
* integration tests
* adjust all integration tests
* reduce hover noise
* add pane id to in place
* more integration tests
* style: rustfmt
* update plugin assets
* update assets and snapshots
* add pr
Diffstat (limited to 'default-plugins/tab-bar/src/line.rs')
| -rw-r--r-- | default-plugins/tab-bar/src/line.rs | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/default-plugins/tab-bar/src/line.rs b/default-plugins/tab-bar/src/line.rs index aa76ce27..99b85f05 100644 --- a/default-plugins/tab-bar/src/line.rs +++ b/default-plugins/tab-bar/src/line.rs @@ -224,7 +224,10 @@ pub fn tab_line( mode_info: &ModeInfo, hide_swap_layout_indicator: bool, background: &PaletteColor, -) -> Vec<LinePart> { + active_pane_scroll: Option<(usize, usize)>, + is_alternate_tab: bool, + new_tab_button_is_hovered: bool, +) -> (Vec<LinePart>, Option<(usize, usize)>) { let mut tabs_after_active = all_tabs.split_off(active_tab_index); let mut tabs_before_active = all_tabs; let active_tab = if !tabs_after_active.is_empty() { @@ -249,6 +252,9 @@ pub fn tab_line( ) }) }; + if swap_layout_indicator.is_none() { + swap_layout_indicator = active_pane_scroll.map(|scroll| scroll_status(scroll, palette)); + } // Drop indicator if it would cause wrapping (active tab always rendered unconditionally) let prefix_len = get_current_title_len(&prefix); @@ -279,6 +285,33 @@ pub fn tab_line( tab_index: None, }]); + let supports_arrow_fonts = !capabilities.arrow_fonts; + let new_tab_button_background = if supports_arrow_fonts { + if new_tab_button_is_hovered { + palette.ribbon_unselected.emphasis_1 + } else { + palette.ribbon_unselected.background + } + } else if is_alternate_tab { + palette.ribbon_unselected.emphasis_1 + } else { + palette.ribbon_unselected.background + }; + let new_tab_button = new_tab_button_line_part(palette, capabilities, new_tab_button_background); + let used = prefix.iter().map(|p| p.len).sum::<usize>(); + let current_indicator_len = swap_layout_indicator.as_ref().map(|s| s.len).unwrap_or(0); + let room = cols + .saturating_sub(used) + .saturating_sub(current_indicator_len); + let new_tab_button_range = if room >= new_tab_button.len { + let button_start = used; + let button_end = button_start + new_tab_button.len; + prefix.push(new_tab_button); + Some((button_start, button_end)) + } else { + None + }; + if let Some(mut swap_layout_indicator) = swap_layout_indicator.take() { let remaining_space = cols .saturating_sub(prefix.iter().fold(0, |len, part| len + part.len)) @@ -301,7 +334,7 @@ pub fn tab_line( prefix.push(swap_layout_indicator); } - prefix + (prefix, new_tab_button_range) } fn swap_layout_status( @@ -329,6 +362,43 @@ fn swap_layout_status( } } +fn scroll_status(scroll: (usize, usize), palette: Styling) -> LinePart { + let (position, length) = scroll; + let text = format!("[ SCROLL {}/{} ]", position, length); + let text_color = palette.text_unselected.base; + let bg_color = palette.text_unselected.background; + let styled_text = style!(text_color, bg_color).bold().paint(&text); + LinePart { + part: styled_text.to_string(), + len: text.width(), + tab_index: None, + } +} + +fn new_tab_button_line_part( + palette: Styling, + capabilities: PluginCapabilities, + background_color: PaletteColor, +) -> LinePart { + let separator = tab_separator(capabilities); + let separator_width = separator.width(); + let foreground_color = palette.ribbon_unselected.base; + let separator_fill_color = palette.text_unselected.background; + let left_separator = style!(separator_fill_color, background_color).paint(separator); + let right_separator = style!(background_color, separator_fill_color).paint(separator); + let text = "+"; + let styled_text = style!(foreground_color, background_color) + .bold() + .paint(format!(" {} ", text)); + let part = ANSIStrings(&[left_separator, styled_text, right_separator]).to_string(); + let len = text.width() + (separator_width * 2) + 2; + LinePart { + part, + len, + tab_index: None, + } +} + pub fn ribbon_as_line_part(text: &str, is_selected: bool, supports_arrow_fonts: bool) -> LinePart { let ribbon_text = if is_selected { Text::new(text).selected() |
