77 lines
4.9 KiB
Plaintext
77 lines
4.9 KiB
Plaintext
# ---------------------------------------------------------------------------
|
||
# Statusline element-flicker fix (2026-08-19).
|
||
# Sourced at the end of ~/.yadr/.tmux.conf, so these override what it sets.
|
||
# Kept HERE so a yadr re-bootstrap cannot clobber it.
|
||
#
|
||
# SYMPTOM dissimulo reported: "the statusbar is having a seizure -- elements
|
||
# appear and disappear at random." NOT the whole bar blanking (a 30fps screen
|
||
# recording of the bar showed zero frame-to-frame variation, and a whole-desktop
|
||
# capture showed nothing changing near it). Individual ELEMENTS winking out.
|
||
#
|
||
# CAUSE: `#(...)` in a status format is a tmux JOB. While that job is being
|
||
# (re)started its expansion is EMPTY, so the element vanishes until it finishes.
|
||
# tmux re-runs those jobs whenever the status is redrawn and the job is not
|
||
# already running -- and status redraws are driven by PANE ACTIVITY, not by
|
||
# `status-interval`. With a busy TUI in the pane (a `claude` session) the jobs
|
||
# were being restarted several times a second, so the username and the IP
|
||
# flickered in and out constantly. Measured: `#(whoami)` and `#(tmux-net)`
|
||
# expanded EMPTY in 30 out of 30 consecutive renders.
|
||
#
|
||
# FIX: resolve both into tmux USER OPTIONS and reference those. `#{@user}` and
|
||
# `#{@net}` are plain variable lookups -- no job, so nothing can ever be
|
||
# half-started and render empty. Rendered text is byte-identical to before.
|
||
# @user - a username cannot change within a session: read it ONCE.
|
||
# @net - the IP CAN change, so refresh on a slow background loop
|
||
# (4 forks/minute instead of several a second). The loop exits by
|
||
# itself when tmux goes away, because `tmux set` then fails.
|
||
#
|
||
# Bonus, already measured: this also cut the tmux server from ~25% of a core to
|
||
# ~12% and eliminated the fork churn (17 execs/10s -> 0).
|
||
#
|
||
# DO NOT "simplify" #{@user}/#{@net} back to #(whoami)/#(~/.local/bin/tmux-net).
|
||
# That is the bug, not a tidier way of writing it.
|
||
# ---------------------------------------------------------------------------
|
||
run-shell 'tmux set -g @user "$(whoami)"'
|
||
run-shell 'tmux set -g @net "$($HOME/.local/bin/tmux-net)"'
|
||
run-shell -b 'while sleep 60; do tmux set -g @net "$($HOME/.local/bin/tmux-net)" 2>/dev/null || exit 0; done'
|
||
|
||
|
||
# These lengths are measured against the RAW format string, NOT the rendered
|
||
# width: tmux applies them as #{T;=/N:status-right}, truncating BEFORE the
|
||
# #[...] style directives are stripped. status-right renders ~46 columns but is
|
||
# ~129 characters of source. A cap below the raw length severs the string
|
||
# mid-way, which looks exactly like 'the right side of the bar disappeared'.
|
||
# Set here as well as in .tmux.conf so this file stays self-sufficient.
|
||
set -g status-left-length 451
|
||
set -g status-right-length 451
|
||
|
||
set -g status-left '#[fg=colour235,bg=colour252,bold] ❐ #S #[fg=colour252,bg=colour238,nobold]❯#[fg=colour245,bg=colour238,bold] #{@user} '
|
||
# The trailing %S is drawn in bg-on-bg (colour234 on colour234) so it is
|
||
# INVISIBLE, but it makes the status string CHANGE every second.
|
||
#
|
||
# WHY THAT MATTERS -- the second half of the bug: tmux only repaints the status
|
||
# line when its computed content DIFFERS from what it last drew. With the clock
|
||
# at minute resolution and @user/@net static, the string was byte-identical for
|
||
# up to 60s at a stretch; so when anything wiped the bar it STAYED wiped until
|
||
# the minute rolled over. That is the "sometimes the entire bar disappears" half.
|
||
# A once-per-second change forces a repaint, so a wipe self-heals within ~1s.
|
||
# It costs one redraw of one row and NO forks (that is only affordable because
|
||
# the #() jobs above became #{@user}/#{@net}).
|
||
set -g status-right '#[bold][#[nobold,fg=colour229]#h#[fg=default] / #[fg=colour229]#{@net}#[fg=default,bold]]#[nobold,fg=colour255] %-I:%M%P %d-%b-%Y #[fg=colour39]★ Stardate %Y.%j#[fg=colour255] '
|
||
|
||
|
||
# ---- circled window numbers, stamped asynchronously ----------------------
|
||
# The icon is computed ONCE per window change and stored as a window-level
|
||
# user option; the format below is a plain #{@icon} lookup. The old version
|
||
# nested ten #{?#{==:#{window_index},N},...} conditionals evaluated for every
|
||
# window on every redraw, and redraws follow PANE ACTIVITY, not status-interval.
|
||
# run-shell -b is backgrounded, so none of this sits on the render path.
|
||
set -g window-status-format '#[fg=colour235,bg=colour252,nobold] #{?#{@icon},#{@icon},#{window_index}} #{b:pane_current_path} #W '
|
||
set -g window-status-current-format '#[fg=colour234,bg=colour39,bold] [#[fg=colour232,bold]#{?window_zoomed_flag,#[fg=colour228],} #{?#{@icon},#{@icon},#{window_index}} #{b:pane_current_path} #W #[fg=colour234,bold]] '
|
||
|
||
run-shell -b '$HOME/.local/bin/tmux-window-icons'
|
||
set-hook -g after-new-window 'run-shell -b "$HOME/.local/bin/tmux-window-icons"'
|
||
set-hook -g window-linked 'run-shell -b "$HOME/.local/bin/tmux-window-icons"'
|
||
set-hook -g window-unlinked 'run-shell -b "$HOME/.local/bin/tmux-window-icons"'
|
||
set-hook -g session-window-changed 'run-shell -b "$HOME/.local/bin/tmux-window-icons"'
|