From 6e37fc11f4bca39838fce1ba3112a5de99d7c939 Mon Sep 17 00:00:00 2001 From: Bart Mesuere Date: Tue, 18 Aug 2026 15:31:20 +0200 Subject: [PATCH] Replace structopt and clap 2 with clap 4 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 --- Cargo.lock | 244 ++++++++++++++++------------------ Cargo.toml | 3 +- src/commands/bestof.rs | 8 +- src/commands/buildindex.rs | 6 +- src/commands/fastq2fasta.rs | 7 +- src/commands/filter.rs | 14 +- src/commands/joinkmers.rs | 7 +- src/commands/pept2lca.rs | 13 +- src/commands/printindex.rs | 7 +- src/commands/prot2kmer.rs | 8 +- src/commands/prot2kmer2lca.rs | 17 +-- src/commands/prot2tryp.rs | 8 +- src/commands/prot2tryp2lca.rs | 23 ++-- src/commands/seedextend.rs | 14 +- src/commands/snaptaxon.rs | 21 +-- src/commands/splitkmers.rs | 10 +- src/commands/taxa2agg.rs | 42 +++--- src/commands/taxa2freq.rs | 20 +-- src/commands/taxa2tree.rs | 8 +- src/commands/taxonomy.rs | 11 +- src/commands/translate.rs | 24 ++-- src/commands/uniq.rs | 12 +- src/lib.rs | 3 - src/main.rs | 47 +++---- 24 files changed, 297 insertions(+), 280 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 724764dd..50750d3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,12 +27,53 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "winapi", + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", ] [[package]] @@ -57,17 +98,6 @@ dependencies = [ "url", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.5.1" @@ -89,12 +119,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.13.1" @@ -125,19 +149,50 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "clap" -version = "2.34.0" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "core-foundation" version = "0.10.1" @@ -331,13 +386,10 @@ dependencies = [ ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" @@ -454,6 +506,12 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itoa" version = "1.0.18" @@ -556,13 +614,19 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "openssl" version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.13.1", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -629,30 +693,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.107" @@ -738,7 +778,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.1", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -766,7 +806,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.13.1", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -851,33 +891,9 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "strsim" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -891,7 +907,7 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6e163a520367c465f59e0a61a23cfae3b10b6546d78b6f672a382be79f7110" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro2", "quote", "syn 1.0.109", @@ -954,15 +970,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "tinystr" version = "0.8.4" @@ -989,7 +996,6 @@ dependencies = [ "rayon", "regex", "serde_json", - "structopt", "strum", "strum_macros", ] @@ -1006,12 +1012,6 @@ version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "url" version = "2.5.8" @@ -1031,16 +1031,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] -name = "vcpkg" -version = "0.2.15" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "vec_map" -version = "0.8.2" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" @@ -1048,28 +1048,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-link" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index d9d37b4e..37cb460f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ edition = "2018" rust-version = "1.88" [dependencies] -clap = "2.33.0" +clap = { version = "4.6", features = ["derive"] } csv = "1.1.2" error-chain = "0.12.4" fst = "0.4.7" @@ -28,7 +28,6 @@ ordered-float = "1.0.2" rayon = "1.3.0" regex = "1.3.1" serde_json = "1.0.44" -structopt = "0.3.23" strum = "0.17.1" strum_macros = "0.17.1" attohttpc = { version = "0.15.0", features = [ "json" ] } diff --git a/src/commands/bestof.rs b/src/commands/bestof.rs index 7ca1181c..77bd5f6a 100644 --- a/src/commands/bestof.rs +++ b/src/commands/bestof.rs @@ -2,12 +2,14 @@ use std::io; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::taxon::TaxonId; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Selects the best read of every fixed size group /// /// The `umgap bestof` command takes groups of taxon IDs as input and outputs for each group the @@ -44,7 +46,7 @@ use crate::taxon::TaxonId; /// example. pub struct BestOf { /// The number of frames of which to pick the best - #[structopt(short = "f", long = "frames", default_value = "6")] + #[arg(short = 'f', long = "frames", default_value = "6")] pub frames: usize, } diff --git a/src/commands/buildindex.rs b/src/commands/buildindex.rs index 7806441d..6e0f9f52 100644 --- a/src/commands/buildindex.rs +++ b/src/commands/buildindex.rs @@ -2,10 +2,12 @@ use std::io; +use clap::Args; + use crate::errors; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] #[allow(clippy::tabs_in_doc_comments)] /// Builds an index mapping short strings to taxon IDs /// diff --git a/src/commands/fastq2fasta.rs b/src/commands/fastq2fasta.rs index 1549d194..82abdc02 100644 --- a/src/commands/fastq2fasta.rs +++ b/src/commands/fastq2fasta.rs @@ -4,14 +4,16 @@ use std::fs; use std::io; use std::path::PathBuf; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::io::fastq; use crate::utils; #[rustfmt::skip] -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Interleaves FASTQ files into a FASTA stream /// /// The `umgap fastq2fasta` command takes one or more FASTQ files and interleaves them into a single @@ -54,7 +56,6 @@ use crate::utils; /// ``` pub struct FastqToFasta { /// The input files - #[structopt(parse(from_os_str))] pub input: Vec, } diff --git a/src/commands/filter.rs b/src/commands/filter.rs index 50c072e2..5fe8de8b 100644 --- a/src/commands/filter.rs +++ b/src/commands/filter.rs @@ -3,11 +3,13 @@ use std::collections::HashSet; use std::io; +use clap::Args; + use crate::errors; use crate::io::fasta; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Filters a FASTA stream of peptides /// /// The `umgap filter` command takes a FASTA stream of peptides as input and outputs a filtered @@ -48,19 +50,19 @@ use crate::io::fasta; /// ``` pub struct Filter { /// Minimum length required - #[structopt(short = "m", long = "minlen", default_value = "5")] + #[arg(short = 'm', long = "minlen", default_value = "5")] pub min_length: usize, /// Maximum length allowed - #[structopt(short = "M", long = "maxlen", default_value = "50")] + #[arg(short = 'M', long = "maxlen", default_value = "50")] pub max_length: usize, /// Amino acid symbols that a sequence must contain - #[structopt(short = "c", long = "contains", default_value = "")] + #[arg(short = 'c', long = "contains", default_value = "")] pub contains: String, /// Amino acid symbols that a sequence may not contain - #[structopt(short = "l", long = "lacks", default_value = "")] + #[arg(short = 'l', long = "lacks", default_value = "")] pub lacks: String, } diff --git a/src/commands/joinkmers.rs b/src/commands/joinkmers.rs index 82e5db3d..13e0a476 100644 --- a/src/commands/joinkmers.rs +++ b/src/commands/joinkmers.rs @@ -6,13 +6,15 @@ use std::path::PathBuf; use crate::agg; use crate::agg::Aggregator; +use clap::Args; + use crate::errors; use crate::taxon; use crate::taxon::TaxonId; use crate::tree; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] #[allow(clippy::tabs_in_doc_comments)] /// Aggregates a TSV stream of peptides and taxon IDs /// @@ -45,7 +47,6 @@ use crate::tree; /// ``` pub struct JoinKmers { /// An NCBI taxonomy TSV-file as processed by Unipept - #[structopt(parse(from_os_str))] pub taxon_file: PathBuf, } diff --git a/src/commands/pept2lca.rs b/src/commands/pept2lca.rs index 362ee0c5..019e52fd 100644 --- a/src/commands/pept2lca.rs +++ b/src/commands/pept2lca.rs @@ -5,12 +5,14 @@ use std::path::PathBuf; use rayon::iter::{ParallelBridge, ParallelIterator}; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::utils; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Maps a FASTA stream of peptides to taxon IDs /// /// The `umgap pept2lca` command takes one or more amino acid sequences and looks up the @@ -46,17 +48,16 @@ use crate::utils; /// ``` pub struct PeptToLca { /// Map unknown sequences to 0 instead of ignoring them - #[structopt(short = "o", long = "one-on-one")] + #[arg(short = 'o', long = "one-on-one")] pub one_on_one: bool, /// An index that maps peptides to taxon IDs - #[structopt(parse(from_os_str))] pub fst_file: PathBuf, /// Load index in memory instead of memory mapping the file contents. This /// makes querying significantly faster, but requires some initialization /// time. - #[structopt(short = "m", long = "in-memory")] + #[arg(short = 'm', long = "in-memory")] pub fst_in_memory: bool, /// Number of reads grouped into one chunk. Bigger chunks decrease @@ -65,7 +66,7 @@ pub struct PeptToLca { /// a multiple of 12 (all 6 translations multiplied by the two paired-end /// reads) will keep FASTA records that originate from the same reads /// together. - #[structopt(short = "c", long = "chunksize", default_value = "240")] + #[arg(short = 'c', long = "chunksize", default_value = "240")] pub chunk_size: usize, } diff --git a/src/commands/printindex.rs b/src/commands/printindex.rs index 298d845c..0a0105ee 100644 --- a/src/commands/printindex.rs +++ b/src/commands/printindex.rs @@ -5,11 +5,13 @@ use std::path::PathBuf; use fst::Streamer; +use clap::Args; + use crate::errors; use crate::utils; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] #[allow(clippy::tabs_in_doc_comments)] /// Prints the key/value pairs in an index /// @@ -31,7 +33,6 @@ use crate::utils; /// ``` pub struct PrintIndex { /// An index that maps strings to taxon IDs - #[structopt(parse(from_os_str))] pub fst_file: PathBuf, } diff --git a/src/commands/prot2kmer.rs b/src/commands/prot2kmer.rs index accb46ec..761dc921 100644 --- a/src/commands/prot2kmer.rs +++ b/src/commands/prot2kmer.rs @@ -3,11 +3,13 @@ use std::borrow::Cow; use std::io; +use clap::Args; + use crate::errors; use crate::io::fasta; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Splits a FASTA stream of peptides into k-mers /// /// The `umgap prot2kmer` command takes one or more peptides as input and outputs all their k-length @@ -35,7 +37,7 @@ use crate::io::fasta; /// ``` pub struct ProtToKmer { /// The k-mer length - #[structopt(short = "k", long = "length", default_value = "9")] + #[arg(short = 'k', long = "length", default_value = "9")] pub length: usize, } diff --git a/src/commands/prot2kmer2lca.rs b/src/commands/prot2kmer2lca.rs index b397ebf5..29f7e90e 100644 --- a/src/commands/prot2kmer2lca.rs +++ b/src/commands/prot2kmer2lca.rs @@ -10,12 +10,14 @@ use std::sync::Mutex; use rayon::iter::{ParallelBridge, ParallelIterator}; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::utils; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Maps all k-mers from a FASTA stream of peptides to taxon IDs /// /// The `umgap prot2kmer2lca` command takes one or more peptides as input and outputs the lowest @@ -69,15 +71,14 @@ use crate::utils; /// socket using OpenBSD's netcat: `... | nc -NU /path/to/umgap-socket | ...`. pub struct ProtToKmerToLca { /// The length of the k-mers in the index - #[structopt(short = "k", long = "length", default_value = "9")] + #[arg(short = 'k', long = "length", default_value = "9")] pub length: usize, /// Map unknown sequences to 0 instead of ignoring them - #[structopt(short = "o", long = "one-on-one")] + #[arg(short = 'o', long = "one-on-one")] pub one_on_one: bool, /// An index that maps k-mers to taxon IDs - #[structopt(parse(from_os_str))] pub fst_file: PathBuf, /// Instead of reading from stdin and writing to stdout, create a Unix @@ -85,13 +86,13 @@ pub struct ProtToKmerToLca { /// This is especially useful in combination with the `--in-memory` flag: /// you only have to load the index in memory once, after which you can /// query it without having the loading time overhead each time. - #[structopt(parse(from_os_str), short = "s", long = "socket")] + #[arg(short = 's', long = "socket")] pub socket: Option, /// Load index in memory instead of memory mapping the file contents. This /// makes querying significantly faster, but requires some initialization /// time. - #[structopt(short = "m", long = "in-memory")] + #[arg(short = 'm', long = "in-memory")] pub fst_in_memory: bool, /// Number of reads grouped into one chunk. Bigger chunks decrease @@ -100,7 +101,7 @@ pub struct ProtToKmerToLca { /// a multiple of 12 (all 6 translations multiplied by the two paired-end /// reads) will keep FASTA records that originate from the same reads /// together. - #[structopt(short = "c", long = "chunksize", default_value = "240")] + #[arg(short = 'c', long = "chunksize", default_value = "240")] pub chunk_size: usize, } diff --git a/src/commands/prot2tryp.rs b/src/commands/prot2tryp.rs index 8c7e2a7f..e93686ae 100644 --- a/src/commands/prot2tryp.rs +++ b/src/commands/prot2tryp.rs @@ -2,11 +2,13 @@ use std::io; +use clap::Args; + use crate::errors; use crate::io::fasta; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Splits the peptides in a FASTA stream into tryptic peptides /// /// The `umgap prot2tryp` command takes one or more amino acid sequences as input and applies an *in @@ -42,7 +44,7 @@ use crate::io::fasta; pub struct ProtToTryp { /// The cleavage-pattern (regex), i.e. the pattern after which /// the next peptide will be cleaved for tryptic peptides) - #[structopt(short = "p", long = "pattern", default_value = "([KR])([^P])")] + #[arg(short = 'p', long = "pattern", default_value = "([KR])([^P])")] pub pattern: String, } diff --git a/src/commands/prot2tryp2lca.rs b/src/commands/prot2tryp2lca.rs index a4292959..69ee30f4 100644 --- a/src/commands/prot2tryp2lca.rs +++ b/src/commands/prot2tryp2lca.rs @@ -8,12 +8,14 @@ use regex; use rayon::iter::{ParallelBridge, ParallelIterator}; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::utils; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Digests a FASTA stream of peptides and maps all tryptic peptides to taxon IDs /// /// The `umgap prot2tryp2lca` command takes one or more peptides and splits these into @@ -38,17 +40,16 @@ use crate::utils; /// ``` pub struct ProtToTrypToLca { /// Map unknown sequences to 0 instead of ignoring them - #[structopt(short = "o", long = "one-on-one")] + #[arg(short = 'o', long = "one-on-one")] pub one_on_one: bool, /// An index that maps tryptic peptides to taxon IDs - #[structopt(parse(from_os_str))] pub fst_file: PathBuf, /// Load index in memory instead of memory mapping the file contents. This /// makes querying significantly faster, but requires some initialization /// time. - #[structopt(short = "m", long = "in-memory")] + #[arg(short = 'm', long = "in-memory")] pub fst_in_memory: bool, /// Number of reads grouped into one chunk. Bigger chunks decrease @@ -57,28 +58,28 @@ pub struct ProtToTrypToLca { /// a multiple of 12 (all 6 translations multiplied by the two paired-end /// reads) will keep FASTA records that originate from the same reads /// together. - #[structopt(short = "c", long = "chunksize", default_value = "240")] + #[arg(short = 'c', long = "chunksize", default_value = "240")] pub chunk_size: usize, /// The cleavage-pattern (regex), i.e. the pattern after which /// the next peptide will be cleaved for tryptic peptides) - #[structopt(short = "p", long = "pattern", default_value = "([KR])([^P])")] + #[arg(short = 'p', long = "pattern", default_value = "([KR])([^P])")] pub pattern: String, /// Minimum length of tryptic peptides to be mapped - #[structopt(short = "l", long = "minlen", default_value = "5")] + #[arg(short = 'l', long = "minlen", default_value = "5")] pub min_length: usize, /// Maximum length of tryptic peptides to be mapped - #[structopt(short = "L", long = "maxlen", default_value = "50")] + #[arg(short = 'L', long = "maxlen", default_value = "50")] pub max_length: usize, /// Amino acid symbols that a peptide must contain to be processed - #[structopt(short = "k", long = "keep", default_value = "")] + #[arg(short = 'k', long = "keep", default_value = "")] pub contains: String, /// Amino acid symbols that a peptide may not contain to be processed - #[structopt(short = "d", long = "drop", default_value = "")] + #[arg(short = 'd', long = "drop", default_value = "")] pub lacks: String, } diff --git a/src/commands/seedextend.rs b/src/commands/seedextend.rs index c81efbaa..605d39a0 100644 --- a/src/commands/seedextend.rs +++ b/src/commands/seedextend.rs @@ -4,13 +4,15 @@ use std::cmp; use std::io; use std::path::PathBuf; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::taxon; use crate::taxon::TaxonId; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Selects promising regions in sequences of taxon IDs /// /// The `umgap seedextend` command takes one or more sequences of taxon IDs and selects regions of @@ -62,19 +64,19 @@ use crate::taxon::TaxonId; /// (higher or lower) with the `-p` option. pub struct SeedExtend { /// The minimum length of equal taxa to count as seed - #[structopt(short = "s", long = "min-seed-size", default_value = "2")] + #[arg(short = 's', long = "min-seed-size", default_value = "2")] pub min_seed_size: usize, /// The maximum length of a gap between seeds in an extension - #[structopt(short = "g", long = "max-gap-size", default_value = "0")] + #[arg(short = 'g', long = "max-gap-size", default_value = "0")] pub max_gap_size: usize, /// Use taxon ranks in given NCBI taxonomy tsv-file to pick extended seed with highest score - #[structopt(short = "r", long = "ranked", parse(from_os_str))] + #[arg(short = 'r', long = "ranked")] pub ranked: Option, /// The score penalty for gaps in extended seeds - #[structopt(short = "p", long = "penalty", default_value = "5")] + #[arg(short = 'p', long = "penalty", default_value = "5")] pub penalty: usize, } diff --git a/src/commands/snaptaxon.rs b/src/commands/snaptaxon.rs index 90ec72d5..5a4e9cea 100644 --- a/src/commands/snaptaxon.rs +++ b/src/commands/snaptaxon.rs @@ -5,14 +5,19 @@ use std::io::BufRead; use std::io::Write; use std::path::PathBuf; +use std::str::FromStr; + +use clap::builder::{PossibleValuesParser, TypedValueParser}; +use clap::Args; + use crate::errors; use crate::rank; use crate::rank::Rank; use crate::taxon; use crate::taxon::TaxonId; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Snaps taxon IDs to a specific rank or listed taxa /// /// The `umgap snaptaxon` command takes one or more taxon IDs. For each taxon, it searches amongst @@ -49,23 +54,23 @@ use crate::taxon::TaxonId; /// ``` pub struct SnapTaxon { /// The rank to snap towards. - #[structopt( - short = "r", + #[arg( + short = 'r', long = "rank", - possible_values = &Rank::variants() + value_parser = PossibleValuesParser::new(Rank::variants().iter().copied()) + .map(|s| Rank::from_str(&s).expect("a possible value always parses")), )] pub rank: Option, /// A taxon to snap towards (allow multiple times). - #[structopt(short = "t", long = "taxons")] + #[arg(short = 't', long = "taxons")] pub taxons: Vec, /// Include the invalidated taxa from the taxonomy - #[structopt(short = "i", long = "invalid")] + #[arg(short = 'i', long = "invalid")] pub invalid: bool, /// An NCBI taxonomy TSV-file as processed by Unipept - #[structopt(parse(from_os_str))] pub taxon_file: PathBuf, } diff --git a/src/commands/splitkmers.rs b/src/commands/splitkmers.rs index 7bc3280f..c6109ee5 100644 --- a/src/commands/splitkmers.rs +++ b/src/commands/splitkmers.rs @@ -2,12 +2,14 @@ use std::io; +use clap::Args; + use crate::errors; use crate::taxon::TaxonId; #[rustfmt::skip] -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Splits a TSV stream of peptides and taxon IDs into k-mers and taxon IDs /// /// The `umgap splitkmers` command takes tab-separated taxon IDs and protein sequences and outputs @@ -41,11 +43,11 @@ use crate::taxon::TaxonId; /// ``` pub struct SplitKmers { /// The k-mer length - #[structopt(short = "k", long = "length", default_value = "9")] + #[arg(short = 'k', long = "length", default_value = "9")] pub length: usize, /// Print only the (k-1)-mer suffixes of the k-mers starting with this character, if any - #[structopt(short = "p", long = "prefix", default_value = "")] + #[arg(short = 'p', long = "prefix", default_value = "")] pub prefix: String, } diff --git a/src/commands/taxa2agg.rs b/src/commands/taxa2agg.rs index 57c1118f..f5e3b304 100644 --- a/src/commands/taxa2agg.rs +++ b/src/commands/taxa2agg.rs @@ -6,6 +6,9 @@ use std::path::PathBuf; use std::str::FromStr; use crate::agg; +use clap::builder::{PossibleValuesParser, TypedValueParser}; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::rmq; @@ -13,8 +16,8 @@ use crate::taxon; use crate::taxon::TaxonId; use crate::tree; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Aggregates taxon IDs in a FASTA stream /// /// The `umgap taxa2agg` command takes one or more lists of taxon IDs and aggregates them into a @@ -60,41 +63,42 @@ use crate::tree; /// 1.0`). pub struct TaxaToAgg { /// Each taxon is followed by a score between 0 and 1 - #[structopt(short = "s", long = "scored")] + #[arg(short = 's', long = "scored")] pub scored: bool, /// Let all taxa snap to taxa with a named rank (such as species) during calculations - #[structopt(short = "r", long = "ranked")] + #[arg(short = 'r', long = "ranked")] pub ranked_only: bool, /// The method to use for aggregation - #[structopt( - short = "m", - long = "method", - default_value = "tree", - possible_values = &Method::variants() + #[arg( + short = 'm', + long = "method", + default_value = "tree", + value_parser = PossibleValuesParser::new(Method::variants().iter().copied()) + .map(|s| Method::from_str(&s).expect("a possible value always parses")), )] pub method: Method, /// The strategy to use for aggregation - #[structopt( - short = "a", - long = "aggregate", - default_value = "hybrid", - possible_values = &Strategy::variants() + #[arg( + short = 'a', + long = "aggregate", + default_value = "hybrid", + value_parser = PossibleValuesParser::new(Strategy::variants().iter().copied()) + .map(|s| Strategy::from_str(&s).expect("a possible value always parses")), )] pub strategy: Strategy, /// The factor for the hybrid aggregation, from 0.0 (MRTL) to 1.0 (LCA*) - #[structopt(short = "f", long = "factor", default_value = "0.25")] + #[arg(short = 'f', long = "factor", default_value = "0.25")] pub factor: f32, /// The smallest input frequency for a taxon to be included in the aggregation - #[structopt(short = "l", long = "lower-bound", default_value = "0")] + #[arg(short = 'l', long = "lower-bound", default_value = "0")] pub lower_bound: f32, /// An NCBI taxonomy TSV-file as processed by Unipept - #[structopt(parse(from_os_str))] pub taxon_file: PathBuf, } @@ -184,7 +188,7 @@ pub fn taxa2agg(args: TaxaToAgg) -> errors::Result<()> { /// An aggregation method #[allow(missing_docs)] -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Method { Tree, RangeMinimumQuery, @@ -211,7 +215,7 @@ impl FromStr for Method { /// An aggregation strategy #[allow(missing_docs)] -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Strategy { LowestCommonAncestor, Hybrid, diff --git a/src/commands/taxa2freq.rs b/src/commands/taxa2freq.rs index 85234162..216a7224 100644 --- a/src/commands/taxa2freq.rs +++ b/src/commands/taxa2freq.rs @@ -8,13 +8,18 @@ use std::io::BufReader; use std::io::Write; use std::path::PathBuf; +use std::str::FromStr; + +use clap::builder::{PossibleValuesParser, TypedValueParser}; +use clap::Args; + use crate::errors; use crate::rank; use crate::rank::Rank; use crate::taxon; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Counts ranked taxon occurrences in a stream of taxon IDs or arguments /// /// The `umgap taxa2freq` command creates a frequency table of a list of taxa on a given target rank @@ -61,24 +66,23 @@ use crate::taxon; /// ``` pub struct TaxaToFreq { /// The rank to show - #[structopt( - short = "r", + #[arg( + short = 'r', long = "rank", default_value = "species", - possible_values = &Rank::variants() + value_parser = PossibleValuesParser::new(Rank::variants().iter().copied()) + .map(|s| Rank::from_str(&s).expect("a possible value always parses")), )] pub rank: Rank, /// The minimum frequency to be reported - #[structopt(short = "f", long = "frequency", default_value = "1")] + #[arg(short = 'f', long = "frequency", default_value = "1")] pub min_frequency: usize, /// An NCBI taxonomy TSV-file as processed by Unipept - #[structopt(parse(from_os_str))] pub taxon_file: PathBuf, /// Multiple comparative input files - #[structopt(parse(from_os_str))] pub input_files: Vec, } diff --git a/src/commands/taxa2tree.rs b/src/commands/taxa2tree.rs index 41d60f80..3789cc03 100644 --- a/src/commands/taxa2tree.rs +++ b/src/commands/taxa2tree.rs @@ -5,12 +5,14 @@ use std::io; use serde_json::json; +use clap::Args; + use crate::errors; use crate::io::fasta; use crate::taxon::TaxonId; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Visualizes a stream of taxon IDs using the Unipept API /// /// The `umgap taxa2tree` command, similar to the `unipept taxa2tree` command, takes one or more @@ -33,7 +35,7 @@ use crate::taxon::TaxonId; /// ``` pub struct TaxaToTree { /// Host the result online and return the URL - #[structopt(short = "u", long = "url")] + #[arg(short = 'u', long = "url")] pub url: bool, } diff --git a/src/commands/taxonomy.rs b/src/commands/taxonomy.rs index 1140c425..01d9d89e 100644 --- a/src/commands/taxonomy.rs +++ b/src/commands/taxonomy.rs @@ -5,13 +5,15 @@ use std::io::BufRead; use std::io::Write; use std::path::PathBuf; +use clap::Args; + use crate::errors; use crate::rank; use crate::taxon; #[rustfmt::skip] -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] #[allow(clippy::tabs_in_doc_comments)] /// Includes info in a stream of taxon IDs /// @@ -72,16 +74,15 @@ use crate::taxon; /// ``` pub struct Taxonomy { /// An NCBI taxonomy TSV-file as processed by Unipept - #[structopt(parse(from_os_str))] pub taxon_file: PathBuf, /// Show the full lineage of a taxon. Ranks below the given taxon /// whill be empty. - #[structopt(short = "a", long = "all")] + #[arg(short = 'a', long = "all")] pub all_ranks: bool, /// Do not output the TSV header - #[structopt(short = "H", long = "no-header")] + #[arg(short = 'H', long = "no-header")] pub no_header: bool, } diff --git a/src/commands/translate.rs b/src/commands/translate.rs index a60d6192..0a8391ed 100644 --- a/src/commands/translate.rs +++ b/src/commands/translate.rs @@ -6,11 +6,14 @@ use std::str::FromStr; use crate::dna::translation::TranslationTable; use crate::dna::Strand; +use clap::builder::{PossibleValuesParser, TypedValueParser}; +use clap::Args; + use crate::errors; use crate::io::fasta; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Translates a FASTA stream of DNA reads to peptides /// /// The `umgap translate` command takes one or more DNA sequences and translates them into amino @@ -45,31 +48,32 @@ use crate::io::fasta; /// bacterial, archaeal and plant plastid code. pub struct Translate { /// Replace each start-codon with methionine - #[structopt(short = "m", long = "methionine")] + #[arg(short = 'm', long = "methionine")] pub methionine: bool, /// Read and output all six frames - #[structopt(short = "a", long = "all-frames", conflicts_with = "frame")] + #[arg(short = 'a', long = "all-frames", conflicts_with = "frame")] pub all_frames: bool, /// Adds a reading frame (1, 2, 3, 1R, 2R or 3R) - #[structopt( - short = "f", + #[arg( + short = 'f', long = "frame", - possible_values = &Frame::variants() + value_parser = PossibleValuesParser::new(Frame::variants().iter().copied()) + .map(|s| Frame::from_str(&s).expect("a possible value always parses")), )] pub frames: Vec, /// Append a bar (|) and the name of the frame to the fasta header - #[structopt(short = "n", long = "append-name")] + #[arg(short = 'n', long = "append-name")] pub append_name: bool, /// Translation table to use - #[structopt(short = "t", long = "table", default_value = "1")] + #[arg(short = 't', long = "table", default_value = "1")] pub table: String, /// Instead of normal use, print the selected table and exit - #[structopt(short = "s", long = "show-table")] + #[arg(short = 's', long = "show-table")] pub show_table: bool, } diff --git a/src/commands/uniq.rs b/src/commands/uniq.rs index 1c35b6ee..bcbd9b59 100644 --- a/src/commands/uniq.rs +++ b/src/commands/uniq.rs @@ -2,11 +2,13 @@ use std::io; +use clap::Args; + use crate::errors; use crate::io::fasta; -#[derive(Debug, StructOpt)] -#[structopt(verbatim_doc_comment)] +#[derive(Debug, Args)] +#[command(verbatim_doc_comment)] /// Joins consecutive FASTA records with the same header /// /// The `umgap uniq` command can for example be used to join together the predictions of 2 paired @@ -40,15 +42,15 @@ use crate::io::fasta; /// ``` pub struct Uniq { /// Separator between output items - #[structopt(short = "s", long = "separator", default_value = "\n")] + #[arg(short = 's', long = "separator", default_value = "\n")] pub separator: String, /// Wrap the output sequences - #[structopt(short = "w", long = "wrap")] + #[arg(short = 'w', long = "wrap")] pub wrap: bool, /// Strip FASTA headers after this string - #[structopt(short = "d", long = "delimiter")] + #[arg(short = 'd', long = "delimiter")] pub delimiter: Option, } diff --git a/src/lib.rs b/src/lib.rs index 9cbfee3f..0537b07e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,9 +18,6 @@ extern crate lazy_static; #[macro_use] extern crate assert_matches; -#[macro_use] -extern crate structopt; - #[macro_use] extern crate strum_macros; diff --git a/src/main.rs b/src/main.rs index 57a0ff97..34561c51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,12 @@ use error_chain::quick_main; -use structopt::StructOpt; +use clap::Parser; use umgap::commands; use umgap::errors::Result; quick_main!(|| -> Result<()> { - match Opt::from_args() { + match Opt::parse() { Opt::BestOf(args) => commands::bestof::bestof(args), Opt::BuildIndex(args) => commands::buildindex::buildindex(args), Opt::FastqToFasta(args) => commands::fastq2fasta::fastq2fasta(args), @@ -38,26 +38,27 @@ quick_main!(|| -> Result<()> { /// The term taxon ID refers to an identifier of a NCBI taxonomy (which should be the same version /// in the whole pipeline). #[rustfmt::skip] -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] +#[command(version, propagate_version = true)] pub enum Opt { - #[structopt(name = "bestof")] BestOf(commands::bestof::BestOf), - #[structopt(name = "buildindex")] BuildIndex(commands::buildindex::BuildIndex), - #[structopt(name = "fastq2fasta")] FastqToFasta(commands::fastq2fasta::FastqToFasta), - #[structopt(name = "filter")] Filter(commands::filter::Filter), - #[structopt(name = "joinkmers")] JoinKmers(commands::joinkmers::JoinKmers), - #[structopt(name = "pept2lca")] PeptToLca(commands::pept2lca::PeptToLca), - #[structopt(name = "printindex")] PrintIndex(commands::printindex::PrintIndex), - #[cfg(target_family = "unix")] #[structopt(name = "prot2kmer2lca")] ProtToKmerToLca(commands::prot2kmer2lca::ProtToKmerToLca), - #[structopt(name = "prot2kmer")] ProtToKmer(commands::prot2kmer::ProtToKmer), - #[structopt(name = "prot2tryp2lca")] ProtToTrypToLca(commands::prot2tryp2lca::ProtToTrypToLca), - #[structopt(name = "prot2tryp")] ProtToTryp(commands::prot2tryp::ProtToTryp), - #[structopt(name = "seedextend")] SeedExtend(commands::seedextend::SeedExtend), - #[structopt(name = "snaptaxon")] SnapTaxon(commands::snaptaxon::SnapTaxon), - #[structopt(name = "splitkmers")] SplitKmers(commands::splitkmers::SplitKmers), - #[structopt(name = "taxa2agg")] TaxaToAgg(commands::taxa2agg::TaxaToAgg), - #[structopt(name = "taxa2freq")] TaxaToFreq(commands::taxa2freq::TaxaToFreq), - #[structopt(name = "taxa2tree")] TaxaToTree(commands::taxa2tree::TaxaToTree), - #[structopt(name = "taxonomy")] Taxonomy(commands::taxonomy::Taxonomy), - #[structopt(name = "translate")] Translate(commands::translate::Translate), - #[structopt(name = "uniq")] Uniq(commands::uniq::Uniq), + #[command(name = "bestof")] BestOf(commands::bestof::BestOf), + #[command(name = "buildindex")] BuildIndex(commands::buildindex::BuildIndex), + #[command(name = "fastq2fasta")] FastqToFasta(commands::fastq2fasta::FastqToFasta), + #[command(name = "filter")] Filter(commands::filter::Filter), + #[command(name = "joinkmers")] JoinKmers(commands::joinkmers::JoinKmers), + #[command(name = "pept2lca")] PeptToLca(commands::pept2lca::PeptToLca), + #[command(name = "printindex")] PrintIndex(commands::printindex::PrintIndex), + #[cfg(target_family = "unix")] #[command(name = "prot2kmer2lca")] ProtToKmerToLca(commands::prot2kmer2lca::ProtToKmerToLca), + #[command(name = "prot2kmer")] ProtToKmer(commands::prot2kmer::ProtToKmer), + #[command(name = "prot2tryp2lca")] ProtToTrypToLca(commands::prot2tryp2lca::ProtToTrypToLca), + #[command(name = "prot2tryp")] ProtToTryp(commands::prot2tryp::ProtToTryp), + #[command(name = "seedextend")] SeedExtend(commands::seedextend::SeedExtend), + #[command(name = "snaptaxon")] SnapTaxon(commands::snaptaxon::SnapTaxon), + #[command(name = "splitkmers")] SplitKmers(commands::splitkmers::SplitKmers), + #[command(name = "taxa2agg")] TaxaToAgg(commands::taxa2agg::TaxaToAgg), + #[command(name = "taxa2freq")] TaxaToFreq(commands::taxa2freq::TaxaToFreq), + #[command(name = "taxa2tree")] TaxaToTree(commands::taxa2tree::TaxaToTree), + #[command(name = "taxonomy")] Taxonomy(commands::taxonomy::Taxonomy), + #[command(name = "translate")] Translate(commands::translate::Translate), + #[command(name = "uniq")] Uniq(commands::uniq::Uniq), }