Skip to content

fix(renderer): keep a preserve-colors widget's Powerline background after its resets - #687

Open
eric-engberg wants to merge 1 commit into
sirmalloc:mainfrom
eric-engberg:fix/custom-command-powerline-background
Open

eric-engberg wants to merge 1 commit into
sirmalloc:mainfrom
eric-engberg:fix/custom-command-powerline-background

Conversation

@eric-engberg

Copy link
Copy Markdown
Contributor

What

In Powerline mode, a Custom Command with preserve colors on keeps its segment background all the way to the separator arrow. Before, the command's own reset cleared the background, which left a cell of terminal background (the trailing padding) between the text and the arrow. Any text after a reset in the middle of the output lost it too.

Why

The Powerline renderer emits the segment background once, before the widget's text. Command output usually ends with \x1b[0m, and Custom Command appends one itself after cutting colored output to its max width. That full reset clears the background as well, so everything after it is drawn on the terminal's background. With printf '\033[31mhello\033[0m' on a blue segment:

\x1b[48;5;26m \x1b[31mhello\x1b[0m \x1b[0m\x1b[38;5;26m\x1b[48;5;70m<arrow>
                                  ^ padding with no background

How

After each SGR sequence in the preserved text that clears the background, the segment background is emitted again. That covers a full reset (0, an empty parameter, alone or combined such as 0;32) and 49. The arguments of extended colors (38/48/58 with ;5;n or ;2;r;g;b) are skipped, so a 0 or 49 among them isn't read as a reset.

Nothing else changes:

  • The command's own colors, including backgrounds it sets itself, are kept.
  • The full reset after the widget is unchanged, so nothing leaks into the separator.
  • Widgets without a background aren't touched.
  • Widgets that don't preserve colors aren't touched either; a global foreground override already strips the command's codes.
  • Plain mode isn't changed: it colors the padding separately, so the reset at the end of the output leaves no gap there.

Demo

A sample line (scripts/payload.example.json) with a Custom Command running printf '\033[1;34mbuild ok\033[0m' with preserve colors, between Model and Context Length, on the Nord Aurora theme. Look at the cell before the arrow after build ok. Plain mode renders the same before and after, so it has no stills.

Powerline: before

Preserve-colors Custom Command segment before the fix, Powerline mode

Powerline: after

Preserve-colors Custom Command segment after the fix, Powerline mode

Testing

  • New renderer tests: the background comes back after the command's trailing reset, so the padding and the arrow stay in the segment. It also comes back after 0;32, 49 and \x1b[m mid-output. The first two fail on main; the third guards that extended colors with 0/49 arguments are left alone.
  • New unit tests for the helper: 0, empty, 00, ;1 and 39;49 restore the background; 1;31, 38;5;0, 48;2;0;49;0, 58;5;49 and 39 don't.
  • bun test: 2787 pass, 0 fail. bun run lint passes.
  • The two changed test files under Node (Vitest): 39 pass (34 existing, 5 new).
  • Built CLI under Bun 1.4.2 and Node 26.10.0, with the demo line: both runtimes agree. Powerline output differs from main only by the re-applied background, and plain output is the same as main. With the baseline line, both modes are the same as main. The TUI opens and exits cleanly under both.

…fter its resets

In Powerline mode a widget that preserves its own colors (a Custom
Command with preserve colors on) gets its segment background once,
before its text. Command output usually ends with \x1b[0m, and Custom
Command appends one after cutting colored output to its max width; that
reset cleared the background too, so the trailing padding, and any text
after a reset mid-output, showed the terminal's background before the
separator arrow:

  \x1b[48;5;26m \x1b[31mhello\x1b[0m \x1b[0m<arrow>

Re-apply the segment background after each SGR sequence in the
preserved text that clears it: a full reset (0 or an empty parameter,
alone or combined like 0;32) or 49. The arguments of extended colors
(38/48/58;5;n and ;2;r;g;b) are skipped, so a 0 or 49 among them isn't
read as a reset. The command's own colors, including its own
backgrounds, are kept, and the full reset after the widget is
unchanged. Widgets without a background, and plain mode (which colors
the padding separately), are untouched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant