diff --git a/events/left-status.lua b/events/left-status.lua index d967024..b0176b7 100644 --- a/events/left-status.lua +++ b/events/left-status.lua @@ -11,18 +11,19 @@ local GLYPH_SEMI_CIRCLE_RIGHT = nf.ple_right_half_circle_thick --[[ '' ]] local GLYPH_KEY_TABLE = nf.md_table_key --[[ '󱏅' ]] local GLYPH_KEY = nf.md_key --[[ '󰌆' ]] +---@type table local colors = { default = { bg = '#fab387', fg = '#1c1b19' }, scircle = { bg = 'rgba(0, 0, 0, 0.4)', fg = '#fab387' }, } -local cells = Cells:new(colors) +local cells = Cells:new() cells - :add_segment(1, GLYPH_SEMI_CIRCLE_LEFT, 'scircle', attr(attr.intensity('Bold'))) - :add_segment(2, ' ', 'default', attr(attr.intensity('Bold'))) - :add_segment(3, ' ', 'default', attr(attr.intensity('Bold'))) - :add_segment(4, GLYPH_SEMI_CIRCLE_RIGHT, 'scircle', attr(attr.intensity('Bold'))) + :add_segment(1, GLYPH_SEMI_CIRCLE_LEFT, colors.scircle, attr(attr.intensity('Bold'))) + :add_segment(2, ' ', colors.default, attr(attr.intensity('Bold'))) + :add_segment(3, ' ', colors.default, attr(attr.intensity('Bold'))) + :add_segment(4, GLYPH_SEMI_CIRCLE_RIGHT, colors.scircle, attr(attr.intensity('Bold'))) M.setup = function() wezterm.on('update-right-status', function(window, _pane) diff --git a/events/new-tab-button.lua b/events/new-tab-button.lua index 9e8c3ce..6fe2d2e 100644 --- a/events/new-tab-button.lua +++ b/events/new-tab-button.lua @@ -9,21 +9,22 @@ local attr = Cells.attr local M = {} +---@type table -- stylua: ignore local colors = { - label_text = { bg = 'rgba(0, 0, 0, 0)', fg = '#CDD6F4' }, - icon_default = { bg = 'rgba(0, 0, 0, 0)', fg = '#89B4FA' }, - icon_wsl = { bg = 'rgba(0, 0, 0, 0)', fg = '#FAB387' }, - icon_ssh = { bg = 'rgba(0, 0, 0, 0)', fg = '#F38BA8' }, - icon_unix = { bg = 'rgba(0, 0, 0, 0)', fg = '#CBA6F7' }, + label_text = { fg = '#CDD6F4' }, + icon_default = { fg = '#89B4FA' }, + icon_wsl = { fg = '#FAB387' }, + icon_ssh = { fg = '#F38BA8' }, + icon_unix = { fg = '#CBA6F7' }, } -local cells = Cells:new(colors) - :add_segment('icon_default', ' ' .. nf.md_domain .. ' ', 'icon_default') - :add_segment('icon_wsl', ' ' .. nf.cod_terminal_linux .. ' ', 'icon_wsl') - :add_segment('icon_ssh', ' ' .. nf.md_ssh .. ' ', 'icon_ssh') - :add_segment('icon_unix', ' ' .. nf.dev_gnu .. ' ', 'icon_unix') - :add_segment('label_text', '', 'label_text', attr(attr.intensity('Bold'))) +local cells = Cells:new() + :add_segment('icon_default', ' ' .. nf.md_domain .. ' ', colors.icon_default) + :add_segment('icon_wsl', ' ' .. nf.cod_terminal_linux .. ' ', colors.icon_wsl) + :add_segment('icon_ssh', ' ' .. nf.md_ssh .. ' ', colors.icon_ssh) + :add_segment('icon_unix', ' ' .. nf.dev_gnu .. ' ', colors.icon_unix) + :add_segment('label_text', '', colors.label_text, attr(attr.intensity('Bold'))) local function build_choices() local choices = {} diff --git a/events/right-status.lua b/events/right-status.lua index c549db3..6323ce0 100644 --- a/events/right-status.lua +++ b/events/right-status.lua @@ -37,6 +37,7 @@ local charging_icons = { nf.md_battery_charging, } + ---@type table -- stylua: ignore local colors = { date = { fg = '#fab387', bg = 'rgba(0, 0, 0, 0.4)' }, @@ -44,14 +45,14 @@ local colors = { separator = { fg = '#74c7ec', bg = 'rgba(0, 0, 0, 0.4)' } } -local cells = Cells:new(colors) +local cells = Cells:new() cells - :add_segment('date_icon', ICON_DATE .. ' ', 'date', attr(attr.intensity('Bold'))) - :add_segment('date_text', '', 'date', attr(attr.intensity('Bold'))) - :add_segment('separator', ' ' .. ICON_SEPARATOR .. ' ', 'separator') - :add_segment('battery_icon', '', 'battery') - :add_segment('battery_text', '', 'battery', attr(attr.intensity('Bold'))) + :add_segment('date_icon', ICON_DATE .. ' ', colors.date, attr(attr.intensity('Bold'))) + :add_segment('date_text', '', colors.date, attr(attr.intensity('Bold'))) + :add_segment('separator', ' ' .. ICON_SEPARATOR .. ' ', colors.separator) + :add_segment('battery_icon', '', colors.battery) + :add_segment('battery_text', '', colors.battery, attr(attr.intensity('Bold'))) ---@return string, string local function battery_info() diff --git a/events/tab-title.lua b/events/tab-title.lua index 3464cce..371f17e 100644 --- a/events/tab-title.lua +++ b/events/tab-title.lua @@ -33,24 +33,20 @@ local RENDER_VARIANTS = { { 'scircle_left', 'wsl', 'title', 'unseen_output', 'padding', 'scircle_right' }, } +---@type table -- stylua: ignore -local COLORS = { - default = { bg = '#45475A', fg = '#1C1B19' }, - default_hover = { bg = '#587D8C', fg = '#1C1B19' }, - default_active = { bg = '#7FB4CA', fg = '#11111B' }, - unseen_output = { bg = '#45475A', fg = '#FFA066' }, - unseen_output_hover = { bg = '#587D8C', fg = '#FFA066' }, - unseen_output_active = { bg = '#7FB4CA', fg = '#FFA066' }, - scircle = { bg = 'rgba(0, 0, 0, 0.4)', fg = '#45475A' }, - scircle_hover = { bg = 'rgba(0, 0, 0, 0.4)', fg = '#587D8C' }, - scircle_active = { bg = 'rgba(0, 0, 0, 0.4)', fg = '#7FB4CA' }, -} - --- stylua: ignore -local SEGMENT_COLORS = { - scircle = { default = 'scircle', hover = 'scircle_hover', active = 'scircle_active', }, - text = { default = 'default', hover = 'default_hover', active = 'default_active', }, - unseen_output = { default = 'unseen_output', hover = 'unseen_output_hover', active = 'unseen_output_active', }, +local colors = { + text_default = { bg = '#45475A', fg = '#1C1B19' }, + text_hover = { bg = '#587D8C', fg = '#1C1B19' }, + text_active = { bg = '#7FB4CA', fg = '#11111B' }, + + unseen_output_default = { bg = '#45475A', fg = '#FFA066' }, + unseen_output_hover = { bg = '#587D8C', fg = '#FFA066' }, + unseen_output_active = { bg = '#7FB4CA', fg = '#FFA066' }, + + scircle_default = { bg = 'rgba(0, 0, 0, 0.4)', fg = '#45475A' }, + scircle_hover = { bg = 'rgba(0, 0, 0, 0.4)', fg = '#587D8C' }, + scircle_active = { bg = 'rgba(0, 0, 0, 0.4)', fg = '#7FB4CA' }, } ---@param proc string @@ -107,7 +103,7 @@ Tab.__index = Tab function Tab:new() local tab = { title = '', - cells = Cells:new(COLORS), + cells = Cells:new(), title_locked = false, is_wsl = false, is_admin = false, @@ -133,24 +129,15 @@ function Tab:set_info(pane, max_width) self.title = create_title(process_name, pane.title, max_width, inset) end ----@param is_active boolean ----@param hover boolean -function Tab:set_cells(is_active, hover) - local color_variant = 'default' - if is_active then - color_variant = 'active' - elseif hover then - color_variant = 'hover' - end - +function Tab:set_cells() self.cells - :add_segment('scircle_left', GLYPH_SCIRCLE_LEFT, SEGMENT_COLORS['scircle'][color_variant]) - :add_segment('admin', ' ' .. GLYPH_ADMIN, SEGMENT_COLORS['text'][color_variant]) - :add_segment('wsl', ' ' .. GLYPH_LINUX, SEGMENT_COLORS['text'][color_variant]) - :add_segment('title', ' ', SEGMENT_COLORS['text'][color_variant], attr(attr.intensity('Bold'))) - :add_segment('unseen_output', ' ' .. GLYPH_CIRCLE, SEGMENT_COLORS['unseen_output'][color_variant]) - :add_segment('padding', ' ', SEGMENT_COLORS['text'][color_variant]) - :add_segment('scircle_right', GLYPH_SCIRCLE_RIGHT, SEGMENT_COLORS['scircle'][color_variant]) + :add_segment('scircle_left', GLYPH_SCIRCLE_LEFT) + :add_segment('admin', ' ' .. GLYPH_ADMIN) + :add_segment('wsl', ' ' .. GLYPH_LINUX) + :add_segment('title', ' ', nil, attr(attr.intensity('Bold'))) + :add_segment('unseen_output', ' ' .. GLYPH_CIRCLE) + :add_segment('padding', ' ') + :add_segment('scircle_right', GLYPH_SCIRCLE_RIGHT) end ---@param title string @@ -162,22 +149,22 @@ end ---@param is_active boolean ---@param hover boolean function Tab:update_cells(is_active, hover) - local color_variant = 'default' + local tab_state = 'default' if is_active then - color_variant = 'active' + tab_state = 'active' elseif hover then - color_variant = 'hover' + tab_state = 'hover' end self.cells:update_segment_text('title', ' ' .. self.title) self.cells - :update_segment_colors('scircle_left', SEGMENT_COLORS['scircle'][color_variant]) - :update_segment_colors('admin', SEGMENT_COLORS['text'][color_variant]) - :update_segment_colors('wsl', SEGMENT_COLORS['text'][color_variant]) - :update_segment_colors('title', SEGMENT_COLORS['text'][color_variant]) - :update_segment_colors('unseen_output', SEGMENT_COLORS['unseen_output'][color_variant]) - :update_segment_colors('padding', SEGMENT_COLORS['text'][color_variant]) - :update_segment_colors('scircle_right', SEGMENT_COLORS['scircle'][color_variant]) + :update_segment_colors('scircle_left', colors['scircle_' .. tab_state]) + :update_segment_colors('admin', colors['text_' .. tab_state]) + :update_segment_colors('wsl', colors['text_' .. tab_state]) + :update_segment_colors('title', colors['text_' .. tab_state]) + :update_segment_colors('unseen_output', colors['unseen_output_' .. tab_state]) + :update_segment_colors('padding', colors['text_' .. tab_state]) + :update_segment_colors('scircle_right', colors['scircle_' .. tab_state]) end ---@return FormatItem[] (ref: https://wezfurlong.org/wezterm/config/lua/wezterm/format.html) @@ -230,10 +217,11 @@ M.setup = function() -- BUILTIN EVENT wezterm.on('format-tab-title', function(tab, _tabs, _panes, _config, hover, max_width) + print(tab_list) if not tab_list[tab.tab_id] then tab_list[tab.tab_id] = Tab:new() tab_list[tab.tab_id]:set_info(tab.active_pane, max_width) - tab_list[tab.tab_id]:set_cells(tab.is_active, hover) + tab_list[tab.tab_id]:set_cells() return tab_list[tab.tab_id]:render() end diff --git a/utils/cells.lua b/utils/cells.lua index 5db20e3..fa46882 100644 --- a/utils/cells.lua +++ b/utils/cells.lua @@ -45,18 +45,16 @@ attr.underline = function(type) return { Attribute = { Underline = type } } end ----@class Cells.Colors ----@field default {bg: string, fg: string} ----@field [string] {bg: string, fg: string} +---@alias Cells.SegmentColors {bg?: string|'UNSET', fg?: string|'UNSET'} ---@class Cells.Segment ----@field color string ---@field items FormatItem[] +---@field has_bg boolean +---@field has_fg boolean ---Format item generator for `wezterm.format` (ref: ) ---@class Cells ---@field segments table ----@field colors Cells.Colors local Cells = {} Cells.__index = Cells @@ -71,30 +69,30 @@ Cells.attr = setmetatable(attr, { end, }) ----@param colors Cells.Colors -function Cells:new(colors) +function Cells:new() return setmetatable({ segments = {}, - colors = colors, }, self) end ---@param segment_id string|number the segment id ---@param text string the text to push ----@param color string|'default' the color variant to use (default is 'default') ----@param attributes FormatItem.Attribute[]|nil use bold text +---@param color? Cells.SegmentColors the bg and fg colors for text +---@param attributes? FormatItem.Attribute[] use bold text function Cells:add_segment(segment_id, text, color, attributes) - color = color or 'default' - local colors = self.colors[color] - if not colors then - error('Color variant "' .. color .. '" not found') - end + color = color or {} ---@type FormatItem[] local items = {} - table.insert(items, { Background = { Color = colors.bg } }) - table.insert(items, { Foreground = { Color = colors.fg } }) + if color.bg then + assert(color.bg ~= 'UNSET', 'Cannot use UNSET when adding new segment') + table.insert(items, { Background = { Color = color.bg } }) + end + if color.fg then + assert(color.bg ~= 'UNSET', 'Cannot use UNSET when adding new segment') + table.insert(items, { Foreground = { Color = color.fg } }) + end if attributes and #attributes > 0 then for _, attr_ in ipairs(attributes) do table.insert(items, attr_) @@ -105,8 +103,9 @@ function Cells:add_segment(segment_id, text, color, attributes) ---@type Cells.Segment self.segments[segment_id] = { - color = color, items = items, + has_bg = color.bg ~= nil, + has_fg = color.fg ~= nil, } return self @@ -120,14 +119,6 @@ function Cells:_check_segment(segment_id) end end ----@private ----@param color string -function Cells:_check_color(color) - if not self.colors[color] then - error('Color variant "' .. color .. '" not found') - end -end - ---@param segment_id string|number the segment id ---@param text string the text to push function Cells:update_segment_text(segment_id, text) @@ -138,14 +129,54 @@ function Cells:update_segment_text(segment_id, text) end ---@param segment_id string|number the segment id ----@param color string|'default' the color variant to use (default is 'default') +---@param color Cells.SegmentColors the bg and fg colors for text function Cells:update_segment_colors(segment_id, color) - color = color or 'default' + assert(type(color) == 'table', 'Color must be a table') + self:_check_segment(segment_id) - self:_check_color(color) - self.segments[segment_id].items[1] = { Background = { Color = self.colors[color].bg } } - self.segments[segment_id].items[2] = { Foreground = { Color = self.colors[color].fg } } + local has_bg = self.segments[segment_id].has_bg + local has_fg = self.segments[segment_id].has_fg + + if color.bg then + if has_bg and color.bg == 'UNSET' then + table.remove(self.segments[segment_id].items, 1) + has_bg = false + goto bg_end + end + + if has_bg then + self.segments[segment_id].items[1] = { Background = { Color = color.bg } } + else + table.insert(self.segments[segment_id].items, 1, { Background = { Color = color.bg } }) + has_bg = true + end + end + ::bg_end:: + + if color.fg then + local fg_idx = has_bg and 2 or 1 + if has_fg and color.fg == 'UNSET' then + table.remove(self.segments[segment_id].items, fg_idx) + has_fg = false + goto fg_end + end + + if has_fg then + self.segments[segment_id].items[fg_idx] = { Foreground = { Color = color.fg } } + else + table.insert( + self.segments[segment_id].items, + fg_idx, + { Foreground = { Color = color.fg } } + ) + has_fg = true + end + end + ::fg_end:: + + self.segments[segment_id].has_bg = has_bg + self.segments[segment_id].has_fg = has_fg return self end