tab-title.lua
1 local wezterm = require('wezterm') 2 3 -- Inspired by https://github.com/wez/wezterm/discussions/628#discussioncomment-1874614 4 5 local nf = wezterm.nerdfonts 6 7 local ICON_SEMI_CIRCLE_LEFT = nf.ple_left_half_circle_thick --[[ '' ]] 8 local ICON_SEMI_CIRCLE_RIGHT = nf.ple_right_half_circle_thick --[[ '' ]] 9 local ICON_CIRCLE = nf.fa_circle --[[ '' ]] 10 local ICON_ADMIN = nf.md_shield_half_full --[[ '' ]] 11 12 local M = {} 13 14 local __cells__ = {} -- wezterm FormatItems (ref: https://wezfurlong.org/wezterm/config/lua/wezterm/format.html) 15 16 -- stylua: ignore 17 local colors = { 18 default = { bg = '#45475a', fg = '#1c1b19' }, 19 is_active = { bg = '#7FB4CA', fg = '#11111b' }, 20 hover = { bg = '#587d8c', fg = '#1c1b19' }, 21 } 22 23 -- TODO: Needs work, pane titles are still clunky 24 local _set_process_name = function(s) 25 return string.gsub(s, '(.*[/\\])(.*)', '%2') 26 end 27 28 local _set_tab_idx = function(tabs, tab) 29 local tab_idx = 1 30 31 for i, t in ipairs(tabs) do 32 if t.tab_id == tab.tab_id then 33 tab_idx = i 34 break 35 end 36 end 37 38 return tab_idx 39 end 40 41 local _set_title = function(process_name, base_title, max_width, inset) 42 local title 43 inset = inset or 6 44 45 if process_name:len() == 0 then 46 title = '❓' .. process_name 47 elseif process_name:len() < 4 or process_name == 'zsh' or process_name == 'bash' then 48 title = '⚠️ ~ ' .. process_name 49 else 50 title = base_title 51 end 52 53 if title:len() > max_width - inset then 54 local diff = title:len() - max_width + inset 55 title = wezterm.truncate_right(title, title:len() - diff) 56 end 57 58 return title 59 end 60 61 -- TODO: Needs further work 62 local _check_if_admin = function(p) 63 if p:match('^Administrator: ') then 64 return true 65 end 66 return false 67 end 68 69 ---@param fg string 70 ---@param bg string 71 ---@param attribute table 72 ---@param text string 73 local _push = function(bg, fg, attribute, text) 74 table.insert(__cells__, { Background = { Color = bg } }) 75 table.insert(__cells__, { Foreground = { Color = fg } }) 76 table.insert(__cells__, { Attribute = attribute }) 77 table.insert(__cells__, { Text = text }) 78 end 79 80 M.setup = function() 81 wezterm.on('format-tab-title', function(tab, tabs, _, _, hover, max_width) 82 __cells__ = {} 83 84 local bg 85 local fg 86 local process_name = _set_process_name(tab.active_pane.foreground_process_name) 87 local is_admin = _check_if_admin(tab.active_pane.title) 88 local title = _set_title(process_name, tab.active_pane.title, max_width, (is_admin and 8)) 89 90 local tab_idx = _set_tab_idx(tabs, tab) 91 92 if tab.is_active then 93 bg = colors.is_active.bg 94 fg = colors.is_active.fg 95 title = tab_idx .. ' ' .. title 96 elseif hover then 97 bg = colors.hover.bg 98 fg = colors.hover.fg 99 title = tab_idx .. ' ' .. title 100 else 101 bg = colors.default.bg 102 fg = colors.default.fg 103 title = tab_idx .. ' ' .. title 104 end 105 106 local has_unseen_output = false 107 for _, pane in ipairs(tab.panes) do 108 if pane.has_unseen_output then 109 has_unseen_output = true 110 break 111 end 112 end 113 114 -- Left semi-circle 115 _push('rgba(0, 0, 0, 0.4)', bg, { Intensity = 'Bold' }, ICON_SEMI_CIRCLE_LEFT) 116 117 -- 118 -- Admin Icon 119 if is_admin then 120 _push(bg, fg, { Intensity = 'Bold' }, ' ' .. ICON_ADMIN) 121 end 122 123 -- Title 124 _push(bg, fg, { Intensity = 'Bold' }, ' ' .. title) 125 126 -- Unseen output alert 127 if has_unseen_output then 128 _push(bg, '#FFA066', { Intensity = 'Bold' }, ' ' .. ICON_CIRCLE) 129 end 130 131 -- Right padding 132 _push(bg, fg, { Intensity = 'Bold' }, ' ') 133 134 -- Right semi-circle 135 _push('rgba(0, 0, 0, 0.4)', bg, { Intensity = 'Bold' }, ICON_SEMI_CIRCLE_RIGHT) 136 137 return __cells__ 138 end) 139 end 140 141 return M