-
-
Notifications
You must be signed in to change notification settings - Fork 685
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add(plugin): `compact-bar` & `compact` layout * add(nix): `compact-bar` plugin * add(config): `compact-bar` to the config * add(workspace): `compact-bar` to workspace members * add(assets): `compact-bar` * chore(fmt): rustfmt * add(nix): add `compact-bar` * add: compact layout to dump command * nix(build): fix destination of copy command * add(makefile): add `compact-bar` to `plugin-build` * add(layout): `compact-bar` to layout * add: install `compact-bar` plugin * fix(test): update input plugin test * fix(plugin): default colors for compact-bar
- Loading branch information
Showing
18 changed files
with
779 additions
and
199 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[build] | ||
target = "wasm32-wasi" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "compact-bar" | ||
version = "0.1.0" | ||
authors = ["Alexander Kenji Berthold <aks.kenji@protonmail.com>" ] | ||
edition = "2021" | ||
license = "MIT" | ||
|
||
[dependencies] | ||
colored = "2" | ||
ansi_term = "0.12" | ||
unicode-width = "0.1.8" | ||
zellij-tile = { path = "../../zellij-tile" } | ||
zellij-tile-utils = { path = "../../zellij-tile-utils" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../LICENSE.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
use ansi_term::ANSIStrings; | ||
use unicode_width::UnicodeWidthStr; | ||
|
||
use crate::{LinePart, ARROW_SEPARATOR}; | ||
use zellij_tile::prelude::*; | ||
use zellij_tile_utils::style; | ||
|
||
fn get_current_title_len(current_title: &[LinePart]) -> usize { | ||
current_title.iter().map(|p| p.len).sum() | ||
} | ||
|
||
// move elements from before_active and after_active into tabs_to_render while they fit in cols | ||
// adds collapsed_tabs to the left and right if there's left over tabs that don't fit | ||
fn populate_tabs_in_tab_line( | ||
tabs_before_active: &mut Vec<LinePart>, | ||
tabs_after_active: &mut Vec<LinePart>, | ||
tabs_to_render: &mut Vec<LinePart>, | ||
cols: usize, | ||
palette: Palette, | ||
capabilities: PluginCapabilities, | ||
) { | ||
let mut middle_size = get_current_title_len(tabs_to_render); | ||
|
||
let mut total_left = 0; | ||
let mut total_right = 0; | ||
loop { | ||
let left_count = tabs_before_active.len(); | ||
let right_count = tabs_after_active.len(); | ||
let collapsed_left = left_more_message(left_count, palette, tab_separator(capabilities)); | ||
let collapsed_right = right_more_message(right_count, palette, tab_separator(capabilities)); | ||
|
||
let total_size = collapsed_left.len + middle_size + collapsed_right.len; | ||
|
||
if total_size > cols { | ||
// break and dont add collapsed tabs to tabs_to_render, they will not fit | ||
break; | ||
} | ||
|
||
let left = if let Some(tab) = tabs_before_active.last() { | ||
tab.len | ||
} else { | ||
usize::MAX | ||
}; | ||
|
||
let right = if let Some(tab) = tabs_after_active.first() { | ||
tab.len | ||
} else { | ||
usize::MAX | ||
}; | ||
|
||
// total size is shortened if the next tab to be added is the last one, as that will remove the collapsed tab | ||
let size_by_adding_left = | ||
left.saturating_add(total_size) | ||
.saturating_sub(if left_count == 1 { | ||
collapsed_left.len | ||
} else { | ||
0 | ||
}); | ||
let size_by_adding_right = | ||
right | ||
.saturating_add(total_size) | ||
.saturating_sub(if right_count == 1 { | ||
collapsed_right.len | ||
} else { | ||
0 | ||
}); | ||
|
||
let left_fits = size_by_adding_left <= cols; | ||
let right_fits = size_by_adding_right <= cols; | ||
// active tab is kept in the middle by adding to the side that | ||
// has less width, or if the tab on the other side doesn' fit | ||
if (total_left <= total_right || !right_fits) && left_fits { | ||
// add left tab | ||
let tab = tabs_before_active.pop().unwrap(); | ||
middle_size += tab.len; | ||
total_left += tab.len; | ||
tabs_to_render.insert(0, tab); | ||
} else if right_fits { | ||
// add right tab | ||
let tab = tabs_after_active.remove(0); | ||
middle_size += tab.len; | ||
total_right += tab.len; | ||
tabs_to_render.push(tab); | ||
} else { | ||
// there's either no space to add more tabs or no more tabs to add, so we're done | ||
tabs_to_render.insert(0, collapsed_left); | ||
tabs_to_render.push(collapsed_right); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
fn left_more_message(tab_count_to_the_left: usize, palette: Palette, separator: &str) -> LinePart { | ||
if tab_count_to_the_left == 0 { | ||
return LinePart::default(); | ||
} | ||
let more_text = if tab_count_to_the_left < 10000 { | ||
format!(" ← +{} ", tab_count_to_the_left) | ||
} else { | ||
" ← +many ".to_string() | ||
}; | ||
// 238 | ||
// chars length plus separator length on both sides | ||
let more_text_len = more_text.width() + 2 * separator.width(); | ||
let text_color = match palette.theme_hue { | ||
ThemeHue::Dark => palette.white, | ||
ThemeHue::Light => palette.black, | ||
}; | ||
let left_separator = style!(text_color, palette.orange).paint(separator); | ||
let more_styled_text = style!(text_color, palette.orange).bold().paint(more_text); | ||
let right_separator = style!(palette.orange, text_color).paint(separator); | ||
let more_styled_text = | ||
ANSIStrings(&[left_separator, more_styled_text, right_separator]).to_string(); | ||
LinePart { | ||
part: more_styled_text, | ||
len: more_text_len, | ||
} | ||
} | ||
|
||
fn right_more_message( | ||
tab_count_to_the_right: usize, | ||
palette: Palette, | ||
separator: &str, | ||
) -> LinePart { | ||
if tab_count_to_the_right == 0 { | ||
return LinePart::default(); | ||
}; | ||
let more_text = if tab_count_to_the_right < 10000 { | ||
format!(" +{} → ", tab_count_to_the_right) | ||
} else { | ||
" +many → ".to_string() | ||
}; | ||
// chars length plus separator length on both sides | ||
let more_text_len = more_text.width() + 2 * separator.width(); | ||
let text_color = match palette.theme_hue { | ||
ThemeHue::Dark => palette.white, | ||
ThemeHue::Light => palette.black, | ||
}; | ||
let left_separator = style!(text_color, palette.orange).paint(separator); | ||
let more_styled_text = style!(text_color, palette.orange).bold().paint(more_text); | ||
let right_separator = style!(palette.orange, text_color).paint(separator); | ||
let more_styled_text = | ||
ANSIStrings(&[left_separator, more_styled_text, right_separator]).to_string(); | ||
LinePart { | ||
part: more_styled_text, | ||
len: more_text_len, | ||
} | ||
} | ||
|
||
fn tab_line_prefix( | ||
session_name: Option<&str>, | ||
mode: InputMode, | ||
palette: Palette, | ||
cols: usize, | ||
) -> Vec<LinePart> { | ||
let prefix_text = " Zellij ".to_string(); | ||
|
||
let prefix_text_len = prefix_text.chars().count(); | ||
let text_color = match palette.theme_hue { | ||
ThemeHue::Dark => palette.white, | ||
ThemeHue::Light => palette.black, | ||
}; | ||
let bg_color = match palette.theme_hue { | ||
ThemeHue::Dark => palette.black, | ||
ThemeHue::Light => palette.white, | ||
}; | ||
let prefix_styled_text = style!(text_color, bg_color).bold().paint(prefix_text); | ||
let mut parts = vec![LinePart { | ||
part: prefix_styled_text.to_string(), | ||
len: prefix_text_len, | ||
}]; | ||
if let Some(name) = session_name { | ||
let name_part = format!("({}) ", name); | ||
let name_part_len = name_part.width(); | ||
let text_color = match palette.theme_hue { | ||
ThemeHue::Dark => palette.white, | ||
ThemeHue::Light => palette.black, | ||
}; | ||
let name_part_styled_text = style!(text_color, bg_color).bold().paint(name_part); | ||
if cols.saturating_sub(prefix_text_len) >= name_part_len { | ||
parts.push(LinePart { | ||
part: name_part_styled_text.to_string(), | ||
len: name_part_len, | ||
}) | ||
} | ||
} | ||
let mode_part = format!("({:?})", mode); | ||
let mode_part_len = mode_part.width(); | ||
let mode_part_styled_text = style!(text_color, bg_color).bold().paint(mode_part); | ||
if cols.saturating_sub(prefix_text_len) >= mode_part_len { | ||
parts.push(LinePart { | ||
part: format!("({:^6})", mode_part_styled_text), | ||
len: mode_part_len, | ||
}) | ||
} | ||
parts | ||
} | ||
|
||
pub fn tab_separator(capabilities: PluginCapabilities) -> &'static str { | ||
if !capabilities.arrow_fonts { | ||
ARROW_SEPARATOR | ||
} else { | ||
"" | ||
} | ||
} | ||
|
||
pub fn tab_line( | ||
session_name: Option<&str>, | ||
mut all_tabs: Vec<LinePart>, | ||
active_tab_index: usize, | ||
cols: usize, | ||
palette: Palette, | ||
capabilities: PluginCapabilities, | ||
mode: InputMode, | ||
) -> Vec<LinePart> { | ||
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() { | ||
tabs_after_active.remove(0) | ||
} else { | ||
tabs_before_active.pop().unwrap() | ||
}; | ||
let mut prefix = tab_line_prefix(session_name, mode, palette, cols); | ||
let prefix_len = get_current_title_len(&prefix); | ||
|
||
// if active tab alone won't fit in cols, don't draw any tabs | ||
if prefix_len + active_tab.len > cols { | ||
return prefix; | ||
} | ||
|
||
let mut tabs_to_render = vec![active_tab]; | ||
|
||
populate_tabs_in_tab_line( | ||
&mut tabs_before_active, | ||
&mut tabs_after_active, | ||
&mut tabs_to_render, | ||
cols.saturating_sub(prefix_len), | ||
palette, | ||
capabilities, | ||
); | ||
prefix.append(&mut tabs_to_render); | ||
prefix | ||
} |
Oops, something went wrong.