NO_COLOR suppresses non-color attributes, not just color
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 171
- Forks
- 44
- Avg merge
- 2h 34m
- Merged PRs (30d)
- 6
Description
NO_COLOR suppresses non-color attributes, not just color
Summary
When NO_COLOR is set, anstream strips all ANSI escape sequences —
bold, dim, italic, underline, reverse, strikethrough, etc. — not only
color. This diverges from no-color.org
(or its source),
whose FAQ is explicit:
Q: Should the presence of
NO_COLORdisable other styling such as
bold, underline, and italic?A: No. This standard only signals the user's intention regarding
adding ANSI color to text output.
Reproduction
NO_COLOR resolves to ColorChoice::Never → StripStream, whose
StripBytes engine (driven by anstyle_parse) discards every CSI escape
without inspecting its SGR parameters. Verified on anstream 1.0.0:
use std::io::Write as _;
let mut out = anstream::AutoStream::new(Vec::new(), anstream::ColorChoice::Never);
write!(out, "\x1b[1mbold\x1b[22m \x1b[4munderline\x1b[24m \x1b[31mred\x1b[39m").unwrap();
assert_eq!(String::from_utf8(out.into_inner()).unwrap(), "bold underline red");
Bold and underline are stripped along with the red color. Per the FAQ, only
color should be suppressed; the expected output is
\x1b[1mbold\x1b[22m \x1b[4munderline\x1b[24m red.
Suggested direction
A spec-correct color-only strip needs to distinguish color SGR parameters
from attribute parameters and re-emit only the latter. Most of the
primitives for this already live in the workspace: anstyle::Style
separates fg/bg/underline-color from effects, and anstyle-parse
already produces the SGR parameter list via csi_dispatch. The missing
piece is a decode step (param list → Style delta) so a strip adapter can
track the active style and render only effects. If a shared decoder
lived in anstyle, other consumers could reuse it for the same spec
alignment — but the shape is of course the maintainers' call.
One design point worth flagging: ColorChoice::Never is reached today for
NO_COLOR, for non-terminals, and for CLICOLOR disabled. The FAQ
constrains only the NO_COLOR case, so it may be cleanest for NO_COLOR
to resolve to a color-only path while the other Never callers keep the
full strip (pipe-to-file output today is fully flat, which is arguably
desirable for logs).
Notes
- The empty-string trigger is already handled correctly upstream:
anstyle_query::no_color()isnon_empty(NO_COLOR), soNO_COLOR=""
disables nothing, per spec. This issue is only about the scope of
suppression. - This cascades to dependents routing through
anstream(env_logger,
clapwith itscolorfeature), which would inherit the fix. crosstermis a working example of color-onlyNO_COLORhandling —
it gatesColored(fg/bg/underline-color) but emitsSetAttributes
unconditionally.- Related: #192 (env-var support context).
Versioning
I'd frame this as a bug fix (patch bump) with a one-line CHANGELOG note
acknowledging the observable output change, but defer to the project's
own version policy.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the NO_COLOR path from anstream::ColorChoice::Never through StripStream and StripBytes, then inspect anstyle::Style and anstyle-parse's csi_dispatch. Reproduce the example and trace how SGR parameters are discarded. Done means NO_COLOR preserves non-color effects while suppressing color, with coverage for the described output and existing Never behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100