aboutsummaryrefslogtreecommitdiffstats
path: root/default-tiles
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2021-03-03 18:52:17 +0100
committerGitHub <noreply@github.com>2021-03-03 18:52:17 +0100
commit845478fe111eaf93af261ce4f5066ce0e7b39b89 (patch)
treeb0aa1055cf98947c4ae2f34c4db3742eb0e37800 /default-tiles
parentMerge pull request #213 from zellij-org/build-fix (diff)
downloadsl0ppij-845478fe111eaf93af261ce4f5066ce0e7b39b89.tar.gz
sl0ppij-845478fe111eaf93af261ce4f5066ce0e7b39b89.tar.xz
sl0ppij-845478fe111eaf93af261ce4f5066ce0e7b39b89.zip
New tab styling (#216)
* draft * feat(tabbar): new ui * style(fmt): rustfmt
Diffstat (limited to 'default-tiles')
-rw-r--r--default-tiles/tab-bar/src/line.rs165
-rw-r--r--default-tiles/tab-bar/src/main.rs41
-rw-r--r--default-tiles/tab-bar/src/tab.rs52
3 files changed, 246 insertions, 12 deletions
diff --git a/default-tiles/tab-bar/src/line.rs b/default-tiles/tab-bar/src/line.rs
new file mode 100644
index 00000000..f28fab3f
--- /dev/null
+++ b/default-tiles/tab-bar/src/line.rs
@@ -0,0 +1,165 @@
+use colored::*;
+
+use crate::{LinePart, ARROW_SEPARATOR};
+
+fn get_current_title_len(current_title: &[LinePart]) -> usize {
+ current_title
+ .iter()
+ .fold(0, |acc, title_part| acc + title_part.len)
+}
+
+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,
+) {
+ let mut take_next_tab_from_tabs_after = true;
+ loop {
+ if tabs_before_active.is_empty() && tabs_after_active.is_empty() {
+ break;
+ }
+ let current_title_len = get_current_title_len(&tabs_to_render);
+ if current_title_len >= cols {
+ break;
+ }
+ let should_take_next_tab = take_next_tab_from_tabs_after;
+ let can_take_next_tab = !tabs_after_active.is_empty()
+ && tabs_after_active.get(0).unwrap().len + current_title_len <= cols;
+ let can_take_previous_tab = !tabs_before_active.is_empty()
+ && tabs_before_active.last().unwrap().len + current_title_len <= cols;
+ if should_take_next_tab && can_take_next_tab {
+ let next_tab = tabs_after_active.remove(0);
+ tabs_to_render.push(next_tab);
+ take_next_tab_from_tabs_after = false;
+ } else if can_take_previous_tab {
+ let previous_tab = tabs_before_active.pop().unwrap();
+ tabs_to_render.insert(0, previous_tab);
+ take_next_tab_from_tabs_after = true;
+ } else if can_take_next_tab {
+ let next_tab = tabs_after_active.remove(0);
+ tabs_to_render.push(next_tab);
+ take_next_tab_from_tabs_after = false;
+ } else {
+ break;
+ }
+ }
+}
+
+fn left_more_message(tab_count_to_the_left: usize) -> LinePart {
+ if tab_count_to_the_left == 0 {
+ return LinePart {
+ part: String::new(),
+ len: 0,
+ };
+ }
+ let more_text = if tab_count_to_the_left < 10000 {
+ format!(" ← +{} ", tab_count_to_the_left)
+ } else {
+ format!(" ← +many ")
+ };
+ let more_styled_text = format!(
+ "{}{}",
+ more_text.black().on_yellow(),
+ ARROW_SEPARATOR.yellow().on_black(),
+ );
+ LinePart {
+ part: more_styled_text,
+ len: more_text.chars().count() + 1, // 1 for the arrow
+ }
+}
+
+fn right_more_message(tab_count_to_the_right: usize) -> LinePart {
+ if tab_count_to_the_right == 0 {
+ return LinePart {
+ part: String::new(),
+ len: 0,
+ };
+ };
+ let more_text = if tab_count_to_the_right < 10000 {
+ format!(" +{} → ", tab_count_to_the_right)
+ } else {
+ format!(" +many → ")
+ };
+ let more_styled_text = format!(
+ "{}{}{}",
+ ARROW_SEPARATOR.black().on_yellow(),
+ more_text.black().on_yellow(),
+ ARROW_SEPARATOR.yellow().on_black(),
+ );
+ LinePart {
+ part: more_styled_text,
+ len: more_text.chars().count() + 2, // 2 for the arrows
+ }
+}
+
+fn add_previous_tabs_msg(
+ tabs_before_active: &mut Vec<LinePart>,
+ tabs_to_render: &mut Vec<LinePart>,
+ title_bar: &mut Vec<LinePart>,
+ cols: usize,
+) {
+ while get_current_title_len(&tabs_to_render) +
+ // get_tabs_before_len(tabs_before_active.len()) >= cols {
+ left_more_message(tabs_before_active.len()).len
+ >= cols
+ {
+ tabs_before_active.push(tabs_to_render.remove(0));
+ }
+ let left_more_message = left_more_message(tabs_before_active.len());
+ title_bar.push(left_more_message);
+}
+
+fn add_next_tabs_msg(
+ tabs_after_active: &mut Vec<LinePart>,
+ title_bar: &mut Vec<LinePart>,
+ cols: usize,
+) {
+ while get_current_title_len(&title_bar) +
+ // get_tabs_after_len(tabs_after_active.len()) >= cols {
+ right_more_message(tabs_after_active.len()).len
+ >= cols
+ {
+ tabs_after_active.insert(0, title_bar.pop().unwrap());
+ }
+ let right_more_message = right_more_message(tabs_after_active.len());
+ title_bar.push(right_more_message);
+}
+
+pub fn tab_line(
+ mut all_tabs: Vec<LinePart>,
+ active_tab_index: usize,
+ cols: usize,
+) -> Vec<LinePart> {
+ let mut tabs_to_render: Vec<LinePart> = vec![];
+ 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()
+ };
+ tabs_to_render.push(active_tab);
+
+ populate_tabs_in_tab_line(
+ &mut tabs_before_active,
+ &mut tabs_after_active,
+ &mut tabs_to_render,
+ cols,
+ );
+
+ let mut tab_line: Vec<LinePart> = vec![];
+ if !tabs_before_active.is_empty() {
+ add_previous_tabs_msg(
+ &mut tabs_before_active,
+ &mut tabs_to_render,
+ &mut tab_line,
+ cols,
+ );
+ }
+ tab_line.append(&mut tabs_to_render);
+ if !tabs_after_active.is_empty() {
+ add_next_tabs_msg(&mut tabs_after_active, &mut tab_line, cols);
+ }
+ tab_line
+}
diff --git a/default-tiles/tab-bar/src/main.rs b/default-tiles/tab-bar/src/main.rs
index 78a57aca..8a334334 100644
--- a/default-tiles/tab-bar/src/main.rs
+++ b/default-tiles/tab-bar/src/main.rs
@@ -1,12 +1,25 @@
-use colored::*;
+mod line;
+mod tab;
+
use zellij_tile::*;
+use crate::line::tab_line;
+use crate::tab::nameless_tab;
+
+#[derive(Debug)]
+pub struct LinePart {
+ part: String,
+ len: usize,
+}
+
#[derive(Default)]
struct State {
active_tab_index: usize,
num_tabs: usize,
}
+static ARROW_SEPARATOR: &str = "";
+
register_tile!(State);
impl ZellijTile for State {
@@ -18,19 +31,23 @@ impl ZellijTile for State {
self.num_tabs = 0;
}
- fn draw(&mut self, _rows: usize, _cols: usize) {
+ fn draw(&mut self, _rows: usize, cols: usize) {
+ if self.num_tabs == 0 {
+ return;
+ }
+ let mut all_tabs: Vec<LinePart> = vec![];
+ for i in 0..self.num_tabs {
+ let tab = nameless_tab(i, i == self.active_tab_index);
+ all_tabs.push(tab);
+ }
+
+ let tab_line = tab_line(all_tabs, self.active_tab_index, cols);
+
let mut s = String::new();
- let active_tab = self.active_tab_index + 1;
- for i in 1..=self.num_tabs {
- let tab;
- if i == active_tab {
- tab = format!("*{} ", i).black().bold().on_magenta();
- } else {
- tab = format!("-{} ", i).white();
- }
- s = format!("{}{}", s, tab);
+ for bar_part in tab_line {
+ s = format!("{}{}", s, bar_part.part);
}
- println!("Tabs: {}\u{1b}[40m\u{1b}[0K", s);
+ println!("{}\u{1b}[40m\u{1b}[0K", s);
}
fn update_tabs(&mut self, active_tab_index: usize, num_tabs: usize) {
diff --git a/default-tiles/tab-bar/src/tab.rs b/default-tiles/tab-bar/src/tab.rs
new file mode 100644
index 00000000..78a9ba0b
--- /dev/null
+++ b/default-tiles/tab-bar/src/tab.rs
@@ -0,0 +1,52 @@
+use colored::*;
+
+use crate::{LinePart, ARROW_SEPARATOR};
+
+pub fn active_tab(text: String, is_furthest_to_the_left: bool) -> LinePart {
+ let left_separator = if is_furthest_to_the_left {
+ " ".black().on_magenta()
+ } else {
+ ARROW_SEPARATOR.black().on_magenta()
+ };
+ let right_separator = ARROW_SEPARATOR.magenta().on_black();
+ let tab_styled_text = format!("{}{}{}", left_separator, text, right_separator)
+ .black()
+ .bold()
+ .on_magenta();
+ let tab_text_len = text.chars().count() + 2; // 2 for left and right separators
+ LinePart {
+ part: format!("{}", tab_styled_text),
+ len: tab_text_len,
+ }
+}
+
+pub fn non_active_tab(text: String, is_furthest_to_the_left: bool) -> LinePart {
+ let left_separator = if is_furthest_to_the_left {
+ " ".black().on_green()
+ } else {
+ ARROW_SEPARATOR.black().on_green()
+ };
+ let right_separator = ARROW_SEPARATOR.green().on_black();
+ let tab_styled_text = format!("{}{}{}", left_separator, text, right_separator)
+ .black()
+ .bold()
+ .on_green();
+ let tab_text_len = text.chars().count() + 2; // 2 for the left and right separators
+ LinePart {
+ part: format!("{}", tab_styled_text),
+ len: tab_text_len,
+ }
+}
+
+pub fn tab(text: String, is_active_tab: bool, is_furthest_to_the_left: bool) -> LinePart {
+ if is_active_tab {
+ active_tab(text, is_furthest_to_the_left)
+ } else {
+ non_active_tab(text, is_furthest_to_the_left)
+ }
+}
+
+pub fn nameless_tab(index: usize, is_active_tab: bool) -> LinePart {
+ let tab_text = format!(" Tab #{} ", index + 1);
+ tab(tab_text, is_active_tab, index == 0)
+}