diff options
| author | denis <denismaximov98@gmail.com> | 2021-04-22 11:45:29 +0300 |
|---|---|---|
| committer | denis <denismaximov98@gmail.com> | 2021-04-22 11:45:29 +0300 |
| commit | 8d98ca7da0bc278a832e4e7de23ff63a84deb529 (patch) | |
| tree | e7fdfaa6c1ae25e7737dbb36bd1dbcb94d62ab47 /default-plugins/status-bar/src | |
| parent | wip: fixing the first arrow (diff) | |
| parent | fix(cargo): reduce crate size by 4.8MB using `cargo diet`, to 77kB (diff) | |
| download | sl0ppij-8d98ca7da0bc278a832e4e7de23ff63a84deb529.tar.gz sl0ppij-8d98ca7da0bc278a832e4e7de23ff63a84deb529.tar.xz sl0ppij-8d98ca7da0bc278a832e4e7de23ff63a84deb529.zip | |
wip: merge main in
Diffstat (limited to 'default-plugins/status-bar/src')
| -rw-r--r-- | default-plugins/status-bar/src/first_line.rs | 395 | ||||
| -rw-r--r-- | default-plugins/status-bar/src/main.rs | 76 | ||||
| -rw-r--r-- | default-plugins/status-bar/src/second_line.rs | 365 |
3 files changed, 836 insertions, 0 deletions
diff --git a/default-plugins/status-bar/src/first_line.rs b/default-plugins/status-bar/src/first_line.rs new file mode 100644 index 00000000..4053210d --- /dev/null +++ b/default-plugins/status-bar/src/first_line.rs @@ -0,0 +1,395 @@ +use ansi_term::{ANSIStrings, Color::RGB, Style}; +use zellij_tile::prelude::*; + +use crate::colors::{BLACK, BRIGHT_GRAY, GRAY, GREEN, RED, WHITE}; +use crate::{LinePart, ARROW_SEPARATOR}; + +struct CtrlKeyShortcut { + mode: CtrlKeyMode, + action: CtrlKeyAction, +} + +impl CtrlKeyShortcut { + pub fn new(mode: CtrlKeyMode, action: CtrlKeyAction) -> Self { + CtrlKeyShortcut { mode, action } + } +} + +enum CtrlKeyAction { + Lock, + Pane, + Tab, + Resize, + Scroll, + Quit, +} + +enum CtrlKeyMode { + Unselected, + Selected, + Disabled, +} + +impl CtrlKeyShortcut { + pub fn full_text(&self) -> String { + match self.action { + CtrlKeyAction::Lock => String::from("LOCK"), + CtrlKeyAction::Pane => String::from("PANE"), + CtrlKeyAction::Tab => String::from("TAB"), + CtrlKeyAction::Resize => String::from("RESIZE"), + CtrlKeyAction::Scroll => String::from("SCROLL"), + CtrlKeyAction::Quit => String::from("QUIT"), + } + } + pub fn shortened_text(&self) -> String { + match self.action { + CtrlKeyAction::Lock => String::from("LOCK"), + CtrlKeyAction::Pane => String::from("ane"), + CtrlKeyAction::Tab => String::from("ab"), + CtrlKeyAction::Resize => String::from("esize"), + CtrlKeyAction::Scroll => String::from("croll"), + CtrlKeyAction::Quit => String::from("uit"), + } + } + pub fn letter_shortcut(&self) -> char { + match self.action { + CtrlKeyAction::Lock => 'g', + CtrlKeyAction::Pane => 'p', + CtrlKeyAction::Tab => 't', + CtrlKeyAction::Resize => 'r', + CtrlKeyAction::Scroll => 's', + CtrlKeyAction::Quit => 'q', + } + } +} + +fn unselected_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.fg.0, palette.fg.1, palette.fg.2)) + .paint(ARROW_SEPARATOR); + let char_left_separator = Style::new() + .bold() + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(" <"); + let char_shortcut = Style::new() + .bold() + .fg(RGB(palette.red.0, palette.red.1, palette.red.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(letter.to_string()); + let char_right_separator = Style::new() + .bold() + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(">"); + let styled_text = Style::new() + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(format!("{} ", text)); + 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: ANSIStrings(&[ + prefix_separator, + char_left_separator, + char_shortcut, + char_right_separator, + styled_text, + suffix_separator, + ]) + .to_string(), + len: text.chars().count() + 7, // 2 for the arrows, 3 for the char separators, 1 for the character, 1 for the text padding + } +} + +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() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .bold() + .paint(format!(" <")); + let char_shortcut = Style::new() + .bold() + .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() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .bold() + .paint(format!(">")); + let styled_text = Style::new() + .fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .bold() + .paint(format!("{} ", text)); + 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: ANSIStrings(&[ + prefix_separator, + char_left_separator, + char_shortcut, + char_right_separator, + styled_text, + suffix_separator, + ]) + .to_string(), + len: text.chars().count() + 7, // 2 for the arrows, 3 for the char separators, 1 for the character, 1 for the text padding + } +} + +fn disabled_mode_shortcut(text: &str, palette: Palette) -> LinePart { + let prefix_separator = Style::new() + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint(ARROW_SEPARATOR); + let styled_text = Style::new() + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .dimmed() + .paint(format!("{} ", text)); + 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, 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(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .on(RGB(palette.green.0, palette.green.1, palette.green.2)) + .paint(ARROW_SEPARATOR); + let char_shortcut = Style::new() + .bold() + .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(RGB(palette.green.0, palette.green.1, palette.green.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint(ARROW_SEPARATOR); + LinePart { + part: ANSIStrings(&[prefix_separator, char_shortcut, suffix_separator]).to_string(), + len, + } +} + +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(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .paint(ARROW_SEPARATOR); + let char_shortcut = Style::new() + .bold() + .fg(RGB(palette.red.0, palette.red.1, palette.red.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(char_shortcut_text); + 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: ANSIStrings(&[prefix_separator, char_shortcut, suffix_separator]).to_string(), + len, + } +} + +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), palette) + } + CtrlKeyMode::Selected => { + selected_mode_shortcut(letter_shortcut, &format!(" {}", full_text), palette) + } + CtrlKeyMode::Disabled => { + disabled_mode_shortcut(&format!(" <{}> {}", letter_shortcut, full_text), palette) + } + } +} + +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 { + CtrlKeyAction::Lock => format!(" {}", shortened_text), + _ => shortened_text, + }; + match key.mode { + CtrlKeyMode::Unselected => { + unselected_mode_shortcut(letter_shortcut, &shortened_text, palette) + } + CtrlKeyMode::Selected => selected_mode_shortcut(letter_shortcut, &shortened_text, palette), + CtrlKeyMode::Disabled => disabled_mode_shortcut( + &format!(" <{}>{}", letter_shortcut, shortened_text), + palette, + ), + CtrlKeyMode::Disabled => disabled_mode_shortcut( + &format!(" <{}>{}", letter_shortcut, shortened_text), + palette, + ), + } +} + +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, 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], palette: Palette) -> LinePart { + let mut line_part = LinePart::default(); + for ctrl_key in keys { + let key = full_ctrl_key(ctrl_key, palette); + line_part.part = format!("{}{}", line_part.part, key.part); + line_part.len += key.len; + } + if line_part.len < max_len { + return line_part; + } + line_part = LinePart::default(); + for ctrl_key in keys { + let key = shortened_ctrl_key(ctrl_key, palette); + line_part.part = format!("{}{}", line_part.part, key.part); + line_part.len += key.len; + } + if line_part.len < max_len { + return line_part; + } + line_part = LinePart::default(); + for ctrl_key in keys { + let key = single_letter_ctrl_key(ctrl_key, palette); + line_part.part = format!("{}{}", line_part.part, key.part); + line_part.len += key.len; + } + if line_part.len < max_len { + return line_part; + } + line_part = LinePart::default(); + line_part +} + +pub fn superkey(palette: Palette) -> LinePart { + let prefix_text = " Ctrl + "; + let prefix = Style::new() + .fg(RGB(palette.bg.0, palette.bg.1, palette.bg.2)) + .on(RGB(palette.fg.0, palette.fg.1, palette.fg.2)) + .bold() + .paint(prefix_text); + + 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: ANSIStrings(&[prefix, suffix_separator]).to_string(), + len: prefix_text.chars().count(), + } +} + +pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart { + match &help.mode { + InputMode::Locked => key_indicators( + max_len, + &[ + CtrlKeyShortcut::new(CtrlKeyMode::Selected, CtrlKeyAction::Lock), + CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Pane), + CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Tab), + CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Resize), + CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Scroll), + CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Quit), + ], + help.palette, + ), + InputMode::Resize => key_indicators( + max_len, + &[ + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Lock), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Pane), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Tab), + CtrlKeyShortcut::new(CtrlKeyMode::Selected, CtrlKeyAction::Resize), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), + ], + help.palette, + ), + InputMode::Pane => key_indicators( + max_len, + &[ + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Lock), + CtrlKeyShortcut::new(CtrlKeyMode::Selected, CtrlKeyAction::Pane), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Tab), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Resize), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), + ], + help.palette, + ), + InputMode::Tab | InputMode::RenameTab => key_indicators( + max_len, + &[ + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Lock), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Pane), + CtrlKeyShortcut::new(CtrlKeyMode::Selected, CtrlKeyAction::Tab), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Resize), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), + ], + help.palette, + ), + InputMode::Scroll => key_indicators( + max_len, + &[ + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Lock), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Pane), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Tab), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Resize), + CtrlKeyShortcut::new(CtrlKeyMode::Selected, CtrlKeyAction::Scroll), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), + ], + help.palette, + ), + InputMode::Normal => key_indicators( + max_len, + &[ + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Lock), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Pane), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Tab), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Resize), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll), + CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit), + ], + help.palette, + ), + } +} diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs new file mode 100644 index 00000000..10322c52 --- /dev/null +++ b/default-plugins/status-bar/src/main.rs @@ -0,0 +1,76 @@ +mod first_line; +mod second_line; + +use std::fmt::{Display, Error, Formatter}; +use zellij_tile::{data::Theme, prelude::*}; + +use first_line::{ctrl_keys, superkey}; +use second_line::keybinds; + +pub mod colors { + use ansi_term::Colour::{self, Fixed}; + pub const WHITE: Colour = Fixed(255); + pub const BLACK: Colour = Fixed(16); + pub const GREEN: Colour = Fixed(154); + pub const ORANGE: Colour = Fixed(166); + pub const GRAY: Colour = Fixed(238); + pub const BRIGHT_GRAY: Colour = Fixed(245); + pub const RED: Colour = Fixed(88); +} + +// for more of these, copy paste from: https://en.wikipedia.org/wiki/Box-drawing_character +static ARROW_SEPARATOR: &str = ""; +static MORE_MSG: &str = " ... "; + +#[derive(Default)] +struct State { + mode_info: ModeInfo, +} + +register_plugin!(State); + +#[derive(Default)] +pub struct LinePart { + part: String, + len: usize, +} + +impl Display for LinePart { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "{}", self.part) + } +} + +impl ZellijPlugin for State { + fn load(&mut self) { + set_selectable(false); + set_invisible_borders(true); + set_max_height(2); + subscribe(&[EventType::ModeUpdate]); + } + + fn update(&mut self, event: Event) { + if let Event::ModeUpdate(mode_info) = event { + self.mode_info = mode_info; + } + } + + fn render(&mut self, _rows: usize, cols: usize) { + let superkey = superkey(self.mode_info.palette); + let ctrl_keys = ctrl_keys(&self.mode_info, cols - superkey.len); + + let first_line = format!("{}{}", superkey, ctrl_keys); + let second_line = keybinds(&self.mode_info, cols); + + // [48;5;238m is gray background, [0K is so that it fills the rest of the line + // [m is background reset, [0K is so that it clears the rest of the line + println!( + "{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", + first_line, + self.mode_info.palette.bg.0, + self.mode_info.palette.bg.1, + self.mode_info.palette.bg.2 + ); + println!("\u{1b}[m{}\u{1b}[0K", second_line); + } +} diff --git a/default-plugins/status-bar/src/second_line.rs b/default-plugins/status-bar/src/second_line.rs new file mode 100644 index 00000000..6ecba662 --- /dev/null +++ b/default-plugins/status-bar/src/second_line.rs @@ -0,0 +1,365 @@ +// use colored::*; +use ansi_term::{ANSIStrings, Color::RGB, Style}; +use zellij_tile::{data::Theme, prelude::*}; + +use crate::colors::{GREEN, ORANGE, WHITE}; +use crate::{LinePart, MORE_MSG}; + +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(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.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(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.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.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.2)) + .paint("> "); + let description_len = description.chars().count(); + let description = Style::new() + .on(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.2)) + .bold() + .paint(description); + let len = shortcut_len + description_len + separator.chars().count(); + LinePart { + part: format!( + "{}", + ANSIStrings(&[ + separator, + shortcut_left_separator, + shortcut, + shortcut_right_separator, + description + ]) + ), + len, + } +} + +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(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.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(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.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.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.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(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.2)) + .bold() + .paint(description_first_word); + let len = shortcut_len + description_first_word_length + separator.chars().count(); + LinePart { + part: format!( + "{}", + ANSIStrings(&[ + separator, + shortcut_left_separator, + shortcut, + shortcut_right_separator, + description_first_word, + ]) + ), + len, + } +} +fn quicknav_full() -> LinePart { + let text_first_part = " Tip: "; + let alt = "Alt"; + let text_second_part = " + "; + let new_pane_shortcut = "n"; + let text_third_part = " => open new pane. "; + let second_alt = "Alt"; + let text_fourth_part = " + "; + let brackets_navigation = "[]"; + let text_fifth_part = " or "; + let hjkl_navigation = "hjkl"; + let text_sixths_part = " => navigate between panes."; + let len = text_first_part.chars().count() + + alt.chars().count() + + text_second_part.chars().count() + + new_pane_shortcut.chars().count() + + text_third_part.chars().count() + + second_alt.chars().count() + + text_fourth_part.chars().count() + + brackets_navigation.chars().count() + + text_fifth_part.chars().count() + + hjkl_navigation.chars().count() + + text_sixths_part.chars().count(); + LinePart { + part: format!( + "{}{}{}{}{}{}{}{}{}{}{}", + text_first_part, + Style::new().fg(ORANGE).bold().paint(alt), + text_second_part, + Style::new().fg(GREEN).bold().paint(new_pane_shortcut), + text_third_part, + Style::new().fg(ORANGE).bold().paint(second_alt), + text_fourth_part, + Style::new().fg(GREEN).bold().paint(brackets_navigation), + text_fifth_part, + Style::new().fg(GREEN).bold().paint(hjkl_navigation), + text_sixths_part, + ), + len, + } +} + +fn quicknav_medium() -> LinePart { + let text_first_part = " Tip: "; + let alt = "Alt"; + let text_second_part = " + "; + let new_pane_shortcut = "n"; + let text_third_part = " => new pane. "; + let second_alt = "Alt"; + let text_fourth_part = " + "; + let brackets_navigation = "[]"; + let text_fifth_part = " or "; + let hjkl_navigation = "hjkl"; + let text_sixths_part = " => navigate."; + let len = text_first_part.chars().count() + + alt.chars().count() + + text_second_part.chars().count() + + new_pane_shortcut.chars().count() + + text_third_part.chars().count() + + second_alt.chars().count() + + text_fourth_part.chars().count() + + brackets_navigation.chars().count() + + text_fifth_part.chars().count() + + hjkl_navigation.chars().count() + + text_sixths_part.chars().count(); + LinePart { + part: format!( + "{}{}{}{}{}{}{}{}{}{}{}", + text_first_part, + Style::new().fg(ORANGE).bold().paint(alt), + text_second_part, + Style::new().fg(GREEN).bold().paint(new_pane_shortcut), + text_third_part, + Style::new().fg(ORANGE).bold().paint(second_alt), + text_fourth_part, + Style::new().fg(GREEN).bold().paint(brackets_navigation), + text_fifth_part, + Style::new().fg(GREEN).bold().paint(hjkl_navigation), + text_sixths_part, + ), + len, + } +} + +fn quicknav_short() -> LinePart { + let text_first_part = " QuickNav: "; + let alt = "Alt"; + let text_second_part = " + "; + let new_pane_shortcut = "n"; + let text_third_part = "/"; + let brackets_navigation = "[]"; + let text_fifth_part = "/"; + let hjkl_navigation = "hjkl"; + let len = text_first_part.chars().count() + + alt.chars().count() + + text_second_part.chars().count() + + new_pane_shortcut.chars().count() + + text_third_part.chars().count() + + brackets_navigation.chars().count() + + text_fifth_part.chars().count() + + hjkl_navigation.chars().count(); + LinePart { + part: format!( + "{}{}{}{}{}{}{}{}", + text_first_part, + Style::new().fg(ORANGE).bold().paint(alt), + text_second_part, + Style::new().fg(GREEN).bold().paint(new_pane_shortcut), + text_third_part, + Style::new().fg(GREEN).bold().paint(brackets_navigation), + text_fifth_part, + Style::new().fg(GREEN).bold().paint(hjkl_navigation), + ), + len, + } +} + +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() + .fg(RGB(palette.white.0, palette.white.1, palette.white.2)) + .bold() + .paint(locked_text); + LinePart { + part: format!("{}", locked_styled_text), + len: locked_text_len, + } +} + +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(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.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(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.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.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.2)) + .paint("> "); + let description_len = description.chars().count(); + let description = Style::new() + .on(RGB(palette.black.0, palette.black.1, palette.black.2)) + .fg(RGB(palette.white.0, palette.white.1, palette.white.2)) + .bold() + .paint(description); + let len = shortcut_len + description_len + separator.chars().count(); + LinePart { + part: format!( + "{}", + ANSIStrings(&[ + separator, + shortcut_left_separator, + shortcut, + shortcut_right_separator, + description + ]) + ), + len, + } +} + +fn full_shortcut_list(help: &ModeInfo) -> LinePart { + match help.mode { + InputMode::Normal => quicknav_full(), + InputMode::Locked => locked_interface_indication(help.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, help.palette); + line_part.len += shortcut.len; + line_part.part = format!("{}{}", line_part.part, shortcut,); + } + let select_pane_shortcut = select_pane_shortcut(help.keybinds.is_empty(), help.palette); + line_part.len += select_pane_shortcut.len; + line_part.part = format!("{}{}", line_part.part, select_pane_shortcut,); + line_part + } + } +} + +fn shortened_shortcut_list(help: &ModeInfo) -> LinePart { + match help.mode { + InputMode::Normal => quicknav_medium(), + InputMode::Locked => locked_interface_indication(help.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, help.palette); + line_part.len += shortcut.len; + line_part.part = format!("{}{}", line_part.part, shortcut,); + } + let select_pane_shortcut = select_pane_shortcut(help.keybinds.is_empty(), help.palette); + line_part.len += select_pane_shortcut.len; + line_part.part = format!("{}{}", line_part.part, select_pane_shortcut,); + line_part + } + } +} + +fn best_effort_shortcut_list(help: &ModeInfo, max_len: usize) -> LinePart { + match help.mode { + InputMode::Normal => { + let line_part = quicknav_short(); + if line_part.len <= max_len { + line_part + } else { + LinePart::default() + } + } + InputMode::Locked => { + let line_part = locked_interface_indication(help.palette); + if line_part.len <= max_len { + line_part + } else { + LinePart::default() + } + } + _ => { + let mut line_part = LinePart::default(); + for (i, (letter, description)) in help.keybinds.iter().enumerate() { + let shortcut = first_word_shortcut(i == 0, &letter, &description, help.palette); + if line_part.len + shortcut.len + MORE_MSG.chars().count() > max_len { + // TODO: better + line_part.part = format!("{}{}", line_part.part, MORE_MSG); + line_part.len += MORE_MSG.chars().count(); + break; + } + line_part.len += shortcut.len; + line_part.part = format!("{}{}", line_part.part, shortcut); + } + let select_pane_shortcut = select_pane_shortcut(help.keybinds.is_empty(), help.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,); + } + line_part + } + } +} + +pub fn keybinds(help: &ModeInfo, max_width: usize) -> LinePart { + let full_shortcut_list = full_shortcut_list(help); + if full_shortcut_list.len <= max_width { + return full_shortcut_list; + } + let shortened_shortcut_list = shortened_shortcut_list(help); + if shortened_shortcut_list.len <= max_width { + return shortened_shortcut_list; + } + best_effort_shortcut_list(help, max_width) +} |
