feat(wezterm): modular tab bar
This commit is contained in:
parent
7079dd47ea
commit
660a035a93
3 changed files with 276 additions and 88 deletions
|
@ -1,10 +1,115 @@
|
|||
local wezterm = require("wezterm")
|
||||
|
||||
local DIVIDERS = {
|
||||
LEFT = utf8.char(0xe0be),
|
||||
RIGHT = utf8.char(0xe0bc),
|
||||
local M = {}
|
||||
|
||||
M.config = {
|
||||
dividers = "slant_right",
|
||||
indicator = {
|
||||
leader = {
|
||||
enabled = true,
|
||||
off = " ",
|
||||
on = " ",
|
||||
},
|
||||
mode = {
|
||||
enabled = true,
|
||||
names = {
|
||||
resize_mode = "RESIZE",
|
||||
copy_mode = "VISUAL",
|
||||
search_mode = "SEARCH",
|
||||
},
|
||||
},
|
||||
},
|
||||
tabs = {
|
||||
numerals = "arabic",
|
||||
pane_count = "superscript",
|
||||
brackets = {
|
||||
active = { "", ":" },
|
||||
inactive = { "", ":" },
|
||||
},
|
||||
},
|
||||
clock = {
|
||||
enabled = true,
|
||||
format = "%H:%M",
|
||||
},
|
||||
}
|
||||
|
||||
local function tableMerge(t1, t2)
|
||||
for k, v in pairs(t2) do
|
||||
if type(v) == "table" then
|
||||
if type(t1[k] or false) == "table" then
|
||||
tableMerge(t1[k] or {}, t2[k] or {})
|
||||
else
|
||||
t1[k] = v
|
||||
end
|
||||
else
|
||||
t1[k] = v
|
||||
end
|
||||
end
|
||||
return t1
|
||||
end
|
||||
|
||||
local C = {}
|
||||
|
||||
M.setup = function(config)
|
||||
M.config = tableMerge(M.config, config)
|
||||
local dividers = {
|
||||
slant_right = {
|
||||
left = utf8.char(0xe0be),
|
||||
right = utf8.char(0xe0bc),
|
||||
},
|
||||
slant_left = {
|
||||
left = utf8.char(0xe0ba),
|
||||
right = utf8.char(0xe0b8),
|
||||
},
|
||||
arrows = {
|
||||
left = utf8.char(0xe0b2),
|
||||
right = utf8.char(0xe0b0),
|
||||
},
|
||||
rounded = {
|
||||
left = utf8.char(0xe0b6),
|
||||
right = utf8.char(0xe0b4),
|
||||
},
|
||||
}
|
||||
|
||||
C.div = {
|
||||
l = "",
|
||||
r = "",
|
||||
}
|
||||
if M.config.dividers then
|
||||
C.div.l = dividers[M.config.dividers].left
|
||||
C.div.r = dividers[M.config.dividers].right
|
||||
end
|
||||
|
||||
C.leader = {
|
||||
enabled = M.config.indicator.leader.enabled or true,
|
||||
off = M.config.indicator.leader.off,
|
||||
on = M.config.indicator.leader.on,
|
||||
}
|
||||
|
||||
C.mode = {
|
||||
enabled = M.config.indicator.mode.enabled,
|
||||
names = M.config.indicator.mode.names,
|
||||
}
|
||||
|
||||
C.tabs = {
|
||||
numerals = M.config.tabs.numerals,
|
||||
pane_count_style = M.config.tabs.pane_count,
|
||||
brackets = {
|
||||
active = M.config.tabs.brackets.active,
|
||||
inactive = M.config.tabs.brackets.inactive,
|
||||
},
|
||||
}
|
||||
|
||||
C.clock = {
|
||||
enabled = M.config.clock.enabled,
|
||||
format = M.config.clock.format,
|
||||
}
|
||||
|
||||
C.p = (M.config.dividers == "rounded") and "" or " "
|
||||
|
||||
wezterm.log_info(C)
|
||||
end
|
||||
|
||||
-- superscript/subscript
|
||||
local function numberStyle(number, script)
|
||||
local scripts = {
|
||||
|
@ -48,6 +153,21 @@ local function numberStyle(number, script)
|
|||
return result
|
||||
end
|
||||
|
||||
local roman_numerals = {
|
||||
"Ⅰ",
|
||||
"Ⅱ",
|
||||
"Ⅲ",
|
||||
"Ⅳ",
|
||||
"Ⅴ",
|
||||
"Ⅵ",
|
||||
"Ⅶ",
|
||||
"Ⅷ",
|
||||
"Ⅸ",
|
||||
"Ⅹ",
|
||||
"Ⅺ",
|
||||
"Ⅻ",
|
||||
}
|
||||
|
||||
-- custom tab bar
|
||||
wezterm.on(
|
||||
"format-tab-title",
|
||||
|
@ -109,29 +229,47 @@ wezterm.on(
|
|||
e_fg = inactive_bg
|
||||
end
|
||||
|
||||
local tabi = wezterm.mux.get_tab(tab.tab_id)
|
||||
local muxpanes = tabi:panes()
|
||||
local count = #muxpanes == 1 and "" or tostring(#muxpanes)
|
||||
local index = tab.tab_index + 1 .. ": "
|
||||
|
||||
-- start and end hardcoded numbers are the Powerline + " " padding
|
||||
local fillerwidth = 2 + string.len(index) + string.len(count) + 2
|
||||
|
||||
local tabtitle = tab.active_pane.title
|
||||
if (#tabtitle + fillerwidth) > config.tab_max_width then
|
||||
tabtitle = string.sub(
|
||||
tab.active_pane.title,
|
||||
1,
|
||||
(config.tab_max_width - fillerwidth - 1)
|
||||
) .. "…"
|
||||
local pane_count = ""
|
||||
if C.tabs.pane_count_style then
|
||||
local tabi = wezterm.mux.get_tab(tab.tab_id)
|
||||
local muxpanes = tabi:panes()
|
||||
local count = #muxpanes == 1 and "" or tostring(#muxpanes)
|
||||
pane_count = numberStyle(count, C.tabs.pane_count_style)
|
||||
end
|
||||
|
||||
local title = string.format(
|
||||
" %s%s%s ",
|
||||
index,
|
||||
tabtitle,
|
||||
numberStyle(count, "superscript")
|
||||
)
|
||||
local index_i
|
||||
if C.tabs.numerals == "roman" then
|
||||
index_i = roman_numerals[tab.tab_index + 1]
|
||||
else
|
||||
index_i = tab.tab_index + 1
|
||||
end
|
||||
|
||||
if tab.is_active then
|
||||
index = string.format(
|
||||
"%s%s%s ",
|
||||
C.tabs.brackets.active[1],
|
||||
index_i,
|
||||
C.tabs.brackets.active[2]
|
||||
)
|
||||
else
|
||||
index = string.format(
|
||||
"%s%s%s ",
|
||||
C.tabs.brackets.inactive[1],
|
||||
index_i,
|
||||
C.tabs.brackets.inactive[2]
|
||||
)
|
||||
end
|
||||
|
||||
-- start and end hardcoded numbers are the Powerline + " " padding
|
||||
local fillerwidth = 2 + string.len(index) + string.len(pane_count) + 2
|
||||
|
||||
local tabtitle = tab.active_pane.title
|
||||
local width = config.tab_max_width - fillerwidth - 1
|
||||
if (#tabtitle + fillerwidth) > config.tab_max_width then
|
||||
tabtitle = wezterm.truncate_right(tabtitle, width) .. "…"
|
||||
end
|
||||
|
||||
local title = string.format(" %s%s%s%s", index, tabtitle, pane_count, C.p)
|
||||
|
||||
return {
|
||||
{ Background = { Color = s_bg } },
|
||||
|
@ -139,84 +277,71 @@ wezterm.on(
|
|||
{ Text = title },
|
||||
{ Background = { Color = e_bg } },
|
||||
{ Foreground = { Color = e_fg } },
|
||||
{ Text = DIVIDERS.RIGHT },
|
||||
{ Text = C.div.r },
|
||||
}
|
||||
end
|
||||
)
|
||||
|
||||
local function arrContains(arr, val)
|
||||
for _, v in ipairs(arr) do
|
||||
if v == val then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local nonpadded_apps = { "nvim", "btop", "btm" }
|
||||
|
||||
wezterm.on("smartpadding", function(window, pane)
|
||||
local fgp = pane:get_foreground_process_info()
|
||||
if fgp == nil then
|
||||
return
|
||||
elseif arrContains(nonpadded_apps, fgp.name) then
|
||||
window:set_config_overrides({
|
||||
window_padding = { left = 0, right = 0, top = 0, bottom = 0 },
|
||||
})
|
||||
else
|
||||
window:set_config_overrides({
|
||||
window_padding = wezterm.GLOBAL.smart_padding,
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
-- custom status
|
||||
wezterm.on("update-status", function(window, pane)
|
||||
if wezterm.GLOBAL.smart_padding ~= nil then
|
||||
wezterm.emit("smartpadding", window, pane)
|
||||
local active_kt = window:active_key_table() ~= nil
|
||||
local show = C.leader.enabled or (active_kt and C.mode.enabled)
|
||||
if not show then
|
||||
window:set_left_status("")
|
||||
return
|
||||
end
|
||||
|
||||
local palette = window:effective_config().resolved_palette
|
||||
|
||||
local leader = ""
|
||||
if C.leader.enabled then
|
||||
local leader_text = C.leader.off
|
||||
if window:leader_is_active() then
|
||||
leader_text = C.leader.on
|
||||
end
|
||||
leader = wezterm.format({
|
||||
{ Foreground = { Color = palette.background } },
|
||||
{ Background = { Color = palette.ansi[5] } },
|
||||
{ Text = " " .. leader_text .. C.p },
|
||||
})
|
||||
end
|
||||
|
||||
local mode = ""
|
||||
if C.mode.enabled then
|
||||
local mode_text = ""
|
||||
local active = window:active_key_table()
|
||||
if C.mode.names[active] ~= nil then
|
||||
mode_text = C.mode.names[active] .. ""
|
||||
end
|
||||
mode = wezterm.format({
|
||||
{ Foreground = { Color = palette.background } },
|
||||
{ Background = { Color = palette.ansi[5] } },
|
||||
{ Attribute = { Intensity = "Bold" } },
|
||||
{ Text = mode_text },
|
||||
"ResetAttributes",
|
||||
})
|
||||
end
|
||||
|
||||
local first_tab_active = window:mux_window():tabs_with_info()[1].is_active
|
||||
|
||||
local leader_text = " "
|
||||
if window:leader_is_active() then
|
||||
leader_text = " "
|
||||
end
|
||||
|
||||
local mode_text = ""
|
||||
local mode = window:active_key_table()
|
||||
local modes = {
|
||||
resize_mode = "RESIZE",
|
||||
}
|
||||
if modes[mode] ~= nil then
|
||||
mode_text = modes[mode]
|
||||
end
|
||||
|
||||
local divider_bg = first_tab_active and palette.ansi[2]
|
||||
or palette.tab_bar.inactive_tab.bg_color
|
||||
|
||||
window:set_left_status(wezterm.format({
|
||||
{ Foreground = { Color = palette.background } },
|
||||
{ Background = { Color = palette.ansi[5] } },
|
||||
{ Text = leader_text },
|
||||
{ Attribute = { Intensity = "Bold" } },
|
||||
{ Text = mode_text },
|
||||
"ResetAttributes",
|
||||
local divider = wezterm.format({
|
||||
{ Background = { Color = divider_bg } },
|
||||
{ Foreground = { Color = palette.ansi[5] } },
|
||||
{ Text = DIVIDERS.RIGHT },
|
||||
}))
|
||||
{ Text = C.div.r },
|
||||
})
|
||||
|
||||
local time = wezterm.time.now():format("%H:%M")
|
||||
local sun_is_up = wezterm.time.now():sun_times(48.2, 16.366667).up
|
||||
local icon = sun_is_up and " " or " "
|
||||
local text = string.format("%s %s", icon, time)
|
||||
window:set_left_status(leader .. mode .. divider)
|
||||
|
||||
window:set_right_status(wezterm.format({
|
||||
{ Background = { Color = palette.tab_bar.background } },
|
||||
{ Foreground = { Color = palette.ansi[6] } },
|
||||
{ Text = text },
|
||||
}))
|
||||
if C.clock.enabled then
|
||||
local time = wezterm.time.now():format(C.clock.format)
|
||||
window:set_right_status(wezterm.format({
|
||||
{ Background = { Color = palette.tab_bar.background } },
|
||||
{ Foreground = { Color = palette.ansi[6] } },
|
||||
{ Text = time },
|
||||
}))
|
||||
end
|
||||
end)
|
||||
|
||||
return M
|
||||
|
|
34
home/apps/wezterm/extra.lua
Normal file
34
home/apps/wezterm/extra.lua
Normal file
|
@ -0,0 +1,34 @@
|
|||
local wezterm = require("wezterm")
|
||||
|
||||
local function arrContains(arr, val)
|
||||
for _, v in ipairs(arr) do
|
||||
if v == val then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local nonpadded_apps = { "nvim", "btop", "btm" }
|
||||
|
||||
wezterm.on("smartpadding", function(window, pane)
|
||||
local fgp = pane:get_foreground_process_info()
|
||||
if fgp == nil then
|
||||
return
|
||||
elseif arrContains(nonpadded_apps, fgp.name) then
|
||||
window:set_config_overrides({
|
||||
window_padding = { left = 0, right = 0, top = 0, bottom = 0 },
|
||||
})
|
||||
else
|
||||
window:set_config_overrides({
|
||||
window_padding = wezterm.GLOBAL.smart_padding,
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
wezterm.on("update-status", function(window, pane)
|
||||
if wezterm.GLOBAL.smart_padding ~= nil then
|
||||
wezterm.emit("smartpadding", window, pane)
|
||||
end
|
||||
end)
|
|
@ -1,6 +1,35 @@
|
|||
local wezterm = require("wezterm")
|
||||
local theme = require("theme")
|
||||
require("bar")
|
||||
require("bar").setup({
|
||||
dividers = "slant_right", -- or "slant_left", "arrows", "rounded", false
|
||||
indicator = {
|
||||
leader = {
|
||||
enabled = true,
|
||||
icon_off = " ",
|
||||
icon_on = " ",
|
||||
},
|
||||
mode = {
|
||||
enabled = true,
|
||||
names = {
|
||||
resize_mode = "RESIZE",
|
||||
copy_mode = "VISUAL",
|
||||
search_mode = "SEARCH",
|
||||
},
|
||||
},
|
||||
},
|
||||
tabs = {
|
||||
numerals = "arabic", -- or "roman"
|
||||
pane_count = "superscript", -- or "subscript", false
|
||||
brackets = {
|
||||
active = { "", ":" },
|
||||
inactive = { "", ":" },
|
||||
},
|
||||
},
|
||||
clock = { -- note that this overrides the whole set_right_status
|
||||
enabled = true,
|
||||
format = "%H:%M", -- use https://wezfurlong.org/wezterm/config/lua/wezterm.time/Time/format.html
|
||||
},
|
||||
})
|
||||
|
||||
wezterm.GLOBAL = {
|
||||
font = "berkeley",
|
||||
|
|
Loading…
Reference in a new issue