Skip to content

Add --color=auto|always|never to control ANSI output (#81)#109

Merged
raphaelsty merged 1 commit into
mainfrom
feat/color-output
May 28, 2026
Merged

Add --color=auto|always|never to control ANSI output (#81)#109
raphaelsty merged 1 commit into
mainfrom
feat/color-output

Conversation

@raphaelsty
Copy link
Copy Markdown
Collaborator

Closes #81.

Problem

colgrep emits color through two independent channels:

  1. the colored crate (.cyan() file headers, .dimmed() line numbers), and
  2. raw ANSI escapes from syntect syntax highlighting in display.rs.

colored honors NO_COLOR, but syntect doesn't — so output always contained escape sequences regardless of NO_COLOR/CLICOLOR/CLICOLOR_FORCE/TERM. As @divaltor noted, that pollutes context for agents/plugins that consume the output directly rather than through a terminal.

Change

A small color module resolves a single decision from --color and applies it to both channels:

  • sets the colored crate override (so every .cyan()/.dimmed() obeys), and
  • records the result for the syntect path to consult via colorize_enabled().

display.rs now prints plain, line-numbered text (no syntect, no \x1b[0m) when color is off.

--color auto     # default: color only on a TTY, honoring NO_COLOR / CLICOLOR / CLICOLOR_FORCE
--color always   # force color even when piped
--color never    # plain text, zero ANSI escapes

The flag is global, so it works on every subcommand (colgrep --color never ..., colgrep search --color never ..., etc.). Env handling in auto: CLICOLOR_FORCE (non-empty, non-0) forces on; else NO_COLOR (non-empty) disables; else CLICOLOR=0 disables; else colorize only on a TTY. An explicit --color always/never always wins.

A nice side effect: because auto now respects the TTY, piped output is plain by default too — which is the behavior @divaltor originally expected from NO_COLOR.

Testing

Unit tests for the env/auto-detection and the global toggle. End-to-end (verbose -c path, which is what triggers syntax highlighting), counting actual ESC (0x1b) bytes in captured output:

Invocation ESC bytes
--color never 0
default auto, piped (non-TTY) 0
NO_COLOR=1 (auto) 0
user's exact repro + --color never 0
--color always 1047
CLICOLOR_FORCE=1 (auto, piped) >0
NO_COLOR=1 --color always >0 (explicit wins)

Plain output keeps line numbers and content intact; cargo fmt/clippy/full colgrep test suite (541 lib + 55 bin) green.

Note on the follow-up ask

The issue also floated "might add an option to disable line numbers." I kept this PR scoped to color since that's the titled request and what the maintainer comment committed to; happy to add --no-line-numbers in a follow-up if wanted.

colgrep emitted color through two independent channels: the `colored`
crate (headers, line numbers) and raw ANSI escapes from `syntect` syntax
highlighting. `colored` honors NO_COLOR, but syntect never did, so output
always contained escape codes regardless of NO_COLOR/CLICOLOR/TERM — a
problem for agents and pipes that consume the output directly.

- New `color` module resolves one decision from --color (default auto) and
  applies it to BOTH channels: it sets the `colored` override and records
  the result for the syntect path to consult via colorize_enabled().
- `auto` honors CLICOLOR_FORCE, NO_COLOR, CLICOLOR, and stdout TTY, so
  piped output is now plain by default too.
- `never` makes display.rs print plain line-numbered text (no syntect,
  no \x1b[0m); `.dimmed()`/`.cyan()` go through the colored override.
- Global flag, so it works on every subcommand.

NO_COLOR and CLICOLOR_FORCE are honored in auto mode; --color always wins
when set explicitly.

Verified: --color=never and default-auto-when-piped emit 0 ANSI bytes;
--color=always emits color even with NO_COLOR set; plain output keeps
line numbers and content intact.
@raphaelsty raphaelsty merged commit ebfc5d4 into main May 28, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add option to generate not-colorized output

1 participant