Skip to content

nl: match GNU's errors for its numeric and numbering-style option values - #14314

Closed
arbelonson-source wants to merge 1 commit into
uutils:mainfrom
arbelonson-source:fix/nl-option-value-messages
Closed

nl: match GNU's errors for its numeric and numbering-style option values#14314
arbelonson-source wants to merge 1 commit into
uutils:mainfrom
arbelonson-source:fix/nl-option-value-messages

Conversation

@arbelonson-source

Copy link
Copy Markdown
Contributor

What

nl's numeric options (-i/--line-increment, -l/--join-blank-lines,
-v/--starting-line-number, -w/--number-width) validated their
values with clap's own i64/u64 value parser, which caused two
separate problems:

1. A negative value as its own argument was rejected as an unrecognized flag:

$ nl -i -5 f

# GNU: accepts it fine
# uutils, before this PR:
error: unexpected argument '-5' found
  tip: to pass '-5' as a value, use '-- -5'

(The attached form, -i-5, already worked -- only the separate-argument form was broken.)

2. An invalid value got clap's own generic wording, and conflated two GNU messages that mean different things:

$ nl -w bogus f
# GNU:    nl: invalid line number field width: 'bogus'
# before: error: invalid value 'bogus' for '--number-width <NUMBER>': invalid digit found in string

$ nl -w 2147483648 f   # --number-width is a plain C `int`; this overflows it
# GNU:    nl: invalid line number field width: '2147483648': Value too large for defined data type

$ nl -w 0 f   # fits in `int` fine, but --number-width also requires a *positive* value
# GNU:    nl: invalid line number field width: '0': Numerical result out of range

The last two are genuinely different failure modes in GNU's wording
(overflowing the option's own C integer width vs. fitting that width
but failing a separate business-rule check) and needed to stay
distinguished.

Also fixed

The header/body/footer numbering-style options (-h/-b/-f) and
the number-format option (-n) have the same underlying "clap's own
wording instead of GNU's" problem (via a plain value_parser and
PossibleValuesParser respectively). GNU reports each with a
field-specific message ("invalid header numbering style" vs "body" vs
"footer", vs "invalid line numbering format" for -n), appends "Try
--help" (which the numeric options and a bad regular expression for
-h/-b/-f do not), and -- unlike the numeric options, which stop
parsing immediately at the first bad one -- collects every bad
style/format option and reports them together, in the order they were
actually given on the command line.

Replaced the existing parse_options error path (a generic "Invalid
arguments supplied." preamble + a plain joined list) with GNU's real
shape: per-error nl: -prefixed lines (only the first of which the
outer error handler adds automatically) and a single trailing hint
line only when appropriate.

Testing

  • cargo test -p uu_nl / full tests/by-util/test_nl.rs suite: 69 passed, 0 failed.
  • Fixed 9 existing tests that had encoded clap's wrong wording as the expected result.
  • Added regression tests for the separate-argument negative-value case (the actual reported bug) on both -i and -v.
  • Manually diffed ~26 cases (invalid, negative, boundary, overflow, multi-error, regex-error) across all 8 affected options against GNU nl 9.11 under LC_ALL=C.
  • cargo clippy -p uu_nl --all-targets -- -D warnings and cargo fmt --check: clean.

This PR was written with AI assistance (Claude Opus 5, via Claude Code). I've tested the changes but please review the code carefully.

nl's numeric options (-i/--line-increment, -l/--join-blank-lines,
-v/--starting-line-number, -w/--number-width) validated their values
with clap's own i64/u64 value_parser, so:

- a negative value passed as its own argument (`-i -5`, not the
  attached `-i-5`) was rejected as an unrecognized flag instead of
  being read as the option's value, since these Args did not have
  allow_hyphen_values;
- an invalid value produced clap's own generic wording instead of
  GNU's (e.g. 'invalid digit found in string' instead of "invalid line
  number increment: 'bogus'"), and did not distinguish GNU's two
  distinct overflow messages: a value that overflows the *option's
  own* underlying integer width (e.g. --number-width is a plain C
  int, so anything outside i32 -- even though it parses as an i64 just
  fine) is "Value too large for defined data type", while one that
  fits that width but falls outside the option's accepted range (e.g.
  --number-width also requires a positive value) is "Numerical result
  out of range".

Also fixes the header/body/footer numbering style options (-h, -b, -f)
and the number format option (-n), which validated via a plain
value_parser and clap's own PossibleValuesParser respectively, same
underlying wording problem. GNU reports each of these with a
field-specific message ("invalid header numbering style", vs "body"
vs "footer", vs "invalid line numbering format" for -n) that a single
generic message can't produce, appends 'Try --help' (which the numeric
options and an invalid regular expression for -h/-b/-f do not), and --
unlike the numeric options, which stop parsing immediately at the
first bad one -- collects every bad style/format option and reports
them together, in the order they were actually given on the command
line.

Replaced the existing 'Invalid arguments supplied.' preamble + joined
list, which didn't match any of this, with per-error 'nl: ' prefixed
lines (only the first of which the outer error handler adds for us)
and a single trailing hint line when appropriate.

AI-assisted-by: Claude Opus 5, via Claude Code
@oech3

oech3 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

You should use value_parser and allow_hyphen_values instead to show what user should do instead of matching with GNU.
@arbelonson-source Please stop removing clap's error message without any vaid reason.

@arbelonson-source

Copy link
Copy Markdown
Contributor Author

Closing proactively — same template as the batch you just closed (#14304, #14312, etc.): reworks clap's already-correct wording to match GNU's text. There's a genuine secondary fix bundled in here too (negative values as their own arg were rejected as unrecognized flags), but given #14304 got closed despite having the same kind of bundled fix, I'll assume the wording-matching part outweighs it. Happy to reopen a hyphen-values-only version if that's wanted separately — just say the word.

@sylvestre

Copy link
Copy Markdown
Contributor

sure
thanks

@github-actions

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/tail/symlink (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/cut/bounded-memory (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/cut/cut-huge-range is now being skipped but was previously passing.

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.

3 participants