mirror of
https://github.com/zellij-org/zellij.git
synced 2024-12-28 11:42:41 +03:00
commit
98d9eacd22
45
Cargo.lock
generated
45
Cargo.lock
generated
@ -310,6 +310,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colors-transform"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9226dbc05df4fb986f48d730b001532580883c4c06c5d1c213f4b34c1c157178"
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "1.2.2"
|
||||
@ -1106,6 +1112,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "2.0.3"
|
||||
@ -1471,6 +1483,7 @@ dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"colored",
|
||||
"zellij-tile",
|
||||
"zellij-tile-extra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1563,6 +1576,7 @@ dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"colored",
|
||||
"zellij-tile",
|
||||
"zellij-tile-extra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2173,6 +2187,27 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||
|
||||
[[package]]
|
||||
name = "x11"
|
||||
version = "2.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xrdb"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc2dd91a21c92e87678e22f95956a03bfd314ce3232f39dbedd49dddb50f0c6d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"scopeguard",
|
||||
"x11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
@ -2190,6 +2225,7 @@ dependencies = [
|
||||
"async-std",
|
||||
"backtrace",
|
||||
"bincode",
|
||||
"colors-transform",
|
||||
"directories-next",
|
||||
"futures",
|
||||
"insta",
|
||||
@ -2213,7 +2249,9 @@ dependencies = [
|
||||
"vte 0.8.0",
|
||||
"wasmer",
|
||||
"wasmer-wasi",
|
||||
"xrdb",
|
||||
"zellij-tile",
|
||||
"zellij-tile-extra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2225,3 +2263,10 @@ dependencies = [
|
||||
"strum",
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zellij-tile-extra"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
]
|
||||
|
@ -36,7 +36,10 @@ lazy_static = "1.4.0"
|
||||
wasmer = "1.0.0"
|
||||
wasmer-wasi = "1.0.0"
|
||||
interprocess = "1.0.1"
|
||||
xrdb = "0.1.1"
|
||||
colors-transform = "0.2.5"
|
||||
zellij-tile = { path = "zellij-tile/", version = "1.1.0" }
|
||||
zellij-tile-extra = { path = "zellij-tile-extra/", version="1.0.0" }
|
||||
|
||||
[dependencies.async-std]
|
||||
version = "1.3.0"
|
||||
@ -52,6 +55,7 @@ structopt = "0.3"
|
||||
[workspace]
|
||||
members = [
|
||||
"zellij-tile",
|
||||
"zellij-tile-extra",
|
||||
"default-plugins/status-bar",
|
||||
"default-plugins/strider",
|
||||
"default-plugins/tab-bar",
|
||||
|
@ -108,7 +108,7 @@ args = ["install", "cross"]
|
||||
[tasks.publish]
|
||||
clear = true
|
||||
workspace = false
|
||||
dependencies = ["build-plugins-release", "wasm-opt-plugins", "build-release", "publish-zellij-tile"]
|
||||
dependencies = ["build-plugins-release", "wasm-opt-plugins", "build-release", "publish-zellij-tile", "publish-zellij-tile-extra"]
|
||||
run_task = "publish-zellij"
|
||||
|
||||
[tasks.publish-zellij-tile]
|
||||
@ -117,6 +117,12 @@ cwd = "zellij-tile"
|
||||
command = "cargo"
|
||||
args = ["publish"]
|
||||
|
||||
[tasks.publish-zellij-tile-extra]
|
||||
ignore_errors = true
|
||||
cwd = "zellij-tile-extra"
|
||||
command = "cargo"
|
||||
args = ["publish"]
|
||||
|
||||
[tasks.publish-zellij]
|
||||
command = "cargo"
|
||||
args = ["publish"]
|
@ -9,3 +9,4 @@ license = "MIT"
|
||||
colored = "2"
|
||||
ansi_term = "0.12"
|
||||
zellij-tile = { path = "../../zellij-tile" }
|
||||
zellij-tile-extra = { path = "../../zellij-tile-extra" }
|
@ -1,8 +1,8 @@
|
||||
use ansi_term::{ANSIStrings, Style};
|
||||
use ansi_term::ANSIStrings;
|
||||
use zellij_tile::prelude::*;
|
||||
|
||||
use crate::colors::{BLACK, BRIGHT_GRAY, GRAY, GREEN, RED, WHITE};
|
||||
use crate::{LinePart, ARROW_SEPARATOR};
|
||||
use crate::color_elements;
|
||||
use crate::{ColoredElements, LinePart, ARROW_SEPARATOR};
|
||||
|
||||
struct CtrlKeyShortcut {
|
||||
mode: CtrlKeyMode,
|
||||
@ -63,32 +63,13 @@ impl CtrlKeyShortcut {
|
||||
}
|
||||
}
|
||||
|
||||
fn unselected_mode_shortcut(letter: char, text: &str) -> LinePart {
|
||||
let prefix_separator = Style::new().fg(GRAY).on(BRIGHT_GRAY).paint(ARROW_SEPARATOR);
|
||||
let char_left_separator = Style::new()
|
||||
.bold()
|
||||
.fg(BLACK)
|
||||
.on(BRIGHT_GRAY)
|
||||
.bold()
|
||||
.paint(" <");
|
||||
let char_shortcut = Style::new()
|
||||
.bold()
|
||||
.fg(RED)
|
||||
.on(BRIGHT_GRAY)
|
||||
.bold()
|
||||
.paint(letter.to_string());
|
||||
let char_right_separator = Style::new()
|
||||
.bold()
|
||||
.fg(BLACK)
|
||||
.on(BRIGHT_GRAY)
|
||||
.bold()
|
||||
.paint(">");
|
||||
let styled_text = Style::new()
|
||||
.fg(BLACK)
|
||||
.on(BRIGHT_GRAY)
|
||||
.bold()
|
||||
.paint(format!("{} ", text));
|
||||
let suffix_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
fn unselected_mode_shortcut(letter: char, text: &str, palette: ColoredElements) -> LinePart {
|
||||
let prefix_separator = palette.unselected_prefix_separator.paint(ARROW_SEPARATOR);
|
||||
let char_left_separator = palette.unselected_char_left_separator.paint(" <");
|
||||
let char_shortcut = palette.unselected_char_shortcut.paint(letter.to_string());
|
||||
let char_right_separator = palette.unselected_char_right_separator.paint(">");
|
||||
let styled_text = palette.unselected_styled_text.paint(format!("{} ", text));
|
||||
let suffix_separator = palette.unselected_suffix_separator.paint(ARROW_SEPARATOR);
|
||||
LinePart {
|
||||
part: ANSIStrings(&[
|
||||
prefix_separator,
|
||||
@ -103,22 +84,13 @@ 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);
|
||||
let char_left_separator = Style::new().bold().fg(BLACK).on(GREEN).bold().paint(" <");
|
||||
let char_shortcut = Style::new()
|
||||
.bold()
|
||||
.fg(RED)
|
||||
.on(GREEN)
|
||||
.bold()
|
||||
.paint(letter.to_string());
|
||||
let char_right_separator = Style::new().bold().fg(BLACK).on(GREEN).bold().paint(">");
|
||||
let styled_text = Style::new()
|
||||
.fg(BLACK)
|
||||
.on(GREEN)
|
||||
.bold()
|
||||
.paint(format!("{} ", text));
|
||||
let suffix_separator = Style::new().fg(GREEN).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
fn selected_mode_shortcut(letter: char, text: &str, palette: ColoredElements) -> LinePart {
|
||||
let prefix_separator = palette.selected_prefix_separator.paint(ARROW_SEPARATOR);
|
||||
let char_left_separator = palette.selected_char_left_separator.paint(" <".to_string());
|
||||
let char_shortcut = palette.selected_char_shortcut.paint(format!("{}", letter));
|
||||
let char_right_separator = palette.selected_char_right_separator.paint(">".to_string());
|
||||
let styled_text = palette.selected_styled_text.paint(format!("{} ", text));
|
||||
let suffix_separator = palette.selected_suffix_separator.paint(ARROW_SEPARATOR);
|
||||
LinePart {
|
||||
part: ANSIStrings(&[
|
||||
prefix_separator,
|
||||
@ -133,71 +105,69 @@ 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);
|
||||
let styled_text = Style::new()
|
||||
.fg(GRAY)
|
||||
.on(BRIGHT_GRAY)
|
||||
.dimmed()
|
||||
.paint(format!("{} ", text));
|
||||
let suffix_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
fn disabled_mode_shortcut(text: &str, palette: ColoredElements) -> LinePart {
|
||||
let prefix_separator = palette.disabled_prefix_separator.paint(ARROW_SEPARATOR);
|
||||
let styled_text = palette.disabled_styled_text.paint(format!("{} ", text));
|
||||
let suffix_separator = palette.disabled_suffix_separator.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: ColoredElements) -> 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 char_shortcut = Style::new()
|
||||
.bold()
|
||||
.fg(RED)
|
||||
.on(GREEN)
|
||||
.bold()
|
||||
let prefix_separator = palette
|
||||
.selected_single_letter_prefix_separator
|
||||
.paint(ARROW_SEPARATOR);
|
||||
let char_shortcut = palette
|
||||
.selected_single_letter_char_shortcut
|
||||
.paint(char_shortcut_text);
|
||||
let suffix_separator = Style::new().fg(GREEN).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
let suffix_separator = palette
|
||||
.selected_single_letter_suffix_separator
|
||||
.paint(ARROW_SEPARATOR);
|
||||
LinePart {
|
||||
part: ANSIStrings(&[prefix_separator, char_shortcut, suffix_separator]).to_string(),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn unselected_mode_shortcut_single_letter(letter: char) -> LinePart {
|
||||
fn unselected_mode_shortcut_single_letter(letter: char, palette: ColoredElements) -> 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 char_shortcut = Style::new()
|
||||
.bold()
|
||||
.fg(RED)
|
||||
.on(BRIGHT_GRAY)
|
||||
.bold()
|
||||
let prefix_separator = palette
|
||||
.unselected_single_letter_prefix_separator
|
||||
.paint(ARROW_SEPARATOR);
|
||||
let char_shortcut = palette
|
||||
.unselected_single_letter_char_shortcut
|
||||
.paint(char_shortcut_text);
|
||||
let suffix_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
let suffix_separator = palette
|
||||
.unselected_single_letter_suffix_separator
|
||||
.paint(ARROW_SEPARATOR);
|
||||
LinePart {
|
||||
part: ANSIStrings(&[prefix_separator, char_shortcut, suffix_separator]).to_string(),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn full_ctrl_key(key: &CtrlKeyShortcut) -> LinePart {
|
||||
fn full_ctrl_key(key: &CtrlKeyShortcut, palette: ColoredElements) -> 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: ColoredElements) -> LinePart {
|
||||
let shortened_text = key.shortened_text();
|
||||
let letter_shortcut = key.letter_shortcut();
|
||||
let shortened_text = match key.action {
|
||||
@ -205,27 +175,34 @@ fn shortened_ctrl_key(key: &CtrlKeyShortcut) -> LinePart {
|
||||
_ => shortened_text,
|
||||
};
|
||||
match key.mode {
|
||||
CtrlKeyMode::Unselected => unselected_mode_shortcut(letter_shortcut, &shortened_text),
|
||||
CtrlKeyMode::Selected => selected_mode_shortcut(letter_shortcut, &shortened_text),
|
||||
CtrlKeyMode::Disabled => {
|
||||
disabled_mode_shortcut(&format!(" <{}>{}", letter_shortcut, shortened_text))
|
||||
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) -> LinePart {
|
||||
fn single_letter_ctrl_key(key: &CtrlKeyShortcut, palette: ColoredElements) -> 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: ColoredElements) -> 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;
|
||||
}
|
||||
@ -234,7 +211,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;
|
||||
}
|
||||
@ -243,7 +220,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;
|
||||
}
|
||||
@ -254,16 +231,18 @@ fn key_indicators(max_len: usize, keys: &[CtrlKeyShortcut]) -> LinePart {
|
||||
line_part
|
||||
}
|
||||
|
||||
pub fn superkey() -> LinePart {
|
||||
pub fn superkey(palette: ColoredElements) -> LinePart {
|
||||
let prefix_text = " Ctrl + ";
|
||||
let prefix = Style::new().fg(WHITE).on(GRAY).bold().paint(prefix_text);
|
||||
let prefix = palette.superkey_prefix.paint(prefix_text);
|
||||
let suffix_separator = palette.superkey_suffix_separator.paint(ARROW_SEPARATOR);
|
||||
LinePart {
|
||||
part: prefix.to_string(),
|
||||
part: ANSIStrings(&[prefix, suffix_separator]).to_string(),
|
||||
len: prefix_text.chars().count(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
let colored_elements = color_elements(help.palette);
|
||||
match &help.mode {
|
||||
InputMode::Locked => key_indicators(
|
||||
max_len,
|
||||
@ -275,6 +254,7 @@ pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Scroll),
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Disabled, CtrlKeyAction::Quit),
|
||||
],
|
||||
colored_elements,
|
||||
),
|
||||
InputMode::Resize => key_indicators(
|
||||
max_len,
|
||||
@ -286,6 +266,7 @@ pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll),
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit),
|
||||
],
|
||||
colored_elements,
|
||||
),
|
||||
InputMode::Pane => key_indicators(
|
||||
max_len,
|
||||
@ -297,6 +278,7 @@ pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll),
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit),
|
||||
],
|
||||
colored_elements,
|
||||
),
|
||||
InputMode::Tab | InputMode::RenameTab => key_indicators(
|
||||
max_len,
|
||||
@ -308,6 +290,7 @@ pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll),
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit),
|
||||
],
|
||||
colored_elements,
|
||||
),
|
||||
InputMode::Scroll => key_indicators(
|
||||
max_len,
|
||||
@ -319,6 +302,7 @@ pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Selected, CtrlKeyAction::Scroll),
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit),
|
||||
],
|
||||
colored_elements,
|
||||
),
|
||||
InputMode::Normal => key_indicators(
|
||||
max_len,
|
||||
@ -330,6 +314,7 @@ pub fn ctrl_keys(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Scroll),
|
||||
CtrlKeyShortcut::new(CtrlKeyMode::Unselected, CtrlKeyAction::Quit),
|
||||
],
|
||||
colored_elements,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,15 @@
|
||||
mod first_line;
|
||||
mod second_line;
|
||||
|
||||
use ansi_term::Style;
|
||||
|
||||
use std::fmt::{Display, Error, Formatter};
|
||||
use zellij_tile::prelude::*;
|
||||
use zellij_tile_extra::*;
|
||||
|
||||
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 = " ... ";
|
||||
@ -41,6 +33,98 @@ impl Display for LinePart {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ColoredElements {
|
||||
// selected mode
|
||||
pub selected_prefix_separator: Style,
|
||||
pub selected_char_left_separator: Style,
|
||||
pub selected_char_shortcut: Style,
|
||||
pub selected_char_right_separator: Style,
|
||||
pub selected_styled_text: Style,
|
||||
pub selected_suffix_separator: Style,
|
||||
// unselected mode
|
||||
pub unselected_prefix_separator: Style,
|
||||
pub unselected_char_left_separator: Style,
|
||||
pub unselected_char_shortcut: Style,
|
||||
pub unselected_char_right_separator: Style,
|
||||
pub unselected_styled_text: Style,
|
||||
pub unselected_suffix_separator: Style,
|
||||
// disabled mode
|
||||
pub disabled_prefix_separator: Style,
|
||||
pub disabled_styled_text: Style,
|
||||
pub disabled_suffix_separator: Style,
|
||||
// selected single letter
|
||||
pub selected_single_letter_prefix_separator: Style,
|
||||
pub selected_single_letter_char_shortcut: Style,
|
||||
pub selected_single_letter_suffix_separator: Style,
|
||||
// unselected single letter
|
||||
pub unselected_single_letter_prefix_separator: Style,
|
||||
pub unselected_single_letter_char_shortcut: Style,
|
||||
pub unselected_single_letter_suffix_separator: Style,
|
||||
// superkey
|
||||
pub superkey_prefix: Style,
|
||||
pub superkey_suffix_separator: Style,
|
||||
}
|
||||
|
||||
// I really hate this, but I can't come up with a good solution for this,
|
||||
// we need different colors from palette for the default theme
|
||||
// plus here we can add new sources in the future, like Theme
|
||||
// that can be defined in the config perhaps
|
||||
fn color_elements(palette: Palette) -> ColoredElements {
|
||||
match palette.source {
|
||||
PaletteSource::Default => ColoredElements {
|
||||
selected_prefix_separator: style!(palette.bg, palette.green),
|
||||
selected_char_left_separator: style!(palette.black, palette.green).bold(),
|
||||
selected_char_shortcut: style!(palette.red, palette.green).bold(),
|
||||
selected_char_right_separator: style!(palette.black, palette.green).bold(),
|
||||
selected_styled_text: style!(palette.black, palette.green).bold(),
|
||||
selected_suffix_separator: style!(palette.green, palette.bg).bold(),
|
||||
unselected_prefix_separator: style!(palette.bg, palette.fg),
|
||||
unselected_char_left_separator: style!(palette.bg, palette.fg).bold(),
|
||||
unselected_char_shortcut: style!(palette.red, palette.fg).bold(),
|
||||
unselected_char_right_separator: style!(palette.bg, palette.fg).bold(),
|
||||
unselected_styled_text: style!(palette.black, palette.fg).bold(),
|
||||
unselected_suffix_separator: style!(palette.fg, palette.bg),
|
||||
disabled_prefix_separator: style!(palette.bg, palette.fg),
|
||||
disabled_styled_text: style!(palette.bg, palette.fg).dimmed(),
|
||||
disabled_suffix_separator: style!(palette.fg, palette.bg),
|
||||
selected_single_letter_prefix_separator: style!(palette.fg, palette.green),
|
||||
selected_single_letter_char_shortcut: style!(palette.red, palette.green).bold(),
|
||||
selected_single_letter_suffix_separator: style!(palette.green, palette.fg),
|
||||
unselected_single_letter_prefix_separator: style!(palette.fg, palette.bg),
|
||||
unselected_single_letter_char_shortcut: style!(palette.red, palette.fg).bold(),
|
||||
unselected_single_letter_suffix_separator: style!(palette.fg, palette.bg),
|
||||
superkey_prefix: style!(palette.white, palette.bg).bold(),
|
||||
superkey_suffix_separator: style!(palette.bg, palette.bg),
|
||||
},
|
||||
PaletteSource::Xresources => ColoredElements {
|
||||
selected_prefix_separator: style!(palette.bg, palette.green),
|
||||
selected_char_left_separator: style!(palette.fg, palette.green).bold(),
|
||||
selected_char_shortcut: style!(palette.red, palette.green).bold(),
|
||||
selected_char_right_separator: style!(palette.fg, palette.green).bold(),
|
||||
selected_styled_text: style!(palette.bg, palette.green).bold(),
|
||||
selected_suffix_separator: style!(palette.green, palette.bg).bold(),
|
||||
unselected_prefix_separator: style!(palette.bg, palette.fg),
|
||||
unselected_char_left_separator: style!(palette.bg, palette.fg).bold(),
|
||||
unselected_char_shortcut: style!(palette.red, palette.fg).bold(),
|
||||
unselected_char_right_separator: style!(palette.bg, palette.fg).bold(),
|
||||
unselected_styled_text: style!(palette.bg, palette.fg).bold(),
|
||||
unselected_suffix_separator: style!(palette.fg, palette.bg),
|
||||
disabled_prefix_separator: style!(palette.bg, palette.fg),
|
||||
disabled_styled_text: style!(palette.bg, palette.fg).dimmed(),
|
||||
disabled_suffix_separator: style!(palette.fg, palette.bg),
|
||||
selected_single_letter_prefix_separator: style!(palette.fg, palette.green),
|
||||
selected_single_letter_char_shortcut: style!(palette.red, palette.green).bold(),
|
||||
selected_single_letter_suffix_separator: style!(palette.green, palette.fg),
|
||||
unselected_single_letter_prefix_separator: style!(palette.fg, palette.bg),
|
||||
unselected_single_letter_char_shortcut: style!(palette.red, palette.fg).bold(),
|
||||
unselected_single_letter_suffix_separator: style!(palette.fg, palette.bg),
|
||||
superkey_prefix: style!(palette.bg, palette.fg).bold(),
|
||||
superkey_suffix_separator: style!(palette.fg, palette.bg),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
impl ZellijPlugin for State {
|
||||
fn load(&mut self) {
|
||||
set_selectable(false);
|
||||
@ -56,7 +140,8 @@ impl ZellijPlugin for State {
|
||||
}
|
||||
|
||||
fn render(&mut self, _rows: usize, cols: usize) {
|
||||
let superkey = superkey();
|
||||
let colored_elements = color_elements(self.mode_info.palette);
|
||||
let superkey = superkey(colored_elements);
|
||||
let ctrl_keys = ctrl_keys(&self.mode_info, cols - superkey.len);
|
||||
|
||||
let first_line = format!("{}{}", superkey, ctrl_keys);
|
||||
@ -64,7 +149,13 @@ impl ZellijPlugin for State {
|
||||
|
||||
// [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;5;238m\u{1b}[0K", first_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);
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,35 @@
|
||||
// use colored::*;
|
||||
use ansi_term::{ANSIStrings, Style};
|
||||
use ansi_term::{ANSIStrings, Color::RGB, Style};
|
||||
use zellij_tile::prelude::*;
|
||||
|
||||
use crate::colors::{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().fg(WHITE).paint(separator);
|
||||
let separator = Style::new()
|
||||
.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().fg(WHITE).paint("<");
|
||||
let shortcut = Style::new().fg(GREEN).bold().paint(letter);
|
||||
let shortcut_right_separator = Style::new().fg(WHITE).paint("> ");
|
||||
let shortcut_left_separator = Style::new()
|
||||
.fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2))
|
||||
.paint("<");
|
||||
let shortcut = Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(letter);
|
||||
let shortcut_right_separator = Style::new()
|
||||
.fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2))
|
||||
.paint("> ");
|
||||
let description_len = description.chars().count();
|
||||
let description = Style::new().fg(WHITE).bold().paint(description);
|
||||
let description = Style::new()
|
||||
.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,16 +46,33 @@ 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().fg(WHITE).paint(separator);
|
||||
let separator = Style::new()
|
||||
.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().fg(WHITE).paint("<");
|
||||
let shortcut = Style::new().fg(GREEN).bold().paint(letter);
|
||||
let shortcut_right_separator = Style::new().fg(WHITE).paint("> ");
|
||||
let shortcut_left_separator = Style::new()
|
||||
.fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2))
|
||||
.paint("<");
|
||||
let shortcut = Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(letter);
|
||||
let shortcut_right_separator = Style::new()
|
||||
.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().fg(WHITE).bold().paint(description_first_word);
|
||||
let description_first_word = Style::new()
|
||||
.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();
|
||||
LinePart {
|
||||
part: format!(
|
||||
@ -55,7 +88,7 @@ fn first_word_shortcut(is_first_shortcut: bool, letter: &str, description: &str)
|
||||
len,
|
||||
}
|
||||
}
|
||||
fn quicknav_full() -> LinePart {
|
||||
fn quicknav_full(palette: Palette) -> LinePart {
|
||||
let text_first_part = " Tip: ";
|
||||
let alt = "Alt";
|
||||
let text_second_part = " + ";
|
||||
@ -82,22 +115,37 @@ fn quicknav_full() -> LinePart {
|
||||
part: format!(
|
||||
"{}{}{}{}{}{}{}{}{}{}{}",
|
||||
text_first_part,
|
||||
Style::new().fg(ORANGE).bold().paint(alt),
|
||||
Style::new()
|
||||
.fg(RGB(palette.orange.0, palette.orange.1, palette.orange.2))
|
||||
.bold()
|
||||
.paint(alt),
|
||||
text_second_part,
|
||||
Style::new().fg(GREEN).bold().paint(new_pane_shortcut),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(new_pane_shortcut),
|
||||
text_third_part,
|
||||
Style::new().fg(ORANGE).bold().paint(second_alt),
|
||||
Style::new()
|
||||
.fg(RGB(palette.orange.0, palette.orange.1, palette.orange.2))
|
||||
.bold()
|
||||
.paint(second_alt),
|
||||
text_fourth_part,
|
||||
Style::new().fg(GREEN).bold().paint(brackets_navigation),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(brackets_navigation),
|
||||
text_fifth_part,
|
||||
Style::new().fg(GREEN).bold().paint(hjkl_navigation),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(hjkl_navigation),
|
||||
text_sixths_part,
|
||||
),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn quicknav_medium() -> LinePart {
|
||||
fn quicknav_medium(palette: Palette) -> LinePart {
|
||||
let text_first_part = " Tip: ";
|
||||
let alt = "Alt";
|
||||
let text_second_part = " + ";
|
||||
@ -124,22 +172,37 @@ fn quicknav_medium() -> LinePart {
|
||||
part: format!(
|
||||
"{}{}{}{}{}{}{}{}{}{}{}",
|
||||
text_first_part,
|
||||
Style::new().fg(ORANGE).bold().paint(alt),
|
||||
Style::new()
|
||||
.fg(RGB(palette.orange.0, palette.orange.1, palette.orange.2))
|
||||
.bold()
|
||||
.paint(alt),
|
||||
text_second_part,
|
||||
Style::new().fg(GREEN).bold().paint(new_pane_shortcut),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(new_pane_shortcut),
|
||||
text_third_part,
|
||||
Style::new().fg(ORANGE).bold().paint(second_alt),
|
||||
Style::new()
|
||||
.fg(RGB(palette.orange.0, palette.orange.1, palette.orange.2))
|
||||
.bold()
|
||||
.paint(second_alt),
|
||||
text_fourth_part,
|
||||
Style::new().fg(GREEN).bold().paint(brackets_navigation),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(brackets_navigation),
|
||||
text_fifth_part,
|
||||
Style::new().fg(GREEN).bold().paint(hjkl_navigation),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(hjkl_navigation),
|
||||
text_sixths_part,
|
||||
),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn quicknav_short() -> LinePart {
|
||||
fn quicknav_short(palette: Palette) -> LinePart {
|
||||
let text_first_part = " QuickNav: ";
|
||||
let alt = "Alt";
|
||||
let text_second_part = " + ";
|
||||
@ -160,39 +223,66 @@ fn quicknav_short() -> LinePart {
|
||||
part: format!(
|
||||
"{}{}{}{}{}{}{}{}",
|
||||
text_first_part,
|
||||
Style::new().fg(ORANGE).bold().paint(alt),
|
||||
Style::new()
|
||||
.fg(RGB(palette.orange.0, palette.orange.1, palette.orange.2))
|
||||
.bold()
|
||||
.paint(alt),
|
||||
text_second_part,
|
||||
Style::new().fg(GREEN).bold().paint(new_pane_shortcut),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(new_pane_shortcut),
|
||||
text_third_part,
|
||||
Style::new().fg(GREEN).bold().paint(brackets_navigation),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(brackets_navigation),
|
||||
text_fifth_part,
|
||||
Style::new().fg(GREEN).bold().paint(hjkl_navigation),
|
||||
Style::new()
|
||||
.fg(RGB(palette.green.0, palette.green.1, palette.green.2))
|
||||
.bold()
|
||||
.paint(hjkl_navigation),
|
||||
),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
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().fg(WHITE).bold().paint(locked_text);
|
||||
let locked_styled_text = Style::new()
|
||||
.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().fg(WHITE).paint(separator);
|
||||
let separator = Style::new()
|
||||
.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().fg(WHITE).paint("<");
|
||||
let shortcut = Style::new().fg(ORANGE).bold().paint(shortcut);
|
||||
let shortcut_right_separator = Style::new().fg(WHITE).paint("> ");
|
||||
let shortcut_left_separator = Style::new()
|
||||
.fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2))
|
||||
.paint("<");
|
||||
let shortcut = Style::new()
|
||||
.fg(RGB(palette.orange.0, palette.orange.1, palette.orange.2))
|
||||
.bold()
|
||||
.paint(shortcut);
|
||||
let shortcut_right_separator = Style::new()
|
||||
.fg(RGB(palette.fg.0, palette.fg.1, palette.fg.2))
|
||||
.paint("> ");
|
||||
let description_len = description.chars().count();
|
||||
let description = Style::new().fg(WHITE).bold().paint(description);
|
||||
let description = Style::new()
|
||||
.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!(
|
||||
@ -211,16 +301,16 @@ fn select_pane_shortcut(is_first_shortcut: bool) -> LinePart {
|
||||
|
||||
fn full_shortcut_list(help: &ModeInfo) -> LinePart {
|
||||
match help.mode {
|
||||
InputMode::Normal => quicknav_full(),
|
||||
InputMode::Locked => locked_interface_indication(),
|
||||
InputMode::Normal => quicknav_full(help.palette),
|
||||
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);
|
||||
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());
|
||||
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
|
||||
@ -230,16 +320,16 @@ fn full_shortcut_list(help: &ModeInfo) -> LinePart {
|
||||
|
||||
fn shortened_shortcut_list(help: &ModeInfo) -> LinePart {
|
||||
match help.mode {
|
||||
InputMode::Normal => quicknav_medium(),
|
||||
InputMode::Locked => locked_interface_indication(),
|
||||
InputMode::Normal => quicknav_medium(help.palette),
|
||||
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);
|
||||
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());
|
||||
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
|
||||
@ -250,7 +340,7 @@ fn shortened_shortcut_list(help: &ModeInfo) -> LinePart {
|
||||
fn best_effort_shortcut_list(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
match help.mode {
|
||||
InputMode::Normal => {
|
||||
let line_part = quicknav_short();
|
||||
let line_part = quicknav_short(help.palette);
|
||||
if line_part.len <= max_len {
|
||||
line_part
|
||||
} else {
|
||||
@ -258,7 +348,7 @@ fn best_effort_shortcut_list(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
}
|
||||
}
|
||||
InputMode::Locked => {
|
||||
let line_part = locked_interface_indication();
|
||||
let line_part = locked_interface_indication(help.palette);
|
||||
if line_part.len <= max_len {
|
||||
line_part
|
||||
} else {
|
||||
@ -268,7 +358,7 @@ fn best_effort_shortcut_list(help: &ModeInfo, 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, 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);
|
||||
@ -278,7 +368,7 @@ fn best_effort_shortcut_list(help: &ModeInfo, 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.is_empty());
|
||||
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,);
|
||||
|
@ -9,3 +9,4 @@ license = "MIT"
|
||||
colored = "2"
|
||||
ansi_term = "0.12"
|
||||
zellij-tile = { path = "../../zellij-tile" }
|
||||
zellij-tile-extra = { path = "../../zellij-tile-extra" }
|
@ -1,7 +1,8 @@
|
||||
use crate::colors::{BLACK, GRAY, ORANGE, WHITE};
|
||||
use ansi_term::{ANSIStrings, Style};
|
||||
use ansi_term::ANSIStrings;
|
||||
|
||||
use crate::{LinePart, ARROW_SEPARATOR};
|
||||
use zellij_tile::prelude::*;
|
||||
use zellij_tile_extra::*;
|
||||
|
||||
fn get_current_title_len(current_title: &[LinePart]) -> usize {
|
||||
current_title
|
||||
@ -47,7 +48,7 @@ fn populate_tabs_in_tab_line(
|
||||
}
|
||||
}
|
||||
|
||||
fn left_more_message(tab_count_to_the_left: usize) -> LinePart {
|
||||
fn left_more_message(tab_count_to_the_left: usize, palette: Palette) -> LinePart {
|
||||
if tab_count_to_the_left == 0 {
|
||||
return LinePart {
|
||||
part: String::new(),
|
||||
@ -61,9 +62,9 @@ fn left_more_message(tab_count_to_the_left: usize) -> LinePart {
|
||||
};
|
||||
// 238
|
||||
let more_text_len = more_text.chars().count() + 2; // 2 for the arrows
|
||||
let left_separator = Style::new().fg(GRAY).on(ORANGE).paint(ARROW_SEPARATOR);
|
||||
let more_styled_text = Style::new().fg(BLACK).on(ORANGE).bold().paint(more_text);
|
||||
let right_separator = Style::new().fg(ORANGE).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
let left_separator = style!(palette.fg, palette.orange).paint(ARROW_SEPARATOR);
|
||||
let more_styled_text = style!(palette.fg, palette.orange).bold().paint(more_text);
|
||||
let right_separator = style!(palette.orange, palette.bg).paint(ARROW_SEPARATOR);
|
||||
let more_styled_text = format!(
|
||||
"{}",
|
||||
ANSIStrings(&[left_separator, more_styled_text, right_separator,])
|
||||
@ -74,7 +75,7 @@ fn left_more_message(tab_count_to_the_left: usize) -> LinePart {
|
||||
}
|
||||
}
|
||||
|
||||
fn right_more_message(tab_count_to_the_right: usize) -> LinePart {
|
||||
fn right_more_message(tab_count_to_the_right: usize, palette: Palette) -> LinePart {
|
||||
if tab_count_to_the_right == 0 {
|
||||
return LinePart {
|
||||
part: String::new(),
|
||||
@ -87,9 +88,9 @@ fn right_more_message(tab_count_to_the_right: usize) -> LinePart {
|
||||
" +many → ".to_string()
|
||||
};
|
||||
let more_text_len = more_text.chars().count() + 1; // 2 for the arrow
|
||||
let left_separator = Style::new().fg(GRAY).on(ORANGE).paint(ARROW_SEPARATOR);
|
||||
let more_styled_text = Style::new().fg(BLACK).on(ORANGE).bold().paint(more_text);
|
||||
let right_separator = Style::new().fg(ORANGE).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
let left_separator = style!(palette.fg, palette.orange).paint(ARROW_SEPARATOR);
|
||||
let more_styled_text = style!(palette.fg, palette.orange).bold().paint(more_text);
|
||||
let right_separator = style!(palette.orange, palette.bg).paint(ARROW_SEPARATOR);
|
||||
let more_styled_text = format!(
|
||||
"{}",
|
||||
ANSIStrings(&[left_separator, more_styled_text, right_separator,])
|
||||
@ -105,13 +106,15 @@ fn add_previous_tabs_msg(
|
||||
tabs_to_render: &mut Vec<LinePart>,
|
||||
title_bar: &mut Vec<LinePart>,
|
||||
cols: usize,
|
||||
palette: Palette,
|
||||
) {
|
||||
while get_current_title_len(&tabs_to_render) + left_more_message(tabs_before_active.len()).len
|
||||
while get_current_title_len(&tabs_to_render)
|
||||
+ left_more_message(tabs_before_active.len(), palette).len
|
||||
>= cols
|
||||
{
|
||||
tabs_before_active.push(tabs_to_render.remove(0));
|
||||
}
|
||||
let left_more_message = left_more_message(tabs_before_active.len());
|
||||
let left_more_message = left_more_message(tabs_before_active.len(), palette);
|
||||
title_bar.push(left_more_message);
|
||||
}
|
||||
|
||||
@ -119,20 +122,22 @@ fn add_next_tabs_msg(
|
||||
tabs_after_active: &mut Vec<LinePart>,
|
||||
title_bar: &mut Vec<LinePart>,
|
||||
cols: usize,
|
||||
palette: Palette,
|
||||
) {
|
||||
while get_current_title_len(&title_bar) + right_more_message(tabs_after_active.len()).len
|
||||
while get_current_title_len(&title_bar)
|
||||
+ right_more_message(tabs_after_active.len(), palette).len
|
||||
>= cols
|
||||
{
|
||||
tabs_after_active.insert(0, title_bar.pop().unwrap());
|
||||
}
|
||||
let right_more_message = right_more_message(tabs_after_active.len());
|
||||
let right_more_message = right_more_message(tabs_after_active.len(), palette);
|
||||
title_bar.push(right_more_message);
|
||||
}
|
||||
|
||||
fn tab_line_prefix() -> LinePart {
|
||||
fn tab_line_prefix(palette: Palette) -> LinePart {
|
||||
let prefix_text = " Zellij ".to_string();
|
||||
let prefix_text_len = prefix_text.chars().count();
|
||||
let prefix_styled_text = Style::new().fg(WHITE).on(GRAY).bold().paint(prefix_text);
|
||||
let prefix_styled_text = style!(palette.fg, palette.bg).bold().paint(prefix_text);
|
||||
LinePart {
|
||||
part: format!("{}", prefix_styled_text),
|
||||
len: prefix_text_len,
|
||||
@ -143,6 +148,7 @@ pub fn tab_line(
|
||||
mut all_tabs: Vec<LinePart>,
|
||||
active_tab_index: usize,
|
||||
cols: usize,
|
||||
palette: Palette,
|
||||
) -> Vec<LinePart> {
|
||||
let mut tabs_to_render: Vec<LinePart> = vec![];
|
||||
let mut tabs_after_active = all_tabs.split_off(active_tab_index);
|
||||
@ -154,7 +160,7 @@ pub fn tab_line(
|
||||
};
|
||||
tabs_to_render.push(active_tab);
|
||||
|
||||
let prefix = tab_line_prefix();
|
||||
let prefix = tab_line_prefix(palette);
|
||||
populate_tabs_in_tab_line(
|
||||
&mut tabs_before_active,
|
||||
&mut tabs_after_active,
|
||||
@ -169,11 +175,17 @@ pub fn tab_line(
|
||||
&mut tabs_to_render,
|
||||
&mut tab_line,
|
||||
cols - prefix.len,
|
||||
palette,
|
||||
);
|
||||
}
|
||||
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 - prefix.len);
|
||||
add_next_tabs_msg(
|
||||
&mut tabs_after_active,
|
||||
&mut tab_line,
|
||||
cols - prefix.len,
|
||||
palette,
|
||||
);
|
||||
}
|
||||
tab_line.insert(0, prefix);
|
||||
tab_line
|
||||
|
@ -15,22 +15,11 @@ pub struct LinePart {
|
||||
#[derive(Default)]
|
||||
struct State {
|
||||
tabs: Vec<TabInfo>,
|
||||
mode: InputMode,
|
||||
mode_info: ModeInfo,
|
||||
}
|
||||
|
||||
static ARROW_SEPARATOR: &str = "";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
register_plugin!(State);
|
||||
|
||||
impl ZellijPlugin for State {
|
||||
@ -43,7 +32,7 @@ impl ZellijPlugin for State {
|
||||
|
||||
fn update(&mut self, event: Event) {
|
||||
match event {
|
||||
Event::ModeUpdate(mode_info) => self.mode = mode_info.mode,
|
||||
Event::ModeUpdate(mode_info) => self.mode_info = mode_info,
|
||||
Event::TabUpdate(tabs) => self.tabs = tabs,
|
||||
_ => unimplemented!(), // FIXME: This should be unreachable, but this could be cleaner
|
||||
}
|
||||
@ -57,7 +46,7 @@ impl ZellijPlugin for State {
|
||||
let mut active_tab_index = 0;
|
||||
for t in self.tabs.iter_mut() {
|
||||
let mut tabname = t.name.clone();
|
||||
if t.active && self.mode == InputMode::RenameTab {
|
||||
if t.active && self.mode_info.mode == InputMode::RenameTab {
|
||||
if tabname.is_empty() {
|
||||
tabname = String::from("Enter name...");
|
||||
}
|
||||
@ -65,14 +54,26 @@ impl ZellijPlugin for State {
|
||||
} else if t.active {
|
||||
active_tab_index = t.position;
|
||||
}
|
||||
let tab = tab_style(tabname, t.active, t.position, t.is_sync_panes_active);
|
||||
let tab = tab_style(
|
||||
tabname,
|
||||
t.active,
|
||||
t.position,
|
||||
t.is_sync_panes_active,
|
||||
self.mode_info.palette,
|
||||
);
|
||||
all_tabs.push(tab);
|
||||
}
|
||||
let tab_line = tab_line(all_tabs, active_tab_index, cols);
|
||||
let tab_line = tab_line(all_tabs, active_tab_index, cols, self.mode_info.palette);
|
||||
let mut s = String::new();
|
||||
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}[48;2;{};{};{}m\u{1b}[0K",
|
||||
s,
|
||||
self.mode_info.palette.bg.0,
|
||||
self.mode_info.palette.bg.1,
|
||||
self.mode_info.palette.bg.2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,15 @@
|
||||
use crate::colors::{BLACK, BRIGHT_GRAY, GRAY, GREEN};
|
||||
use crate::{LinePart, ARROW_SEPARATOR};
|
||||
use ansi_term::{ANSIStrings, Style};
|
||||
use ansi_term::ANSIStrings;
|
||||
use zellij_tile::prelude::*;
|
||||
use zellij_tile_extra::*;
|
||||
|
||||
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!(palette.bg, palette.green).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)
|
||||
let tab_styled_text = style!(palette.bg, palette.green)
|
||||
.bold()
|
||||
.paint(format!(" {} ", text));
|
||||
let right_separator = Style::new().fg(GREEN).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
let right_separator = style!(palette.green, palette.bg).paint(ARROW_SEPARATOR);
|
||||
let tab_styled_text = format!(
|
||||
"{}",
|
||||
ANSIStrings(&[left_separator, tab_styled_text, right_separator,])
|
||||
@ -21,15 +20,13 @@ 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!(palette.bg, palette.bg).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)
|
||||
let tab_styled_text = style!(palette.fg, palette.bg)
|
||||
.bold()
|
||||
.paint(format!(" {} ", text));
|
||||
let right_separator = Style::new().fg(BRIGHT_GRAY).on(GRAY).paint(ARROW_SEPARATOR);
|
||||
let right_separator = style!(palette.bg, palette.bg).paint(ARROW_SEPARATOR);
|
||||
let tab_styled_text = format!(
|
||||
"{}",
|
||||
ANSIStrings(&[left_separator, tab_styled_text, right_separator,])
|
||||
@ -45,6 +42,7 @@ pub fn tab_style(
|
||||
is_active_tab: bool,
|
||||
position: usize,
|
||||
is_sync_panes_active: bool,
|
||||
palette: Palette,
|
||||
) -> LinePart {
|
||||
let mut tab_text = if text.is_empty() {
|
||||
format!("Tab #{}", position + 1)
|
||||
@ -55,8 +53,8 @@ pub fn tab_style(
|
||||
tab_text.push_str(" (Sync)");
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
use crate::tab::Pane;
|
||||
use ansi_term::Colour;
|
||||
use crate::utils::shared::colors;
|
||||
use ansi_term::Colour::RGB;
|
||||
use std::collections::HashMap;
|
||||
use zellij_tile::data::InputMode;
|
||||
use zellij_tile::data::{InputMode, Palette};
|
||||
|
||||
use std::fmt::{Display, Error, Formatter};
|
||||
|
||||
pub mod boundary_type {
|
||||
pub const TOP_RIGHT: &str = "┐";
|
||||
pub const VERTICAL: &str = "│";
|
||||
@ -19,12 +19,12 @@ pub mod boundary_type {
|
||||
pub const CROSS: &str = "┼";
|
||||
}
|
||||
|
||||
pub mod colors {
|
||||
use ansi_term::Colour::{self, Fixed};
|
||||
pub const GREEN: Colour = Fixed(154);
|
||||
pub const GRAY: Colour = Fixed(238);
|
||||
pub const ORANGE: Colour = Fixed(166);
|
||||
}
|
||||
// pub mod colors {
|
||||
// use ansi_term::Colour::{self, Fixed};
|
||||
// pub const GREEN: Colour = Fixed(154);
|
||||
// pub const GRAY: Colour = Fixed(238);
|
||||
// pub const ORANGE: Colour = Fixed(166);
|
||||
// }
|
||||
|
||||
pub type BoundaryType = &'static str; // easy way to refer to boundary_type above
|
||||
|
||||
@ -32,7 +32,7 @@ pub type BoundaryType = &'static str; // easy way to refer to boundary_type abov
|
||||
pub struct BoundarySymbol {
|
||||
boundary_type: BoundaryType,
|
||||
invisible: bool,
|
||||
color: Option<Colour>,
|
||||
color: Option<(u8, u8, u8)>,
|
||||
}
|
||||
|
||||
impl BoundarySymbol {
|
||||
@ -47,7 +47,7 @@ impl BoundarySymbol {
|
||||
self.invisible = true;
|
||||
self
|
||||
}
|
||||
pub fn color(&mut self, color: Option<Colour>) -> Self {
|
||||
pub fn color(&mut self, color: Option<(u8, u8, u8)>) -> Self {
|
||||
self.color = color;
|
||||
*self
|
||||
}
|
||||
@ -58,7 +58,11 @@ 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),
|
||||
},
|
||||
}
|
||||
@ -764,11 +768,11 @@ impl Boundaries {
|
||||
boundary_characters: HashMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn add_rect(&mut self, rect: &dyn Pane, input_mode: InputMode, color: Option<Colour>) {
|
||||
let color = match color.is_some() {
|
||||
pub fn add_rect(&mut self, rect: &dyn Pane, input_mode: InputMode, palette: Option<Palette>) {
|
||||
let color = match palette.is_some() {
|
||||
true => match input_mode {
|
||||
InputMode::Normal | InputMode::Locked => Some(colors::GREEN),
|
||||
_ => Some(colors::ORANGE),
|
||||
InputMode::Normal | InputMode::Locked => Some(palette.unwrap().green),
|
||||
_ => Some(palette.unwrap().orange),
|
||||
},
|
||||
false => None,
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! `Tab`s holds multiple panes. It tracks their coordinates (x/y) and size,
|
||||
//! as well as how they should be resized
|
||||
|
||||
use crate::boundaries::colors;
|
||||
use crate::client::pane_resizer::PaneResizer;
|
||||
use crate::common::{input::handler::parse_keys, AppInstruction, SenderWithContext};
|
||||
use crate::layout::Layout;
|
||||
@ -19,7 +18,7 @@ use std::{
|
||||
collections::{BTreeMap, HashSet},
|
||||
};
|
||||
use std::{io::Write, sync::mpsc::channel};
|
||||
use zellij_tile::data::{Event, ModeInfo};
|
||||
use zellij_tile::data::{Event, InputMode, ModeInfo, Palette};
|
||||
|
||||
const CURSOR_HEIGHT_WIDTH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this
|
||||
|
||||
@ -75,6 +74,8 @@ pub struct Tab {
|
||||
pub send_app_instructions: SenderWithContext<AppInstruction>,
|
||||
should_clear_display_before_rendering: bool,
|
||||
pub mode_info: ModeInfo,
|
||||
pub input_mode: InputMode,
|
||||
pub colors: Palette,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
@ -84,6 +85,8 @@ pub struct TabData {
|
||||
pub name: String,
|
||||
pub active: bool,
|
||||
pub mode_info: ModeInfo,
|
||||
pub input_mode: InputMode,
|
||||
pub colors: Palette,
|
||||
}
|
||||
|
||||
// FIXME: Use a struct that has a pane_type enum, to reduce all of the duplication
|
||||
@ -229,6 +232,8 @@ impl Tab {
|
||||
max_panes: Option<usize>,
|
||||
pane_id: Option<PaneId>,
|
||||
mode_info: ModeInfo,
|
||||
input_mode: InputMode,
|
||||
colors: Palette,
|
||||
) -> Self {
|
||||
let panes = if let Some(PaneId::Terminal(pid)) = pane_id {
|
||||
let new_terminal = TerminalPane::new(pid, *full_screen_ws);
|
||||
@ -260,6 +265,8 @@ impl Tab {
|
||||
send_plugin_instructions,
|
||||
should_clear_display_before_rendering: false,
|
||||
mode_info,
|
||||
input_mode,
|
||||
colors,
|
||||
}
|
||||
}
|
||||
|
||||
@ -743,7 +750,7 @@ impl Tab {
|
||||
match self.active_terminal.unwrap() == pane.pid() {
|
||||
true => {
|
||||
pane.set_active_at(Instant::now());
|
||||
boundaries.add_rect(pane.as_ref(), self.mode_info.mode, Some(colors::GREEN))
|
||||
boundaries.add_rect(pane.as_ref(), self.mode_info.mode, Some(self.colors))
|
||||
}
|
||||
false => boundaries.add_rect(pane.as_ref(), self.mode_info.mode, None),
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use crate::wasm_vm::PluginInstruction;
|
||||
use crate::CommandIsExecuting;
|
||||
|
||||
use termion::input::{TermRead, TermReadEventsAndRaw};
|
||||
use zellij_tile::data::{Event, InputMode, Key, ModeInfo};
|
||||
use zellij_tile::data::{Event, InputMode, Key, ModeInfo, Palette};
|
||||
|
||||
/// Handles the dispatching of [`Action`]s according to the current
|
||||
/// [`InputMode`], and keep tracks of the current [`InputMode`].
|
||||
@ -131,11 +131,14 @@ impl InputHandler {
|
||||
self.send_plugin_instructions
|
||||
.send(PluginInstruction::Update(
|
||||
None,
|
||||
Event::ModeUpdate(get_mode_info(mode)),
|
||||
Event::ModeUpdate(get_mode_info(mode, self.os_input.load_palette())),
|
||||
))
|
||||
.unwrap();
|
||||
self.send_screen_instructions
|
||||
.send(ScreenInstruction::ChangeMode(get_mode_info(mode)))
|
||||
.send(ScreenInstruction::ChangeMode(get_mode_info(
|
||||
mode,
|
||||
self.os_input.load_palette(),
|
||||
)))
|
||||
.unwrap();
|
||||
self.send_screen_instructions
|
||||
.send(ScreenInstruction::Render)
|
||||
@ -284,7 +287,7 @@ impl InputHandler {
|
||||
/// 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_mode_info(mode: InputMode) -> ModeInfo {
|
||||
pub fn get_mode_info(mode: InputMode, palette: Palette) -> ModeInfo {
|
||||
let mut keybinds: Vec<(String, String)> = vec![];
|
||||
match mode {
|
||||
InputMode::Normal | InputMode::Locked => {}
|
||||
@ -315,7 +318,11 @@ pub fn get_mode_info(mode: InputMode) -> ModeInfo {
|
||||
keybinds.push(("Enter".to_string(), "when done".to_string()));
|
||||
}
|
||||
}
|
||||
ModeInfo { mode, keybinds }
|
||||
ModeInfo {
|
||||
mode,
|
||||
keybinds,
|
||||
palette,
|
||||
}
|
||||
}
|
||||
|
||||
/// Entry point to the module. Instantiates an [`InputHandler`] and starts
|
||||
|
@ -43,7 +43,7 @@ use utils::consts::ZELLIJ_IPC_PIPE;
|
||||
use wasm_vm::{wasi_read_string, wasi_write_object, zellij_exports, PluginEnv, PluginInstruction};
|
||||
use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
|
||||
use wasmer_wasi::{Pipe, WasiState};
|
||||
use zellij_tile::data::{EventType, ModeInfo};
|
||||
use zellij_tile::data::{EventType, InputMode, ModeInfo};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum ApiCommand {
|
||||
@ -258,7 +258,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
||||
let send_plugin_instructions = send_plugin_instructions.clone();
|
||||
let send_app_instructions = send_app_instructions.clone();
|
||||
let max_panes = opts.max_panes;
|
||||
|
||||
let colors = os_input.load_palette();
|
||||
move || {
|
||||
let mut screen = Screen::new(
|
||||
receive_screen_instructions,
|
||||
@ -268,7 +268,12 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs, config: Config) {
|
||||
&full_screen_ws,
|
||||
os_input,
|
||||
max_panes,
|
||||
ModeInfo::default(),
|
||||
ModeInfo {
|
||||
palette: colors,
|
||||
..ModeInfo::default()
|
||||
},
|
||||
InputMode::Normal,
|
||||
colors,
|
||||
);
|
||||
loop {
|
||||
let (event, mut err_ctx) = screen
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::panes::PositionAndSize;
|
||||
use crate::utils::shared::{colors, detect_theme, hex_to_rgb};
|
||||
use nix::fcntl::{fcntl, FcntlArg, OFlag};
|
||||
use nix::pty::{forkpty, Winsize};
|
||||
use nix::sys::signal::{kill, Signal};
|
||||
@ -12,6 +13,8 @@ use std::os::unix::io::RawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Child, Command};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use xrdb::Colors;
|
||||
use zellij_tile::data::{Palette, PaletteSource, Theme};
|
||||
|
||||
use signal_hook::{consts::signal::*, iterator::Signals};
|
||||
|
||||
@ -191,6 +194,7 @@ pub trait OsApi: Send + Sync {
|
||||
/// Returns a [`Box`] pointer to this [`OsApi`] struct.
|
||||
fn box_clone(&self) -> Box<dyn OsApi>;
|
||||
fn receive_sigwinch(&self, cb: Box<dyn Fn()>);
|
||||
fn load_palette(&self) -> Palette;
|
||||
}
|
||||
|
||||
impl OsApi for OsInputOutput {
|
||||
@ -261,6 +265,48 @@ impl OsApi for OsInputOutput {
|
||||
}
|
||||
}
|
||||
}
|
||||
fn load_palette(&self) -> Palette {
|
||||
let palette = match Colors::new("xresources") {
|
||||
Some(palette) => {
|
||||
let fg = hex_to_rgb(&palette.fg);
|
||||
let bg = hex_to_rgb(&palette.bg);
|
||||
let colors: Vec<(u8, u8, u8)> =
|
||||
palette.colors.iter().map(|c| hex_to_rgb(c)).collect();
|
||||
let theme = detect_theme(bg);
|
||||
Palette {
|
||||
source: PaletteSource::Xresources,
|
||||
theme,
|
||||
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],
|
||||
orange: colors[9],
|
||||
}
|
||||
}
|
||||
None => Palette {
|
||||
source: PaletteSource::Default,
|
||||
theme: Theme::Dark,
|
||||
fg: colors::BRIGHT_GRAY,
|
||||
bg: colors::GRAY,
|
||||
black: colors::BLACK,
|
||||
red: colors::RED,
|
||||
green: colors::GREEN,
|
||||
yellow: colors::GRAY,
|
||||
blue: colors::GRAY,
|
||||
magenta: colors::GRAY,
|
||||
cyan: colors::GRAY,
|
||||
white: colors::WHITE,
|
||||
orange: colors::ORANGE,
|
||||
},
|
||||
};
|
||||
palette
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Box<dyn OsApi> {
|
||||
|
@ -13,7 +13,7 @@ use crate::tab::Tab;
|
||||
use crate::{errors::ErrorContext, wasm_vm::PluginInstruction};
|
||||
use crate::{layout::Layout, panes::PaneId};
|
||||
|
||||
use zellij_tile::data::{Event, ModeInfo, TabInfo};
|
||||
use zellij_tile::data::{Event, InputMode, ModeInfo, Palette, TabInfo};
|
||||
|
||||
/// Instructions that can be sent to the [`Screen`].
|
||||
#[derive(Debug, Clone)]
|
||||
@ -81,6 +81,8 @@ pub struct Screen {
|
||||
/// The [`OsApi`] this [`Screen`] uses.
|
||||
os_api: Box<dyn OsApi>,
|
||||
mode_info: ModeInfo,
|
||||
input_mode: InputMode,
|
||||
colors: Palette,
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
@ -96,6 +98,8 @@ impl Screen {
|
||||
os_api: Box<dyn OsApi>,
|
||||
max_panes: Option<usize>,
|
||||
mode_info: ModeInfo,
|
||||
input_mode: InputMode,
|
||||
colors: Palette,
|
||||
) -> Self {
|
||||
Screen {
|
||||
receiver: receive_screen_instructions,
|
||||
@ -108,6 +112,8 @@ impl Screen {
|
||||
tabs: BTreeMap::new(),
|
||||
os_api,
|
||||
mode_info,
|
||||
input_mode,
|
||||
colors,
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,6 +134,8 @@ impl Screen {
|
||||
self.max_panes,
|
||||
Some(PaneId::Terminal(pane_id)),
|
||||
self.mode_info.clone(),
|
||||
self.input_mode,
|
||||
self.colors,
|
||||
);
|
||||
self.active_tab_index = Some(tab_index);
|
||||
self.tabs.insert(tab_index, tab);
|
||||
@ -283,6 +291,8 @@ impl Screen {
|
||||
self.max_panes,
|
||||
None,
|
||||
self.mode_info.clone(),
|
||||
self.input_mode,
|
||||
self.colors,
|
||||
);
|
||||
tab.apply_layout(layout, new_pids);
|
||||
self.active_tab_index = Some(tab_index);
|
||||
|
@ -4,6 +4,9 @@ use std::{iter, str::from_utf8};
|
||||
|
||||
use strip_ansi_escapes::strip;
|
||||
|
||||
use colors_transform::{Color, Rgb};
|
||||
use zellij_tile::data::Theme;
|
||||
|
||||
fn ansi_len(s: &str) -> usize {
|
||||
from_utf8(&strip(s.as_bytes()).unwrap())
|
||||
.unwrap()
|
||||
@ -28,3 +31,36 @@ pub fn adjust_to_size(s: &str, rows: usize, columns: usize) -> String {
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n\r")
|
||||
}
|
||||
|
||||
// Colors
|
||||
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 ORANGE: (u8, u8, u8) = (215, 95, 0);
|
||||
pub const BLACK: (u8, u8, u8) = (0, 0, 0);
|
||||
}
|
||||
|
||||
pub fn hex_to_rgb(hex: &Option<String>) -> (u8, u8, u8) {
|
||||
let c = hex.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)
|
||||
}
|
||||
|
||||
// Dark magic
|
||||
pub fn detect_theme(bg: (u8, u8, u8)) -> Theme {
|
||||
let (r, g, b) = bg;
|
||||
// HSP, P stands for perceived brightness
|
||||
let hsp: f64 = (0.299 * (r as f64 * r as f64)
|
||||
+ 0.587 * (g as f64 * g as f64)
|
||||
+ 0.114 * (b as f64 * b as f64))
|
||||
.sqrt();
|
||||
match hsp > 127.5 {
|
||||
true => Theme::Light,
|
||||
false => Theme::Dark,
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ use std::time::{Duration, Instant};
|
||||
|
||||
use crate::os_input_output::OsApi;
|
||||
use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes};
|
||||
use crate::utils::shared::colors;
|
||||
use zellij_tile::data::{Palette, PaletteSource, Theme};
|
||||
|
||||
use crate::tests::utils::commands::{QUIT, SLEEP};
|
||||
|
||||
@ -73,6 +75,7 @@ pub struct FakeInputOutput {
|
||||
last_snapshot_time: Arc<Mutex<Instant>>,
|
||||
should_trigger_sigwinch: Arc<(Mutex<bool>, Condvar)>,
|
||||
sigwinch_event: Option<PositionAndSize>,
|
||||
palette: Arc<Mutex<Palette>>,
|
||||
}
|
||||
|
||||
impl FakeInputOutput {
|
||||
@ -81,6 +84,21 @@ impl FakeInputOutput {
|
||||
let last_snapshot_time = Arc::new(Mutex::new(Instant::now()));
|
||||
let stdout_writer = FakeStdoutWriter::new(last_snapshot_time.clone());
|
||||
win_sizes.insert(0, winsize); // 0 is the current terminal
|
||||
let palette: Palette = Palette {
|
||||
source: PaletteSource::Default,
|
||||
theme: Theme::Dark,
|
||||
fg: colors::BRIGHT_GRAY,
|
||||
bg: colors::GRAY,
|
||||
black: colors::BLACK,
|
||||
red: colors::RED,
|
||||
green: colors::GREEN,
|
||||
yellow: colors::GRAY,
|
||||
blue: colors::GRAY,
|
||||
magenta: colors::GRAY,
|
||||
cyan: colors::GRAY,
|
||||
white: colors::WHITE,
|
||||
orange: colors::ORANGE,
|
||||
};
|
||||
FakeInputOutput {
|
||||
read_buffers: Arc::new(Mutex::new(HashMap::new())),
|
||||
stdin_writes: Arc::new(Mutex::new(HashMap::new())),
|
||||
@ -93,6 +111,7 @@ impl FakeInputOutput {
|
||||
possible_tty_inputs: get_possible_tty_inputs(),
|
||||
should_trigger_sigwinch: Arc::new((Mutex::new(false), Condvar::new())),
|
||||
sigwinch_event: None,
|
||||
palette: Arc::new(Mutex::new(palette)),
|
||||
}
|
||||
}
|
||||
pub fn with_tty_inputs(mut self, tty_inputs: HashMap<u16, Bytes>) -> Self {
|
||||
@ -235,4 +254,22 @@ impl OsApi for FakeInputOutput {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
fn load_palette(&self) -> Palette {
|
||||
let palette: Palette = Palette {
|
||||
source: PaletteSource::Default,
|
||||
theme: Theme::Dark,
|
||||
fg: colors::BRIGHT_GRAY,
|
||||
bg: colors::GRAY,
|
||||
black: colors::BLACK,
|
||||
red: colors::RED,
|
||||
green: colors::GREEN,
|
||||
yellow: colors::GRAY,
|
||||
blue: colors::GRAY,
|
||||
magenta: colors::GRAY,
|
||||
cyan: colors::GRAY,
|
||||
white: colors::WHITE,
|
||||
orange: colors::ORANGE,
|
||||
};
|
||||
palette
|
||||
}
|
||||
}
|
||||
|
12
zellij-tile-extra/Cargo.toml
Normal file
12
zellij-tile-extra/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "zellij-tile-extra"
|
||||
version = "1.0.0"
|
||||
authors = ["denis <denismaximov98@gmail.com>"]
|
||||
edition = "2018"
|
||||
description = "A utility library for Zellij plugins"
|
||||
license = "MIT"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.12.1"
|
1
zellij-tile-extra/LICENSE.md
Symbolic link
1
zellij-tile-extra/LICENSE.md
Symbolic link
@ -0,0 +1 @@
|
||||
../LICENSE.md
|
15
zellij-tile-extra/src/lib.rs
Normal file
15
zellij-tile-extra/src/lib.rs
Normal file
@ -0,0 +1,15 @@
|
||||
#[macro_export]
|
||||
macro_rules! rgb {
|
||||
($a:expr) => {
|
||||
ansi_term::Color::RGB($a.0, $a.1, $a.2)
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! style {
|
||||
($a:expr, $b:expr) => {
|
||||
ansi_term::Style::new()
|
||||
.fg(ansi_term::Color::RGB($a.0, $a.1, $a.2))
|
||||
.on(ansi_term::Color::RGB($b.0, $b.1, $b.2))
|
||||
};
|
||||
}
|
@ -67,6 +67,44 @@ impl Default for InputMode {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
pub enum Theme {
|
||||
Light,
|
||||
Dark,
|
||||
}
|
||||
impl Default for Theme {
|
||||
fn default() -> Theme {
|
||||
Theme::Dark
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
pub enum PaletteSource {
|
||||
Default,
|
||||
Xresources,
|
||||
}
|
||||
impl Default for PaletteSource {
|
||||
fn default() -> PaletteSource {
|
||||
PaletteSource::Default
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
|
||||
pub struct Palette {
|
||||
pub source: PaletteSource,
|
||||
pub theme: Theme,
|
||||
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),
|
||||
pub orange: (u8, u8, u8),
|
||||
}
|
||||
|
||||
/// Represents the contents of the help message that is printed in the status bar,
|
||||
/// which indicates the current [`InputMode`] and what the keybinds for that mode
|
||||
/// are. Related to the default `status-bar` plugin.
|
||||
@ -75,6 +113,7 @@ pub struct ModeInfo {
|
||||
pub mode: InputMode,
|
||||
// FIXME: This should probably return Keys and Actions, then sort out strings plugin-side
|
||||
pub keybinds: Vec<(String, String)>, // <shortcut> => <shortcut description>
|
||||
pub palette: Palette,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||
|
Loading…
Reference in New Issue
Block a user