Skip to content

Replace structopt and clap 2 with clap 4 - #15

Open
bmesuere wants to merge 1 commit into
feature/fst-0.4from
feature/clap-4
Open

Replace structopt and clap 2 with clap 4#15
bmesuere wants to merge 1 commit into
feature/fst-0.4from
feature/clap-4

Conversation

@bmesuere

@bmesuere bmesuere commented Aug 18, 2026

Copy link
Copy Markdown
Member

Stacked on #14. With both merged, the dependency tree has zero RustSec advisories, down from six.

This clears the remaining five: structopt is in maintenance mode (RUSTSEC-2022-0104), and clap 2 drags in ansi_term (RUSTSEC-2021-0139), atty (RUSTSEC-2021-0145, RUSTSEC-2024-0375) and proc-macro-error (RUSTSEC-2024-0370).

The mechanical part

StructOpt becomes Args (or Parser for the top-level enum), #[structopt(...)] becomes #[arg(...)] on fields and #[command(...)] on containers, short flags take a char instead of a &str, and parse(from_os_str) disappears because clap 4 handles PathBuf itself.

The part that needed thought

clap 4 dropped Arg::possible_values. Deriving ValueEnum would have been the idiomatic replacement, but it would have changed the accepted strings — and one of them matters: Rank's CLI list deliberately omits "no rank" even though its FromStr accepts it. Keeping PossibleValuesParser over the existing variants() lists preserves both the accepted values and the listing in the help output.

Verification

I built the old binary from phase1 and compared the two directly, rather than trusting the help text to look similar.

  • Interface: identical short/long flags, defaults and possible values across all 20 subcommands. The only diffs are clap 4 quoting things in its output — empty defaults shown as "", multi-word ranks as "species group", uniq's newline default as "\n". No value changed.
  • Behaviour: byte-identical output from both binaries for filter (defaults, -m/-M, -c), prot2tryp, prot2kmer -k, translate (-f 1, -f 1R -n, -a) and uniq (default, -d, -w).
  • Value enums: same accept/reject decision for every case tried — species, "species group", bogus, rmq, lca* — including "no rank" still refused.
  • 38 tests pass, cargo +nightly fmt --check clean, and the full pipeline still runs end to end through FragGeneScanRs to tryptic peptides.

Worth knowing

Help output is reformatted by clap 4: Usage: rather than USAGE:, flags and options merged into one section, values quoted. The website documentation reproduces this output in places, so those pages will drift.

Exit codes for CLI usage errors change from 1 to 2. clap 4 uses exit code 2 for argument errors where clap 2 used 1. Verified: translate -f 9, filter --bogus and taxa2agg -m nope all went from 1 to 2. Runtime errors (missing file, malformed input) still exit 1. Anything scripting against a nonzero exit is fine; anything matching on -eq 1 specifically is not.

Error wording also changed, e.g. Found argument '10' which wasn't expected became unexpected argument '10' found.

Clears the last five advisories in the tree: structopt is in maintenance
mode (RUSTSEC-2022-0104) and clap 2 drags in ansi_term (RUSTSEC-2021-0139),
atty (RUSTSEC-2021-0145, RUSTSEC-2024-0375) and proc-macro-error
(RUSTSEC-2024-0370). Together with the fst upgrade this leaves the
dependency tree with none.

The derive translation is mechanical: StructOpt becomes Args or Parser,
#[structopt(...)] becomes #[arg(...)] on fields and #[command(...)] on
containers, short flags take a char rather than a string, and
parse(from_os_str) is gone since clap 4 handles PathBuf itself.

The one part that needed thought is the argument enums. clap 4 dropped
Arg::possible_values, and deriving ValueEnum would have changed the accepted
strings, which matter here: Rank's CLI list deliberately leaves out "no rank"
even though its FromStr accepts it. Keeping PossibleValuesParser over the
existing variants() lists preserves both the accepted values and the listing
in the help output.

Verified against the old binary: identical flags, defaults and accepted
values across all 20 subcommands, identical output on filter, prot2tryp,
prot2kmer, translate and uniq, and the same accept/reject decisions for every
rank, method and strategy, including "no rank" still being refused.

Help text is reformatted by clap 4 (Usage: rather than USAGE:, flags and
options in one section, values quoted). The website documentation shows this
output in places.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 18, 2026 13:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

2 participants