diff --git a/.changelog/unreleased/improvements/64-clap-up-v4.md b/.changelog/unreleased/improvements/64-clap-up-v4.md new file mode 100644 index 00000000000..3c385edb500 --- /dev/null +++ b/.changelog/unreleased/improvements/64-clap-up-v4.md @@ -0,0 +1,2 @@ +- Update clap to the latest version. + ([\#64](https://github.com/anoma/namada/issues/64)) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 26b227f7453..73583d9790c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,55 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstream" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" version = "1.0.71" @@ -424,17 +473,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -1108,21 +1146,32 @@ dependencies = [ [[package]] name = "clap" -version = "3.0.0-beta.2" -source = "git+https://github.com/clap-rs/clap/?tag=v3.0.0-beta.2#08b2f4d4289eca8a9225bbc56d5a5ad1e99e38e1" +version = "4.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2686c4115cb0810d9a984776e197823d08ec94f176549a89a9efded477c456dc" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e53afce1efce6ed1f633cf0e57612fe51db54a1ee4fd8f8503d078fe02d69ae" dependencies = [ - "atty", + "anstream", + "anstyle", "bitflags", - "indexmap", - "lazy_static", - "os_str_bytes", + "clap_lex", "strsim", - "termcolor", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + [[package]] name = "clru" version = "0.5.0" @@ -1155,6 +1204,12 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "concat-idents" version = "1.1.4" @@ -2505,15 +2560,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.2.6" @@ -3039,6 +3085,18 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -4236,12 +4294,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "os_str_bytes" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85" - [[package]] name = "output_vt100" version = "0.1.3" @@ -6117,15 +6169,6 @@ dependencies = [ "time", ] -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - [[package]] name = "termtree" version = "0.4.1" @@ -6143,15 +6186,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "textwrap" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.40" @@ -6862,6 +6896,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.8.2" @@ -6895,12 +6935,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index b5643167bc0..dda1e1268fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ byteorder = "1.4.2" borsh = "0.9.0" chrono = {version = "0.4.22", default-features = false, features = ["clock", "std"]} circular-queue = "0.2.6" -clap = {git = "https://github.com/clap-rs/clap/", tag = "v3.0.0-beta.2", default-features = false, features = ["std", "suggestions", "color", "cargo"]} +clap = "4.3.4" clru = {git = "https://github.com/marmeladema/clru-rs.git", rev = "71ca566"} color-eyre = "0.5.10" concat-idents = "1.1.2" diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index b3078037ff7..fc69508319f 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -9,7 +9,7 @@ pub mod context; mod utils; -use clap::{AppSettings, ArgGroup, ArgMatches}; +use clap::{ArgGroup, ArgMatches, ColorChoice}; use color_eyre::eyre::Result; pub use utils::safe_exit; use utils::*; @@ -26,8 +26,6 @@ const CLIENT_CMD: &str = "client"; const WALLET_CMD: &str = "wallet"; pub mod cmds { - use clap::AppSettings; - use super::utils::*; use super::{args, ArgMatches, CLIENT_CMD, NODE_CMD, WALLET_CMD}; @@ -129,7 +127,8 @@ pub mod cmds { ::add_sub( App::new(Self::CMD) .about("Node sub-commands.") - .setting(AppSettings::SubcommandRequiredElseHelp), + .subcommand_required(true) + .arg_required_else_help(true), ) } } @@ -279,7 +278,8 @@ pub mod cmds { ::add_sub( App::new(Self::CMD) .about("Client sub-commands.") - .setting(AppSettings::SubcommandRequiredElseHelp), + .subcommand_required(true) + .arg_required_else_help(true), ) } } @@ -356,7 +356,8 @@ pub mod cmds { ::add_sub( App::new(Self::CMD) .about("Wallet sub-commands.") - .setting(AppSettings::SubcommandRequiredElseHelp), + .subcommand_required(true) + .arg_required_else_help(true), ) } } @@ -391,7 +392,8 @@ pub mod cmds { "Keypair management, including methods to generate and \ look-up keys.", ) - .setting(AppSettings::SubcommandRequiredElseHelp) + .subcommand_required(true) + .arg_required_else_help(true) .subcommand(KeyRestore::def()) .subcommand(KeyGen::def()) .subcommand(KeyFind::def()) @@ -539,7 +541,8 @@ pub mod cmds { including methods to generate and look-up addresses and \ keys.", ) - .setting(AppSettings::SubcommandRequiredElseHelp) + .subcommand_required(true) + .arg_required_else_help(true) .subcommand(MaspGenSpendKey::def()) .subcommand(MaspGenPayAddr::def()) .subcommand(MaspAddAddrKey::def()) @@ -699,7 +702,8 @@ pub mod cmds { "Address management, including methods to generate and \ look-up addresses.", ) - .setting(AppSettings::SubcommandRequiredElseHelp) + .subcommand_required(true) + .arg_required_else_help(true) .subcommand(AddressGen::def()) .subcommand(AddressRestore::def()) .subcommand(AddressOrAliasFind::def()) @@ -975,7 +979,8 @@ pub mod cmds { fn def() -> App { App::new(Self::CMD) - .setting(AppSettings::SubcommandRequiredElseHelp) + .subcommand_required(true) + .arg_required_else_help(true) .about("Configuration sub-commands.") .subcommand(ConfigGen::def()) } @@ -1625,7 +1630,8 @@ pub mod cmds { .subcommand(InitGenesisValidator::def()) .subcommand(PkToTmAddress::def()) .subcommand(DefaultBaseDir::def()) - .setting(AppSettings::SubcommandRequiredElseHelp) + .subcommand_required(true) + .arg_required_else_help(true) } } @@ -1947,8 +1953,8 @@ pub mod args { /// Add global args definition. Should be added to every top-level /// command. pub fn def(app: App) -> App { - app.arg(CHAIN_ID_OPT.def().about("The chain ID.")) - .arg(BASE_DIR.def().about( + app.arg(CHAIN_ID_OPT.def().help("The chain ID.")) + .arg(BASE_DIR.def().help( "The base directory is where the nodes, client and wallet \ configuration and state is stored. This value can also \ be set via `NAMADA_BASE_DIR` environment variable, but \ @@ -1958,7 +1964,7 @@ pub mod args { Unix,`$HOME/Library/Application Support/Namada` on \ Mac,and `%AppData%\\Namada` on Windows.", )) - .arg(WASM_DIR.def().about( + .arg(WASM_DIR.def().help( "Directory with built WASM validity predicates, \ transactions. This value can also be set via \ `NAMADA_WASM_DIR` environment variable, but the argument \ @@ -1979,7 +1985,7 @@ pub mod args { } fn def(app: App) -> App { - app.arg(NAMADA_START_TIME.def().about( + app.arg(NAMADA_START_TIME.def().help( "The start time of the ledger. Accepts a relaxed form of \ RFC3339. A space or a 'T' are accepted as the separator \ between the date and time components. Additional spaces are \ @@ -2015,18 +2021,18 @@ pub mod args { app.arg( NAMADA_START_TIME .def() - .about("The start time of the ledger."), + .help("The start time of the ledger."), ) - .arg(BLOCK_HEIGHT.def().about("The block height to run until.")) - .arg(HALT_ACTION.def().about("Halt at the given block height")) + .arg(BLOCK_HEIGHT.def().help("The block height to run until.")) + .arg(HALT_ACTION.def().help("Halt at the given block height")) .arg( SUSPEND_ACTION .def() - .about("Suspend consensus at the given block height"), + .help("Suspend consensus at the given block height"), ) .group( ArgGroup::new("find_flags") - .args(&[HALT_ACTION.name, SUSPEND_ACTION.name]) + .args([HALT_ACTION.name, SUSPEND_ACTION.name]) .required(true), ) } @@ -2057,17 +2063,19 @@ pub mod args { fn def(app: App) -> App { app - // .arg(BLOCK_HEIGHT_OPT.def().about( + // .arg(BLOCK_HEIGHT_OPT.def().help( // "The block height to dump. Defaults to latest committed // block.", )) - .arg(OUT_FILE_PATH_OPT.def().about( + .arg(OUT_FILE_PATH_OPT.def().help( "Path for the output file (omitting file extension). \ Defaults to \"db_dump.{block_height}.toml\" in the \ current working directory.", )) - .arg(HISTORIC.def().about( - "If provided, dump also the diff of the last height", - )) + .arg( + HISTORIC.def().help( + "If provided, dump also the diff of the last height", + ), + ) } } @@ -2095,7 +2103,7 @@ pub mod args { app.add_args::>().arg( TX_HASH .def() - .about("The hash of the transaction being looked up."), + .help("The hash of the transaction being looked up."), ) } } @@ -2130,9 +2138,9 @@ pub mod args { .arg( CODE_PATH .def() - .about("The path to the transaction's WASM code."), + .help("The path to the transaction's WASM code."), ) - .arg(DATA_PATH_OPT.def().about( + .arg(DATA_PATH_OPT.def().help( "The data file at this path containing arbitrary bytes \ will be passed to the transaction code when it's \ executed.", @@ -2178,17 +2186,17 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(TRANSFER_SOURCE.def().about( + .arg(TRANSFER_SOURCE.def().help( "The source account address. The source's key may be used \ to produce the signature.", )) - .arg(TRANSFER_TARGET.def().about( + .arg(TRANSFER_TARGET.def().help( "The target account address. The target's key may be used \ to produce the signature.", )) - .arg(TOKEN.def().about("The transfer token.")) - .arg(SUB_PREFIX.def().about("The token's sub prefix.")) - .arg(AMOUNT.def().about("The amount to transfer in decimal.")) + .arg(TOKEN.def().help("The transfer token.")) + .arg(SUB_PREFIX.def().help("The token's sub prefix.")) + .arg(AMOUNT.def().help("The amount to transfer in decimal.")) } } @@ -2240,24 +2248,24 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(SOURCE.def().about( + .arg(SOURCE.def().help( "The source account address. The source's key is used to \ produce the signature.", )) - .arg(RECEIVER.def().about( + .arg(RECEIVER.def().help( "The receiver address on the destination chain as string.", )) - .arg(TOKEN.def().about("The transfer token.")) - .arg(SUB_PREFIX.def().about("The token's sub prefix.")) - .arg(AMOUNT.def().about("The amount to transfer in decimal.")) - .arg(PORT_ID.def().about("The port ID.")) - .arg(CHANNEL_ID.def().about("The channel ID.")) + .arg(TOKEN.def().help("The transfer token.")) + .arg(SUB_PREFIX.def().help("The token's sub prefix.")) + .arg(AMOUNT.def().help("The amount to transfer in decimal.")) + .arg(PORT_ID.def().help("The port ID.")) + .arg(CHANNEL_ID.def().help("The channel ID.")) .arg( TIMEOUT_HEIGHT .def() - .about("The timeout height of the destination chain."), + .help("The timeout height of the destination chain."), ) - .arg(TIMEOUT_SEC_OFFSET.def().about("The timeout as seconds.")) + .arg(TIMEOUT_SEC_OFFSET.def().help("The timeout as seconds.")) } } @@ -2293,15 +2301,15 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(SOURCE.def().about( + .arg(SOURCE.def().help( "The source account's address that signs the transaction.", )) - .arg(CODE_PATH_OPT.def().about( + .arg(CODE_PATH_OPT.def().help( "The path to the validity predicate WASM code to be used \ for the new account. Uses the default user VP if none \ specified.", )) - .arg(PUBLIC_KEY.def().about( + .arg(PUBLIC_KEY.def().help( "A public key to be used for the new account in \ hexadecimal encoding.", )) @@ -2361,42 +2369,42 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(SOURCE.def().about( + .arg(SOURCE.def().help( "The source account's address that signs the transaction.", )) - .arg(SCHEME.def().about( + .arg(SCHEME.def().help( "The key scheme/type used for the validator keys. \ Currently supports ed25519 and secp256k1.", )) - .arg(VALIDATOR_ACCOUNT_KEY.def().about( + .arg(VALIDATOR_ACCOUNT_KEY.def().help( "A public key for the validator account. A new one will \ be generated if none given.", )) - .arg(VALIDATOR_CONSENSUS_KEY.def().about( + .arg(VALIDATOR_CONSENSUS_KEY.def().help( "A consensus key for the validator account. A new one \ will be generated if none given.", )) - .arg(PROTOCOL_KEY.def().about( + .arg(PROTOCOL_KEY.def().help( "A public key for signing protocol transactions. A new \ one will be generated if none given.", )) - .arg(COMMISSION_RATE.def().about( + .arg(COMMISSION_RATE.def().help( "The commission rate charged by the validator for \ delegation rewards. Expressed as a decimal between 0 and \ 1. This is a required parameter.", )) - .arg(MAX_COMMISSION_RATE_CHANGE.def().about( + .arg(MAX_COMMISSION_RATE_CHANGE.def().help( "The maximum change per epoch in the commission rate \ charged by the validator for delegation rewards. \ Expressed as a decimal between 0 and 1. This is a \ required parameter.", )) - .arg(VALIDATOR_CODE_PATH.def().about( + .arg(VALIDATOR_CODE_PATH.def().help( "The path to the validity predicate WASM code to be used \ for the validator account. Uses the default validator VP \ if none specified.", )) - .arg(UNSAFE_DONT_ENCRYPT.def().about( + .arg(UNSAFE_DONT_ENCRYPT.def().help( "UNSAFE: Do not encrypt the generated keypairs. Do not \ use this for keys used in a live network.", )) @@ -2431,11 +2439,11 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() .arg( - CODE_PATH.def().about( + CODE_PATH.def().help( "The path to the new validity predicate WASM code.", ), ) - .arg(ADDRESS.def().about( + .arg(ADDRESS.def().help( "The account's address. It's key is used to produce the \ signature.", )) @@ -2474,9 +2482,9 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(VALIDATOR.def().about("Validator address.")) - .arg(AMOUNT.def().about("Amount of tokens to stake in a bond.")) - .arg(SOURCE_OPT.def().about( + .arg(VALIDATOR.def().help("Validator address.")) + .arg(AMOUNT.def().help("Amount of tokens to stake in a bond.")) + .arg(SOURCE_OPT.def().help( "Source address for delegations. For self-bonds, the \ validator is also the source.", )) @@ -2513,13 +2521,13 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(VALIDATOR.def().about("Validator address.")) + .arg(VALIDATOR.def().help("Validator address.")) .arg( AMOUNT .def() - .about("Amount of tokens to unbond from a bond."), + .help("Amount of tokens to unbond from a bond."), ) - .arg(SOURCE_OPT.def().about( + .arg(SOURCE_OPT.def().help( "Source address for unbonding from delegations. For \ unbonding from self-bonds, the validator is also the \ source.", @@ -2570,13 +2578,13 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(DATA_PATH.def().about( + .arg(DATA_PATH.def().help( "The data path file (json) that describes the proposal.", )) .arg( PROPOSAL_OFFLINE .def() - .about("Flag if the proposal vote should run offline."), + .help("Flag if the proposal vote should run offline."), ) } } @@ -2644,8 +2652,8 @@ pub mod args { .arg( PROPOSAL_ID_OPT .def() - .about("The proposal identifier.") - .conflicts_with_all(&[ + .help("The proposal identifier.") + .conflicts_with_all([ PROPOSAL_OFFLINE.name, DATA_PATH_OPT.name, ]), @@ -2653,12 +2661,12 @@ pub mod args { .arg( PROPOSAL_VOTE .def() - .about("The vote for the proposal. Either yay or nay"), + .help("The vote for the proposal. Either yay or nay"), ) .arg( PROPOSAL_VOTE_PGF_OPT .def() - .about( + .help( "The list of proposed councils and spending \ caps:\n$council1 $cap1 $council2 $cap2 ... \ (council is bech32m encoded address, cap is \ @@ -2670,7 +2678,7 @@ pub mod args { .arg( PROPOSAL_VOTE_ETH_OPT .def() - .about( + .help( "The signing key and message bytes (hex encoded) \ to be signed: $signing_key $message", ) @@ -2680,13 +2688,13 @@ pub mod args { .arg( PROPOSAL_OFFLINE .def() - .about("Flag if the proposal vote should run offline.") + .help("Flag if the proposal vote should run offline.") .conflicts_with(PROPOSAL_ID.name), ) .arg( DATA_PATH_OPT .def() - .about( + .help( "The data path file (json) that describes the \ proposal.", ) @@ -2714,7 +2722,7 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(PUBLIC_KEY.def().about("A public key to reveal.")) + .arg(PUBLIC_KEY.def().help("A public key to reveal.")) } } @@ -2737,7 +2745,7 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(PROPOSAL_ID_OPT.def().about("The proposal identifier.")) + .arg(PROPOSAL_ID_OPT.def().help("The proposal identifier.")) } } @@ -2781,11 +2789,11 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(PROPOSAL_ID_OPT.def().about("The proposal identifier.")) + .arg(PROPOSAL_ID_OPT.def().help("The proposal identifier.")) .arg( PROPOSAL_OFFLINE .def() - .about( + .help( "Flag if the proposal result should run on \ offline data.", ) @@ -2794,7 +2802,7 @@ pub mod args { .arg( DATA_PATH_OPT .def() - .about( + .help( "The path to the folder containing the proposal \ json and votes", ) @@ -2855,8 +2863,8 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(VALIDATOR.def().about("Validator address.")) - .arg(SOURCE_OPT.def().about( + .arg(VALIDATOR.def().help("Validator address.")) + .arg(SOURCE_OPT.def().help( "Source address for withdrawing from delegations. For \ withdrawing from self-bonds, the validator is also the \ source.", @@ -2891,10 +2899,10 @@ pub mod args { .arg( EPOCH .def() - .about("The epoch for which to query conversions."), + .help("The epoch for which to query conversions."), ) .arg( - TOKEN_OPT.def().about( + TOKEN_OPT.def().help( "The token address for which to query conversions.", ), ) @@ -2934,22 +2942,22 @@ pub mod args { .arg( BALANCE_OWNER .def() - .about("The account address whose balance to query."), + .help("The account address whose balance to query."), ) .arg( TOKEN_OPT .def() - .about("The token's address whose balance to query."), + .help("The token's address whose balance to query."), ) .arg( - NO_CONVERSIONS.def().about( + NO_CONVERSIONS.def().help( "Whether not to automatically perform conversions.", ), ) .arg( - SUB_PREFIX.def().about( - "The token's sub prefix whose balance to query.", - ), + SUB_PREFIX + .def() + .help("The token's sub prefix whose balance to query."), ) } } @@ -2978,10 +2986,10 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(BALANCE_OWNER.def().about( + .arg(BALANCE_OWNER.def().help( "The account address that queried transfers must involve.", )) - .arg(TOKEN_OPT.def().about( + .arg(TOKEN_OPT.def().help( "The token address that queried transfers must involve.", )) } @@ -3012,14 +3020,14 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() .arg( - OWNER_OPT.def().about( + OWNER_OPT.def().help( "The owner account address whose bonds to query.", ), ) .arg( VALIDATOR_OPT .def() - .about("The validator's address whose bonds to query."), + .help("The validator's address whose bonds to query."), ) } } @@ -3048,10 +3056,10 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(VALIDATOR_OPT.def().about( + .arg(VALIDATOR_OPT.def().help( "The validator's address whose bonded stake to query.", )) - .arg(EPOCH.def().about( + .arg(EPOCH.def().help( "The epoch at which to query (last committed, if not \ specified).", )) @@ -3087,13 +3095,13 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(VALIDATOR.def().about( + .arg(VALIDATOR.def().help( "The validator's address whose commission rate to change.", )) .arg( COMMISSION_RATE .def() - .about("The desired new commission rate."), + .help("The desired new commission rate."), ) } } @@ -3128,7 +3136,7 @@ pub mod args { fn def(app: App) -> App { app.add_args::>().arg( - VALIDATOR.def().about( + VALIDATOR.def().help( "The address of the jailed validator to re-activate.", ), ) @@ -3159,10 +3167,10 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(VALIDATOR.def().about( + .arg(VALIDATOR.def().help( "The validator's address whose commission rate to query.", )) - .arg(EPOCH.def().about( + .arg(EPOCH.def().help( "The epoch at which to query (last committed, if not \ specified).", )) @@ -3189,7 +3197,7 @@ pub mod args { app.add_args::>().arg( VALIDATOR_OPT .def() - .about("The validator's address whose slashes to query."), + .help("The validator's address whose slashes to query."), ) } } @@ -3203,7 +3211,7 @@ pub mod args { fn def(app: App) -> App { app.add_args::>().arg( - OWNER.def().about( + OWNER.def().help( "The address of the owner of the delegations to find.", ), ) @@ -3230,7 +3238,7 @@ pub mod args { app.add_args::>().arg( TM_ADDRESS .def() - .about("The address of the validator in Tendermint."), + .help("The address of the validator in Tendermint."), ) } } @@ -3262,7 +3270,7 @@ pub mod args { fn def(app: App) -> App { app.add_args::>() - .arg(STORAGE_KEY.def().about("Storage key")) + .arg(STORAGE_KEY.def().help("Storage key")) } } @@ -3311,42 +3319,42 @@ pub mod args { app.arg( DRY_RUN_TX .def() - .about("Simulate the transaction application."), + .help("Simulate the transaction application."), ) - .arg(DUMP_TX.def().about("Dump transaction bytes to a file.")) - .arg(FORCE.def().about( + .arg(DUMP_TX.def().help("Dump transaction bytes to a file.")) + .arg(FORCE.def().help( "Submit the transaction even if it doesn't pass client checks.", )) - .arg(BROADCAST_ONLY.def().about( + .arg(BROADCAST_ONLY.def().help( "Do not wait for the transaction to be applied. This will \ return once the transaction is added to the mempool.", )) .arg( LEDGER_ADDRESS_DEFAULT .def() - .about(LEDGER_ADDRESS_ABOUT) + .help(LEDGER_ADDRESS_ABOUT) // This used to be "ledger-address", alias for compatibility .alias("ledger-address"), ) - .arg(ALIAS_OPT.def().about( + .arg(ALIAS_OPT.def().help( "If any new account is initialized by the tx, use the given \ alias to save it in the wallet. If multiple accounts are \ initialized, the alias will be the prefix of each new \ address joined with a number.", )) - .arg(WALLET_ALIAS_FORCE.def().about( + .arg(WALLET_ALIAS_FORCE.def().help( "Override the alias without confirmation if it already exists.", )) - .arg(GAS_AMOUNT.def().about( + .arg(GAS_AMOUNT.def().help( "The amount being paid for the inclusion of this transaction", )) - .arg(GAS_TOKEN.def().about("The token for paying the gas")) + .arg(GAS_TOKEN.def().help("The token for paying the gas")) .arg( - GAS_LIMIT.def().about( + GAS_LIMIT.def().help( "The maximum amount of gas needed to run transaction", ), ) - .arg(EXPIRATION_OPT.def().about( + .arg(EXPIRATION_OPT.def().help( "The expiration datetime of the transaction, after which the \ tx won't be accepted anymore. All of these examples are \ equivalent:\n2012-12-12T12:12:12Z\n2012-12-12 \ @@ -3355,7 +3363,7 @@ pub mod args { .arg( SIGNING_KEY_OPT .def() - .about( + .help( "Sign the transaction with the key for the given \ public key, public key hash or alias from your \ wallet.", @@ -3365,12 +3373,13 @@ pub mod args { .arg( SIGNER .def() - .about( + .help( "Sign the transaction with the keypair of the public \ key of the given address.", ) .conflicts_with(SIGNING_KEY_OPT.name), ) + .arg(CHAIN_ID_OPT.def().help("The chain ID.")) } fn parse(matches: &ArgMatches) -> Self { @@ -3422,7 +3431,7 @@ pub mod args { app.arg( LEDGER_ADDRESS_DEFAULT .def() - .about(LEDGER_ADDRESS_ABOUT) + .help(LEDGER_ADDRESS_ABOUT) // This used to be "ledger-address", alias for compatibility .alias("ledger-address"), ) @@ -3452,17 +3461,17 @@ pub mod args { app.arg( ALIAS .def() - .about("An alias to be associated with the new entry."), + .help("An alias to be associated with the new entry."), ) - .arg(ALIAS_FORCE.def().about( + .arg(ALIAS_FORCE.def().help( "Override the alias without confirmation if it already exists.", )) .arg( MASP_VALUE .def() - .about("A spending key, viewing key, or payment address."), + .help("A spending key, viewing key, or payment address."), ) - .arg(UNSAFE_DONT_ENCRYPT.def().about( + .arg(UNSAFE_DONT_ENCRYPT.def().help( "UNSAFE: Do not encrypt the keypair. Do not use this for keys \ used in a live network.", )) @@ -3485,9 +3494,9 @@ pub mod args { app.arg( ALIAS .def() - .about("An alias to be associated with the spending key."), + .help("An alias to be associated with the spending key."), ) - .arg(UNSAFE_DONT_ENCRYPT.def().about( + .arg(UNSAFE_DONT_ENCRYPT.def().help( "UNSAFE: Do not encrypt the keypair. Do not use this for keys \ used in a live network.", )) @@ -3521,15 +3530,15 @@ pub mod args { fn def(app: App) -> App { app.arg( - ALIAS.def().about( + ALIAS.def().help( "An alias to be associated with the payment address.", ), ) - .arg(ALIAS_FORCE.def().about( + .arg(ALIAS_FORCE.def().help( "Override the alias without confirmation if it already exists.", )) - .arg(VIEWING_KEY.def().about("The viewing key.")) - .arg(PIN.def().about( + .arg(VIEWING_KEY.def().help("The viewing key.")) + .arg(PIN.def().help( "Require that the single transaction to this address be \ pinned.", )) @@ -3553,25 +3562,25 @@ pub mod args { } fn def(app: App) -> App { - app.arg(SCHEME.def().about( + app.arg(SCHEME.def().help( "The type of key that should be added. Argument must be \ either ed25519 or secp256k1. If none provided, the default \ key scheme is ed25519.", )) - .arg(ALIAS_OPT.def().about( + .arg(ALIAS_OPT.def().help( "The key and address alias. If none provided, the alias will \ be the public key hash.", )) .arg( ALIAS_FORCE .def() - .about("Force overwrite the alias if it already exists."), + .help("Force overwrite the alias if it already exists."), ) - .arg(UNSAFE_DONT_ENCRYPT.def().about( + .arg(UNSAFE_DONT_ENCRYPT.def().help( "UNSAFE: Do not encrypt the keypair. Do not use this for keys \ used in a live network.", )) - .arg(HD_WALLET_DERIVATION_PATH_OPT.def().about( + .arg(HD_WALLET_DERIVATION_PATH_OPT.def().help( "HD key derivation path. Use keyword `default` to refer to a \ scheme default path:\n- m/44'/60'/0'/0/0 for secp256k1 \ scheme\n- m/44'/877'/0'/0'/0' for ed25519 scheme.\nFor \ @@ -3599,23 +3608,23 @@ pub mod args { } fn def(app: App) -> App { - app.arg(SCHEME.def().about( + app.arg(SCHEME.def().help( "The type of key that should be generated. Argument must be \ either ed25519 or secp256k1. If none provided, the default \ key scheme is ed25519.", )) - .arg(ALIAS_OPT.def().about( + .arg(ALIAS_OPT.def().help( "The key and address alias. If none provided, the alias will \ be the public key hash.", )) - .arg(ALIAS_FORCE.def().about( + .arg(ALIAS_FORCE.def().help( "Override the alias without confirmation if it already exists.", )) - .arg(UNSAFE_DONT_ENCRYPT.def().about( + .arg(UNSAFE_DONT_ENCRYPT.def().help( "UNSAFE: Do not encrypt the keypair. Do not use this for keys \ used in a live network.", )) - .arg(HD_WALLET_DERIVATION_PATH_OPT.def().about( + .arg(HD_WALLET_DERIVATION_PATH_OPT.def().help( "Generate a new key and wallet using BIP39 mnemonic code and \ HD derivation path. Use keyword `default` to refer to a \ scheme default path:\n- m/44'/60'/0'/0/0 for secp256k1 \ @@ -3646,24 +3655,24 @@ pub mod args { app.arg( RAW_PUBLIC_KEY_OPT .def() - .about("A public key associated with the keypair.") - .conflicts_with_all(&[ALIAS_OPT.name, VALUE.name]), + .help("A public key associated with the keypair.") + .conflicts_with_all([ALIAS_OPT.name, VALUE.name]), ) .arg( ALIAS_OPT .def() - .about("An alias associated with the keypair.") + .help("An alias associated with the keypair.") .conflicts_with(VALUE.name), ) .arg( - VALUE.def().about( - "A public key or alias associated with the keypair.", - ), + VALUE + .def() + .help("A public key or alias associated with the keypair."), ) .arg( UNSAFE_SHOW_SECRET .def() - .about("UNSAFE: Print the secret key."), + .help("UNSAFE: Print the secret key."), ) } } @@ -3679,11 +3688,11 @@ pub mod args { } fn def(app: App) -> App { - app.arg(ALIAS.def().about("The alias that is to be found.")) + app.arg(ALIAS.def().help("The alias that is to be found.")) .arg( UNSAFE_SHOW_SECRET .def() - .about("UNSAFE: Print the spending key values."), + .help("UNSAFE: Print the spending key values."), ) } } @@ -3699,11 +3708,11 @@ pub mod args { } fn def(app: App) -> App { - app.arg(DECRYPT.def().about("Decrypt keys that are encrypted.")) + app.arg(DECRYPT.def().help("Decrypt keys that are encrypted.")) .arg( UNSAFE_SHOW_SECRET .def() - .about("UNSAFE: Print the spending key values."), + .help("UNSAFE: Print the spending key values."), ) } } @@ -3719,11 +3728,11 @@ pub mod args { } fn def(app: App) -> App { - app.arg(DECRYPT.def().about("Decrypt keys that are encrypted.")) + app.arg(DECRYPT.def().help("Decrypt keys that are encrypted.")) .arg( UNSAFE_SHOW_SECRET .def() - .about("UNSAFE: Print the secret keys."), + .help("UNSAFE: Print the secret keys."), ) } } @@ -3737,9 +3746,7 @@ pub mod args { fn def(app: App) -> App { app.arg( - ALIAS - .def() - .about("The alias of the key you wish to export."), + ALIAS.def().help("The alias of the key you wish to export."), ) } } @@ -3755,16 +3762,16 @@ pub mod args { app.arg( ALIAS_OPT .def() - .about("An alias associated with the address."), + .help("An alias associated with the address."), ) .arg( RAW_ADDRESS_OPT .def() - .about("The bech32m encoded address string."), + .help("The bech32m encoded address string."), ) .group( ArgGroup::new("find_flags") - .args(&[ALIAS_OPT.name, RAW_ADDRESS_OPT.name]) + .args([ALIAS_OPT.name, RAW_ADDRESS_OPT.name]) .required(true), ) } @@ -3786,15 +3793,15 @@ pub mod args { app.arg( ALIAS .def() - .about("An alias to be associated with the address."), + .help("An alias to be associated with the address."), ) - .arg(ALIAS_FORCE.def().about( + .arg(ALIAS_FORCE.def().help( "Override the alias without confirmation if it already exists.", )) .arg( RAW_ADDRESS .def() - .about("The bech32m encoded address string."), + .help("The bech32m encoded address string."), ) } } @@ -3822,11 +3829,11 @@ pub mod args { } fn def(app: App) -> App { - app.arg(CHAIN_ID.def().about("The chain ID. The chain must be known in the repository: \ + app.arg(CHAIN_ID.def().help("The chain ID. The chain must be known in the repository: \ https://github.com/heliaxdev/anoma-network-config")) - .arg(GENESIS_VALIDATOR.def().about("The alias of the genesis validator that you want to set up as, if any.")) - .arg(PRE_GENESIS_PATH.def().about("The path to the pre-genesis directory for genesis validator, if any. Defaults to \"{base-dir}/pre-genesis/{genesis-validator}\".")) - .arg(DONT_PREFETCH_WASM.def().about( + .arg(GENESIS_VALIDATOR.def().help("The alias of the genesis validator that you want to set up as, if any.")) + .arg(PRE_GENESIS_PATH.def().help("The path to the pre-genesis directory for genesis validator, if any. Defaults to \"{base-dir}/pre-genesis/{genesis-validator}\".")) + .arg(DONT_PREFETCH_WASM.def().help( "Do not pre-fetch WASM.", )) } @@ -3844,7 +3851,7 @@ pub mod args { } fn def(app: App) -> App { - app.arg(RAW_PUBLIC_KEY.def().about( + app.arg(RAW_PUBLIC_KEY.def().help( "The consensus public key to be converted to Tendermint \ address.", )) @@ -3876,7 +3883,7 @@ pub mod args { } fn def(app: App) -> App { - app.arg(CHAIN_ID.def().about("The chain ID. The chain must be known in the https://github.com/heliaxdev/anoma-network-config repository, in which case it should have pre-built wasms available for download.")) + app.arg(CHAIN_ID.def().help("The chain ID. The chain must be known in the https://github.com/heliaxdev/anoma-network-config repository, in which case it should have pre-built wasms available for download.")) } } @@ -3920,41 +3927,41 @@ pub mod args { fn def(app: App) -> App { app.arg( - GENESIS_PATH.def().about( + GENESIS_PATH.def().help( "Path to the preliminary genesis configuration file.", ), ) .arg( WASM_CHECKSUMS_PATH .def() - .about("Path to the WASM checksums file."), + .help("Path to the WASM checksums file."), ) - .arg(CHAIN_ID_PREFIX.def().about( + .arg(CHAIN_ID_PREFIX.def().help( "The chain ID prefix. Up to 19 alphanumeric, '.', '-' or '_' \ characters.", )) - .arg(UNSAFE_DONT_ENCRYPT.def().about( + .arg(UNSAFE_DONT_ENCRYPT.def().help( "UNSAFE: Do not encrypt the generated keypairs. Do not use \ this for keys used in a live network.", )) - .arg(CONSENSUS_TIMEOUT_COMMIT.def().about( + .arg(CONSENSUS_TIMEOUT_COMMIT.def().help( "The Tendermint consensus timeout_commit configuration as \ e.g. `1s` or `1000ms`. Defaults to 10 seconds.", )) - .arg(LOCALHOST.def().about( + .arg(LOCALHOST.def().help( "Use localhost address for P2P and RPC connections for the \ validators ledger", )) - .arg(ALLOW_DUPLICATE_IP.def().about( + .arg(ALLOW_DUPLICATE_IP.def().help( "Toggle to disable guard against peers connecting from the \ same IP. This option shouldn't be used in mainnet.", )) .arg( DONT_ARCHIVE .def() - .about("Do NOT create the release archive."), + .help("Do NOT create the release archive."), ) - .arg(ARCHIVE_DIR.def().about( + .arg(ARCHIVE_DIR.def().help( "Specify a directory into which to store the archive. Default \ is the current working directory.", )) @@ -3991,26 +3998,26 @@ pub mod args { } fn def(app: App) -> App { - app.arg(ALIAS.def().about("The validator address alias.")) - .arg(NET_ADDRESS.def().about( + app.arg(ALIAS.def().help("The validator address alias.")) + .arg(NET_ADDRESS.def().help( "Static {host:port} of your validator node's P2P address. \ Namada uses port `26656` for P2P connections by default, \ but you can configure a different value.", )) - .arg(COMMISSION_RATE.def().about( + .arg(COMMISSION_RATE.def().help( "The commission rate charged by the validator for \ delegation rewards. This is a required parameter.", )) - .arg(MAX_COMMISSION_RATE_CHANGE.def().about( + .arg(MAX_COMMISSION_RATE_CHANGE.def().help( "The maximum change per epoch in the commission rate \ charged by the validator for delegation rewards. This is \ a required parameter.", )) - .arg(UNSAFE_DONT_ENCRYPT.def().about( + .arg(UNSAFE_DONT_ENCRYPT.def().help( "UNSAFE: Do not encrypt the generated keypairs. Do not \ use this for keys used in a live network.", )) - .arg(SCHEME.def().about( + .arg(SCHEME.def().help( "The key scheme/type used for the validator keys. \ Currently supports ed25519 and secp256k1.", )) @@ -4046,7 +4053,6 @@ pub enum NamadaClient { pub fn namada_client_cli() -> Result { let app = namada_client_app(); - let mut app = cmds::NamadaClient::add_sub(app); let matches = app.clone().get_matches(); match Cmd::parse(&matches) { Some(cmd) => { @@ -4062,6 +4068,7 @@ pub fn namada_client_cli() -> Result { } } None => { + let mut app = app; app.print_help().unwrap(); safe_exit(2); } @@ -4077,7 +4084,9 @@ fn namada_app() -> App { let app = App::new(APP_NAME) .version(namada_version()) .about("Namada command line interface.") - .setting(AppSettings::SubcommandRequiredElseHelp); + .color(ColorChoice::Auto) + .subcommand_required(true) + .arg_required_else_help(true); cmds::Namada::add_sub(args::Global::def(app)) } @@ -4085,7 +4094,9 @@ fn namada_node_app() -> App { let app = App::new(APP_NAME) .version(namada_version()) .about("Namada node command line interface.") - .setting(AppSettings::SubcommandRequiredElseHelp); + .color(ColorChoice::Auto) + .subcommand_required(true) + .arg_required_else_help(true); cmds::NamadaNode::add_sub(args::Global::def(app)) } @@ -4093,7 +4104,9 @@ fn namada_client_app() -> App { let app = App::new(APP_NAME) .version(namada_version()) .about("Namada client command line interface.") - .setting(AppSettings::SubcommandRequiredElseHelp); + .color(ColorChoice::Auto) + .subcommand_required(true) + .arg_required_else_help(true); cmds::NamadaClient::add_sub(args::Global::def(app)) } @@ -4101,6 +4114,8 @@ fn namada_wallet_app() -> App { let app = App::new(APP_NAME) .version(namada_version()) .about("Namada wallet command line interface.") - .setting(AppSettings::SubcommandRequiredElseHelp); + .color(ColorChoice::Auto) + .subcommand_required(true) + .arg_required_else_help(true); cmds::NamadaWallet::add_sub(args::Global::def(app)) } diff --git a/apps/src/lib/cli/utils.rs b/apps/src/lib/cli/utils.rs index 56965d72efa..eac233ed28a 100644 --- a/apps/src/lib/cli/utils.rs +++ b/apps/src/lib/cli/utils.rs @@ -3,22 +3,21 @@ use std::fmt::Debug; use std::marker::PhantomData; use std::str::FromStr; -use clap::ArgMatches; +use clap::{ArgAction, ArgMatches}; use color_eyre::eyre::Result; use super::args; use super::context::{Context, FromContext}; // We only use static strings -pub type App = clap::App<'static>; -pub type ClapArg = clap::Arg<'static>; +pub type App = clap::Command; +pub type ClapArg = clap::Arg; pub trait Cmd: Sized { fn add_sub(app: App) -> App; fn parse(matches: &ArgMatches) -> Option; fn parse_or_print_help(app: App) -> Result<(Self, Context)> { - let mut app = Self::add_sub(app); let matches = app.clone().get_matches(); match Self::parse(&matches) { Some(cmd) => { @@ -27,6 +26,7 @@ pub trait Cmd: Sized { Ok((cmd, context)) } None => { + let mut app = app; app.print_help().unwrap(); safe_exit(2); } @@ -160,7 +160,7 @@ impl Arg { pub fn def(&self) -> ClapArg { ClapArg::new(self.name) .long(self.name) - .takes_value(true) + .num_args(1) .required(true) } } @@ -177,14 +177,14 @@ where impl Arg> { pub fn parse(&self, matches: &ArgMatches) -> FromContext { - let raw = matches.value_of(self.name).unwrap(); + let raw = matches.get_one::(self.name).unwrap(); FromContext::new(raw.to_string()) } } impl ArgOpt { pub fn def(&self) -> ClapArg { - ClapArg::new(self.name).long(self.name).takes_value(true) + ClapArg::new(self.name).long(self.name).num_args(1) } } @@ -200,7 +200,7 @@ where impl ArgOpt> { pub fn parse(&self, matches: &ArgMatches) -> Option> { - let raw = matches.value_of(self.name)?; + let raw = matches.get_one::(self.name).map(|s| s.as_str())?; Some(FromContext::new(raw.to_string())) } } @@ -211,7 +211,7 @@ where ::Err: Debug, { pub fn def(&self) -> ClapArg { - ClapArg::new(self.name).long(self.name).takes_value(true) + ClapArg::new(self.name).long(self.name).num_args(1) } pub fn parse(&self, matches: &ArgMatches) -> T { @@ -228,7 +228,7 @@ where ::Err: Debug, { pub fn def(&self) -> ClapArg { - ClapArg::new(self.name).long(self.name).takes_value(true) + ClapArg::new(self.name).long(self.name).num_args(1) } pub fn parse(&self, matches: &ArgMatches) -> FromContext { @@ -242,11 +242,13 @@ where impl ArgFlag { pub fn def(&self) -> ClapArg { - ClapArg::new(self.name).long(self.name).takes_value(false) + ClapArg::new(self.name) + .long(self.name) + .action(ArgAction::SetTrue) } pub fn parse(&self, matches: &ArgMatches) -> bool { - matches.is_present(self.name) + matches.get_flag(self.name) } } @@ -257,14 +259,16 @@ where ::Err: Debug, { pub fn def(&self) -> ClapArg { - ClapArg::new(self.name).long(self.name).multiple(true) + ClapArg::new(self.name) + .long(self.name) + .action(ArgAction::Append) } pub fn parse(&self, matches: &ArgMatches) -> Vec { matches - .values_of(self.name) + .get_many(self.name) .unwrap_or_default() - .map(|raw| { + .map(|raw: &String| { raw.parse().unwrap_or_else(|e| { eprintln!( "Failed to parse the {} argument. Raw value: {}, \ @@ -307,11 +311,11 @@ where T: FromStr, T::Err: Debug, { - args.value_of(field).map(|arg| { - arg.parse().unwrap_or_else(|e| { + args.get_one::(field).map(|s| { + s.as_str().parse().unwrap_or_else(|e| { eprintln!( "Failed to parse the argument {}. Raw value: {}, error: {:?}", - field, arg, e + field, s, e ); safe_exit(1) })