diff options
| author | Paul Buetow <paul@buetow.org> | 2025-09-08 10:05:04 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-09-08 10:05:04 +0300 |
| commit | 0dcf347c3fbc6e4ffb7e46294f5dd92dbbcd98ef (patch) | |
| tree | 7503979ac4d44843f1cfcc8da54b77b4a24ff4bd | |
| parent | cead3ebde8f3aee0ef8677158d37f4d04c6629dc (diff) | |
tmux: improve white-on-purple legibility; bump version to v0.9.0v0.9.0
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | internal/tmux/status.go | 85 | ||||
| -rw-r--r-- | internal/version.go | 2 |
3 files changed, 73 insertions, 17 deletions
@@ -59,6 +59,9 @@ Hexai can surface live progress in tmux's status line via a user option. Add thi set -g status-right '#{@hexai_status} #[fg=colour8]| %H:%M' ``` +- Note: `colour8` is typically “bright black” (a dim grey) in many themes. + If it’s low-contrast on your background, change it (e.g., `colour7` or `white`). + - CLI updates `@hexai_status` at start (⏳ provider:model) and on completion with compact stats (↑sent, ↓recv, rpm, reqs). - LSP emits an initial heartbeat on client initialize and periodic compact stats (provider, model, rpm, reqs, bytes). - The TUI action runner sets a ready heartbeat and a completion heartbeat with stats. diff --git a/internal/tmux/status.go b/internal/tmux/status.go index 1d2a8ee..6d76bcb 100644 --- a/internal/tmux/status.go +++ b/internal/tmux/status.go @@ -9,6 +9,16 @@ import ( "codeberg.org/snonux/hexai/internal/textutil" ) +// baseFGToken is a placeholder inserted by status formatters wherever the +// base foreground color should be restored. The theming layer (applyTheme) +// replaces this token with a tmux color sequence matching the active theme's +// foreground, which fixes readability when a theme sets a non-default fg. +const ( + baseFGToken = "\x1EHEXAI_BASE_FG\x1E" + arrowUpToken = "\x1EHEXAI_ARROW_UP\x1E" + arrowDownToken = "\x1EHEXAI_ARROW_DOWN\x1E" +) + // Enabled reports whether tmux status updates are enabled via env (default: on). func Enabled() bool { v := strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS")) @@ -48,17 +58,17 @@ func FormatLLMStatsStatusColored(provider, model string, reqs int64, rpm float64 in := textutil.HumanBytes(inBytes) out := textutil.HumanBytes(outBytes) // Keep it compact; colorize prefix and arrows; use fg resets so a themed bg can persist. - // colour8 = dim grey, colour3 = yellow (up), colour2 = green (down) + // Arrows use theme-aware styles; bytes immediately switch to base fg for contrast. return fmt.Sprintf( - "#[fg=colour8]LLM:#[fg=default]%s:%s #[fg=colour3]↑%s#[fg=default] #[fg=colour2]↓%s#[fg=default] %.1frpm %dr", - provider, model, in, out, rpm, reqs, + "%sLLM:%s:%s %s↑%s%s %s↓%s%s %.1frpm %dr", + baseFGToken, provider, model, arrowUpToken, baseFGToken, in, arrowDownToken, baseFGToken, out, rpm, reqs, ) } // FormatLLMStartStatus renders a short colored heartbeat at start/initialize time. // Example: "LLM:openai:gpt-4.1 ⏳" func FormatLLMStartStatus(provider, model string) string { - return fmt.Sprintf("#[fg=colour8]LLM:#[fg=default]%s:%s #[fg=colour11]⏳#[fg=default]", provider, model) + return fmt.Sprintf("%sLLM:%s:%s #[fg=colour11]⏳%s", baseFGToken, provider, model, baseFGToken) } // applyTheme wraps the status string with a user-selected tmux style if requested. @@ -68,23 +78,66 @@ func applyTheme(s string) string { // Allow explicit fg/bg override fg := strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS_FG")) bg := strings.TrimSpace(os.Getenv("HEXAI_TMUX_STATUS_BG")) - if fg != "" || bg != "" { + // Determine base foreground and background from env or theme presets + baseFG := "" + wrap := false + if fg != "" || bg != "" { // explicit override path + wrap = true if fg == "" { - fg = "default" + baseFG = "default" + } else { + baseFG = fg + } + // bg used as provided (may be empty) + } else { + switch theme { + case "white-on-purple", "purple", "magenta", "white-on-magenta": + baseFG, bg, wrap = "white", "magenta", true + case "black-on-yellow", "yellow", "black-on-gold": + baseFG, bg, wrap = "black", "yellow", true + case "white-on-blue", "blue", "white-on-navy": + baseFG, bg, wrap = "white", "blue", true } - if bg == "" { - bg = "default" + if baseFG == "" { // no theme selected + baseFG = "default" + } + } + + // Theme-aware arrow styles + upStyle, downStyle := "#[fg=colour3]", "#[fg=colour2]" // defaults: yellow up, green down + if fg != "" || bg != "" { // explicit override path: match arrows to base fg, bold for visibility + upStyle = "#[bold,fg=" + baseFG + "]" + downStyle = upStyle + } else { + switch theme { + case "white-on-purple", "purple", "magenta", "white-on-magenta": + upStyle, downStyle = "#[bold,fg=black]", "#[bold,fg=black]" + case "black-on-yellow", "yellow", "black-on-gold": + upStyle, downStyle = "#[bold,fg=black]", "#[bold,fg=black]" + case "white-on-blue", "blue", "white-on-navy": + upStyle, downStyle = "#[bold,fg=white]", "#[bold,fg=white]" } - return "#[fg=" + fg + ",bg=" + bg + "]" + s + "#[fg=default,bg=default]" } - if theme == "white-on-purple" || theme == "purple" || theme == "magenta" || theme == "white-on-magenta" { - return "#[fg=white,bg=magenta]" + s + "#[fg=default,bg=default]" + + // Replace base-foreground and arrow placeholders with selected styles + if strings.Contains(s, baseFGToken) { + s = strings.ReplaceAll(s, baseFGToken, "#[fg="+baseFG+"]") + } + if strings.Contains(s, arrowUpToken) { + s = strings.ReplaceAll(s, arrowUpToken, upStyle) } - if theme == "black-on-yellow" || theme == "yellow" || theme == "black-on-gold" { - return "#[fg=black,bg=yellow]" + s + "#[fg=default,bg=default]" + if strings.Contains(s, arrowDownToken) { + s = strings.ReplaceAll(s, arrowDownToken, downStyle) + } + + if !wrap { + return s } - if theme == "white-on-blue" || theme == "blue" || theme == "white-on-navy" { - return "#[fg=white,bg=blue]" + s + "#[fg=default,bg=default]" + // Wrap with base fg and optional bg, then reset at the end + prefix := "#[fg=" + baseFG + if bg != "" { + prefix += ",bg=" + bg } - return s + prefix += "]" + return prefix + s + "#[fg=default,bg=default]" } diff --git a/internal/version.go b/internal/version.go index e32d6fb..3162341 100644 --- a/internal/version.go +++ b/internal/version.go @@ -1,4 +1,4 @@ // Summary: Hexai semantic version identifier used by CLI and LSP binaries. package internal -const Version = "0.8.0" +const Version = "0.9.0" |
