You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It suppresses all styling — bold, italic, underline, dim, reverse,
blink, hidden, strikethrough — not only color, contrary to the FAQ:
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.
It treats NO_COLOR="" (present but empty) as active. The spec requires
present and not an empty string; an empty value disables nothing.
Reproduction
Both bugs are in StyledObject::fmt (src/utils.rs, the impl_fmt! macro):
the entire emit block — fg, bg, andself.style.attrs — sits behind a
single colors_enabled() / colors_enabled_stderr() gate, which flips to false when env::var("NO_COLOR").is_ok() (src/unix_term.rs, src/windows_term/mod.rs).
Verified on console 0.16.4 — style("X").fg(Color::Red).attr(Attribute::Bold):
set_colors_enabled(true);let on = format!("{st}{s}{st:#}");// "\x1b[31m\x1b[1mX..."set_colors_enabled(false);let off = format!("{st}{s}{st:#}");// "X" — bold gone too
off contains neither \x1b[31m (red) nor \x1b[1m (bold). Per the FAQ,
only the color should be gone; bold should survive.
Expected (spec-aligned)
Use the right fd when reading unix terminal size #1 scope: When NO_COLOR is active, suppress color only; keep emitting self.style.attrs (bold/dim/italic/underline/blink/reverse/hidden/strikethrough). Style already separates fg/bg from attrs, so the fix is to move the attrs emit outside the colors_enabled() gate.
Get terminal size from /dev/tty directly #2 trigger:NO_COLOR="" should disable nothing. Replace env::var("NO_COLOR").is_ok() with a non-empty check
(e.g. env::var_os("NO_COLOR").is_some_and(|v| !v.is_empty())).
Notes
crossterm is a working example of color-only NO_COLOR handling — it
gates fg/bg/underline-color but emits SetAttributes unconditionally.
This cascades to dependents using console for styling — dialoguer and indicatif — which would inherit the fix.
I'm framing this as a bug fix (patch bump), but defer to the project's
own version policy.
NO_COLORdrops non-color attributes and treats empty value as activeSummary
consolehonorsNO_COLORbut in two ways that diverge fromno-color.org
(or its source):
It suppresses all styling — bold, italic, underline, dim, reverse,
blink, hidden, strikethrough — not only color, contrary to the FAQ:
It treats
NO_COLOR=""(present but empty) as active. The spec requirespresent and not an empty string; an empty value disables nothing.
Reproduction
Both bugs are in
StyledObject::fmt(src/utils.rs, theimpl_fmt!macro):the entire emit block — fg, bg, and
self.style.attrs— sits behind asingle
colors_enabled()/colors_enabled_stderr()gate, which flips tofalsewhenenv::var("NO_COLOR").is_ok()(src/unix_term.rs,src/windows_term/mod.rs).Verified on
console0.16.4 —style("X").fg(Color::Red).attr(Attribute::Bold):offcontains neither\x1b[31m(red) nor\x1b[1m(bold). Per the FAQ,only the color should be gone; bold should survive.
Expected (spec-aligned)
NO_COLORis active, suppress color only; keep emittingself.style.attrs(bold/dim/italic/underline/blink/reverse/hidden/strikethrough).Stylealready separatesfg/bgfromattrs, so the fix is to move theattrsemit outside thecolors_enabled()gate.NO_COLOR=""should disable nothing. Replaceenv::var("NO_COLOR").is_ok()with a non-empty check(e.g.
env::var_os("NO_COLOR").is_some_and(|v| !v.is_empty())).Notes
crosstermis a working example of color-onlyNO_COLORhandling — itgates fg/bg/underline-color but emits
SetAttributesunconditionally.consolefor styling —dialoguerandindicatif— which would inherit the fix.own version policy.