From 2c402b0b1d6a21220dca65835335bacfe3fe43e6 Mon Sep 17 00:00:00 2001 From: denis Date: Fri, 26 Mar 2021 16:42:38 +0200 Subject: [PATCH] wip: scary how messy it is, but it's a start --- Cargo.lock | 2 - default-tiles/status-bar/src/first_line.rs | 157 ++++++++++++-------- default-tiles/status-bar/src/main.rs | 8 +- default-tiles/status-bar/src/second_line.rs | 137 ++++++++++++----- default-tiles/tab-bar/src/main.rs | 5 +- default-tiles/tab-bar/src/tab.rs | 41 +++-- src/client/boundaries.rs | 17 +-- src/client/tab.rs | 4 +- src/common/input/handler.rs | 84 ++++++++++- src/common/mod.rs | 61 +------- zellij-tile/src/shim.rs | 18 +++ 11 files changed, 346 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bc19623..ea601aaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,7 +30,6 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" dependencies = [ - "serde", "winapi", ] @@ -2321,7 +2320,6 @@ dependencies = [ name = "zellij-tile" version = "0.5.0" dependencies = [ - "ansi_term 0.12.1", "serde", "serde_json", ] diff --git a/default-tiles/status-bar/src/first_line.rs b/default-tiles/status-bar/src/first_line.rs index bd9c5425..fd6ae50a 100644 --- a/default-tiles/status-bar/src/first_line.rs +++ b/default-tiles/status-bar/src/first_line.rs @@ -1,4 +1,4 @@ -use ansi_term::{ANSIStrings, Style}; +use ansi_term::{ANSIStrings, Color::RGB, Style}; use zellij_tile::*; use crate::colors::{BLACK, BRIGHT_GRAY, GRAY, GREEN, RED, WHITE}; @@ -63,32 +63,38 @@ impl CtrlKeyShortcut { } } -fn unselected_mode_shortcut(letter: char, text: &str) -> LinePart { - let prefix_separator = Style::new().fg(GRAY).on(BRIGHT_GRAY).paint(ARROW_SEPARATOR); +fn unselected_mode_shortcut(letter: char, text: &str, palette: Palette) -> LinePart { + let prefix_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); let char_left_separator = Style::new() .bold() - .fg(BLACK) - .on(BRIGHT_GRAY) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) .bold() .paint(format!(" <")); let char_shortcut = Style::new() .bold() - .fg(RED) - .on(BRIGHT_GRAY) + .fg(RGB(palette.red.0, palette.red.1, palette.red.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) .bold() .paint(format!("{}", letter)); let char_right_separator = Style::new() .bold() - .fg(BLACK) - .on(BRIGHT_GRAY) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) .bold() .paint(format!(">")); let styled_text = Style::new() - .fg(BLACK) - .on(BRIGHT_GRAY) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) .bold() .paint(format!("{} ", text)); - let suffix_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR); + let suffix_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); LinePart { part: format!( "{}", @@ -105,32 +111,38 @@ fn unselected_mode_shortcut(letter: char, text: &str) -> LinePart { } } -fn selected_mode_shortcut(letter: char, text: &str) -> LinePart { - let prefix_separator = Style::new().fg(GRAY).on(GREEN).paint(ARROW_SEPARATOR); +fn selected_mode_shortcut(letter: char, text: &str, palette: Palette) -> LinePart { + let prefix_separator = Style::new() + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .paint(ARROW_SEPARATOR); let char_left_separator = Style::new() .bold() - .fg(BLACK) - .on(GREEN) + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) .bold() .paint(format!(" <")); let char_shortcut = Style::new() .bold() - .fg(RED) - .on(GREEN) + .fg(RGB(palette.red.0, palette.red.1, palette.red.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) .bold() .paint(format!("{}", letter)); let char_right_separator = Style::new() .bold() - .fg(BLACK) - .on(GREEN) + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) .bold() .paint(format!(">")); let styled_text = Style::new() - .fg(BLACK) - .on(GREEN) + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) .bold() .paint(format!("{} ", text)); - let suffix_separator = Style::new().fg(GREEN).on(GRAY).paint(ARROW_SEPARATOR); + let suffix_separator = Style::new() + .fg(RGB(palette.green.0, palette.green.1, palette.green.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .paint(ARROW_SEPARATOR); LinePart { part: format!( "{}", @@ -147,31 +159,43 @@ fn selected_mode_shortcut(letter: char, text: &str) -> LinePart { } } -fn disabled_mode_shortcut(text: &str) -> LinePart { - let prefix_separator = Style::new().fg(GRAY).on(BRIGHT_GRAY).paint(ARROW_SEPARATOR); +fn disabled_mode_shortcut(text: &str, palette: Palette) -> LinePart { + let prefix_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); let styled_text = Style::new() - .fg(GRAY) - .on(BRIGHT_GRAY) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) .dimmed() .paint(format!("{} ", text)); - let suffix_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR); + let suffix_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); LinePart { part: format!("{}{}{}", prefix_separator, styled_text, suffix_separator), len: text.chars().count() + 2 + 1, // 2 for the arrows, 1 for the padding in the end } } -fn selected_mode_shortcut_single_letter(letter: char) -> LinePart { +fn selected_mode_shortcut_single_letter(letter: char, palette: Palette) -> LinePart { let char_shortcut_text = format!(" {} ", letter); let len = char_shortcut_text.chars().count() + 4; // 2 for the arrows, 2 for the padding - let prefix_separator = Style::new().fg(GRAY).on(GREEN).paint(ARROW_SEPARATOR); + let prefix_separator = Style::new() + .fg(RGB(palette.black.0, palette.black.1, palette.black.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .paint(ARROW_SEPARATOR); let char_shortcut = Style::new() .bold() - .fg(RED) - .on(GREEN) + .fg(RGB(palette.red.0, palette.red.1, palette.red.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) .bold() .paint(char_shortcut_text); - let suffix_separator = Style::new().fg(GREEN).on(GRAY).paint(ARROW_SEPARATOR); + let suffix_separator = Style::new() + .fg(RGB(palette.green.0, palette.green.1, palette.green.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); LinePart { part: format!( "{}", @@ -181,17 +205,23 @@ fn selected_mode_shortcut_single_letter(letter: char) -> LinePart { } } -fn unselected_mode_shortcut_single_letter(letter: char) -> LinePart { +fn unselected_mode_shortcut_single_letter(letter: char, palette: Palette) -> LinePart { let char_shortcut_text = format!(" {} ", letter); let len = char_shortcut_text.chars().count() + 4; // 2 for the arrows, 2 for the padding - let prefix_separator = Style::new().fg(GRAY).on(BRIGHT_GRAY).paint(ARROW_SEPARATOR); + let prefix_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); let char_shortcut = Style::new() .bold() - .fg(RED) - .on(BRIGHT_GRAY) + .fg(RGB(palette.red.0, palette.red.1, palette.red.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) .bold() .paint(char_shortcut_text); - let suffix_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR); + let suffix_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); LinePart { part: format!( "{}", @@ -201,23 +231,23 @@ fn unselected_mode_shortcut_single_letter(letter: char) -> LinePart { } } -fn full_ctrl_key(key: &CtrlKeyShortcut) -> LinePart { +fn full_ctrl_key(key: &CtrlKeyShortcut, palette: Palette) -> LinePart { let full_text = key.full_text(); let letter_shortcut = key.letter_shortcut(); match key.mode { CtrlKeyMode::Unselected => { - unselected_mode_shortcut(letter_shortcut, &format!(" {}", full_text)) + unselected_mode_shortcut(letter_shortcut, &format!(" {}", full_text), palette) } CtrlKeyMode::Selected => { - selected_mode_shortcut(letter_shortcut, &format!(" {}", full_text)) + selected_mode_shortcut(letter_shortcut, &format!(" {}", full_text), palette) } CtrlKeyMode::Disabled => { - disabled_mode_shortcut(&format!(" <{}> {}", letter_shortcut, full_text)) + disabled_mode_shortcut(&format!(" <{}> {}", letter_shortcut, full_text), palette) } } } -fn shortened_ctrl_key(key: &CtrlKeyShortcut) -> LinePart { +fn shortened_ctrl_key(key: &CtrlKeyShortcut, palette: Palette) -> LinePart { let shortened_text = key.shortened_text(); let letter_shortcut = key.letter_shortcut(); let shortened_text = match key.action { @@ -226,30 +256,31 @@ fn shortened_ctrl_key(key: &CtrlKeyShortcut) -> LinePart { }; match key.mode { CtrlKeyMode::Unselected => { - unselected_mode_shortcut(letter_shortcut, &format!("{}", shortened_text)) + unselected_mode_shortcut(letter_shortcut, &format!("{}", shortened_text), palette) } CtrlKeyMode::Selected => { - selected_mode_shortcut(letter_shortcut, &format!("{}", shortened_text)) - } - CtrlKeyMode::Disabled => { - disabled_mode_shortcut(&format!(" <{}>{}", letter_shortcut, shortened_text)) + selected_mode_shortcut(letter_shortcut, &format!("{}", shortened_text), palette) } + CtrlKeyMode::Disabled => disabled_mode_shortcut( + &format!(" <{}>{}", letter_shortcut, shortened_text), + palette, + ), } } -fn single_letter_ctrl_key(key: &CtrlKeyShortcut) -> LinePart { +fn single_letter_ctrl_key(key: &CtrlKeyShortcut, palette: Palette) -> LinePart { let letter_shortcut = key.letter_shortcut(); match key.mode { - CtrlKeyMode::Unselected => unselected_mode_shortcut_single_letter(letter_shortcut), - CtrlKeyMode::Selected => selected_mode_shortcut_single_letter(letter_shortcut), - CtrlKeyMode::Disabled => disabled_mode_shortcut(&format!(" {}", letter_shortcut)), + CtrlKeyMode::Unselected => unselected_mode_shortcut_single_letter(letter_shortcut, palette), + CtrlKeyMode::Selected => selected_mode_shortcut_single_letter(letter_shortcut, palette), + CtrlKeyMode::Disabled => disabled_mode_shortcut(&format!(" {}", letter_shortcut), palette), } } -fn key_indicators(max_len: usize, keys: &[CtrlKeyShortcut]) -> LinePart { +fn key_indicators(max_len: usize, keys: &[CtrlKeyShortcut], palette: Palette) -> LinePart { let mut line_part = LinePart::default(); for ctrl_key in keys { - let key = full_ctrl_key(ctrl_key); + let key = full_ctrl_key(ctrl_key, palette); line_part.part = format!("{}{}", line_part.part, key.part); line_part.len += key.len; } @@ -258,7 +289,7 @@ fn key_indicators(max_len: usize, keys: &[CtrlKeyShortcut]) -> LinePart { } line_part = LinePart::default(); for ctrl_key in keys { - let key = shortened_ctrl_key(ctrl_key); + let key = shortened_ctrl_key(ctrl_key, palette); line_part.part = format!("{}{}", line_part.part, key.part); line_part.len += key.len; } @@ -267,7 +298,7 @@ fn key_indicators(max_len: usize, keys: &[CtrlKeyShortcut]) -> LinePart { } line_part = LinePart::default(); for ctrl_key in keys { - let key = single_letter_ctrl_key(ctrl_key); + let key = single_letter_ctrl_key(ctrl_key, palette); line_part.part = format!("{}{}", line_part.part, key.part); line_part.len += key.len; } @@ -278,9 +309,13 @@ fn key_indicators(max_len: usize, keys: &[CtrlKeyShortcut]) -> LinePart { line_part } -pub fn superkey() -> LinePart { +pub fn superkey(palette: Palette) -> LinePart { let prefix_text = " Ctrl + "; - let prefix = Style::new().fg(WHITE).on(GRAY).bold().paint(prefix_text); + let prefix = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .bold() + .paint(prefix_text); LinePart { part: format!("{}", prefix), len: prefix_text.chars().count(), @@ -299,6 +334,7 @@ pub fn ctrl_keys(help: &Help, max_len: usize) -> LinePart { CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Scroll), CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Quit), ], + help.palette, ), InputMode::Resize => key_indicators( max_len, @@ -310,6 +346,7 @@ pub fn ctrl_keys(help: &Help, max_len: usize) -> LinePart { CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), ], + help.palette, ), InputMode::Pane => key_indicators( max_len, @@ -321,6 +358,7 @@ pub fn ctrl_keys(help: &Help, max_len: usize) -> LinePart { CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), ], + help.palette, ), InputMode::Tab | InputMode::RenameTab => key_indicators( max_len, @@ -332,6 +370,7 @@ pub fn ctrl_keys(help: &Help, max_len: usize) -> LinePart { CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), ], + help.palette, ), InputMode::Scroll => key_indicators( max_len, @@ -343,6 +382,7 @@ pub fn ctrl_keys(help: &Help, max_len: usize) -> LinePart { CtrlKeyShortcut::new(CtrlKeyMode::Selected, CtrlKeyAction::Scroll), CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), ], + help.palette, ), InputMode::Normal | _ => key_indicators( max_len, @@ -354,6 +394,7 @@ pub fn ctrl_keys(help: &Help, max_len: usize) -> LinePart { CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), ], + help.palette, ), } } diff --git a/default-tiles/status-bar/src/main.rs b/default-tiles/status-bar/src/main.rs index 6d41fb7b..f1b9f47a 100644 --- a/default-tiles/status-bar/src/main.rs +++ b/default-tiles/status-bar/src/main.rs @@ -48,15 +48,15 @@ impl ZellijTile for State { fn draw(&mut self, _rows: usize, cols: usize) { let help = get_help(); - let superkey = superkey(); + let superkey = superkey(help.palette); let ctrl_keys = ctrl_keys(&help, cols - superkey.len); let first_line = format!("{}{}", superkey, ctrl_keys); - let second_line = keybinds(&help, cols); + let second_line = keybinds(&help, cols, help.palette); // [48;5;238m is gray background, [0K is so that it fills the rest of the line // [48;5;16m is black background, [0K is so that it fills the rest of the line - println!("{}\u{1b}[48;5;238m\u{1b}[0K", first_line); - println!("{}\u{1b}[48;5;16m\u{1b}[0K", second_line); + println!("{}\u{1b}[{};{};{}m\u{1b}[0K", first_line, help.palette.bg.0, help.palette.bg.1, help.palette.bg.2); + println!("{}\u{1b}[{};{};{}m\u{1b}[0K", second_line, help.palette.bg.0, help.palette.bg.1, help.palette.bg.2); } } diff --git a/default-tiles/status-bar/src/second_line.rs b/default-tiles/status-bar/src/second_line.rs index 45c33a8e..21d5a994 100644 --- a/default-tiles/status-bar/src/second_line.rs +++ b/default-tiles/status-bar/src/second_line.rs @@ -1,19 +1,41 @@ // use colored::*; -use ansi_term::{ANSIStrings, Style}; +use ansi_term::{ANSIStrings, Color::RGB, Style}; use zellij_tile::*; use crate::colors::{BLACK, GREEN, ORANGE, WHITE}; use crate::{LinePart, MORE_MSG}; -fn full_length_shortcut(is_first_shortcut: bool, letter: &str, description: &str) -> LinePart { +fn full_length_shortcut( + is_first_shortcut: bool, + letter: &str, + description: &str, + palette: Palette, +) -> LinePart { let separator = if is_first_shortcut { " " } else { " / " }; - let separator = Style::new().on(BLACK).fg(WHITE).paint(separator); + let separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint(separator); let shortcut_len = letter.chars().count() + 3; // 2 for <>'s around shortcut, 1 for the space - let shortcut_left_separator = Style::new().on(BLACK).fg(WHITE).paint("<"); - let shortcut = Style::new().on(BLACK).fg(GREEN).bold().paint(letter); - let shortcut_right_separator = Style::new().on(BLACK).fg(WHITE).paint("> "); + let shortcut_left_separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint("<"); + let shortcut = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(ORANGE) + .bold() + .paint(letter); + let shortcut_right_separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint("> "); let description_len = description.chars().count(); - let description = Style::new().on(BLACK).fg(WHITE).bold().paint(description); + let description = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(description); let len = shortcut_len + description_len + separator.chars().count(); LinePart { part: format!( @@ -30,18 +52,36 @@ fn full_length_shortcut(is_first_shortcut: bool, letter: &str, description: &str } } -fn first_word_shortcut(is_first_shortcut: bool, letter: &str, description: &str) -> LinePart { +fn first_word_shortcut( + is_first_shortcut: bool, + letter: &str, + description: &str, + palette: Palette, +) -> LinePart { let separator = if is_first_shortcut { " " } else { " / " }; - let separator = Style::new().on(BLACK).fg(WHITE).paint(separator); + let separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint(separator); let shortcut_len = letter.chars().count() + 3; // 2 for <>'s around shortcut, 1 for the space - let shortcut_left_separator = Style::new().on(BLACK).fg(WHITE).paint("<"); - let shortcut = Style::new().on(BLACK).fg(GREEN).bold().paint(letter); - let shortcut_right_separator = Style::new().on(BLACK).fg(WHITE).paint("> "); + let shortcut_left_separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint("<"); + let shortcut = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.green.0, palette.green.1, palette.green.2)) + .bold() + .paint(letter); + let shortcut_right_separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint("> "); let description_first_word = description.split(' ').next().unwrap_or(""); let description_first_word_length = description_first_word.chars().count(); let description_first_word = Style::new() - .on(BLACK) - .fg(WHITE) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) .bold() .paint(description_first_word); let len = shortcut_len + description_first_word_length + separator.chars().count(); @@ -60,27 +100,48 @@ fn first_word_shortcut(is_first_shortcut: bool, letter: &str, description: &str) } } -fn locked_interface_indication() -> LinePart { +fn locked_interface_indication(palette: Palette) -> LinePart { let locked_text = " -- INTERFACE LOCKED -- "; let locked_text_len = locked_text.chars().count(); - let locked_styled_text = Style::new().on(BLACK).fg(WHITE).bold().paint(locked_text); + let locked_styled_text = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(locked_text); LinePart { part: format!("{}", locked_styled_text), len: locked_text_len, } } -fn select_pane_shortcut(is_first_shortcut: bool) -> LinePart { +fn select_pane_shortcut(is_first_shortcut: bool, palette: Palette) -> LinePart { let shortcut = "ENTER"; let description = "Select pane"; let separator = if is_first_shortcut { " " } else { " / " }; - let separator = Style::new().on(BLACK).fg(WHITE).paint(separator); + let separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint(separator); let shortcut_len = shortcut.chars().count() + 3; // 2 for <>'s around shortcut, 1 for the space - let shortcut_left_separator = Style::new().on(BLACK).fg(WHITE).paint("<"); - let shortcut = Style::new().on(BLACK).fg(ORANGE).bold().paint(shortcut); - let shortcut_right_separator = Style::new().on(BLACK).fg(WHITE).paint("> "); + let shortcut_left_separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint("<"); + let shortcut = Style::new() + .on(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(ORANGE) + .bold() + .paint(shortcut); + let shortcut_right_separator = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint("> "); let description_len = description.chars().count(); - let description = Style::new().on(BLACK).fg(WHITE).bold().paint(description); + let description = Style::new() + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(description); let len = shortcut_len + description_len + separator.chars().count(); LinePart { part: format!( @@ -97,18 +158,18 @@ fn select_pane_shortcut(is_first_shortcut: bool) -> LinePart { } } -fn full_shortcut_list(help: &Help) -> LinePart { +fn full_shortcut_list(help: &Help, palette: Palette) -> LinePart { match help.mode { InputMode::Normal => LinePart::default(), - InputMode::Locked => locked_interface_indication(), + InputMode::Locked => locked_interface_indication(palette), _ => { let mut line_part = LinePart::default(); for (i, (letter, description)) in help.keybinds.iter().enumerate() { - let shortcut = full_length_shortcut(i == 0, &letter, &description); + let shortcut = full_length_shortcut(i == 0, &letter, &description, palette); line_part.len += shortcut.len; line_part.part = format!("{}{}", line_part.part, shortcut,); } - let select_pane_shortcut = select_pane_shortcut(help.keybinds.len() == 0); + let select_pane_shortcut = select_pane_shortcut(help.keybinds.len() == 0, palette); line_part.len += select_pane_shortcut.len; line_part.part = format!("{}{}", line_part.part, select_pane_shortcut,); line_part @@ -116,18 +177,18 @@ fn full_shortcut_list(help: &Help) -> LinePart { } } -fn shortened_shortcut_list(help: &Help) -> LinePart { +fn shortened_shortcut_list(help: &Help, palette: Palette) -> LinePart { match help.mode { InputMode::Normal => LinePart::default(), - InputMode::Locked => locked_interface_indication(), + InputMode::Locked => locked_interface_indication(palette), _ => { let mut line_part = LinePart::default(); for (i, (letter, description)) in help.keybinds.iter().enumerate() { - let shortcut = first_word_shortcut(i == 0, &letter, &description); + let shortcut = first_word_shortcut(i == 0, &letter, &description, palette); line_part.len += shortcut.len; line_part.part = format!("{}{}", line_part.part, shortcut,); } - let select_pane_shortcut = select_pane_shortcut(help.keybinds.len() == 0); + let select_pane_shortcut = select_pane_shortcut(help.keybinds.len() == 0, palette); line_part.len += select_pane_shortcut.len; line_part.part = format!("{}{}", line_part.part, select_pane_shortcut,); line_part @@ -135,11 +196,11 @@ fn shortened_shortcut_list(help: &Help) -> LinePart { } } -fn best_effort_shortcut_list(help: &Help, max_len: usize) -> LinePart { +fn best_effort_shortcut_list(help: &Help, max_len: usize, palette: Palette) -> LinePart { match help.mode { InputMode::Normal => LinePart::default(), InputMode::Locked => { - let line_part = locked_interface_indication(); + let line_part = locked_interface_indication(palette); if line_part.len <= max_len { line_part } else { @@ -149,7 +210,7 @@ fn best_effort_shortcut_list(help: &Help, max_len: usize) -> LinePart { _ => { let mut line_part = LinePart::default(); for (i, (letter, description)) in help.keybinds.iter().enumerate() { - let shortcut = first_word_shortcut(i == 0, &letter, &description); + let shortcut = first_word_shortcut(i == 0, &letter, &description, palette); if line_part.len + shortcut.len + MORE_MSG.chars().count() > max_len { // TODO: better line_part.part = format!("{}{}", line_part.part, MORE_MSG); @@ -159,7 +220,7 @@ fn best_effort_shortcut_list(help: &Help, max_len: usize) -> LinePart { line_part.len += shortcut.len; line_part.part = format!("{}{}", line_part.part, shortcut,); } - let select_pane_shortcut = select_pane_shortcut(help.keybinds.len() == 0); + let select_pane_shortcut = select_pane_shortcut(help.keybinds.len() == 0, palette); if line_part.len + select_pane_shortcut.len <= max_len { line_part.len += select_pane_shortcut.len; line_part.part = format!("{}{}", line_part.part, select_pane_shortcut,); @@ -169,14 +230,14 @@ fn best_effort_shortcut_list(help: &Help, max_len: usize) -> LinePart { } } -pub fn keybinds(help: &Help, max_width: usize) -> LinePart { - let full_shortcut_list = full_shortcut_list(help); +pub fn keybinds(help: &Help, max_width: usize, palette: Palette) -> LinePart { + let full_shortcut_list = full_shortcut_list(help, palette); if full_shortcut_list.len <= max_width { return full_shortcut_list; } - let shortened_shortcut_list = shortened_shortcut_list(help); + let shortened_shortcut_list = shortened_shortcut_list(help, palette); if shortened_shortcut_list.len <= max_width { return shortened_shortcut_list; } - return best_effort_shortcut_list(help, max_width); + return best_effort_shortcut_list(help, max_width, palette); } diff --git a/default-tiles/tab-bar/src/main.rs b/default-tiles/tab-bar/src/main.rs index 8c025336..2de936b2 100644 --- a/default-tiles/tab-bar/src/main.rs +++ b/default-tiles/tab-bar/src/main.rs @@ -60,6 +60,7 @@ impl ZellijTile for State { } fn draw(&mut self, _rows: usize, cols: usize) { + let help = get_help(); if self.tabs.is_empty() { return; } @@ -77,7 +78,7 @@ impl ZellijTile for State { } else if t.active { active_tab_index = t.position; } - let tab = tab_style(tabname, t.active, t.position); + let tab = tab_style(tabname, t.active, t.position, help.palette); all_tabs.push(tab); } let tab_line = tab_line(all_tabs, active_tab_index, cols); @@ -85,7 +86,7 @@ impl ZellijTile for State { for bar_part in tab_line { s = format!("{}{}", s, bar_part.part); } - println!("{}\u{1b}[48;5;238m\u{1b}[0K", s); + println!("{}\u{1b}[{};{};{}m\u{1b}[0K", s, help.palette.bg.0, help.palette.bg.1, help.palette.bg.2); } fn update_tabs(&mut self) { diff --git a/default-tiles/tab-bar/src/tab.rs b/default-tiles/tab-bar/src/tab.rs index a4c7c376..96654a16 100644 --- a/default-tiles/tab-bar/src/tab.rs +++ b/default-tiles/tab-bar/src/tab.rs @@ -1,16 +1,23 @@ use crate::colors::{BLACK, BRIGHT_GRAY, GRAY, GREEN}; use crate::{LinePart, ARROW_SEPARATOR}; -use ansi_term::{ANSIStrings, Style}; +use ansi_term::{ANSIStrings, Color::RGB, Style}; +use zellij_tile::Palette; -pub fn active_tab(text: String) -> LinePart { - let left_separator = Style::new().fg(GRAY).on(GREEN).paint(ARROW_SEPARATOR); +pub fn active_tab(text: String, palette: Palette) -> LinePart { + let left_separator = Style::new() + .fg(RGB(palette.black.0, palette.black.1, palette.black.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .paint(ARROW_SEPARATOR); let tab_text_len = text.chars().count() + 4; // 2 for left and right separators, 2 for the text padding let tab_styled_text = Style::new() - .fg(BLACK) - .on(GREEN) + .fg(RGB(palette.black.0, palette.black.1, palette.black.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) .bold() .paint(format!(" {} ", text)); - let right_separator = Style::new().fg(GREEN).on(GRAY).paint(ARROW_SEPARATOR); + let right_separator = Style::new() + .fg(RGB(palette.green.0, palette.green.1, palette.green.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); let tab_styled_text = format!( "{}", ANSIStrings(&[left_separator, tab_styled_text, right_separator,]) @@ -21,15 +28,21 @@ pub fn active_tab(text: String) -> LinePart { } } -pub fn non_active_tab(text: String) -> LinePart { - let left_separator = Style::new().fg(GRAY).on(BRIGHT_GRAY).paint(ARROW_SEPARATOR); +pub fn non_active_tab(text: String, palette: Palette) -> LinePart { + let left_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); let tab_text_len = text.chars().count() + 4; // 2 for left and right separators, 2 for the padding let tab_styled_text = Style::new() - .fg(BLACK) - .on(BRIGHT_GRAY) + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) .bold() .paint(format!(" {} ", text)); - let right_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR); + let right_separator = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .paint(ARROW_SEPARATOR); let tab_styled_text = format!( "{}", ANSIStrings(&[left_separator, tab_styled_text, right_separator,]) @@ -40,15 +53,15 @@ pub fn non_active_tab(text: String) -> LinePart { } } -pub fn tab_style(text: String, is_active_tab: bool, position: usize) -> LinePart { +pub fn tab_style(text: String, is_active_tab: bool, position: usize, palette: Palette) -> LinePart { let tab_text = if text.is_empty() { format!("Tab #{}", position + 1) } else { text }; if is_active_tab { - active_tab(tab_text) + active_tab(tab_text, palette) } else { - non_active_tab(tab_text) + non_active_tab(tab_text, palette) } } diff --git a/src/client/boundaries.rs b/src/client/boundaries.rs index 6ad83bd8..e7c2cb03 100644 --- a/src/client/boundaries.rs +++ b/src/client/boundaries.rs @@ -1,5 +1,5 @@ -use crate::{common::{Palette, input::handler::InputMode}, tab::Pane}; -use ansi_term::Colour; +use crate::{common::{input::handler::Palette, colors, input::handler::InputMode}, tab::Pane}; +use ansi_term::Colour::RGB; use std::collections::HashMap; use std::fmt::{Display, Error, Formatter}; @@ -18,20 +18,13 @@ pub mod boundary_type { pub const CROSS: &str = "┼"; } -pub mod colors { - use ansi_term::Colour::{self, Fixed}; - pub const WHITE: Colour = Fixed(255); - pub const GREEN: Colour = Fixed(154); - pub const GRAY: Colour = Fixed(238); -} - pub type BoundaryType = &'static str; // easy way to refer to boundary_type above #[derive(Clone, Copy, Debug)] pub struct BoundarySymbol { boundary_type: BoundaryType, invisible: bool, - color: Option, + color: Option<(u8, u8, u8)>, } impl BoundarySymbol { @@ -46,7 +39,7 @@ impl BoundarySymbol { self.invisible = true; self } - pub fn color(&mut self, color: Option) -> Self { + pub fn color(&mut self, color: Option<(u8, u8, u8)>) -> Self { self.color = color; *self } @@ -57,7 +50,7 @@ impl Display for BoundarySymbol { match self.invisible { true => write!(f, " "), false => match self.color { - Some(color) => write!(f, "{}", color.paint(self.boundary_type)), + Some(color) => write!(f, "{}", RGB(color.0, color.1, color.2).paint(self.boundary_type)), None => write!(f, "{}", self.boundary_type), }, } diff --git a/src/client/tab.rs b/src/client/tab.rs index 9d6ae896..56970851 100644 --- a/src/client/tab.rs +++ b/src/client/tab.rs @@ -1,13 +1,13 @@ //! `Tab`s holds multiple panes. It tracks their coordinates (x/y) and size, //! as well as how they should be resized -use crate::common::{AppInstruction, Palette, SenderWithContext, input::handler::InputMode}; +use crate::common::{AppInstruction, SenderWithContext, input::handler::{Palette, InputMode}}; use crate::layout::Layout; use crate::panes::{PaneId, PositionAndSize, TerminalPane}; use crate::pty_bus::{PtyInstruction, VteEvent}; use crate::wasm_vm::{PluginInputType, PluginInstruction}; use crate::{ - boundaries::{colors, Boundaries}, + boundaries::Boundaries, panes::PluginPane, }; use crate::{os_input_output::OsApi, utils::shared::pad_to_size}; diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs index 2d5e965f..4f77c0ae 100644 --- a/src/common/input/handler.rs +++ b/src/common/input/handler.rs @@ -9,6 +9,9 @@ use crate::pty_bus::PtyInstruction; use crate::screen::ScreenInstruction; use crate::wasm_vm::{EventType, PluginInputType, PluginInstruction}; use crate::CommandIsExecuting; +use xrdb::Colors; +use colors_transform::{Rgb, Color}; +use crate::common::utils::logging::debug_log_to_file; use serde::{Deserialize, Serialize}; use strum_macros::EnumIter; @@ -299,6 +302,7 @@ pub enum InputMode { pub struct Help { pub mode: InputMode, pub keybinds: Vec<(String, String)>, // => + pub palette: Palette } impl Default for InputMode { @@ -307,11 +311,89 @@ impl Default for InputMode { } } +pub mod colors { + pub const WHITE: (u8, u8, u8) = (238, 238, 238); + pub const GREEN: (u8, u8, u8) = (175, 255, 0); + pub const GRAY: (u8, u8, u8) = (68, 68, 68); + pub const BRIGHT_GRAY: (u8, u8, u8) = (138, 138, 138); + pub const RED: (u8, u8, u8) = (135, 0, 0); + pub const BLACK: (u8, u8, u8) = (0, 0, 0); +} + +#[derive(Clone, Copy, Default, Debug, Serialize, Deserialize)] +pub struct Palette { + pub fg: (u8, u8, u8), + pub bg: (u8, u8, u8), + pub black: (u8, u8, u8), + pub red: (u8, u8, u8), + pub green: (u8, u8, u8), + pub yellow: (u8, u8, u8), + pub blue: (u8, u8, u8), + pub magenta: (u8, u8, u8), + pub cyan: (u8, u8, u8), + pub white: (u8, u8, u8), +} + +impl Palette { + pub fn new() -> Self { + let palette = match Colors::new("xresources") { + Some(colors) => { + let fg = colors.fg.unwrap(); + let fg_imm = &fg; + let fg_hex: &str = &fg_imm; + let fg = Rgb::from_hex_str(fg_hex).unwrap().as_tuple(); + let fg = (fg.0 as u8, fg.1 as u8, fg.2 as u8); + let bg = colors.bg.unwrap(); + let bg_imm = &bg; + let bg_hex: &str = &bg_imm; + let bg = Rgb::from_hex_str(bg_hex).unwrap().as_tuple(); + let bg = (bg.0 as u8, bg.1 as u8, bg.2 as u8); + let colors: Vec<(u8, u8, u8)> = colors.colors.iter().map(|c| { + let c = c.clone(); + let imm_str = &c.unwrap(); + let hex_str: &str = &imm_str; + let rgb = Rgb::from_hex_str(hex_str).unwrap().as_tuple(); + (rgb.0 as u8, rgb.1 as u8, rgb.2 as u8) + }).collect(); + Self { + fg, + bg, + black: colors[0], + red: colors[1], + green: colors[2], + yellow: colors[3], + blue: colors[4], + magenta: colors[5], + cyan: colors[6], + white: colors[7] + } + }, + None => { + Self { + fg: colors::BRIGHT_GRAY, + bg: colors::BLACK, + black: colors::BLACK, + red: colors::RED, + green: colors::GREEN, + yellow: colors::GRAY, + blue: colors::GRAY, + magenta: colors::GRAY, + cyan: colors::GRAY, + white: colors::WHITE + } + } + }; + palette + } +} + + /// Creates a [`Help`] struct indicating the current [`InputMode`] and its keybinds /// (as pairs of [`String`]s). // TODO this should probably be automatically generated in some way pub fn get_help(mode: InputMode) -> Help { let mut keybinds: Vec<(String, String)> = vec![]; + let mut palette = Palette::new(); match mode { InputMode::Normal | InputMode::Locked => {} InputMode::Resize => { @@ -339,7 +421,7 @@ pub fn get_help(mode: InputMode) -> Help { keybinds.push(("Enter".to_string(), "when done".to_string())); } } - Help { mode, keybinds } + Help { mode, keybinds, palette } } /// Entry point to the module. Instantiates an [`InputHandler`] and starts diff --git a/src/common/mod.rs b/src/common/mod.rs index b061c785..2bbc18bd 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -30,13 +30,14 @@ use wasmer_wasi::{Pipe, WasiState}; use crate::cli::CliArgs; use crate::layout::Layout; +use crate::common::input::handler::Palette; use command_is_executing::CommandIsExecuting; use errors::{AppContext, ContextType, ErrorContext, PluginContext, PtyContext, ScreenContext}; use input::handler::input_loop; use os_input_output::OsApi; use pty_bus::{PtyBus, PtyInstruction}; use screen::{Screen, ScreenInstruction}; -use utils::consts::{ZELLIJ_IPC_PIPE, ZELLIJ_ROOT_PLUGIN_DIR}; +use utils::{consts::{ZELLIJ_IPC_PIPE, ZELLIJ_ROOT_PLUGIN_DIR}, logging::debug_log_to_file}; use wasm_vm::{ wasi_stdout, wasi_write_string, zellij_imports, EventType, PluginInputType, PluginInstruction, }; @@ -152,62 +153,11 @@ pub enum AppInstruction { } pub mod colors { - use ansi_term::Colour::{self, Fixed}; - pub const WHITE: Colour = Fixed(255); - pub const GREEN: Colour = Fixed(154); - pub const GRAY: Colour = Fixed(238); + pub const WHITE: (u8, u8, u8) = (238, 238, 238); + pub const GREEN: (u8, u8, u8) = (175, 255, 0); + pub const GRAY: (u8, u8, u8) = (68, 68, 68); } -#[derive(Clone, Copy)] -pub struct Palette { - pub black: ansi_term::Color, - pub red: ansi_term::Color, - pub green: ansi_term::Color, - pub yellow: ansi_term::Color, - pub blue: ansi_term::Color, - pub magenta: ansi_term::Color, - pub cyan: ansi_term::Color, - pub white: ansi_term::Color, -} - -impl Palette { - pub fn new() -> Self { - let palette = match Colors::new("xresources") { - Some(colors) => { - let colors: Vec = colors.colors.iter().map(|c| { - let c = c.clone(); - let imm_str = &c.unwrap(); - let hex_str: &str = &imm_str; - let rgb = Rgb::from_hex_str(hex_str).unwrap().as_tuple(); - RGB(rgb.0 as u8, rgb.1 as u8, rgb.2 as u8) - }).collect(); - Self { - black: colors[0], - red: colors[1], - green: colors[2], - yellow: colors[3], - blue: colors[4], - magenta: colors[5], - cyan: colors[6], - white: colors[7] - } - }, - None => { - Self { - black: colors::GRAY, - red: colors::GRAY, - green: colors::GREEN, - yellow: colors::GRAY, - blue: colors::GRAY, - magenta: colors::GRAY, - cyan: colors::GRAY, - white: colors::WHITE - } - } - }; - palette - } -} /// Start Zellij with the specified [`OsApi`] and command-line arguments. // FIXME this should definitely be modularized and split into different functions. @@ -342,6 +292,7 @@ pub fn start(mut os_input: Box, opts: CliArgs) { let send_app_instructions = send_app_instructions.clone(); let max_panes = opts.max_panes; let colors = Palette::new(); + // debug_log_to_file(format!("{:?}", colors)); move || { let mut screen = Screen::new( receive_screen_instructions, diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index b7beb7af..bad9ffa8 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -28,6 +28,7 @@ pub enum Key { pub struct Help { pub mode: InputMode, pub keybinds: Vec<(String, String)>, + pub palette: Palette } // TODO: use same struct from main crate? @@ -51,6 +52,20 @@ pub struct TabData { pub active: bool, } +#[derive(Default, Debug, Copy, Clone, Deserialize, Serialize)] +pub struct Palette { + pub fg: (u8, u8, u8), + pub bg: (u8, u8, u8), + pub black: (u8, u8, u8), + pub red: (u8, u8, u8), + pub green: (u8, u8, u8), + pub yellow: (u8, u8, u8), + pub blue: (u8, u8, u8), + pub magenta: (u8, u8, u8), + pub cyan: (u8, u8, u8), + pub white: (u8, u8, u8), +} + impl Default for InputMode { fn default() -> InputMode { InputMode::Normal @@ -60,6 +75,9 @@ impl Default for InputMode { pub fn get_key() -> Key { deserialize_from_stdin().unwrap() } +pub fn get_palette() -> Palette { + deserialize_from_stdin().unwrap() +} pub fn open_file(path: &Path) { println!("{}", path.to_string_lossy());