local wez = require 'wezterm' local bat = require 'bugabinga.battery' local agent = require 'bugabinga.agent' ---@diagnostic disable-next-line: different-requires local nugu_dark = require 'bugabinga.nugu.palette_dark'.palette ---@diagnostic disable-next-line: different-requires local nugu_light = require 'bugabinga.nugu.palette_light'.palette local palette = nugu_dark local program_icons = { aerc = wez.nerdfonts.md_email, bat = wez.nerdfonts.md_file_document, btm = wez.nerdfonts.md_monitor_dashboard, cargo = wez.nerdfonts.dev_rust, chawan = wez.nerdfonts.md_web, claude = wez.nerdfonts.md_robot_outline, cmus = wez.nerdfonts.md_music, code = wez.nerdfonts.custom_neovim, codex = '', edit = wez.nerdfonts.custom_neovim, fd = wez.nerdfonts.md_folder_search_outline, fin = wez.nerdfonts.md_magnify, firefox = wez.nerdfonts.fa_firefox, fzf = wez.nerdfonts.md_magnify, g = wez.nerdfonts.dev_git, gh = wez.nerdfonts.dev_github_badge, git = wez.nerdfonts.dev_git, gitu = wez.nerdfonts.dev_git, glow = wez.nerdfonts.md_language_markdown, java = wez.nerdfonts.dev_java, jj = wez.nerdfonts.md_source_branch, lazygit = wez.nerdfonts.dev_git, list = wez.nerdfonts.md_folder_multiple, mise = wez.nerdfonts.md_hammer_wrench, mpv = wez.nerdfonts.fa_film, mvn = wez.nerdfonts.dev_maven, neovide = wez.nerdfonts.custom_neovim, node = wez.nerdfonts.dev_nodejs_small, npm = wez.nerdfonts.dev_npm, npx = wez.nerdfonts.dev_npm, nu = wez.nerdfonts.oct_terminal, nvim = wez.nerdfonts.custom_neovim, package = wez.nerdfonts.md_hammer_wrench, podman = wez.nerdfonts.linux_docker, python = wez.nerdfonts.dev_python, rbw = wez.nerdfonts.md_shield_key, rg = wez.nerdfonts.md_file_search, rustc = wez.nerdfonts.dev_rust, show = wez.nerdfonts.md_file_document, ssh = wez.nerdfonts.md_shield_key, topgrade = wez.nerdfonts.md_update, tree = wez.nerdfonts.md_file_tree, tre = wez.nerdfonts.md_file_tree, unpackage = wez.nerdfonts.md_hammer_wrench, uv = wez.nerdfonts.dev_python, vi = wez.nerdfonts.custom_neovim, video = wez.nerdfonts.fa_film, vim = wez.nerdfonts.custom_neovim, web = wez.nerdfonts.fa_firefox, wezterm = wez.nerdfonts.oct_terminal, yazi = wez.nerdfonts.md_folder_open, yy = wez.nerdfonts.md_folder_open, zed = wez.nerdfonts.md_code_braces, zeditor = wez.nerdfonts.md_code_braces, zig = wez.nerdfonts.dev_zig, } local clean = function ( value ) if not value or value == '' then return nil end value = value:gsub( '^%s+', '' ):gsub( '%s+$', '' ) if value == '' then return nil end return value end local basename = function ( value ) if not value or value == '' then return nil end value = value:gsub( '\\', '/' ):gsub( '/+$', '' ) return value:match '([^/]+)$' or value end local use_palette_for_scheme = function ( scheme ) palette = scheme == 'nugu-light' and nugu_light or nugu_dark end local use_palette_for_window = function ( window ) local ok, config = pcall( function () return window:effective_config() end ) if ok and config then use_palette_for_scheme( config.color_scheme ) end end local short_workspace = function ( name, max_width ) name = clean( name ) or 'default' local home = wez.home_dir if home and name:sub( 1, #home ) == home then name = '~' .. name:sub( #home + 1 ) end if name:find( '/', 1, true ) or name:find( '\\', 1, true ) then name = basename( name ) or name end return wez.truncate_right( name, max_width or 18 ) end local workspace_slug = function ( name ) local slug = short_workspace( name ):gsub( '[^%w]', '' ):sub( 1, 3 ):lower() return slug ~= '' and slug or '?' end local workspace_chips = function ( active ) active = clean( active ) or 'default' local ok, names = pcall( wez.mux.get_workspace_names ) if not ok or type( names ) ~= 'table' or #names <= 1 then return short_workspace( active ) end table.sort( names, function ( a, b ) return tostring( a ):lower() < tostring( b ):lower() end ) local parts = {} for _, name in ipairs( names ) do local label = workspace_slug( name ) if name == active then label = '[' .. short_workspace( name, 42 ) .. ']' end table.insert( parts, label ) end return table.concat( parts, ' ' ) end local function starts_with_name( title, name ) if not title or not name then return false end local lower = title:lower() name = name:lower() if lower:sub( 1, #name ) ~= name then return false end local boundary = lower:sub( #name + 1, #name + 1 ) return boundary == '' or boundary:match '%W' ~= nil end local function pane_project( pane ) local cwd = pane and pane.current_working_dir local ok, path = pcall( function () return cwd and cwd.file_path end ) return ok and path and short_workspace( path, 24 ) or nil end local tab_text = function ( tab ) local explicit = clean( tab.tab_title ) if explicit then return explicit end local pane = tab.active_pane local user_vars = pane and pane.user_vars local title = clean( pane and pane.title ) local identity = agent.identity( user_vars ) if identity == 'Pi' then local parts = { (wez.nerdfonts.md_pirate or '\u{f0a08}') .. ' Pi', } local session = clean( user_vars and user_vars.agent_session ) local project = clean( user_vars and user_vars.agent_project ) or pane_project( pane ) if session then table.insert( parts, session ) end if project and project ~= session then table.insert( parts, project ) end return table.concat( parts, ' · ' ) end local program = agent.program( user_vars ) local label = identity or program if not label then return title or 'tab' end if starts_with_name( title, label ) or starts_with_name( title, program ) then label = title else local project = pane_project( pane ) if project then label = label .. ' · ' .. project end end local icon = program_icons[program] return icon and (icon .. ' ' .. label) or label end local zoomed = function ( pane ) local tab = pane:tab() if not tab then return nil end for _, info in ipairs( tab:panes_with_info() ) do if info.is_zoomed then return 'zoom' end end return nil end local host_domain = function () local triple = wez.target_triple or '' if triple:find( 'windows', 1, true ) then return 'WIN', wez.nerdfonts.dev_windows or ' ', palette.warning end if triple:find( 'darwin', 1, true ) then return 'MAC', wez.nerdfonts.dev_apple or ' ', palette.ui.important_local end if triple:find( 'linux', 1, true ) then return 'LIN', wez.nerdfonts.dev_linux or ' ', palette.ui.important_local end if triple:find( 'bsd', 1, true ) then return 'BSD', wez.nerdfonts.md_freebsd or '󰣠 ', palette.ui.important_local end return 'LOC', wez.nerdfonts.cod_terminal or ' ', palette.ui.important_local end local domain_label = function ( domain ) if domain == 'unix' then return 'MUX', wez.nerdfonts.cod_server or wez.nerdfonts.cod_terminal or ' ', palette.info end if not domain or domain == 'local' or domain == 'Local' then return host_domain() end if domain:find( '^WSL:', 1, false ) then return 'WSL', wez.nerdfonts.dev_linux or ' ', palette.ui.important_local end if domain:find( '^scope:', 1, false ) then return 'EXE', wez.nerdfonts.cod_gear or ' ', palette.warning end return (domain:upper():gsub( '[^%w]', '' ):sub( 1, 3 ) .. 'LOC'):sub( 1, 3 ), wez.nerdfonts.cod_terminal or ' ', palette.ui.important_local end wez.on( 'format-tab-title', function ( tab, tabs, panes, config, hover, max_width ) if config then use_palette_for_scheme( config.color_scheme ) end local bg = palette.content.backdrop local fg = palette.content.minor if tab.is_active then bg = palette.ui.focus fg = palette.content.backdrop elseif hover then bg = palette.ui.accent fg = palette.content.backdrop end local marker = tab.is_active and '●' or '○' local progress, progress_state = agent.badge( tab.active_pane.progress ) if not tab.is_active and progress_state == 'working' then fg = palette.info end if not tab.is_active and progress_state == 'error' then fg = palette.error end local title = tab_text( tab ) local suffix = progress and (' ' .. progress) or '' local label = string.format( ' %s %d %s%s ', marker, tab.tab_index + 1, title, suffix ) label = wez.truncate_right( label, math.max( 1, max_width or 32 ) ) return { { Background = { Color = bg, }, }, { Foreground = { Color = fg, }, }, { Attribute = { Intensity = tab.is_active and 'Bold' or 'Normal', }, }, { Text = label, }, 'ResetAttributes', } end ) wez.on( 'format-window-title', function ( tab ) local ok, workspace = pcall( wez.mux.get_active_workspace ) workspace = ok and workspace or 'default' local title = tab and tab_text( tab ) or 'WezTerm' return '[' .. workspace .. '] ' .. title end ) wez.on( 'update-status', function ( window, pane ) local ok_status, status_error = pcall( function () agent.write_snapshot() use_palette_for_window( window ) local right = {} local key_table = window:active_key_table() if window:leader_is_active() then key_table = 'LEADER' end if key_table then right = { { Background = { Color = palette.error, }, }, { Foreground = { Color = palette.ui.backdrop, }, }, { Attribute = { Intensity = 'Bold', }, }, { Text = ' ' .. key_table .. ' ', }, 'ResetAttributes', { Text = ' ', }, } end local ok_zoom, zoomed_state = pcall( zoomed, pane ) if ok_zoom and zoomed_state then table.insert( right, { Foreground = { Color = palette.ui.minor, }, } ) table.insert( right, { Text = zoomed_state .. ' ', } ) end window:set_right_status( wez.format( right ) ) local battery = bat.get_battery_icons( palette ) if battery ~= '' then battery = ' ' .. battery .. ' ' end local ok_domain, domain = pcall( pane.get_domain_name, pane ) local domain_text, domain_icon, domain_color = domain_label( ok_domain and domain or nil ) local workspace = workspace_chips( window:active_workspace() ) window:set_left_status( wez.format { { Text = battery, }, { Foreground = { Color = palette.ui.important_local, }, }, ---@diagnostic disable-next-line: missing-fields { Attribute = { Intensity = 'Bold', }, }, { Text = '● ' .. workspace .. ' ', }, { Foreground = { Color = domain_color, }, }, { Text = domain_icon .. ' ' .. domain_text .. ' ', }, 'ResetAttributes', } ) end ) if not ok_status then wez.log_error( 'status render failed: ' .. tostring( status_error ) ) window:set_right_status( wez.format { { Foreground = { Color = palette.error, }, }, { Text = ' status error ', }, } ) end end ) return function ( cfg ) ---@cast cfg Config cfg.enable_tab_bar = true cfg.hide_tab_bar_if_only_one_tab = false cfg.use_fancy_tab_bar = false cfg.tab_max_width = 128 cfg.show_tabs_in_tab_bar = true cfg.show_new_tab_button_in_tab_bar = false cfg.tab_bar_at_bottom = true end