Add colour support for chain labels in terminal output - #5
Merged
Merged
Conversation
A build with four chains streams four labels down the left of the terminal, and telling them apart meant reading them. Each chain now gets a colour from a palette, in declaration order and round again from the top when a build has more chains than there are colours, and the colour covers the label and the bar in both layouts: the bars make a column in the chain's colour, and what a command wrote goes out exactly as it wrote it. The `[!]` and `[.]` in front of an outcome line stay plain, so the colour says which chain and nothing else. Colour is on where `run` prints to a terminal that says it has colours, and off everywhere else, so a build that pipes its output to a file or greps it for `[!]` gets the same bytes it got before. Four things decide, each one overruling the one before it: - the terminal: stdout is one, and terminfo reports eight colours or more. `TERM` unset or `dumb` counts as none, and where there is no `tput` to ask, a `TERM` that is set and is not `dumb` is taken at its word. - `NO_COLOR`, set to anything at all: no colour. - `FORCE_COLOR`, set to anything but `0`: colour. `FORCE_COLOR=0` is how a good many tools are told to stop, so it is read as a refusal rather than as the name being set. - `COLOR`: `1`, `0`, or `auto` to leave it to the three above. Last, because it is the only one of the four aimed at this library. The question is asked at `run` and not when the library is sourced, since the answer is about the stream `run` prints to and a build script is free to redirect its own output before it gets there. `COLOR_PALETTE` is the colours themselves, as SGR parameters, so `1;36` is bold cyan and `38;5;213` is one of the 256. It defaults to cyan, magenta, green, yellow and blue: the colours a terminal has had since it had eight, less red, which belongs to what a build says about its own failures, and less black and white, which the rest of the line already is. Emptying it is another way of asking for no colour, so the default fills in for a palette that was never set rather than for one that was deliberately emptied. The escape character is written as its bytes, the way the box drawing bar already was: the sources stay ASCII, and `make lint` still says so. Eleven examples cover it, including the precedence between the four and the palette starting again once it runs out.
`set -- $COLOR_PALETTE` split the palette into colours everywhere the suite runs but zsh, which does not split an unquoted expansion at all: there the whole palette arrived as one colour and every label opened with `ESC[36 35 32 33 34m`. Six examples said so on the zsh and macOS zsh jobs, and nothing said so under the eight other shells. The palette is walked a word at a time now, with the expansions that trim a string, which every shell here does the same way. Leading spaces are trimmed between words, so the spacing in a hand written palette does not matter and a palette of nothing but them still reads as the empty one it is. Verified under all nine Linux shells in the matrix rather than the three that were to hand: dash, bash, bash --posix, zsh, zsh --emulate sh, mksh, ksh93, posh and busybox ash, 53 examples and no failures under each.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This change adds optional colour support to parallel.sh, allowing each chain's label to be displayed in a distinct colour when output is sent to a terminal. The colour is applied only to the label and separator bar, leaving command output untouched.
Key Changes
Colour detection logic (
_probe_color): Determines whether to use colours based on a priority system:tputorTERM)NO_COLORenvironment variable (disables colour if set)FORCE_COLORenvironment variable (enables/disables colour, with0meaning disable)COLORvariable (explicit control:1/yes/on/true/alwaysor0/no/off/false/never)Colour assignment (
_colors): Distributes colours fromCOLOR_PALETTEto chains in declaration order, cycling through the palette when more chains exist than coloursOutput formatting: Modified
_emitand_outcomefunctions to wrap labels and separators with colour codes while preserving command output exactly as writtenConfiguration variables:
COLOR: Controls colour mode (defaults toauto)COLOR_PALETTE: SGR parameters for colours (defaults to36 35 32 33 34— cyan, magenta, green, yellow, blue)Test coverage: Comprehensive test suite covering colour detection, palette cycling, empty palettes, outcome formatting, grouped output, and all four decision factors
Implementation Details
[!],[.]) remain plain; only the label is colouredNO_COLOR,FORCE_COLOR) used by other build toolshttps://claude.ai/code/session_017gYMCt5QBRcZ5J2RgUQoD4