feat(status-bar): add multiple tips (#848)
* feat(status-bar): add draft for multiple tips * feat: add TIPS_MAP * Simplified 'tip' function. * chore: update file structure * feat(status-bar): update method of Tip rendering * feat(status-bar): change type of tip in State * refactor(status-bar): related to random tip selection * feat(status-bar): add simple local cache for testing * feat(status-bar): add cache system for tip data * Add mpadir to wasm for plugin to access zellij temp folder. * refactor(status-bar): update cache and utils * fix(status-bar): update file read error * refactor(status-bar): update macros * chore(status-bar): delete test data * chore(status-bar): update missing fixes * feat(status-bar): add detailed error * style: make clippy
This commit is contained in:
parent
2096cafe1d
commit
d79060f69a
11 changed files with 353 additions and 203 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
|
@ -2082,6 +2082,11 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"colored",
|
||||
"lazy_static",
|
||||
"rand 0.8.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"zellij-tile",
|
||||
"zellij-tile-utils",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -8,5 +8,10 @@ license = "MIT"
|
|||
[dependencies]
|
||||
colored = "2"
|
||||
ansi_term = "0.12"
|
||||
lazy_static = "1.4.0"
|
||||
rand = "0.8.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0.30"
|
||||
zellij-tile = { path = "../../zellij-tile" }
|
||||
zellij-tile-utils = { path = "../../zellij-tile-utils" }
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
mod first_line;
|
||||
mod second_line;
|
||||
mod tip;
|
||||
|
||||
use ansi_term::Style;
|
||||
|
||||
|
|
@ -11,6 +12,7 @@ use first_line::{ctrl_keys, superkey};
|
|||
use second_line::{
|
||||
fullscreen_panes_to_hide, keybinds, locked_fullscreen_panes_to_hide, text_copied_hint,
|
||||
};
|
||||
use tip::utils::get_cached_tip_name;
|
||||
|
||||
// for more of these, copy paste from: https://en.wikipedia.org/wiki/Box-drawing_character
|
||||
static ARROW_SEPARATOR: &str = "";
|
||||
|
|
@ -19,6 +21,7 @@ static MORE_MSG: &str = " ... ";
|
|||
#[derive(Default)]
|
||||
struct State {
|
||||
tabs: Vec<TabInfo>,
|
||||
tip_name: String,
|
||||
mode_info: ModeInfo,
|
||||
diplay_text_copied_hint: bool,
|
||||
}
|
||||
|
|
@ -131,6 +134,8 @@ fn color_elements(palette: Palette) -> ColoredElements {
|
|||
|
||||
impl ZellijPlugin for State {
|
||||
fn load(&mut self) {
|
||||
// TODO: Should be able to choose whether to use the cache through config.
|
||||
self.tip_name = get_cached_tip_name();
|
||||
set_selectable(false);
|
||||
subscribe(&[
|
||||
EventType::ModeUpdate,
|
||||
|
|
@ -190,7 +195,7 @@ impl ZellijPlugin for State {
|
|||
second_line = if self.diplay_text_copied_hint {
|
||||
text_copied_hint(&self.mode_info.palette)
|
||||
} else {
|
||||
keybinds(&self.mode_info, cols)
|
||||
keybinds(&self.mode_info, &self.tip_name, cols)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -208,7 +213,7 @@ impl ZellijPlugin for State {
|
|||
second_line = if self.diplay_text_copied_hint {
|
||||
text_copied_hint(&self.mode_info.palette)
|
||||
} else {
|
||||
keybinds(&self.mode_info, cols)
|
||||
keybinds(&self.mode_info, &self.tip_name, cols)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -216,7 +221,7 @@ impl ZellijPlugin for State {
|
|||
second_line = if self.diplay_text_copied_hint {
|
||||
text_copied_hint(&self.mode_info.palette)
|
||||
} else {
|
||||
keybinds(&self.mode_info, cols)
|
||||
keybinds(&self.mode_info, &self.tip_name, cols)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ use ansi_term::{
|
|||
};
|
||||
use zellij_tile::prelude::*;
|
||||
|
||||
use crate::{LinePart, MORE_MSG};
|
||||
use crate::{
|
||||
tip::{data::TIPS, TipFn},
|
||||
LinePart, MORE_MSG,
|
||||
};
|
||||
|
||||
fn full_length_shortcut(
|
||||
is_first_shortcut: bool,
|
||||
|
|
@ -82,194 +85,6 @@ fn first_word_shortcut(
|
|||
len,
|
||||
}
|
||||
}
|
||||
fn quicknav_full(palette: Palette) -> 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 third_alt = "Alt";
|
||||
let text_seventh_parth = " + ";
|
||||
let increase_decrease_parth = "<+->";
|
||||
let text_eighth_parth = " => increase/decrease pane size.";
|
||||
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()
|
||||
+ third_alt.chars().count()
|
||||
+ text_seventh_parth.chars().count()
|
||||
+ increase_decrease_parth.chars().count()
|
||||
+ text_eighth_parth.chars().count();
|
||||
let green_color = match palette.green {
|
||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||
PaletteColor::EightBit(color) => Fixed(color),
|
||||
};
|
||||
let orange_color = match palette.orange {
|
||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||
PaletteColor::EightBit(color) => Fixed(color),
|
||||
};
|
||||
LinePart {
|
||||
part: format!(
|
||||
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
text_first_part,
|
||||
Style::new().fg(orange_color).bold().paint(alt),
|
||||
text_second_part,
|
||||
Style::new().fg(green_color).bold().paint(new_pane_shortcut),
|
||||
text_third_part,
|
||||
Style::new().fg(orange_color).bold().paint(second_alt),
|
||||
text_fourth_part,
|
||||
Style::new()
|
||||
.fg(green_color)
|
||||
.bold()
|
||||
.paint(brackets_navigation),
|
||||
text_fifth_part,
|
||||
Style::new().fg(green_color).bold().paint(hjkl_navigation),
|
||||
text_sixths_part,
|
||||
Style::new().fg(orange_color).bold().paint(third_alt),
|
||||
text_seventh_parth,
|
||||
Style::new()
|
||||
.fg(green_color)
|
||||
.bold()
|
||||
.paint(increase_decrease_parth),
|
||||
text_eighth_parth,
|
||||
),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn quicknav_medium(palette: Palette) -> 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 third_alt = "Alt";
|
||||
let text_seventh_parth = " + ";
|
||||
let increase_decrease_parth = "<+->";
|
||||
let text_eighth_parth = " => resize pane. ";
|
||||
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()
|
||||
+ third_alt.chars().count()
|
||||
+ text_seventh_parth.chars().count()
|
||||
+ increase_decrease_parth.chars().count()
|
||||
+ text_eighth_parth.chars().count();
|
||||
let green_color = match palette.green {
|
||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||
PaletteColor::EightBit(color) => Fixed(color),
|
||||
};
|
||||
let orange_color = match palette.orange {
|
||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||
PaletteColor::EightBit(color) => Fixed(color),
|
||||
};
|
||||
LinePart {
|
||||
part: format!(
|
||||
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||
text_first_part,
|
||||
Style::new().fg(orange_color).bold().paint(alt),
|
||||
text_second_part,
|
||||
Style::new().fg(green_color).bold().paint(new_pane_shortcut),
|
||||
text_third_part,
|
||||
Style::new().fg(orange_color).bold().paint(second_alt),
|
||||
text_fourth_part,
|
||||
Style::new()
|
||||
.fg(green_color)
|
||||
.bold()
|
||||
.paint(brackets_navigation),
|
||||
text_fifth_part,
|
||||
Style::new().fg(green_color).bold().paint(hjkl_navigation),
|
||||
text_sixths_part,
|
||||
Style::new().fg(orange_color).bold().paint(third_alt),
|
||||
text_seventh_parth,
|
||||
Style::new()
|
||||
.fg(green_color)
|
||||
.bold()
|
||||
.paint(increase_decrease_parth),
|
||||
text_eighth_parth,
|
||||
),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn quicknav_short(palette: Palette) -> 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 text_sixth_part = "/";
|
||||
let increase_decrease_part = "+-";
|
||||
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()
|
||||
+ text_sixth_part.chars().count()
|
||||
+ increase_decrease_part.chars().count();
|
||||
let green_color = match palette.green {
|
||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||
PaletteColor::EightBit(color) => Fixed(color),
|
||||
};
|
||||
let orange_color = match palette.orange {
|
||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||
PaletteColor::EightBit(color) => Fixed(color),
|
||||
};
|
||||
LinePart {
|
||||
part: format!(
|
||||
"{}{}{}{}{}{}{}{}{}{}",
|
||||
text_first_part,
|
||||
Style::new().fg(orange_color).bold().paint(alt),
|
||||
text_second_part,
|
||||
Style::new().fg(green_color).bold().paint(new_pane_shortcut),
|
||||
text_third_part,
|
||||
Style::new()
|
||||
.fg(green_color)
|
||||
.bold()
|
||||
.paint(brackets_navigation),
|
||||
text_fifth_part,
|
||||
Style::new().fg(green_color).bold().paint(hjkl_navigation),
|
||||
text_sixth_part,
|
||||
Style::new()
|
||||
.fg(green_color)
|
||||
.bold()
|
||||
.paint(increase_decrease_part),
|
||||
),
|
||||
len,
|
||||
}
|
||||
}
|
||||
|
||||
fn locked_interface_indication(palette: Palette) -> LinePart {
|
||||
let locked_text = " -- INTERFACE LOCKED -- ";
|
||||
|
|
@ -318,9 +133,9 @@ fn select_pane_shortcut(is_first_shortcut: bool, palette: Palette) -> LinePart {
|
|||
}
|
||||
}
|
||||
|
||||
fn full_shortcut_list(help: &ModeInfo) -> LinePart {
|
||||
fn full_shortcut_list(help: &ModeInfo, tip: TipFn) -> LinePart {
|
||||
match help.mode {
|
||||
InputMode::Normal => quicknav_full(help.palette),
|
||||
InputMode::Normal => tip(help.palette),
|
||||
InputMode::Locked => locked_interface_indication(help.palette),
|
||||
_ => {
|
||||
let mut line_part = LinePart::default();
|
||||
|
|
@ -337,9 +152,9 @@ fn full_shortcut_list(help: &ModeInfo) -> LinePart {
|
|||
}
|
||||
}
|
||||
|
||||
fn shortened_shortcut_list(help: &ModeInfo) -> LinePart {
|
||||
fn shortened_shortcut_list(help: &ModeInfo, tip: TipFn) -> LinePart {
|
||||
match help.mode {
|
||||
InputMode::Normal => quicknav_medium(help.palette),
|
||||
InputMode::Normal => tip(help.palette),
|
||||
InputMode::Locked => locked_interface_indication(help.palette),
|
||||
_ => {
|
||||
let mut line_part = LinePart::default();
|
||||
|
|
@ -356,10 +171,10 @@ fn shortened_shortcut_list(help: &ModeInfo) -> LinePart {
|
|||
}
|
||||
}
|
||||
|
||||
fn best_effort_shortcut_list(help: &ModeInfo, max_len: usize) -> LinePart {
|
||||
fn best_effort_shortcut_list(help: &ModeInfo, tip: TipFn, max_len: usize) -> LinePart {
|
||||
match help.mode {
|
||||
InputMode::Normal => {
|
||||
let line_part = quicknav_short(help.palette);
|
||||
let line_part = tip(help.palette);
|
||||
if line_part.len <= max_len {
|
||||
line_part
|
||||
} else {
|
||||
|
|
@ -397,16 +212,19 @@ fn best_effort_shortcut_list(help: &ModeInfo, max_len: usize) -> LinePart {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn keybinds(help: &ModeInfo, max_width: usize) -> LinePart {
|
||||
let full_shortcut_list = full_shortcut_list(help);
|
||||
pub fn keybinds(help: &ModeInfo, tip_name: &str, max_width: usize) -> LinePart {
|
||||
// It is assumed that there is at least one TIP data in the TIPS HasMap.
|
||||
let tip_body = TIPS.get(tip_name).unwrap();
|
||||
|
||||
let full_shortcut_list = full_shortcut_list(help, tip_body.full);
|
||||
if full_shortcut_list.len <= max_width {
|
||||
return full_shortcut_list;
|
||||
}
|
||||
let shortened_shortcut_list = shortened_shortcut_list(help);
|
||||
let shortened_shortcut_list = shortened_shortcut_list(help, tip_body.medium);
|
||||
if shortened_shortcut_list.len <= max_width {
|
||||
return shortened_shortcut_list;
|
||||
}
|
||||
best_effort_shortcut_list(help, max_width)
|
||||
best_effort_shortcut_list(help, tip_body.short, max_width)
|
||||
}
|
||||
|
||||
pub fn text_copied_hint(palette: &Palette) -> LinePart {
|
||||
|
|
|
|||
119
default-plugins/status-bar/src/tip/cache.rs
Normal file
119
default-plugins/status-bar/src/tip/cache.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
use zellij_tile::prelude::get_zellij_version;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Metadata {
|
||||
zellij_version: String,
|
||||
cached_data: HashMap<String, usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LocalCache {
|
||||
path: PathBuf,
|
||||
metadata: Metadata,
|
||||
}
|
||||
|
||||
pub type LocalCacheResult = Result<LocalCache, LocalCacheError>;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum LocalCacheError {
|
||||
// Io error
|
||||
#[error("IoError: {0}")]
|
||||
Io(#[from] io::Error),
|
||||
// Io error with path context
|
||||
#[error("IoError: {0}, File: {1}")]
|
||||
IoPath(io::Error, PathBuf),
|
||||
// Deserialization error
|
||||
#[error("Deserialization error: {0}")]
|
||||
Serde(#[from] serde_json::Error),
|
||||
}
|
||||
|
||||
impl LocalCache {
|
||||
fn from_json(json_cache: &str) -> Result<Metadata, LocalCacheError> {
|
||||
match serde_json::from_str::<Metadata>(json_cache) {
|
||||
Ok(metadata) => Ok(metadata),
|
||||
Err(err) => {
|
||||
if json_cache.is_empty() {
|
||||
return Ok(Metadata {
|
||||
zellij_version: get_zellij_version(),
|
||||
cached_data: HashMap::new(),
|
||||
});
|
||||
}
|
||||
Err(LocalCacheError::Serde(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(path: PathBuf) -> LocalCacheResult {
|
||||
match OpenOptions::new()
|
||||
.read(true)
|
||||
.create(true)
|
||||
.open(path.as_path())
|
||||
{
|
||||
Ok(mut file) => {
|
||||
let mut json_cache = String::new();
|
||||
file.read_to_string(&mut json_cache)
|
||||
.map_err(LocalCacheError::Io)?;
|
||||
|
||||
let metadata = LocalCache::from_json(&json_cache)?;
|
||||
Ok(LocalCache { path, metadata })
|
||||
}
|
||||
Err(e) => Err(LocalCacheError::IoPath(e, path)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flush(&mut self) -> Result<(), LocalCacheError> {
|
||||
match serde_json::to_string(&self.metadata) {
|
||||
Ok(json_cache) => {
|
||||
let mut file = File::create(self.path.as_path())
|
||||
.map_err(|e| LocalCacheError::IoPath(e, self.path.clone()))?;
|
||||
file.write_all(json_cache.as_bytes())
|
||||
.map_err(LocalCacheError::Io)?;
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(LocalCacheError::Serde(e)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) -> Result<(), LocalCacheError> {
|
||||
self.metadata.cached_data.clear();
|
||||
self.flush()
|
||||
}
|
||||
|
||||
pub fn get_version(&self) -> &String {
|
||||
&self.metadata.zellij_version
|
||||
}
|
||||
|
||||
pub fn set_version<S: Into<String>>(&mut self, version: S) {
|
||||
self.metadata.zellij_version = version.into();
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.metadata.cached_data.is_empty()
|
||||
}
|
||||
|
||||
pub fn get_cached_data(&self) -> &HashMap<String, usize> {
|
||||
&self.metadata.cached_data
|
||||
}
|
||||
|
||||
pub fn get_cached_data_set(&self) -> HashSet<String> {
|
||||
self.get_cached_data().keys().cloned().collect()
|
||||
}
|
||||
|
||||
pub fn caching<S: Into<String>>(&mut self, key: S) -> Result<(), LocalCacheError> {
|
||||
let key = key.into();
|
||||
if let Some(item) = self.metadata.cached_data.get_mut(&key) {
|
||||
*item += 1;
|
||||
} else {
|
||||
self.metadata.cached_data.insert(key, 1);
|
||||
}
|
||||
self.flush()
|
||||
}
|
||||
}
|
||||
2
default-plugins/status-bar/src/tip/consts.rs
Normal file
2
default-plugins/status-bar/src/tip/consts.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub const DEFAULT_CACHE_FILE_PATH: &str = "/tmp/status-bar-tips.cache";
|
||||
pub const MAX_CACHE_HITS: usize = 10;
|
||||
100
default-plugins/status-bar/src/tip/data.rs
Normal file
100
default-plugins/status-bar/src/tip/data.rs
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use ansi_term::{
|
||||
unstyled_len, ANSIString, ANSIStrings,
|
||||
Color::{Fixed, RGB},
|
||||
Style,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::{tip::TipBody, LinePart};
|
||||
use zellij_tile::prelude::*;
|
||||
use zellij_tile_utils::palette_match;
|
||||
|
||||
macro_rules! strings {
|
||||
($ANSIStrings:expr) => {{
|
||||
let strings: &[ANSIString<'static>] = $ANSIStrings;
|
||||
|
||||
let ansi_strings = ANSIStrings(strings);
|
||||
|
||||
LinePart {
|
||||
part: format!("{}", ansi_strings),
|
||||
len: unstyled_len(&ansi_strings),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TIPS: HashMap<&'static str, TipBody> = HashMap::from([(
|
||||
"quicknav",
|
||||
TipBody {
|
||||
short: quicknav_short,
|
||||
medium: quicknav_medium,
|
||||
full: quicknav_full,
|
||||
}
|
||||
)]);
|
||||
}
|
||||
|
||||
fn quicknav_full(palette: Palette) -> LinePart {
|
||||
let green_color = palette_match!(palette.green);
|
||||
let orange_color = palette_match!(palette.orange);
|
||||
|
||||
strings!(&[
|
||||
Style::new().paint(" Tip: "),
|
||||
Style::new().fg(orange_color).bold().paint("Alt"),
|
||||
Style::new().paint(" + "),
|
||||
Style::new().fg(green_color).bold().paint("<n>"),
|
||||
Style::new().paint(" => open new pane. "),
|
||||
Style::new().fg(orange_color).bold().paint("Alt"),
|
||||
Style::new().paint(" + "),
|
||||
Style::new().fg(green_color).bold().paint("<[]"),
|
||||
Style::new().paint(" or "),
|
||||
Style::new().fg(green_color).bold().paint("hjkl>"),
|
||||
Style::new().paint(" => navigate between panes. "),
|
||||
Style::new().fg(orange_color).bold().paint("Alt"),
|
||||
Style::new().paint(" + "),
|
||||
Style::new().fg(green_color).bold().paint("<+->"),
|
||||
Style::new().paint(" => increase/decrease pane size."),
|
||||
])
|
||||
}
|
||||
|
||||
fn quicknav_medium(palette: Palette) -> LinePart {
|
||||
let green_color = palette_match!(palette.green);
|
||||
let orange_color = palette_match!(palette.orange);
|
||||
|
||||
strings!(&[
|
||||
Style::new().paint(" Tip: "),
|
||||
Style::new().fg(orange_color).bold().paint("Alt"),
|
||||
Style::new().paint(" + "),
|
||||
Style::new().fg(green_color).bold().paint("<n>"),
|
||||
Style::new().paint(" => new pane. "),
|
||||
Style::new().fg(orange_color).bold().paint("Alt"),
|
||||
Style::new().paint(" + "),
|
||||
Style::new().fg(green_color).bold().paint("<[]"),
|
||||
Style::new().paint(" or "),
|
||||
Style::new().fg(green_color).bold().paint("hjkl>"),
|
||||
Style::new().paint(" => navigate. "),
|
||||
Style::new().fg(orange_color).bold().paint("Alt"),
|
||||
Style::new().paint(" + "),
|
||||
Style::new().fg(green_color).bold().paint("<+->"),
|
||||
Style::new().paint(" => resize pane."),
|
||||
])
|
||||
}
|
||||
|
||||
fn quicknav_short(palette: Palette) -> LinePart {
|
||||
let green_color = palette_match!(palette.green);
|
||||
let orange_color = palette_match!(palette.orange);
|
||||
|
||||
strings!(&[
|
||||
Style::new().paint(" QuickNav: "),
|
||||
Style::new().fg(orange_color).bold().paint("Alt"),
|
||||
Style::new().paint(" + "),
|
||||
Style::new().fg(green_color).bold().paint("n"),
|
||||
Style::new().paint("/"),
|
||||
Style::new().fg(green_color).bold().paint("[]"),
|
||||
Style::new().paint("/"),
|
||||
Style::new().fg(green_color).bold().paint("hjkl"),
|
||||
Style::new().paint("/"),
|
||||
Style::new().fg(green_color).bold().paint("+-"),
|
||||
])
|
||||
}
|
||||
16
default-plugins/status-bar/src/tip/mod.rs
Normal file
16
default-plugins/status-bar/src/tip/mod.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
pub mod cache;
|
||||
pub mod consts;
|
||||
pub mod data;
|
||||
pub mod utils;
|
||||
|
||||
use crate::LinePart;
|
||||
use zellij_tile::prelude::*;
|
||||
|
||||
pub type TipFn = fn(Palette) -> LinePart;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TipBody {
|
||||
pub short: TipFn,
|
||||
pub medium: TipFn,
|
||||
pub full: TipFn,
|
||||
}
|
||||
68
default-plugins/status-bar/src/tip/utils.rs
Normal file
68
default-plugins/status-bar/src/tip/utils.rs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use rand::prelude::{IteratorRandom, SliceRandom};
|
||||
|
||||
use zellij_tile::prelude::get_zellij_version;
|
||||
|
||||
use super::cache::LocalCache;
|
||||
use super::consts::{DEFAULT_CACHE_FILE_PATH, MAX_CACHE_HITS};
|
||||
use super::data::TIPS;
|
||||
|
||||
macro_rules! get_name_and_caching {
|
||||
($cache:expr) => {{
|
||||
let name = get_random_tip_name();
|
||||
$cache.caching(name.clone()).unwrap();
|
||||
return name;
|
||||
}};
|
||||
($cache:expr, $from:expr) => {{
|
||||
let name = $from.choose(&mut rand::thread_rng()).unwrap().to_string();
|
||||
$cache.caching(name.clone()).unwrap();
|
||||
return name;
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn get_random_tip_name() -> String {
|
||||
TIPS.keys()
|
||||
.choose(&mut rand::thread_rng())
|
||||
.unwrap()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn get_cached_tip_name() -> String {
|
||||
let mut local_cache = LocalCache::new(PathBuf::from(DEFAULT_CACHE_FILE_PATH)).unwrap();
|
||||
|
||||
let zellij_version = get_zellij_version();
|
||||
if zellij_version.ne(local_cache.get_version()) {
|
||||
local_cache.set_version(zellij_version);
|
||||
local_cache.clear().unwrap();
|
||||
}
|
||||
|
||||
if local_cache.is_empty() {
|
||||
get_name_and_caching!(local_cache);
|
||||
}
|
||||
|
||||
let usable_tips = local_cache
|
||||
.get_cached_data()
|
||||
.iter()
|
||||
.filter(|(_, &v)| v < MAX_CACHE_HITS)
|
||||
.map(|(k, _)| k.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
if usable_tips.is_empty() {
|
||||
let cached_set = local_cache.get_cached_data_set();
|
||||
let diff = TIPS
|
||||
.keys()
|
||||
.cloned()
|
||||
.filter(|k| !cached_set.contains(&k.to_string()))
|
||||
.collect::<Vec<&str>>();
|
||||
|
||||
if !diff.is_empty() {
|
||||
get_name_and_caching!(local_cache, diff);
|
||||
} else {
|
||||
local_cache.clear().unwrap();
|
||||
get_name_and_caching!(local_cache);
|
||||
}
|
||||
} else {
|
||||
get_name_and_caching!(local_cache, usable_tips);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ use crate::{
|
|||
};
|
||||
|
||||
use zellij_utils::{
|
||||
consts::{VERSION, ZELLIJ_PROJ_DIR},
|
||||
consts::{VERSION, ZELLIJ_PROJ_DIR, ZELLIJ_TMP_DIR},
|
||||
errors::{ContextType, PluginContext},
|
||||
};
|
||||
use zellij_utils::{
|
||||
|
|
@ -272,6 +272,8 @@ fn start_plugin(
|
|||
.unwrap()
|
||||
.map_dir("/data", &plugin_own_data_dir)
|
||||
.unwrap()
|
||||
.map_dir("/tmp", ZELLIJ_TMP_DIR.as_path())
|
||||
.unwrap()
|
||||
.stdin(Box::new(input))
|
||||
.stdout(Box::new(output))
|
||||
.stderr(Box::new(stderr))
|
||||
|
|
|
|||
|
|
@ -5,6 +5,16 @@ macro_rules! rgb {
|
|||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! palette_match {
|
||||
($palette_color:expr) => {
|
||||
match $palette_color {
|
||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||
PaletteColor::EightBit(color) => Fixed(color),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! style {
|
||||
($fg:expr, $bg:expr) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue