fix(cli): print a friendly error when multiple sources are passed#179
fix(cli): print a friendly error when multiple sources are passed#179airvzxf wants to merge 2 commits into
Conversation
Running `mdfried **/PRO*.md` from a shell expands the glob to multiple paths, and clap's default 'error: unexpected argument ...' does not explain that mdfried takes a single source. Detect the multi-positional case (ErrorKind::UnknownArgument whose InvalidArg does not start with '-') and emit a hint that points at quoting the glob or running mdfried once per file. All other argument errors fall through to clap's default formatter, which already includes usage and --help. The clap::Command builder is extracted into a build_cli() helper so the new unit test in mod tests can call try_get_matches_from directly and assert the error kind and offending value, locking the friendly message in against future regressions.
There was a problem hiding this comment.
Pull request overview
This PR improves the mdfried CLI UX by replacing clap’s generic “unexpected argument” output (when multiple positional sources are provided) with a targeted, user-friendly hint that explains the common glob-expansion cause and how to fix it, while preserving clap’s default behavior for unknown flags.
Changes:
- Extracted CLI construction into
build_cli()to enable direct unit testing of clap parsing behavior. - Updated
main()to interceptErrorKind::UnknownArgumentthat looks like an extra positional (invalid arg doesn’t start with-) and print a friendly error before exiting with code2. - Added a unit test to lock in clap’s error kind and
InvalidArgcontext for the second positional argument.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…shape The test only asserts on what clap returns (ErrorKind + ContextKind::InvalidArg), not on the friendly message printed by main(). Reword the comment so it accurately describes what is being locked in, and what would surface a regression.
|
Thanks for the review, @copilot-pull-request-reviewer. The one substantive comment has been applied in 57d02be — the test comment now accurately describes what the assertions lock in (clap's error shape, not the friendly message itself). This PR is ready to merge. The two commits on this branch:
Note: I'm opening this from a fork without write access to |












Closes #178
What
When the user passes more than one positional argument (typically because
a shell glob like
mdfried **/PRO*.mdexpanded to multiple paths),clap returns
ErrorKind::UnknownArgumentfor the second one. mdfriednow detects that specific shape — the offending value does not start
with
-— and prints a friendly hint instead of clap's generic'unexpected argument' message.
Before
After
Exit code stays
2(matches clap's default for argument errors).Why
The
[SOURCE]positional is correctly single-valued; the bug is purelythe error message. clap's default does not mention that mdfried takes
one source at a time, so users who reached for a glob to view several
PROPOSAL.md files get a wall of text that does not explain the actual
problem. Unknown flags (
--foo) keep clap's normal error, since the'single source' hint would be misleading there.
How
build_cli()is extracted frommain()so the new unit test cancall
try_get_matches_fromdirectly.main()now usestry_get_matches_from_mutinstead ofget_matches_mut, interceptsErrorKind::UnknownArgumentwhoseInvalidArgcontext does not start with-, prints the hint,and exits with
2. All other argument errors fall through toclap::error::Error::exit, which keeps the well-tested usage /--helpoutput for the cases that benefit from it.tests::multiple_positional_sources_are_rejected_as_unknown_argument)locks the error kind and the offending value in, so the friendly
message cannot silently regress to clap's default.
Validation
cargo fmt --check— cleancargo clippy --all-targets --no-default-features— no new warnings(the two
#[allow(...)] on document.rswarnings pre-exist on masterand are unrelated)
cargo build --no-default-featurescargo build --release --no-default-featurescargo test --no-default-features --bin mdfried— new test passes;the only failures are the pre-existing
instasnapshot tests thatalso fail on base master
cargo doc --no-depsmdfried a.md b.md→ friendly message, exit 2mdfried --nope→ clap's default error, exit 2mdfried --print-config→ still works