fix(jq): -C null color and NaN's number-then-null wrap match jq 1.7.1 - #3433
Merged
Merged
Conversation
…#3413) jq 1.7.1's default null color is 0;90 (bright black), not the 1;30 this codebase's default-colors table assumed -- confirmed live against both the macOS system build and the Linux release binary, so this isn't an Apple-specific default. A NaN's "null" spelling (JSON has no NaN) also gets a second, distinct treatment: jq wraps it in the number color, then the null color, rather than the plain null color a real null gets. format_json's NaN branches now emit an internal marker text instead of a bare "null" when colorizing (gated by the new JsonFormatOpts::mark_nan_for_color, false everywhere else since the marker isn't valid JSON on its own), and colorize_json recognizes the marker to apply jq's double wrap before stripping it back to the literal "null" text. yq mode's own colorized JSON output (which shares this colorizer) keeps mark_nan_for_color: false -- real yq's own NaN color convention, if any, hasn't been checked against its oracle, so extending this is out of this issue's scope.
…heme choice Code review found the colorize_json NaN-vs-null disambiguation buffered a whole word into a String just to compare it, where a single-character peek (second letter 'a' vs 'u') suffices -- `format_json_impl` never emits any other bare n-leading token. Also cross-references jq::value::NAN_SENTINEL in the marker's own doc comment, since both solve the same smuggle-a-NaN-through-text problem in different pipelines. Separately, verifying #3413's shared default_colors::NULL constant against real yq (not just jq, since succinctly yq's own -o=json -C output shares this colorizer) surfaced a pre-existing, previously unrecorded divergence: real yq v4.53.3 doesn't color null in its own JSON output at all, and uses an entirely different scheme from jq's. Recorded in docs/compliance/yq/limitations.md per ADR-0018 -- this predates #3413 and isn't part of its scope to fix, only to write down now that it's been noticed.
CoverageTotal: 94.33% ⚪ 0 pp vs Comparing No per-file coverage changes vs 🔇 0 ignored region(s), 276 tolerated region(s)
Patch coveragePatch: 100% (65/65 new lines covered)
|
CoverageTotal: 94.42% ⚪ 0 pp vs Comparing No per-file coverage changes vs 🔇 0 ignored region(s), 275 tolerated region(s)
Patch coveragePatch: 100% (65/65 new lines covered)
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
nullcolor is0;90(bright black) — confirmed live against both the macOS system build (jq-1.7.1-apple) and the official Linux release binary (downloaded fresh fromjqlang/jq's GitHub releases), so this is not an Apple-specific default as the issue's own caveat worried it might be. This codebase'sdefault_colors::NULLhad1;30.nullspelling (JSON has no NaN) also gets different treatment from a real null in jq: it's wrapped in the number color first, then the null color (\e[0;39m\e[0;90mnull\e[0m\e[0m), distinguishing it from a real null even though the printed word is identical. This applies whether the NaN is computed (nan) or read from input ("NaN" | tonumber).colorize_jsonoperates on already-rendered JSON text with no access to the originating value, so it can't otherwise tell a NaN's "null" apart from a real one.format_json's two NaN branches now emit an internal marker text instead of a barenullwhen a newJsonFormatOpts::mark_nan_for_colorflag is set (only jq_runner.rs's colorizing call site sets it — the marker is not valid JSON on its own, so every other caller keeps emitting plainnull), andcolorize_jsonrecognizes the marker to apply jq's double wrap before stripping it back to the literalnulltext.Scope note
yq mode's own colorized JSON output (
-o=json -C) shares this same colorizer (confirmed by an existing test's own comment), so it inherits the corrected null color for free, but keepsmark_nan_for_color: false— real yq's own NaN color convention (if it has one at all) hasn't been checked against the yq oracle, and this issue is scoped to jq mode.Test plan
cargo build --features clicargo test --features cli,simd,regex,serde(full suite, 66/66 binaries green)cargo clippy --all-targets --all-features -- -D warningscargo clippy --all-targets --features std,simd,serde,cli,regex,bench-runner,large-tests,mmap-tests -- -D warnings/usr/bin/jq1.7.1 (macOS) and the officialjqlang/jqLinux release binary directly, fornull, computednan,"NaN" | tonumber, and a mixed array ([null, nan, 1]) to confirm the two are distinguished positionally, not just in isolation1;30default (tests/jq_cli_tests.rs,tests/yq_cli_tests.rs)omni-dev coverage diffpatch coverage: 100% (61/61 new lines)