Created
May 4, 2026 04:57
-
-
Save itsmeadarsh2008/103dccb6237ed674d4ea991333bf4c05 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- ╔══════════════════════════════════════════════════════════════════════════╗ | |
| -- ║ The World's Best WezTerm Configuration ║ | |
| -- ║ Platform : Linux / Fedora (NVIDIA) ║ | |
| -- ║ Renderer : OpenGL · adaptive fps ║ | |
| -- ║ Font : JetBrainsMono Nerd Font ║ | |
| -- ║ Theme : Tokyo Night Storm ║ | |
| -- ╚══════════════════════════════════════════════════════════════════════════╝ | |
| local wezterm = require("wezterm") | |
| local act = wezterm.action | |
| local mux = wezterm.mux | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 🎨 PALETTE (Tokyo Night Storm) | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local P = { | |
| bg0 = "#1a1b26", | |
| bg1 = "#1f2035", | |
| bg2 = "#24283b", | |
| bg3 = "#2a2e4a", | |
| bg4 = "#364068", | |
| fg0 = "#c0caf5", | |
| fg1 = "#a9b1d6", | |
| fg2 = "#9aa5ce", | |
| fg3 = "#565f89", | |
| red = "#f7768e", | |
| orange = "#ff9e64", | |
| yellow = "#e0af68", | |
| green = "#9ece6a", | |
| teal = "#1abc9c", | |
| cyan = "#7dcfff", | |
| blue = "#7aa2f7", | |
| purple = "#bb9af7", | |
| pink = "#ff75a0", | |
| } | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- ⌨️ LEADER KEY | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local LEADER = { key = "RightControl", mods = "NONE", timeout_milliseconds = 2000 } | |
| local STATUS_BG = "rgba(26, 27, 38, 0.00)" | |
| local BACKGROUND_DIR = wezterm.home_dir .. "/.config/wezterm/terminal-backgrounds" | |
| local BACKGROUND_IMAGE_HSB = { brightness = 0.75, hue = 1.0, saturation = 1.0 } | |
| local BACKGROUND_READABILITY_OVERLAY = "rgba(15, 18, 29, 0.40)" | |
| local TAB_BAR_COLORS_TRANSPARENT = { | |
| background = "rgba(26, 27, 38, 0.00)", | |
| active_tab = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg0, intensity = "Bold" }, | |
| inactive_tab = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg3 }, | |
| inactive_tab_hover = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg2 }, | |
| new_tab = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg3 }, | |
| new_tab_hover = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.purple }, | |
| } | |
| local BACKGROUND_GRADIENT_SOURCE = { | |
| Gradient = { | |
| orientation = { Linear = { angle = -45.0 } }, | |
| colors = { | |
| "#1c1a22", | |
| "#1a1b26", | |
| "#1a1b26", | |
| "#1a1d27", | |
| }, | |
| blend = "LinearRgb", | |
| noise = 24, | |
| }, | |
| } | |
| local background_files = {} | |
| local current_background_idx = 0 | |
| local function ensure_wezterm_runtime_dir() | |
| local runtime_dir = os.getenv("XDG_RUNTIME_DIR") | |
| if not runtime_dir or runtime_dir == "" then | |
| return | |
| end | |
| local wezterm_runtime_dir = runtime_dir .. "/wezterm" | |
| os.execute(string.format('mkdir -p %q >/dev/null 2>&1', wezterm_runtime_dir)) | |
| end | |
| local function normalize_gui_window(window) | |
| if not window then | |
| return nil | |
| end | |
| if type(window.get_config_overrides) == "function" and type(window.set_config_overrides) == "function" then | |
| return window | |
| end | |
| if type(window.gui_window) == "function" then | |
| local ok, gui = pcall(function() | |
| return window:gui_window() | |
| end) | |
| if ok and gui and type(gui.get_config_overrides) == "function" and type(gui.set_config_overrides) == "function" then | |
| return gui | |
| end | |
| end | |
| return nil | |
| end | |
| local function get_overrides(window) | |
| local gui_window = normalize_gui_window(window) | |
| if not gui_window then | |
| return nil, nil | |
| end | |
| local ok, overrides = pcall(function() | |
| return gui_window:get_config_overrides() | |
| end) | |
| if not ok or type(overrides) ~= "table" then | |
| overrides = {} | |
| end | |
| return gui_window, overrides | |
| end | |
| ensure_wezterm_runtime_dir() | |
| local function refresh_background_files() | |
| background_files = {} | |
| if not os.rename(BACKGROUND_DIR, BACKGROUND_DIR) then | |
| return | |
| end | |
| local cmd = string.format('find %q -maxdepth 1 -type f | sort 2>/dev/null', BACKGROUND_DIR) | |
| local p = io.popen(cmd) | |
| if not p then | |
| return | |
| end | |
| for line in p:lines() do | |
| if line and line ~= "" then | |
| table.insert(background_files, line) | |
| end | |
| end | |
| p:close() | |
| end | |
| local function background_layers_for_path(path) | |
| if path then | |
| return { | |
| { | |
| source = { File = path }, | |
| hsb = BACKGROUND_IMAGE_HSB, | |
| horizontal_align = "Center", | |
| vertical_align = "Middle", | |
| repeat_x = "NoRepeat", | |
| repeat_y = "NoRepeat", | |
| }, | |
| { | |
| source = { Color = BACKGROUND_READABILITY_OVERLAY }, | |
| width = "100%", | |
| height = "100%", | |
| }, | |
| } | |
| end | |
| return { | |
| { source = BACKGROUND_GRADIENT_SOURCE }, | |
| { | |
| source = { Color = BACKGROUND_READABILITY_OVERLAY }, | |
| width = "100%", | |
| height = "100%", | |
| }, | |
| } | |
| end | |
| local function set_tab_bar_background_mode(overrides, transparent) | |
| if transparent then | |
| if type(overrides.colors) ~= "table" then | |
| overrides.colors = {} | |
| end | |
| overrides.colors.tab_bar = TAB_BAR_COLORS_TRANSPARENT | |
| return | |
| end | |
| if type(overrides.colors) == "table" then | |
| overrides.colors.tab_bar = nil | |
| if next(overrides.colors) == nil then | |
| overrides.colors = nil | |
| end | |
| end | |
| end | |
| local function set_background_by_index(window, idx) | |
| local gui_window, overrides = get_overrides(window) | |
| if not gui_window then | |
| return | |
| end | |
| if idx == 0 then | |
| set_tab_bar_background_mode(overrides, false) | |
| overrides.background = nil | |
| overrides.window_background_image = nil | |
| overrides.window_background_image_hsb = nil | |
| gui_window:set_config_overrides(overrides) | |
| return | |
| end | |
| local path = background_files[idx] | |
| if not path then | |
| return | |
| end | |
| set_tab_bar_background_mode(overrides, true) | |
| overrides.background = background_layers_for_path(path) | |
| overrides.window_background_image = nil | |
| overrides.window_background_image_hsb = nil | |
| gui_window:set_config_overrides(overrides) | |
| end | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 📊 RIGHT STATUS BAR | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 🔋 ADAPTIVE GPU — low battery → Software, charging/high → OpenGL | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local LOW_BATTERY_THRESHOLD = 15 | |
| local CPU_FPS = 30 -- low-power software rendering on critical battery | |
| local BAT_FPS = 60 -- balanced software rendering on normal battery | |
| local GPU_FPS = 120 -- full performance when charging | |
| local last_front_end = "OpenGL" | |
| local manual_front_end = nil -- nil = adaptive mode | |
| local DEFAULT_WEBGPU_POWER_PREFERENCE = "HighPerformance" | |
| local WEBGPU_LOWPOWER_THRESHOLD = 20 | |
| local manual_webgpu_power_preference = nil -- nil = battery-aware auto | |
| local FRONT_END_CYCLE = { "OpenGL", "WebGpu", "Software" } | |
| local function next_front_end(current) | |
| for i, v in ipairs(FRONT_END_CYCLE) do | |
| if v == current then | |
| return FRONT_END_CYCLE[(i % #FRONT_END_CYCLE) + 1] | |
| end | |
| end | |
| return FRONT_END_CYCLE[1] | |
| end | |
| local function get_power_state() | |
| local ok, bats = pcall(wezterm.battery_info) | |
| if not ok or not bats or #bats == 0 then | |
| return nil, nil, nil | |
| end | |
| -- Use all available batteries and prefer capacity-weighted percentage. | |
| local weighted_charge = 0 | |
| local weighted_capacity = 0 | |
| for _, b in ipairs(bats) do | |
| local soc = tonumber(b.state_of_charge) | |
| if soc then | |
| local cap = tonumber(b.charge_full) or tonumber(b.energy_full) or 1 | |
| if cap <= 0 then | |
| cap = 1 | |
| end | |
| weighted_charge = weighted_charge + (soc * cap) | |
| weighted_capacity = weighted_capacity + cap | |
| end | |
| end | |
| if weighted_capacity == 0 then | |
| return nil, nil, nil | |
| end | |
| local pct = math.floor((weighted_charge / weighted_capacity) * 100 + 0.5) | |
| pct = math.max(0, math.min(100, pct)) | |
| local state = bats[1].state -- "Charging", "Discharging", "Full", "Empty", "Unknown" | |
| local charging = false | |
| for _, b in ipairs(bats) do | |
| local s = b.state | |
| if s == "Charging" or s == "Full" then | |
| charging = true | |
| break | |
| end | |
| end | |
| return pct, charging, state | |
| end | |
| wezterm.on("cycle-render-front-end", function(window, _) | |
| local gui_window, overrides = get_overrides(window) | |
| if not gui_window then | |
| return | |
| end | |
| local current = manual_front_end or overrides.front_end or last_front_end or "OpenGL" | |
| local nxt = next_front_end(current) | |
| manual_front_end = nxt | |
| overrides.front_end = nxt | |
| gui_window:set_config_overrides(overrides) | |
| end) | |
| wezterm.on("set-render-front-end-auto", function(window, _) | |
| manual_front_end = nil | |
| local gui_window, overrides = get_overrides(window) | |
| if not gui_window then | |
| return | |
| end | |
| overrides.front_end = nil | |
| gui_window:set_config_overrides(overrides) | |
| end) | |
| wezterm.on("toggle-webgpu-power-preference", function(window, _) | |
| if manual_webgpu_power_preference == "HighPerformance" then | |
| manual_webgpu_power_preference = "LowPower" | |
| else | |
| manual_webgpu_power_preference = "HighPerformance" | |
| end | |
| local gui_window, overrides = get_overrides(window) | |
| if not gui_window then | |
| return | |
| end | |
| overrides.webgpu_power_preference = manual_webgpu_power_preference | |
| gui_window:set_config_overrides(overrides) | |
| end) | |
| wezterm.on("set-background-none", function(window, _) | |
| refresh_background_files() | |
| current_background_idx = 0 | |
| set_background_by_index(window, 0) | |
| end) | |
| wezterm.on("cycle-background-image", function(window, _) | |
| refresh_background_files() | |
| current_background_idx = current_background_idx + 1 | |
| if current_background_idx > #background_files then | |
| current_background_idx = 0 | |
| end | |
| set_background_by_index(window, current_background_idx) | |
| end) | |
| wezterm.on("set-webgpu-power-preference-auto", function(window, _) | |
| manual_webgpu_power_preference = nil | |
| local gui_window, overrides = get_overrides(window) | |
| if not gui_window then | |
| return | |
| end | |
| overrides.webgpu_power_preference = nil | |
| gui_window:set_config_overrides(overrides) | |
| end) | |
| wezterm.on("augment-command-palette", function(_, _) | |
| return { | |
| { | |
| brief = "Renderer: Toggle OpenGL -> WebGpu -> Software", | |
| icon = "md_monitor", | |
| action = act.EmitEvent("cycle-render-front-end"), | |
| }, | |
| { | |
| brief = "Renderer: Adaptive (Auto)", | |
| icon = "md_restore", | |
| action = act.EmitEvent("set-render-front-end-auto"), | |
| }, | |
| { | |
| brief = "WebGpu Power: Toggle HighPerformance / LowPower", | |
| icon = "md_speedometer", | |
| action = act.EmitEvent("toggle-webgpu-power-preference"), | |
| }, | |
| { | |
| brief = "WebGpu Power: Auto (Battery-aware)", | |
| icon = "md_battery_sync", | |
| action = act.EmitEvent("set-webgpu-power-preference-auto"), | |
| }, | |
| { | |
| brief = "Background: Cycle next image", | |
| icon = "md_image", | |
| action = act.EmitEvent("cycle-background-image"), | |
| }, | |
| { | |
| brief = "Background: No background", | |
| icon = "md_image_off", | |
| action = act.EmitEvent("set-background-none"), | |
| }, | |
| } | |
| end) | |
| -- 🎵 MPRIS media detection via D-Bus (cached, single shell call) | |
| local mpris_cache = { status = nil, title = "", pos_s = nil, pos_sample_t = 0, ts = 0 } | |
| local MPRIS_TTL = 2 | |
| local function monotonic_time() | |
| return os.clock() | |
| end | |
| local viz_state = { | |
| levels = { 0.12, 0.2, 0.28, 0.18, 0.35, 0.22, 0.4, 0.24, 0.3, 0.2, 0.26, 0.16 }, | |
| vel = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | |
| phases = { 0.1, 0.7, 1.3, 1.9, 2.4, 3.0, 3.6, 4.2, 4.8, 5.4, 5.9, 6.4 }, | |
| speeds = { 1.15, 1.28, 1.42, 1.33, 1.55, 1.46, 1.62, 1.38, 1.51, 1.27, 1.44, 1.58 }, | |
| last = monotonic_time(), | |
| } | |
| local function get_mpris_now_playing() | |
| local now = os.time() | |
| local now_mono = monotonic_time() | |
| if now - mpris_cache.ts < MPRIS_TTL then | |
| local est_pos = mpris_cache.pos_s | |
| if est_pos and mpris_cache.status == "Playing" then | |
| est_pos = est_pos + math.max(0, now_mono - mpris_cache.pos_sample_t) | |
| end | |
| return mpris_cache.status, mpris_cache.title, est_pos | |
| end | |
| mpris_cache.ts = now | |
| local h = io.popen([[bash -c ' | |
| p=$(dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus \ | |
| org.freedesktop.DBus.ListNames 2>/dev/null | grep -oP "\"org\.mpris\.MediaPlayer2\.[^\"]+\"" | head -1 | tr -d "\"") | |
| [ -z "$p" ] && exit 0 | |
| dbus-send --print-reply --dest="$p" /org/mpris/MediaPlayer2 \ | |
| org.freedesktop.DBus.Properties.GetAll \ | |
| string:"org.mpris.MediaPlayer2.Player" 2>/dev/null | |
| ' 2>/dev/null]]) | |
| if not h then | |
| return nil, "" | |
| end | |
| local blob = h:read("*a") | |
| h:close() | |
| if not blob or blob == "" then | |
| mpris_cache.status = nil | |
| mpris_cache.title = "" | |
| mpris_cache.pos_s = nil | |
| mpris_cache.pos_sample_t = now_mono | |
| return nil, "", nil | |
| end | |
| local status = blob:match('PlaybackStatus.-string "(%w+)"') | |
| local title = blob:match('xesam:title.-string "([^"]+)"') or "" | |
| local pos_us = tonumber(blob:match("Position.-int64%s+([%d]+)")) | |
| local pos_s = pos_us and (pos_us / 1000000.0) or nil | |
| if title == "" then | |
| -- Fallback: some players expose only artist metadata. | |
| title = blob:match('xesam:artist.-string "([^"]+)"') or "" | |
| end | |
| if #title > 48 then | |
| title = title:sub(1, 45) .. "..." | |
| end | |
| mpris_cache.status = status | |
| mpris_cache.title = title | |
| mpris_cache.pos_s = pos_s | |
| mpris_cache.pos_sample_t = now_mono | |
| local est_pos = pos_s | |
| if est_pos and status == "Playing" then | |
| est_pos = est_pos + math.max(0, now_mono - mpris_cache.pos_sample_t) | |
| end | |
| return status, title, est_pos | |
| end | |
| local function smooth_noise(x) | |
| return math.sin(x * 1.00) * 0.58 + math.sin(x * 0.57 + 0.8) * 0.30 + math.sin(x * 0.23 + 1.7) * 0.12 | |
| end | |
| local function update_visualizer_smooth(play_pos_s, playing) | |
| local now = monotonic_time() | |
| local dt = now - viz_state.last | |
| dt = math.max(1 / 240, math.min(dt, 0.03)) | |
| viz_state.last = now | |
| local alpha = 1 - math.exp(-dt * 26.0) | |
| for i = 1, #viz_state.levels do | |
| local lvl = viz_state.levels[i] | |
| local p | |
| if playing and play_pos_s then | |
| p = play_pos_s * (viz_state.speeds[i] * 2.8) + i * 0.67 | |
| else | |
| viz_state.phases[i] = viz_state.phases[i] + (viz_state.speeds[i] * dt * 1.6) | |
| p = viz_state.phases[i] | |
| end | |
| local groove_t = play_pos_s or (now * 1.8) | |
| local beat = 0.5 + 0.5 * math.sin(groove_t * 2.25 * math.pi) | |
| local wave = smooth_noise(p + beat * 0.85 + i * 0.11) | |
| local tgt = math.max(0.06, math.min(0.98, 0.5 + wave * (0.28 + beat * 0.12))) | |
| -- Critically damped-ish spring for high-fps, non-jittery motion. | |
| local v = viz_state.vel[i] | |
| local spring = (tgt - lvl) * (18.0 + beat * 4.0) | |
| local damp = v * (8.2 + beat * 1.2) | |
| v = v + (spring - damp) * dt | |
| lvl = lvl + v * dt | |
| lvl = lvl + (tgt - lvl) * alpha * 0.35 | |
| viz_state.vel[i] = v | |
| viz_state.levels[i] = math.max(0.05, math.min(0.99, lvl)) | |
| end | |
| end | |
| local function format_cwd_for_status(path) | |
| local parts = {} | |
| for seg in path:gmatch("[^/]+") do | |
| table.insert(parts, seg) | |
| end | |
| local display = path | |
| local prefix = "" | |
| if #parts > 3 then | |
| prefix = "…/" | |
| parts = { parts[#parts - 2], parts[#parts - 1], parts[#parts] } | |
| end | |
| local colors = { P.green, P.yellow, P.orange, P.blue, P.purple } | |
| local segments = {} | |
| if path:sub(1, 1) == "/" then | |
| table.insert(segments, { Foreground = { Color = P.blue } }) | |
| table.insert(segments, { Text = "/" }) | |
| end | |
| if prefix ~= "" then | |
| table.insert(segments, { Foreground = { Color = P.fg3 } }) | |
| table.insert(segments, { Text = prefix }) | |
| end | |
| for i, seg in ipairs(parts) do | |
| table.insert(segments, { Foreground = { Color = colors[(i - 1) % #colors + 1] } }) | |
| table.insert(segments, { Text = seg }) | |
| if i < #parts then | |
| table.insert(segments, { Foreground = { Color = P.fg3 } }) | |
| table.insert(segments, { Text = "/" }) | |
| end | |
| end | |
| return display, segments | |
| end | |
| wezterm.on("update-right-status", function(window, pane) | |
| local ok, err = pcall(function() | |
| local cells = {} | |
| local function cell(fg, txt) | |
| table.insert(cells, { Background = { Color = STATUS_BG } }) | |
| table.insert(cells, { Foreground = { Color = fg } }) | |
| table.insert(cells, { Text = txt }) | |
| end | |
| -- Mode pill (only shown when a special key table or leader is active) | |
| local kt = window:active_key_table() | |
| local mode_color, mode_label | |
| if kt == "resize_pane" then | |
| mode_color = P.orange | |
| mode_label = " RESIZE " | |
| elseif kt == "move_tab" then | |
| mode_color = P.cyan | |
| mode_label = " MOVE " | |
| elseif window:leader_is_active() then | |
| mode_color = P.purple | |
| mode_label = " LEADER " | |
| end | |
| if mode_label then | |
| table.insert(cells, { Attribute = { Intensity = "Bold" } }) | |
| cell(mode_color, " " .. mode_label .. " ") | |
| table.insert(cells, { Attribute = { Intensity = "Normal" } }) | |
| end | |
| -- 🎵 Music visualiser (MPRIS via D-Bus, no playerctl needed) | |
| local music_status, music_title, music_pos_s = get_mpris_now_playing() | |
| if music_status == "Playing" then | |
| cell(P.bg0, " ") | |
| -- Clean non-dot block progression + neighbor smoothing for a continuous curve. | |
| local bar_chars = { "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" } | |
| local bar_colors = { | |
| P.pink, | |
| P.purple, | |
| P.blue, | |
| P.cyan, | |
| P.teal, | |
| P.green, | |
| P.yellow, | |
| P.orange, | |
| P.pink, | |
| P.purple, | |
| P.blue, | |
| P.cyan, | |
| } | |
| update_visualizer_smooth(music_pos_s, true) | |
| for i = 1, #viz_state.levels do | |
| local prev = viz_state.levels[i - 1] or viz_state.levels[i] | |
| local curr = viz_state.levels[i] | |
| local next = viz_state.levels[i + 1] or viz_state.levels[i] | |
| local smooth_level = prev * 0.22 + curr * 0.56 + next * 0.22 | |
| local idx = math.max(1, math.min(#bar_chars, math.floor(smooth_level * (#bar_chars - 1) + 1.5))) | |
| table.insert(cells, { Background = { Color = STATUS_BG } }) | |
| table.insert(cells, { Foreground = { Color = bar_colors[i] } }) | |
| table.insert(cells, { Text = bar_chars[idx] }) | |
| end | |
| if music_title ~= "" then | |
| cell(P.fg0, " " .. music_title) | |
| end | |
| elseif music_status == "Paused" then | |
| cell(P.fg3, " ") | |
| if music_title ~= "" then | |
| cell(P.fg3, " " .. music_title) | |
| end | |
| end | |
| -- CWD | |
| local cwd_uri = pane:get_current_working_dir() | |
| local cwd_segments = {} | |
| if cwd_uri then | |
| local path = cwd_uri.file_path or tostring(cwd_uri) | |
| local _, segments = format_cwd_for_status(path) | |
| cwd_segments = segments | |
| end | |
| cell(P.cyan, " ") | |
| for _, segment in ipairs(cwd_segments) do | |
| table.insert(cells, segment) | |
| end | |
| if #cwd_segments == 0 then | |
| cell(P.fg1, "unknown") | |
| end | |
| -- Clock | |
| cell(P.blue, " ") | |
| cell(P.fg1, wezterm.strftime("%H:%M %a %d %b")) | |
| -- Battery + Charging mode + Adaptive GPU | |
| local pct, charging, state = get_power_state() | |
| if pct then | |
| -- nf-md-battery icons: 10 levels + charging variants | |
| local bat_icons = { "", "", "", "", "", "", "", "", "", "", "" } | |
| local bat_charging = | |
| { "", "", "", "", "", "", "", "", "", "", "" } | |
| local level = math.max(0, math.min(10, math.floor(pct / 10))) | |
| local ico = charging and bat_charging[level + 1] or bat_icons[level + 1] | |
| local bat_color, bat_dim | |
| if state == "Discharging" then | |
| bat_color = P.fg3 | |
| bat_dim = true | |
| else | |
| if pct < 20 then | |
| bat_color = P.red | |
| elseif pct < 50 then | |
| bat_color = P.orange | |
| elseif pct < 80 then | |
| bat_color = P.green | |
| else | |
| bat_color = P.teal | |
| end | |
| end | |
| local discharge_ico = (state == "Discharging") and " " or "" | |
| cell(bat_color, " " .. ico .. discharge_ico .. " " .. pct .. "%") | |
| -- Adaptive renderer: | |
| -- Charging -> OpenGL @ 120fps | |
| -- Discharging -> Software (<=15% keeps 30fps, otherwise 60fps) | |
| local desired_front_end, desired_fps | |
| if not charging and pct <= LOW_BATTERY_THRESHOLD then | |
| desired_front_end = "Software" | |
| desired_fps = CPU_FPS | |
| elseif not charging then | |
| desired_front_end = "Software" | |
| desired_fps = BAT_FPS | |
| else | |
| desired_front_end = "OpenGL" | |
| desired_fps = GPU_FPS | |
| end | |
| if manual_front_end then | |
| desired_front_end = manual_front_end | |
| end | |
| local desired_webgpu_power_preference = DEFAULT_WEBGPU_POWER_PREFERENCE | |
| if manual_webgpu_power_preference then | |
| desired_webgpu_power_preference = manual_webgpu_power_preference | |
| elseif desired_front_end == "WebGpu" and not charging and pct <= WEBGPU_LOWPOWER_THRESHOLD then | |
| desired_webgpu_power_preference = "LowPower" | |
| end | |
| local gui_window, overrides = get_overrides(window) | |
| if gui_window then | |
| local overrides_changed = false | |
| if desired_front_end ~= last_front_end or overrides.max_fps ~= desired_fps then | |
| last_front_end = desired_front_end | |
| overrides.front_end = desired_front_end | |
| overrides.max_fps = desired_fps | |
| overrides.animation_fps = desired_fps | |
| overrides_changed = true | |
| end | |
| if desired_front_end == "WebGpu" then | |
| if overrides.webgpu_power_preference ~= desired_webgpu_power_preference then | |
| overrides.webgpu_power_preference = desired_webgpu_power_preference | |
| overrides_changed = true | |
| end | |
| elseif overrides.webgpu_power_preference ~= nil then | |
| overrides.webgpu_power_preference = nil | |
| overrides_changed = true | |
| end | |
| if overrides_changed then | |
| gui_window:set_config_overrides(overrides) | |
| end | |
| end | |
| local gpu_label = (last_front_end == "OpenGL") and (" GPU(" .. desired_fps .. "fps)") | |
| or (" CPU(" .. desired_fps .. "fps)") | |
| local gpu_color = bat_dim and P.fg3 or ((last_front_end == "OpenGL") and P.teal or P.orange) | |
| cell(gpu_color, " " .. gpu_label) | |
| end | |
| cell(P.bg0, " ") | |
| window:set_right_status(wezterm.format(cells)) | |
| window:set_left_status("") | |
| end) | |
| if not ok then | |
| -- Never drop the whole status bar if any segment errors. | |
| window:set_left_status("") | |
| window:set_right_status(wezterm.format({ | |
| { Background = { Color = STATUS_BG } }, | |
| { Foreground = { Color = P.red } }, | |
| { Text = " status error " }, | |
| { Foreground = { Color = P.fg2 } }, | |
| { Text = tostring(err) }, | |
| })) | |
| end | |
| end) | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 🏷️ TAB TITLE (process icon · full name · zoom indicator) | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local PROC_ICONS = { | |
| nvim = " ", | |
| vim = " ", | |
| bash = " ", | |
| zsh = " ", | |
| fish = " ", | |
| python = " ", | |
| python3 = " ", | |
| node = " ", | |
| cargo = " ", | |
| rustc = " ", | |
| go = " ", | |
| git = " ", | |
| ssh = " ", | |
| docker = " ", | |
| kubectl = " ", | |
| htop = " ", | |
| btop = " ", | |
| lazygit = " ", | |
| yazi = " ", | |
| helix = " ", | |
| make = " ", | |
| gcc = " ", | |
| clang = " ", | |
| } | |
| local PROC_COLORS = { | |
| nvim = P.green, | |
| vim = P.green, | |
| bash = P.yellow, | |
| zsh = P.cyan, | |
| fish = P.teal, | |
| python = P.yellow, | |
| python3 = P.yellow, | |
| node = P.green, | |
| cargo = P.orange, | |
| rustc = P.orange, | |
| go = P.cyan, | |
| git = P.orange, | |
| ssh = P.purple, | |
| docker = P.blue, | |
| kubectl = P.cyan, | |
| htop = P.red, | |
| btop = P.red, | |
| lazygit = P.orange, | |
| yazi = P.yellow, | |
| helix = P.purple, | |
| } | |
| wezterm.on("format-tab-title", function(tab, _, _, cfg, _, max_width) | |
| local pane = tab.active_pane | |
| local proc = (pane.foreground_process_name or ""):match("([^/]+)$") or "" | |
| local key = proc:lower() | |
| local ico = PROC_ICONS[key] or " " | |
| local color = PROC_COLORS[key] or P.fg3 | |
| local title = (tab.tab_title and #tab.tab_title > 0) and tab.tab_title | |
| or (pane.title or ("Tab " .. (tab.tab_index + 1))) | |
| local zoom = pane.is_zoomed and " " or "" | |
| -- Hard cap at 16 chars for a compact tab bar | |
| local limit = math.min(16, max_width - 6) | |
| if #title > limit then | |
| title = title:sub(1, limit - 1) .. "…" | |
| end | |
| local active = tab.is_active | |
| local tab_palette = { P.blue, P.purple, P.teal, P.orange } | |
| local accent_base = tab_palette[(tab.tab_index % #tab_palette) + 1] | |
| local accent = active and accent_base or P.bg0 | |
| local fg = active and P.fg0 or P.fg3 | |
| local title_bg = "rgba(26, 27, 38, 0.00)" | |
| if cfg and cfg.colors and cfg.colors.tab_bar and cfg.colors.tab_bar.background then | |
| title_bg = cfg.colors.tab_bar.background | |
| end | |
| return wezterm.format({ | |
| { Background = { Color = title_bg } }, | |
| { Foreground = { Color = accent } }, | |
| { Text = "▎" }, | |
| { Foreground = { Color = color } }, | |
| { Attribute = { Intensity = active and "Bold" or "Normal" } }, | |
| { Text = ico }, | |
| { Foreground = { Color = fg } }, | |
| { Text = title .. zoom .. " " }, | |
| }) | |
| end) | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 🚀 LAUNCH MENU (icon-rich, shown via LEADER+Space fuzzy launcher) | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local launch_menu = { | |
| -- Shells | |
| { label = " bash", args = { "bash", "-l" } }, | |
| { label = " zsh", args = { "zsh", "-l" } }, | |
| { label = " fish", args = { "fish", "-l" } }, | |
| -- Editors | |
| { label = " nvim", args = { "nvim" } }, | |
| { label = " vim", args = { "vim" } }, | |
| { label = " helix", args = { "hx" } }, | |
| -- Git | |
| { label = " lazygit", args = { "lazygit" } }, | |
| { label = " git status", args = { "bash", "-c", "git status; exec bash" } }, | |
| { label = " git log --graph", args = { "bash", "-c", "git log --oneline --graph --all -30; exec bash" } }, | |
| -- Files & System | |
| { label = " yazi (file manager)", args = { "yazi" } }, | |
| { label = " btop (resources)", args = { "btop" } }, | |
| { label = " htop (processes)", args = { "htop" } }, | |
| { label = " df -h (disk usage)", args = { "bash", "-c", "df -h; exec bash" } }, | |
| -- REPLs | |
| { label = " python3 REPL", args = { "python3" } }, | |
| { label = " node REPL", args = { "node" } }, | |
| { label = " lua REPL", args = { "lua" } }, | |
| -- Containers | |
| { label = " docker alpine shell", args = { "bash", "-c", "docker run -it --rm alpine sh" } }, | |
| { label = " docker ps", args = { "bash", "-c", "docker ps -a; exec bash" } }, | |
| -- Network | |
| { | |
| label = " ss -tulnp (ports)", | |
| args = { "bash", "-c", "ss -tulnp 2>/dev/null || netstat -tulnp; exec bash" }, | |
| }, | |
| } | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- ⌨️ KEY TABLES (modal) | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local key_tables = { | |
| resize_pane = { | |
| { key = "h", action = act.AdjustPaneSize({ "Left", 5 }) }, | |
| { key = "j", action = act.AdjustPaneSize({ "Down", 5 }) }, | |
| { key = "k", action = act.AdjustPaneSize({ "Up", 5 }) }, | |
| { key = "l", action = act.AdjustPaneSize({ "Right", 5 }) }, | |
| { key = "LeftArrow", action = act.AdjustPaneSize({ "Left", 5 }) }, | |
| { key = "DownArrow", action = act.AdjustPaneSize({ "Down", 5 }) }, | |
| { key = "UpArrow", action = act.AdjustPaneSize({ "Up", 5 }) }, | |
| { key = "RightArrow", action = act.AdjustPaneSize({ "Right", 5 }) }, | |
| { key = "Escape", action = act.PopKeyTable }, | |
| { key = "q", action = act.PopKeyTable }, | |
| { key = "Enter", action = act.PopKeyTable }, | |
| }, | |
| move_tab = { | |
| { key = "h", action = act.MoveTabRelative(-1) }, | |
| { key = "l", action = act.MoveTabRelative(1) }, | |
| { key = "LeftArrow", action = act.MoveTabRelative(-1) }, | |
| { key = "RightArrow", action = act.MoveTabRelative(1) }, | |
| { key = "Escape", action = act.PopKeyTable }, | |
| { key = "q", action = act.PopKeyTable }, | |
| }, | |
| copy_mode = { | |
| { key = "h", action = act.CopyMode("MoveLeft") }, | |
| { key = "j", action = act.CopyMode("MoveDown") }, | |
| { key = "k", action = act.CopyMode("MoveUp") }, | |
| { key = "l", action = act.CopyMode("MoveRight") }, | |
| { key = "w", action = act.CopyMode("MoveForwardWord") }, | |
| { key = "b", action = act.CopyMode("MoveBackwardWord") }, | |
| { key = "e", action = act.CopyMode("MoveForwardWordEnd") }, | |
| { key = "0", action = act.CopyMode("MoveToStartOfLine") }, | |
| { key = "$", action = act.CopyMode("MoveToEndOfLineContent") }, | |
| { key = "^", action = act.CopyMode("MoveToStartOfLineContent") }, | |
| { key = "G", action = act.CopyMode("MoveToScrollbackBottom") }, | |
| { key = "g", action = act.CopyMode("MoveToScrollbackTop") }, | |
| { key = "d", mods = "CTRL", action = act.CopyMode({ MoveByPage = 0.5 }) }, | |
| { key = "u", mods = "CTRL", action = act.CopyMode({ MoveByPage = -0.5 }) }, | |
| { key = "f", mods = "CTRL", action = act.CopyMode("PageDown") }, | |
| { key = "b", mods = "CTRL", action = act.CopyMode("PageUp") }, | |
| { key = "/", action = act.Search({ CaseInSensitiveString = "" }) }, | |
| { key = "n", action = act.CopyMode("NextMatch") }, | |
| { key = "N", action = act.CopyMode("PriorMatch") }, | |
| { key = "v", action = act.CopyMode({ SetSelectionMode = "Cell" }) }, | |
| { key = "V", action = act.CopyMode({ SetSelectionMode = "Line" }) }, | |
| { key = "v", mods = "CTRL", action = act.CopyMode({ SetSelectionMode = "Block" }) }, | |
| { | |
| key = "y", | |
| action = act.Multiple({ | |
| { CopyTo = "ClipboardAndPrimarySelection" }, | |
| { CopyMode = "Close" }, | |
| }), | |
| }, | |
| { | |
| key = "Enter", | |
| action = act.Multiple({ | |
| { CopyTo = "ClipboardAndPrimarySelection" }, | |
| { CopyMode = "Close" }, | |
| }), | |
| }, | |
| { key = "Escape", action = act.CopyMode("Close") }, | |
| { key = "q", action = act.CopyMode("Close") }, | |
| }, | |
| search_mode = { | |
| { key = "Enter", action = act.CopyMode("NextMatch") }, | |
| { key = "n", action = act.CopyMode("NextMatch") }, | |
| { key = "N", action = act.CopyMode("PriorMatch") }, | |
| { key = "Escape", action = act.CopyMode("Close") }, | |
| { key = "r", mods = "CTRL", action = act.CopyMode("CycleMatchType") }, | |
| }, | |
| } | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- ⌨️ KEY BINDINGS | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local keys = { | |
| -- Tabs | |
| { key = "t", mods = "CTRL|SHIFT", action = act.SpawnTab("CurrentPaneDomain") }, | |
| { key = "w", mods = "CTRL|SHIFT", action = act.CloseCurrentTab({ confirm = true }) }, | |
| { key = "c", mods = "LEADER", action = act.SpawnTab("CurrentPaneDomain") }, | |
| { key = "&", mods = "LEADER", action = act.CloseCurrentTab({ confirm = true }) }, | |
| { key = "1", mods = "ALT", action = act.ActivateTab(0) }, | |
| { key = "2", mods = "ALT", action = act.ActivateTab(1) }, | |
| { key = "3", mods = "ALT", action = act.ActivateTab(2) }, | |
| { key = "4", mods = "ALT", action = act.ActivateTab(3) }, | |
| { key = "5", mods = "ALT", action = act.ActivateTab(4) }, | |
| { key = "6", mods = "ALT", action = act.ActivateTab(5) }, | |
| { key = "7", mods = "ALT", action = act.ActivateTab(6) }, | |
| { key = "8", mods = "ALT", action = act.ActivateTab(7) }, | |
| { key = "9", mods = "ALT", action = act.ActivateTab(-1) }, | |
| { key = "1", mods = "LEADER", action = act.ActivateTab(0) }, | |
| { key = "2", mods = "LEADER", action = act.ActivateTab(1) }, | |
| { key = "3", mods = "LEADER", action = act.ActivateTab(2) }, | |
| { key = "4", mods = "LEADER", action = act.ActivateTab(3) }, | |
| { key = "5", mods = "LEADER", action = act.ActivateTab(4) }, | |
| { key = "6", mods = "LEADER", action = act.ActivateTab(5) }, | |
| { key = "7", mods = "LEADER", action = act.ActivateTab(6) }, | |
| { key = "8", mods = "LEADER", action = act.ActivateTab(7) }, | |
| { key = "9", mods = "LEADER", action = act.ActivateTab(-1) }, | |
| { key = "[", mods = "LEADER", action = act.ActivateTabRelative(-1) }, | |
| { key = "]", mods = "LEADER", action = act.ActivateTabRelative(1) }, | |
| { key = "Tab", mods = "CTRL", action = act.ActivateTabRelative(1) }, | |
| { key = "Tab", mods = "CTRL|SHIFT", action = act.ActivateTabRelative(-1) }, | |
| { | |
| key = ",", | |
| mods = "LEADER", | |
| action = act.PromptInputLine({ | |
| description = wezterm.format({ | |
| { Attribute = { Intensity = "Bold" } }, | |
| { Foreground = { Color = P.purple } }, | |
| { Text = " Rename tab: " }, | |
| }), | |
| action = wezterm.action_callback(function(window, _, line) | |
| if line then | |
| window:active_tab():set_title(line) | |
| end | |
| end), | |
| }), | |
| }, | |
| { key = "m", mods = "LEADER", action = act.ActivateKeyTable({ name = "move_tab", one_shot = false }) }, | |
| { key = "<", mods = "CTRL|SHIFT", action = act.MoveTabRelative(-1) }, | |
| { key = ">", mods = "CTRL|SHIFT", action = act.MoveTabRelative(1) }, | |
| -- Pane splits | |
| { key = "|", mods = "LEADER", action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }) }, | |
| { key = "-", mods = "LEADER", action = act.SplitVertical({ domain = "CurrentPaneDomain" }) }, | |
| { key = "\\", mods = "LEADER", action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }) }, | |
| { key = "e", mods = "CTRL|SHIFT", action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }) }, | |
| { key = "o", mods = "CTRL|SHIFT", action = act.SplitVertical({ domain = "CurrentPaneDomain" }) }, | |
| -- Pane navigation — ALT+hjkl | |
| { key = "h", mods = "ALT", action = act.ActivatePaneDirection("Left") }, | |
| { key = "j", mods = "ALT", action = act.ActivatePaneDirection("Down") }, | |
| { key = "k", mods = "ALT", action = act.ActivatePaneDirection("Up") }, | |
| { key = "l", mods = "ALT", action = act.ActivatePaneDirection("Right") }, | |
| { key = "LeftArrow", mods = "ALT", action = act.ActivatePaneDirection("Left") }, | |
| { key = "DownArrow", mods = "ALT", action = act.ActivatePaneDirection("Down") }, | |
| { key = "UpArrow", mods = "ALT", action = act.ActivatePaneDirection("Up") }, | |
| { key = "RightArrow", mods = "ALT", action = act.ActivatePaneDirection("Right") }, | |
| { key = "h", mods = "LEADER", action = act.ActivatePaneDirection("Left") }, | |
| { key = "j", mods = "LEADER", action = act.ActivatePaneDirection("Down") }, | |
| { key = "k", mods = "LEADER", action = act.ActivatePaneDirection("Up") }, | |
| { key = "l", mods = "LEADER", action = act.ActivatePaneDirection("Right") }, | |
| -- Pane resize | |
| { key = "r", mods = "LEADER", action = act.ActivateKeyTable({ name = "resize_pane", one_shot = false }) }, | |
| { key = "LeftArrow", mods = "CTRL|SHIFT", action = act.AdjustPaneSize({ "Left", 5 }) }, | |
| { key = "DownArrow", mods = "CTRL|SHIFT", action = act.AdjustPaneSize({ "Down", 5 }) }, | |
| { key = "UpArrow", mods = "CTRL|SHIFT", action = act.AdjustPaneSize({ "Up", 5 }) }, | |
| { key = "RightArrow", mods = "CTRL|SHIFT", action = act.AdjustPaneSize({ "Right", 5 }) }, | |
| -- Pane management | |
| { key = "z", mods = "LEADER", action = act.TogglePaneZoomState }, | |
| { key = "z", mods = "CTRL|SHIFT", action = act.TogglePaneZoomState }, | |
| { key = "x", mods = "LEADER", action = act.CloseCurrentPane({ confirm = true }) }, | |
| { key = "!", mods = "LEADER", action = act.PaneSelect({ mode = "MoveToNewTab" }) }, | |
| { key = "s", mods = "LEADER", action = act.PaneSelect({ mode = "Activate", alphabet = "1234567890" }) }, | |
| { key = "o", mods = "LEADER", action = act.RotatePanes("Clockwise") }, | |
| { key = "O", mods = "LEADER", action = act.RotatePanes("CounterClockwise") }, | |
| -- Copy / Paste | |
| { key = "c", mods = "CTRL|SHIFT", action = act.CopyTo("ClipboardAndPrimarySelection") }, | |
| { key = "v", mods = "CTRL|SHIFT", action = act.PasteFrom("Clipboard") }, | |
| { key = "Insert", mods = "SHIFT", action = act.PasteFrom("PrimarySelection") }, | |
| { key = "Enter", mods = "LEADER", action = act.ActivateCopyMode }, | |
| { key = "[", mods = "CTRL", action = act.ActivateCopyMode }, | |
| -- Search | |
| { key = "f", mods = "CTRL|SHIFT", action = act.Search({ CaseInSensitiveString = "" }) }, | |
| { key = "/", mods = "LEADER", action = act.Search({ CaseInSensitiveString = "" }) }, | |
| -- Scroll | |
| { key = "u", mods = "CTRL|SHIFT", action = act.ScrollByPage(-0.5) }, | |
| { key = "d", mods = "CTRL|SHIFT", action = act.ScrollByPage(0.5) }, | |
| { key = "PageUp", mods = "SHIFT", action = act.ScrollByPage(-1) }, | |
| { key = "PageDown", mods = "SHIFT", action = act.ScrollByPage(1) }, | |
| { key = "Home", mods = "SHIFT", action = act.ScrollToTop }, | |
| { key = "End", mods = "SHIFT", action = act.ScrollToBottom }, | |
| { key = "g", mods = "LEADER", action = act.ScrollToTop }, | |
| { key = "G", mods = "LEADER", action = act.ScrollToBottom }, | |
| -- Font size | |
| { key = "=", mods = "CTRL", action = act.IncreaseFontSize }, | |
| { key = "-", mods = "CTRL", action = act.DecreaseFontSize }, | |
| { key = "0", mods = "CTRL", action = act.ResetFontSize }, | |
| -- Quick select / URL | |
| { key = "Space", mods = "CTRL|SHIFT", action = act.QuickSelect }, | |
| { | |
| key = "u", | |
| mods = "LEADER", | |
| action = act.QuickSelectArgs({ | |
| patterns = { "https?://\\S+" }, | |
| action = wezterm.action_callback(function(window, pane) | |
| local sel = window:get_selection_text_for_pane(pane) | |
| wezterm.open_with(sel) | |
| end), | |
| }), | |
| }, | |
| -- Launcher / Command palette | |
| { | |
| key = "Space", | |
| mods = "LEADER", | |
| action = act.ShowLauncherArgs({ | |
| flags = "FUZZY|TABS|WORKSPACES|LAUNCH_MENU_ITEMS", | |
| }), | |
| }, | |
| { key = "p", mods = "CTRL|SHIFT", action = act.ActivateCommandPalette }, | |
| { | |
| key = "k", | |
| mods = "CTRL|SHIFT", | |
| action = act.ShowLauncherArgs({ | |
| flags = "FUZZY|TABS|WORKSPACES|LAUNCH_MENU_ITEMS|COMMANDS", | |
| }), | |
| }, | |
| -- Workspaces | |
| { key = "(", mods = "LEADER", action = act.SwitchWorkspaceRelative(-1) }, | |
| { key = ")", mods = "LEADER", action = act.SwitchWorkspaceRelative(1) }, | |
| { | |
| key = "$", | |
| mods = "LEADER", | |
| action = act.PromptInputLine({ | |
| description = "Rename workspace:", | |
| action = wezterm.action_callback(function(window, _, line) | |
| if line then | |
| mux.rename_workspace(mux.get_active_workspace(), line) | |
| end | |
| end), | |
| }), | |
| }, | |
| -- Window | |
| { key = "n", mods = "CTRL|SHIFT", action = act.SpawnWindow }, | |
| { key = "F11", action = act.ToggleFullScreen }, | |
| -- Misc | |
| { key = "l", mods = "CTRL|SHIFT", action = act.ClearScrollback("ScrollbackAndViewport") }, | |
| { key = "r", mods = "CTRL|SHIFT", action = act.ReloadConfiguration }, | |
| { key = "d", mods = "LEADER", action = act.ShowDebugOverlay }, | |
| { key = "L", mods = "LEADER", action = act.SendKey({ key = "l", mods = "CTRL" }) }, | |
| -- Shortcuts reference (LEADER ?) | |
| { | |
| key = "F1", | |
| mods = "CTRL|SHIFT", | |
| action = wezterm.action_callback(function(window, pane) | |
| local W = 72 | |
| local function R(s) | |
| return "║" .. s .. string.rep(" ", W - #s) .. "║" | |
| end | |
| local border_t = "╔" .. string.rep("═", W) .. "╗" | |
| local border_m = "╠" .. string.rep("═", W) .. "╣" | |
| local border_b = "╚" .. string.rep("═", W) .. "╝" | |
| local ref = table.concat({ | |
| "", | |
| border_t, | |
| R(" SHORTCUTS REFERENCE LEADER = Right Ctrl"), | |
| border_m, | |
| R(""), | |
| R(" TABS"), | |
| R(" LEADER c New tab | LEADER & Close tab"), | |
| R(" ALT+1-9 Jump to tab | LEADER [ ] Prev / Next"), | |
| R(" LEADER , Rename tab | LEADER m Move mode"), | |
| R(" CTRL+TAB Next tab | CTRL+SHIFT+TAB Prev tab"), | |
| R(""), | |
| R(" PANES"), | |
| R(" LEADER |\\ Split right | LEADER - Split down"), | |
| R(" ALT+h/j/k/l Navigate | LEADER z Toggle zoom"), | |
| R(" LEADER r Resize mode | LEADER x Close pane"), | |
| R(" LEADER s Pane switcher | LEADER o/O Rotate panes"), | |
| R(" LEADER ! Pane -> new tab |"), | |
| R(""), | |
| R(" COPY / SEARCH"), | |
| R(" LEADER Enter Copy mode (vim) | CTRL+[ Copy mode"), | |
| R(" LEADER / Search | CTRL+SHIFT+F Search"), | |
| R(" CTRL+SHIFT+Spc Quick-select | LEADER u Open URL"), | |
| R(" CTRL+SHIFT+C Copy | CTRL+SHIFT+V Paste"), | |
| R(""), | |
| R(" SCROLL"), | |
| R(" CTRL+SHIFT+U/D Half page up/dn | SHIFT+PgUp/Dn Full page"), | |
| R(" LEADER g/G Top / Bottom |"), | |
| R(""), | |
| R(" LAUNCHER / PALETTE"), | |
| R(" LEADER Space Fuzzy launcher | CTRL+SHIFT+P Cmd palette"), | |
| R(""), | |
| R(" WORKSPACES"), | |
| R(" LEADER ( ) Prev / Next | LEADER $ Rename"), | |
| R(""), | |
| R(" WINDOW / FONT"), | |
| R(" CTRL = / - / 0 Font size | F11 Fullscreen"), | |
| R(" CTRL+SHIFT+N New window | CTRL+SHIFT+R Reload cfg"), | |
| R(""), | |
| R(" GPU MODE (auto-adaptive)"), | |
| R(" Discharging -> Software | Charging -> GPU (OpenGL)"), | |
| R(""), | |
| R(" CTRL+SHIFT+F1 This reference"), | |
| border_b, | |
| "", | |
| }, "\n") | |
| local tmp = os.tmpname() | |
| local f = io.open(tmp, "w") | |
| if f then | |
| f:write(ref) | |
| f:close() | |
| end | |
| window:perform_action( | |
| act.SpawnCommandInNewTab({ | |
| args = { | |
| "bash", | |
| "-c", | |
| "cat " .. tmp .. "; read -n1 -s -p 'Press any key to close...'; rm -f " .. tmp, | |
| }, | |
| }), | |
| pane | |
| ) | |
| end), | |
| }, | |
| } | |
| local mouse_bindings = { | |
| { event = { Down = { streak = 1, button = "Right" } }, mods = "NONE", action = act.PasteFrom("PrimarySelection") }, | |
| { event = { Up = { streak = 1, button = "Left" } }, mods = "CTRL", action = act.OpenLinkAtMouseCursor }, | |
| { event = { Down = { streak = 3, button = "Left" } }, mods = "NONE", action = act.SelectTextAtMouseCursor("Line") }, | |
| } | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 🪟 STARTUP — 16:9 fixed size, centered on screen | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| wezterm.on("gui-startup", function(cmd) | |
| local W, H = 1600, 900 -- 16:9, larger default for modern displays | |
| local _, _, window = mux.spawn_window(cmd or {}) | |
| refresh_background_files() | |
| local gui = window:gui_window() | |
| set_background_by_index(gui, current_background_idx) | |
| gui:set_inner_size(W, H) | |
| local ok, screen_info = pcall(wezterm.gui.screens) | |
| if ok and screen_info then | |
| local s = screen_info.active | |
| gui:set_position((s.x or 0) + math.floor((s.width - W) / 2), (s.y or 0) + math.floor((s.height - H) / 2)) | |
| end | |
| end) | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 🎨 COLOUR SCHEME | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local color_scheme = { | |
| foreground = P.fg0, | |
| background = P.bg0, | |
| cursor_bg = P.cyan, | |
| cursor_fg = P.bg0, | |
| cursor_border = P.cyan, | |
| selection_bg = P.bg3, | |
| selection_fg = P.fg0, | |
| scrollbar_thumb = P.bg4, | |
| split = P.bg4, | |
| launcher_label_bg = { Color = "#203c33" }, | |
| launcher_label_fg = { Color = P.teal }, | |
| input_selector_label_bg = { Color = "#1f3a33" }, | |
| input_selector_label_fg = { Color = P.teal }, | |
| ansi = { P.bg3, P.red, P.green, P.yellow, P.blue, P.purple, P.cyan, P.fg1 }, | |
| brights = { P.fg3, "#ff8a9b", "#b8e886", "#ffc777", "#93b4ff", "#c4a5f8", "#94e2d5", P.fg0 }, | |
| tab_bar = { | |
| background = "rgba(26, 27, 38, 0.00)", | |
| active_tab = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg0, intensity = "Bold" }, | |
| inactive_tab = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg3 }, | |
| inactive_tab_hover = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg2 }, | |
| new_tab = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.fg3 }, | |
| new_tab_hover = { bg_color = "rgba(26, 27, 38, 0.00)", fg_color = P.purple }, | |
| }, | |
| } | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| -- 🚀 MAIN CONFIG | |
| -- ───────────────────────────────────────────────────────────────────────────── | |
| local config = wezterm.config_builder() | |
| config.term = "xterm-256color" | |
| -- Font | |
| config.font = wezterm.font("JetBrainsMono Nerd Font", { weight = "Medium" }) | |
| config.font_size = 14.5 | |
| config.line_height = 1.15 | |
| config.cell_width = 1.05 | |
| config.harfbuzz_features = { | |
| "calt=1", | |
| "clig=1", | |
| "liga=1", | |
| "zero=1", | |
| "ss01=1", | |
| "ss02=1", | |
| "ss19=1", | |
| "ss20=1", | |
| } | |
| config.allow_square_glyphs_to_overflow_width = "WhenFollowedBySpace" | |
| -- Font rendering — light hinting for smooth, modern text (no pixel artifacts) | |
| config.freetype_load_target = "Light" | |
| config.freetype_render_target = "Light" | |
| -- ── Renderer ───────────────────────────────────────────────────────────────── | |
| -- OpenGL: fully GPU-accelerated, zero input lag on Linux/NVIDIA. | |
| -- WebGPU is still experimental on Linux — causes measurable input latency | |
| -- even with proprietary NVIDIA drivers. OpenGL is the right call here. | |
| config.front_end = "OpenGL" | |
| config.webgpu_power_preference = DEFAULT_WEBGPU_POWER_PREFERENCE | |
| config.animation_fps = GPU_FPS | |
| config.max_fps = GPU_FPS | |
| config.cursor_blink_rate = 600 | |
| config.cursor_blink_ease_in = "EaseIn" | |
| config.cursor_blink_ease_out = "EaseOut" | |
| config.default_cursor_style = "BlinkingBlock" | |
| -- Colours | |
| config.colors = color_scheme | |
| config.force_reverse_video_cursor = false | |
| -- Transparency (compositor blur is set at WM level, e.g. picom/compton) | |
| config.window_background_opacity = 0.90 | |
| if wezterm.target_triple:find("windows") then | |
| config.win32_system_backdrop = "Acrylic" | |
| end | |
| -- Window — fully frameless (no WM titlebar on Wayland/KDE) | |
| config.window_decorations = "NONE" | |
| -- Gradient-style colored border (rendered by WezTerm, not the WM) | |
| -- Pastel gradient border with smooth inner glow | |
| config.window_frame = { | |
| border_left_width = "5px", | |
| border_right_width = "5px", | |
| border_bottom_height = "5px", | |
| border_top_height = "5px", | |
| border_top_color = "#cdb4db", | |
| border_right_color = "#ffc8dd", | |
| border_bottom_color = "#a2d2ff", | |
| border_left_color = "#bde0fe", | |
| } | |
| -- Inner gradient uses the 5th color (#ffafcc) and darkened pastels | |
| -- to smooth the border→background transition through the padding | |
| config.window_background_gradient = { | |
| orientation = { Linear = { angle = -45.0 } }, | |
| colors = { | |
| "#1c1a22", -- tinted lavender-dark (top-left, near #cdb4db) | |
| "#1a1b26", | |
| "#1a1b26", | |
| "#1a1b26", | |
| "#1a1d27", -- tinted blue-dark (bottom-right, near #a2d2ff) | |
| }, | |
| blend = "LinearRgb", | |
| noise = 24, | |
| } | |
| -- ↑ On X11 your WM adds its own titlebar. Kill it per-WM: | |
| -- GNOME : gsettings set org.gnome.mutter.wayland xwayland-allow-grabs true | |
| -- + devilspie2 rule: undecorate() | |
| -- KDE : Window Rules → No titlebar & frame → Force → No | |
| -- i3/Sway : for_window [app_id="org.wezfurlong.wezterm"] border none | |
| -- Hyprland : windowrule = noborder, wezterm | |
| -- Openbox : <application name="wezterm"><decor>no</decor></application> | |
| config.window_padding = { left = 16, right = 16, top = 12, bottom = 8 } | |
| config.window_close_confirmation = "AlwaysPrompt" | |
| -- Tab bar | |
| config.enable_tab_bar = true | |
| config.use_fancy_tab_bar = false | |
| config.tab_bar_at_bottom = false | |
| config.hide_tab_bar_if_only_one_tab = false | |
| config.tab_max_width = 22 -- compact tabs; title truncates earlier | |
| config.show_tab_index_in_tab_bar = false | |
| config.show_new_tab_button_in_tab_bar = true | |
| config.switch_to_last_active_tab_when_closing_tab = true | |
| config.status_update_interval = 2000 -- reduce update overhead on battery | |
| -- Fuzzy finder / command palette styling | |
| config.command_palette_bg_color = "rgba(10, 14, 24, 0.97)" | |
| config.command_palette_fg_color = P.teal | |
| config.command_palette_font = wezterm.font("JetBrainsMono Nerd Font", { weight = "Medium" }) | |
| config.command_palette_font_size = 15 | |
| config.command_palette_rows = 18 | |
| -- Scrollback | |
| config.scrollback_lines = 100000 | |
| config.enable_scroll_bar = false | |
| -- Bell | |
| config.audible_bell = "Disabled" | |
| config.visual_bell = { fade_in_duration_ms = 75, fade_out_duration_ms = 75, target = "CursorColor" } | |
| -- Hyperlinks | |
| config.hyperlink_rules = wezterm.default_hyperlink_rules() | |
| table.insert(config.hyperlink_rules, { | |
| regex = [[\b([a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+)\b]], | |
| format = "https://github.com/$1", | |
| }) | |
| -- Quick select | |
| config.quick_select_patterns = { | |
| "[0-9a-f]{7,40}", | |
| "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}", | |
| "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}", | |
| "[\\w./-]+:\\d+", | |
| "sha256:[0-9a-f]{64}", | |
| } | |
| config.quick_select_alphabet = "asdfghjklqwertyuiopzxcvbnm" | |
| -- Selection | |
| config.selection_word_boundary = " \t\n{}[]()\"'`,;:@" | |
| -- Input | |
| config.use_ime = true | |
| config.xim_im_name = "fcitx" -- swap for "ibus" if needed | |
| -- Keys | |
| config.leader = LEADER | |
| config.keys = keys | |
| config.key_tables = key_tables | |
| config.mouse_bindings = mouse_bindings | |
| config.disable_default_key_bindings = false | |
| -- Launch menu | |
| config.launch_menu = launch_menu | |
| -- Misc | |
| config.check_for_updates = true | |
| config.ssh_domains = {} | |
| config.exit_behavior = "Close" | |
| config.clean_exit_codes = { 0, 130 } | |
| config.automatically_reload_config = true | |
| config.enable_wayland = true | |
| config.unicode_version = 14 | |
| config.unzoom_on_switch_pane = true | |
| return config | |
| -- ╔═══════════════════════════════════════════════════════════════════════╗ | |
| -- ║ QUICK REFERENCE LEADER = Right Ctrl ║ | |
| -- ║ ║ | |
| -- ║ Tabs: LEADER c new │ LEADER & close │ ALT+1-9 jump ║ | |
| -- ║ LEADER [ ] prev/next │ LEADER , rename │ m move ║ | |
| -- ║ ║ | |
| -- ║ Panes: LEADER | split right │ LEADER - split down ║ | |
| -- ║ ALT+hjkl navigate │ LEADER z zoom │ r resize ║ | |
| -- ║ LEADER x close │ LEADER s switcher │ o rotate ║ | |
| -- ║ ║ | |
| -- ║ Copy: LEADER Enter copy mode (vim) │ LEADER / search ║ | |
| -- ║ CTRL+SHIFT+Spc quick-select │ LEADER u open URL ║ | |
| -- ║ ║ | |
| -- ║ Launcher: LEADER Space fuzzy launcher ║ | |
| -- ║ CTRL+SHIFT+P command palette ║ | |
| -- ║ ║ | |
| -- ║ Font: CTRL = / - / 0 increase / decrease / reset ║ | |
| -- ║ Misc: CTRL+SHIFT+R reload │ F11 fullscreen ║ | |
| -- ║ Help: CTRL+SHIFT+F1 shortcuts reference (in new tab) ║ | |
| -- ║ GPU: ≤15% → CPU@30 │ ≤40% → GPU@60 │ charging → GPU@120 ║ | |
| -- ╚═══════════════════════════════════════════════════════════════════════╝ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment