mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 06:54:45 +03:00
add config for customizing the tabs and new tab button
```lua local wezterm = require 'wezterm'; -- The filled in variant of the < symbol local SOLID_LEFT_ARROW = utf8.char(0xe0b2) -- The filled in variant of the > symbol local SOLID_RIGHT_ARROW = utf8.char(0xe0b0) return { tab_bar_style = { active_tab_left = wezterm.format({ {Background={Color="#0b0022"}}, {Foreground={Color="#2b2042"}}, {Text=SOLID_LEFT_ARROW}, }), active_tab_right = wezterm.format({ {Background={Color="#0b0022"}}, {Foreground={Color="#2b2042"}}, {Text=SOLID_RIGHT_ARROW}, }), inactive_tab_left = wezterm.format({ {Background={Color="#0b0022"}}, {Foreground={Color="#1b1032"}}, {Text=SOLID_LEFT_ARROW}, }), inactive_tab_right = wezterm.format({ {Background={Color="#0b0022"}}, {Foreground={Color="#1b1032"}}, {Text=SOLID_RIGHT_ARROW}, }), } } ```
This commit is contained in:
parent
62d1d11eaf
commit
eb4323ee59
@ -1,3 +1,4 @@
|
||||
use crate::lua::{format_as_escapes, FormatItem};
|
||||
use crate::*;
|
||||
use luahelper::impl_lua_conversion;
|
||||
use termwiz::cell::CellAttributes;
|
||||
@ -181,6 +182,56 @@ impl Default for TabBarColors {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct TabBarStyle {
|
||||
#[serde(default = "default_tab_left")]
|
||||
pub active_tab_left: String,
|
||||
#[serde(default = "default_tab_right")]
|
||||
pub active_tab_right: String,
|
||||
#[serde(default = "default_tab_left")]
|
||||
pub inactive_tab_left: String,
|
||||
#[serde(default = "default_tab_right")]
|
||||
pub inactive_tab_right: String,
|
||||
#[serde(default = "default_tab_left")]
|
||||
pub inactive_tab_hover_left: String,
|
||||
#[serde(default = "default_tab_right")]
|
||||
pub inactive_tab_hover_right: String,
|
||||
|
||||
#[serde(default = "default_tab_left")]
|
||||
pub new_tab_left: String,
|
||||
#[serde(default = "default_tab_right")]
|
||||
pub new_tab_right: String,
|
||||
#[serde(default = "default_tab_left")]
|
||||
pub new_tab_hover_left: String,
|
||||
#[serde(default = "default_tab_right")]
|
||||
pub new_tab_hover_right: String,
|
||||
}
|
||||
|
||||
impl Default for TabBarStyle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
active_tab_left: default_tab_left(),
|
||||
active_tab_right: default_tab_right(),
|
||||
inactive_tab_left: default_tab_left(),
|
||||
inactive_tab_right: default_tab_right(),
|
||||
inactive_tab_hover_left: default_tab_left(),
|
||||
inactive_tab_hover_right: default_tab_right(),
|
||||
new_tab_left: default_tab_left(),
|
||||
new_tab_right: default_tab_right(),
|
||||
new_tab_hover_left: default_tab_left(),
|
||||
new_tab_hover_right: default_tab_right(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_tab_left() -> String {
|
||||
format_as_escapes(vec![FormatItem::Text(" ".to_string())]).unwrap()
|
||||
}
|
||||
|
||||
fn default_tab_right() -> String {
|
||||
format_as_escapes(vec![FormatItem::Text(" ".to_string())]).unwrap()
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct ColorSchemeFile {
|
||||
/// The color palette
|
||||
|
@ -670,6 +670,9 @@ pub struct Config {
|
||||
/// The color palette
|
||||
pub colors: Option<Palette>,
|
||||
|
||||
#[serde(default)]
|
||||
pub tab_bar_style: TabBarStyle,
|
||||
|
||||
#[serde(skip)]
|
||||
pub resolved_palette: Palette,
|
||||
|
||||
|
@ -173,9 +173,10 @@ struct ChangeWrap(Change);
|
||||
impl_lua_conversion!(ChangeWrap);
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
enum FormatColor {
|
||||
pub enum FormatColor {
|
||||
AnsiColor(AnsiColor),
|
||||
Color(String),
|
||||
Default,
|
||||
}
|
||||
|
||||
impl FormatColor {
|
||||
@ -195,12 +196,13 @@ impl Into<ColorSpec> for FormatColor {
|
||||
.unwrap_or(RgbColor::new(0xff, 0xff, 0xff));
|
||||
rgb.into()
|
||||
}
|
||||
FormatColor::Default => ColorSpec::Default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
enum FormatItem {
|
||||
pub enum FormatItem {
|
||||
Foreground(FormatColor),
|
||||
Background(FormatColor),
|
||||
Attribute(AttributeChange),
|
||||
@ -244,15 +246,17 @@ fn strftime<'lua>(_: &'lua Lua, format: String) -> mlua::Result<String> {
|
||||
Ok(local.format(&format).to_string())
|
||||
}
|
||||
|
||||
fn format<'lua>(_: &'lua Lua, items: Vec<FormatItem>) -> mlua::Result<String> {
|
||||
pub fn format_as_escapes(items: Vec<FormatItem>) -> anyhow::Result<String> {
|
||||
let mut changes: Vec<Change> = items.into_iter().map(Into::into).collect();
|
||||
changes.push(Change::AllAttributes(CellAttributes::default()).into());
|
||||
let mut renderer = new_wezterm_terminfo_renderer();
|
||||
let mut target = FormatTarget { target: vec![] };
|
||||
renderer
|
||||
.render_to(&changes, &mut target)
|
||||
.map_err(|e| mlua::Error::external(e))?;
|
||||
String::from_utf8(target.target).map_err(|e| mlua::Error::external(e))
|
||||
renderer.render_to(&changes, &mut target)?;
|
||||
Ok(String::from_utf8(target.target)?)
|
||||
}
|
||||
|
||||
fn format<'lua>(_: &'lua Lua, items: Vec<FormatItem>) -> mlua::Result<String> {
|
||||
format_as_escapes(items).map_err(|e| mlua::Error::external(e))
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -54,13 +54,59 @@ impl TabBarState {
|
||||
config: &ConfigHandle,
|
||||
right_status: &str,
|
||||
) -> Self {
|
||||
let colors = colors.cloned().unwrap_or_else(TabBarColors::default);
|
||||
|
||||
let active_cell_attrs = colors.active_tab.as_cell_attributes();
|
||||
let inactive_hover_attrs = colors.inactive_tab_hover.as_cell_attributes();
|
||||
let inactive_cell_attrs = colors.inactive_tab.as_cell_attributes();
|
||||
|
||||
let active_tab_left = parse_status_text(
|
||||
&config.tab_bar_style.active_tab_left,
|
||||
active_cell_attrs.clone(),
|
||||
);
|
||||
let active_tab_right = parse_status_text(
|
||||
&config.tab_bar_style.active_tab_right,
|
||||
active_cell_attrs.clone(),
|
||||
);
|
||||
let inactive_tab_left = parse_status_text(
|
||||
&config.tab_bar_style.inactive_tab_left,
|
||||
inactive_cell_attrs.clone(),
|
||||
);
|
||||
let inactive_tab_right = parse_status_text(
|
||||
&config.tab_bar_style.inactive_tab_right,
|
||||
inactive_cell_attrs.clone(),
|
||||
);
|
||||
let inactive_tab_hover_left = parse_status_text(
|
||||
&config.tab_bar_style.inactive_tab_hover_left,
|
||||
inactive_hover_attrs.clone(),
|
||||
);
|
||||
let inactive_tab_hover_right = parse_status_text(
|
||||
&config.tab_bar_style.inactive_tab_hover_right,
|
||||
inactive_hover_attrs.clone(),
|
||||
);
|
||||
|
||||
let new_tab_left = parse_status_text(
|
||||
&config.tab_bar_style.new_tab_left,
|
||||
inactive_cell_attrs.clone(),
|
||||
);
|
||||
let new_tab_right = parse_status_text(
|
||||
&config.tab_bar_style.new_tab_right,
|
||||
inactive_cell_attrs.clone(),
|
||||
);
|
||||
let new_tab_hover_left = parse_status_text(
|
||||
&config.tab_bar_style.new_tab_hover_left,
|
||||
inactive_hover_attrs.clone(),
|
||||
);
|
||||
let new_tab_hover_right = parse_status_text(
|
||||
&config.tab_bar_style.new_tab_hover_right,
|
||||
inactive_hover_attrs.clone(),
|
||||
);
|
||||
|
||||
// We ultimately want to produce a line looking like this:
|
||||
// ` | tab1-title x | tab2-title x | + . - X `
|
||||
// Where the `+` sign will spawn a new tab (or show a context
|
||||
// menu with tab creation options) and the other three chars
|
||||
// are symbols representing minimize, maximize and close.
|
||||
let per_tab_overhead = 2;
|
||||
let system_overhead = 3;
|
||||
|
||||
let tab_titles: Vec<String> = window
|
||||
.iter()
|
||||
@ -95,8 +141,11 @@ impl TabBarState {
|
||||
let titles_len: usize = tab_titles.iter().map(|s| unicode_column_width(s)).sum();
|
||||
let number_of_tabs = tab_titles.len();
|
||||
|
||||
let available_cells =
|
||||
title_width.saturating_sub((number_of_tabs * per_tab_overhead) + system_overhead);
|
||||
let available_cells = title_width.saturating_sub(
|
||||
(number_of_tabs.saturating_sub(1)
|
||||
* (inactive_tab_left.len() + inactive_tab_right.len()))
|
||||
+ (new_tab_left.len() + new_tab_right.len() + 1),
|
||||
);
|
||||
let tab_width_max = if available_cells >= titles_len {
|
||||
// We can render each title with its full width
|
||||
usize::max_value()
|
||||
@ -106,8 +155,6 @@ impl TabBarState {
|
||||
}
|
||||
.min(config.tab_max_width);
|
||||
|
||||
let colors = colors.cloned().unwrap_or_else(TabBarColors::default);
|
||||
|
||||
let mut line = Line::with_width(title_width);
|
||||
|
||||
let active_tab_no = window.get_active_idx();
|
||||
@ -117,23 +164,39 @@ impl TabBarState {
|
||||
for (tab_idx, tab_title) in tab_titles.iter().enumerate() {
|
||||
let tab_title_len = unicode_column_width(tab_title).min(tab_width_max);
|
||||
|
||||
let hover = mouse_x
|
||||
.map(|mouse_x| mouse_x >= x && mouse_x < x + tab_title_len + per_tab_overhead)
|
||||
.unwrap_or(false);
|
||||
let active = tab_idx == active_tab_no;
|
||||
let hover = !active
|
||||
&& mouse_x
|
||||
.map(|mouse_x| {
|
||||
mouse_x >= x
|
||||
&& mouse_x
|
||||
< x + tab_title_len
|
||||
+ (inactive_tab_left.len() + inactive_tab_right.len())
|
||||
})
|
||||
.unwrap_or(false);
|
||||
|
||||
let cell_attrs = if active {
|
||||
colors.active_tab.as_cell_attributes()
|
||||
let (cell_attrs, left, right) = if active {
|
||||
(&active_cell_attrs, &active_tab_left, &active_tab_right)
|
||||
} else if hover {
|
||||
colors.inactive_tab_hover.as_cell_attributes()
|
||||
(
|
||||
&inactive_hover_attrs,
|
||||
&inactive_tab_hover_left,
|
||||
&inactive_tab_hover_right,
|
||||
)
|
||||
} else {
|
||||
colors.inactive_tab.as_cell_attributes()
|
||||
(
|
||||
&inactive_cell_attrs,
|
||||
&inactive_tab_left,
|
||||
&inactive_tab_right,
|
||||
)
|
||||
};
|
||||
|
||||
let tab_start_idx = x;
|
||||
|
||||
line.set_cell(x, Cell::new(' ', cell_attrs.clone()));
|
||||
x += 1;
|
||||
for c in left {
|
||||
line.set_cell(x, c.clone());
|
||||
x += 1;
|
||||
}
|
||||
|
||||
for (idx, sub) in tab_title.graphemes(true).enumerate() {
|
||||
if idx >= tab_width_max {
|
||||
@ -144,8 +207,10 @@ impl TabBarState {
|
||||
x += 1;
|
||||
}
|
||||
|
||||
line.set_cell(x, Cell::new(' ', cell_attrs));
|
||||
x += 1;
|
||||
for c in right {
|
||||
line.set_cell(x, c.clone());
|
||||
x += 1;
|
||||
}
|
||||
|
||||
items.push(TabEntry {
|
||||
item: TabBarItem::Tab(tab_idx),
|
||||
@ -160,22 +225,33 @@ impl TabBarState {
|
||||
.map(|mouse_x| mouse_x >= x && mouse_x < x + 3)
|
||||
.unwrap_or(false);
|
||||
|
||||
let cell_attrs = if hover {
|
||||
colors.inactive_tab_hover.as_cell_attributes()
|
||||
let (cell_attrs, left, right) = if hover {
|
||||
(
|
||||
&inactive_hover_attrs,
|
||||
&new_tab_hover_left,
|
||||
&new_tab_hover_right,
|
||||
)
|
||||
} else {
|
||||
colors.inactive_tab.as_cell_attributes()
|
||||
(&inactive_cell_attrs, &new_tab_left, &new_tab_right)
|
||||
};
|
||||
|
||||
let button_start = x;
|
||||
|
||||
for c in left {
|
||||
line.set_cell(x, c.clone());
|
||||
x += 1;
|
||||
}
|
||||
line.set_cell(x, Cell::new('+', cell_attrs.clone()));
|
||||
for c in right {
|
||||
line.set_cell(x, c.clone());
|
||||
x += 1;
|
||||
}
|
||||
|
||||
items.push(TabEntry {
|
||||
item: TabBarItem::NewTabButton,
|
||||
x,
|
||||
width: 3,
|
||||
x: button_start,
|
||||
width: x - button_start,
|
||||
});
|
||||
|
||||
line.set_cell(x, Cell::new(' ', cell_attrs.clone()));
|
||||
line.set_cell(x + 1, Cell::new('+', cell_attrs.clone()));
|
||||
line.set_cell(x + 2, Cell::new(' ', cell_attrs));
|
||||
x += 3;
|
||||
}
|
||||
|
||||
let black_cell = Cell::new(
|
||||
@ -270,10 +346,18 @@ fn parse_status_text(text: &str, default_cell: CellAttributes) -> Vec<Cell> {
|
||||
pen.set_strikethrough(strike);
|
||||
}
|
||||
Sgr::Foreground(col) => {
|
||||
pen.set_foreground(col);
|
||||
if let ColorSpec::Default = col {
|
||||
pen.set_foreground(default_cell.foreground);
|
||||
} else {
|
||||
pen.set_foreground(col);
|
||||
}
|
||||
}
|
||||
Sgr::Background(col) => {
|
||||
pen.set_background(col);
|
||||
if let ColorSpec::Default = col {
|
||||
pen.set_background(default_cell.background);
|
||||
} else {
|
||||
pen.set_background(col);
|
||||
}
|
||||
}
|
||||
Sgr::UnderlineColor(col) => {
|
||||
pen.set_underline_color(col);
|
||||
|
Loading…
Reference in New Issue
Block a user