* Implement initial structs from spec * kdl configuration unmarshalling * typo text styling * remove is_selected toggle * incorporate new status bar ui into theming * improve test coverage of config behavior * tab bar correction * correct also compact bar * remove spacing between table columns * refactor table styling * use text_unselected.emphasis_1 for keygroup sep * fix tab bar more text * repair field flattening for theme * remove extra styling KDL node * update tests * updated selected text conversion * padding for header bar * minor corrections for existing themes * background handling * compact bar corrections * properly handle opaque method to activate background * update newer plugins to use styling struct * correct omission of selected state * fix: bold typeface for text elements * fix: fg -> white for list_unselected conversion * fix: emphasis and opacity handling for nested_list * correct stylings in the session-manager * fix emphases translation for table component * correct emphasis for run instructions * correct frame_highlight translation for old themes * provide missing implementation of frame_highlight * fencepost emphasis color names * Set a pseudo-None for frame_unselected in old theme conversion * correct alternating bg for simplified-ui * update snapshots * fix inner text padding and errorneous snapshots * suppress warning about deprecated usage of palette * remove unused import * feat(plugins): API to change floating pane coordinates (#3958) * basic functionality through the cli * added to plugin api * add display area and viewport size to TabInfo * fix tests and add new one * some cleanups * refactor: extract pane_id parsing logic * style(fmt): rustfmt * docs(changelog): floating pane coordinate chagne API * fix(tiled-panes): opening panes from the cli (#3963) * feat(plugins): add `PastedText` Event (#3962) * working with text paste * handle utf8 conversion error * feat(plugins): add PastedText Event * docs(changelog): plugins pasted text event * black for table opaque background * properly apply opacity to table * correct padding for explicit width ribbons * feat(plugins): Allow opening panes near plugin (#3966) * added command + terminal variants * added editor variant * style(fmt): rustfmt * docs(changelog): plugin apis to open panes near plugin * feat(plugins): send info about $EDITOR and $SHELL (#3971) * feat(plugins): send info about $EDITOR and $SHELL * fix(e2e): snapshot update * docs(changelog): plugin editor and shell info * fix(floating-panes): when changing coordinates, if a pane is not floating - make it floating (#3972) * fix(panes): when changing floating pane coordinates, if the pane is not floating, float it * style(fmt): rustfmt * docs(changelog): floating pane coordinate fix * fix(break-pane): strip logical position when inserting pane to new tab (#3973) * docs(changelog): logical position fix * Optional frame_unselected theme * fixture with correct width to account for arrow padding * update snapshot and rustfmt --------- Co-authored-by: Aram Drevekenin <aram@poor.dev>
158 lines
4.8 KiB
Rust
158 lines
4.8 KiB
Rust
mod line;
|
|
mod tab;
|
|
|
|
use std::cmp::{max, min};
|
|
use std::collections::BTreeMap;
|
|
use std::convert::TryInto;
|
|
|
|
use tab::get_tab_to_focus;
|
|
use zellij_tile::prelude::*;
|
|
|
|
use crate::line::tab_line;
|
|
use crate::tab::tab_style;
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct LinePart {
|
|
part: String,
|
|
len: usize,
|
|
tab_index: Option<usize>,
|
|
}
|
|
|
|
impl LinePart {
|
|
pub fn append(&mut self, to_append: &LinePart) {
|
|
self.part.push_str(&to_append.part);
|
|
self.len += to_append.len;
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct State {
|
|
tabs: Vec<TabInfo>,
|
|
active_tab_idx: usize,
|
|
mode_info: ModeInfo,
|
|
tab_line: Vec<LinePart>,
|
|
hide_swap_layout_indication: bool,
|
|
}
|
|
|
|
static ARROW_SEPARATOR: &str = "";
|
|
|
|
register_plugin!(State);
|
|
|
|
impl ZellijPlugin for State {
|
|
fn load(&mut self, configuration: BTreeMap<String, String>) {
|
|
self.hide_swap_layout_indication = configuration
|
|
.get("hide_swap_layout_indication")
|
|
.map(|s| s == "true")
|
|
.unwrap_or(false);
|
|
set_selectable(false);
|
|
subscribe(&[
|
|
EventType::TabUpdate,
|
|
EventType::ModeUpdate,
|
|
EventType::Mouse,
|
|
]);
|
|
}
|
|
|
|
fn update(&mut self, event: Event) -> bool {
|
|
let mut should_render = false;
|
|
match event {
|
|
Event::ModeUpdate(mode_info) => {
|
|
if self.mode_info != mode_info {
|
|
should_render = true;
|
|
}
|
|
self.mode_info = mode_info;
|
|
},
|
|
Event::TabUpdate(tabs) => {
|
|
if let Some(active_tab_index) = tabs.iter().position(|t| t.active) {
|
|
// tabs are indexed starting from 1 so we need to add 1
|
|
let active_tab_idx = active_tab_index + 1;
|
|
|
|
if self.active_tab_idx != active_tab_idx || self.tabs != tabs {
|
|
should_render = true;
|
|
}
|
|
self.active_tab_idx = active_tab_idx;
|
|
self.tabs = tabs;
|
|
} else {
|
|
eprintln!("Could not find active tab.");
|
|
}
|
|
},
|
|
Event::Mouse(me) => match me {
|
|
Mouse::LeftClick(_, col) => {
|
|
let tab_to_focus = get_tab_to_focus(&self.tab_line, self.active_tab_idx, col);
|
|
if let Some(idx) = tab_to_focus {
|
|
switch_tab_to(idx.try_into().unwrap());
|
|
}
|
|
},
|
|
Mouse::ScrollUp(_) => {
|
|
switch_tab_to(min(self.active_tab_idx + 1, self.tabs.len()) as u32);
|
|
},
|
|
Mouse::ScrollDown(_) => {
|
|
switch_tab_to(max(self.active_tab_idx.saturating_sub(1), 1) as u32);
|
|
},
|
|
_ => {},
|
|
},
|
|
_ => {
|
|
eprintln!("Got unrecognized event: {:?}", event);
|
|
},
|
|
}
|
|
should_render
|
|
}
|
|
|
|
fn render(&mut self, _rows: usize, cols: usize) {
|
|
if self.tabs.is_empty() {
|
|
return;
|
|
}
|
|
let mut all_tabs: Vec<LinePart> = vec![];
|
|
let mut active_tab_index = 0;
|
|
let mut is_alternate_tab = false;
|
|
for t in &mut self.tabs {
|
|
let mut tabname = t.name.clone();
|
|
if t.active && self.mode_info.mode == InputMode::RenameTab {
|
|
if tabname.is_empty() {
|
|
tabname = String::from("Enter name...");
|
|
}
|
|
active_tab_index = t.position;
|
|
} else if t.active {
|
|
active_tab_index = t.position;
|
|
}
|
|
let tab = tab_style(
|
|
tabname,
|
|
t,
|
|
is_alternate_tab,
|
|
self.mode_info.style.colors,
|
|
self.mode_info.capabilities,
|
|
);
|
|
is_alternate_tab = !is_alternate_tab;
|
|
all_tabs.push(tab);
|
|
}
|
|
|
|
let background = self.mode_info.style.colors.text_unselected.background;
|
|
|
|
self.tab_line = tab_line(
|
|
self.mode_info.session_name.as_deref(),
|
|
all_tabs,
|
|
active_tab_index,
|
|
cols.saturating_sub(1),
|
|
self.mode_info.style.colors,
|
|
self.mode_info.capabilities,
|
|
self.mode_info.style.hide_session_name,
|
|
self.tabs.iter().find(|t| t.active),
|
|
&self.mode_info,
|
|
self.hide_swap_layout_indication,
|
|
&background,
|
|
);
|
|
|
|
let output = self
|
|
.tab_line
|
|
.iter()
|
|
.fold(String::new(), |output, part| output + &part.part);
|
|
|
|
match background {
|
|
PaletteColor::Rgb((r, g, b)) => {
|
|
print!("{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", output, r, g, b);
|
|
},
|
|
PaletteColor::EightBit(color) => {
|
|
print!("{}\u{1b}[48;5;{}m\u{1b}[0K", output, color);
|
|
},
|
|
}
|
|
}
|
|
}
|