console-rs / console-rs/console

NO_COLOR drops non-color attributes and treats empty value as active

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

Nobody has claimed this yet.

Dominant language
Rust
Stars
1.2k
Forks
144
Avg merge
8h 24m
Merged PRs (30d)
4

Description

NO_COLOR drops non-color attributes and treats empty value as active

Summary

console honors NO_COLOR but in two ways that diverge from
no-color.org
(or its source):

  1. 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.

  2. 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, and self.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)

  • #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.
  • #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.

Contributor guide

No contributing guide indexed for this repository

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.

Research direction

Start in src/utils.rs at the StyledObject::fmt implementation and the impl_fmt! macro, then inspect the NO_COLOR checks in src/unix_term.rs and src/windows_term/mod.rs. Verify the formatting paths for color and attributes, and confirm completion when non-color attributes remain active while empty NO_COLOR disables nothing.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.