NO_COLOR suppresses non-color attributes, not just color

Open
#337 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
rust
Domain
cli, devtools

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.

Description

A-stream C-bug S-triage

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_COLOR disable 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::NeverStripStream, 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() is non_empty(NO_COLOR), so NO_COLOR=""
    disables nothing, per spec. This issue is only about the scope of
    suppression.
  • This cascades to dependents routing through anstream (env_logger,
    clap with its color feature), which would inherit the fix.
  • crossterm is a working example of color-only NO_COLOR handling —
    it gates Colored (fg/bg/underline-color) but emits SetAttributes
    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.

Dominant language
HTML
Stars
171
Forks
44
Avg merge
2h 34m
Merged PRs (30d)
6

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rust-cli/anstyle

All issues in rust-cli/anstyle

Similar issues

More CLI issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.