diff --git a/Cargo.lock b/Cargo.lock index 3199aa60..9cdac1bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,97 +1,167 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[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 = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[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 0.61.2", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "clap" -version = "2.34.0" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ - "ansi_term", - "atty", - "bitflags", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "term_size", - "textwrap 0.11.0", - "unicode-width", - "vec_map", + "terminal_size", ] [[package]] -name = "colored" -version = "1.9.4" +name = "clap_complete" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f741c91823341bebf717d4c71bda820630ce065443b58bd1b7451af008355" +checksum = "19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031eb" dependencies = [ - "is-terminal", - "lazy_static", - "winapi", + "clap", ] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "clap_derive" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ - "libc", + "heck", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "hermit-abi" -version = "0.3.9" +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 = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] -name = "is-terminal" -version = "0.4.12" +name = "colored" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "hermit-abi 0.3.9", "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] -name = "lazy_static" -version = "1.5.0" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "pad" @@ -99,7 +169,38 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "unicode-width", + "unicode-width 0.1.13", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] @@ -110,39 +211,40 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "strsim" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "term_size" -version = "0.3.2" +name = "syn" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ - "libc", - "winapi", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "terminal_size" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ - "term_size", - "unicode-width", + "rustix", + "windows-sys 0.61.2", ] [[package]] name = "textwrap" -version = "0.14.2" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" dependencies = [ "smawk", "unicode-linebreak", - "unicode-width", + "unicode-width 0.2.2", ] [[package]] @@ -150,12 +252,19 @@ name = "typical" version = "0.12.1" dependencies = [ "clap", + "clap_complete", "colored", "pad", - "textwrap 0.14.2", + "textwrap", "unicode-segmentation", ] +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + [[package]] name = "unicode-linebreak" version = "0.1.5" @@ -175,32 +284,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "winapi" -version = "0.3.9" +name = "unicode-width" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "utf8parse" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" @@ -211,6 +310,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 5b62feaa..dc6545fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,11 +17,9 @@ clippy.pedantic = { level = "deny", priority = -1 } rust.warnings = "deny" [dependencies] -colored = "1" +clap = { version = "4", features = ["derive", "wrap_help"] } +clap_complete = "4" +colored = "3" pad = "0.1" -textwrap = "0.14" +textwrap = "0.16" unicode-segmentation = "1" - -[dependencies.clap] -version = "2" -features = ["wrap_help"] diff --git a/README.md b/README.md index 29180fd0..fb84fdf6 100644 --- a/README.md +++ b/README.md @@ -670,48 +670,34 @@ typical generate types.t --rust types.rs --typescript types.ts Here are the supported command-line options: ``` -USAGE: - typical - -OPTIONS: - -h, --help - Prints help information - - -v, --version - Prints version information - - -SUBCOMMANDS: - format - Formats a schema and its transitive dependencies - - generate - Generates code for a schema and its transitive dependencies - - help - Prints this message or the help of the given subcommand(s) - - shell-completion - Prints a shell completion script. Supports Zsh, Fish, Zsh, PowerShell, and Elvish. +Usage: typical + +Commands: + generate Generate code for a schema and its transitive dependencies + format Format a schema and its transitive dependencies + shell-completion Print a shell completion script. Supports Bash, Fish, Zsh, PowerShell, and + Elvish. + help Print this message or the help of the given subcommand(s) + +Options: + -v, --version Print version + -h, --help Print help ``` In particular, the `generate` subcommand has the following options: ``` -USAGE: - typical generate [FLAGS] [OPTIONS] - -FLAGS: - -h, --help Prints help information - --list-schemas Lists the schemas imported by the given schema (and the given schema - itself) +Usage: typical generate [OPTIONS] -OPTIONS: - --rust Sets the path of the Rust file to emit - --typescript Sets the path of the TypeScript file to emit +Arguments: + Set the path to the schema -ARGS: - Sets the path of the schema +Options: + --list-schemas List the schemas imported by the given schema (and the given schema + itself) + --rust Set the path to the Rust file to emit + --typescript Set the path to the TypeScript file to emit + -h, --help Print help ``` ## Installation instructions diff --git a/src/main.rs b/src/main.rs index 30cf12f4..0e145473 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,8 @@ use { schema_loader::load_schemas, validator::validate, }, - clap::{App, AppSettings, Arg, Shell, SubCommand}, + clap::{ArgAction, Args, CommandFactory, Parser, Subcommand as ClapSubcommand}, + clap_complete::{Shell, generate}, std::{ fs::{create_dir_all, write}, io::stdout, @@ -37,91 +38,85 @@ const VERSION: &str = env!("CARGO_PKG_VERSION"); // The name of the program binary const BIN_NAME: &str = "typical"; -// Command-line option and subcommand names -const GENERATE_SUBCOMMAND: &str = "generate"; -const GENERATE_SUBCOMMAND_PATH_OPTION: &str = "generate-path"; -const GENERATE_SUBCOMMAND_RUST_OPTION: &str = "rust"; -const GENERATE_SUBCOMMAND_TYPESCRIPT_OPTION: &str = "typescript"; -const GENERATE_SUBCOMMAND_LIST_SCHEMAS_OPTION: &str = "list-schemas"; -const FORMAT_SUBCOMMAND: &str = "format"; -const FORMAT_SUBCOMMAND_PATH_OPTION: &str = "format-path"; -const FORMAT_SUBCOMMAND_CHECK_OPTION: &str = "check"; -const SHELL_COMPLETION_SUBCOMMAND: &str = "shell-completion"; -const SHELL_COMPLETION_SUBCOMMAND_SHELL_OPTION: &str = "shell-completion-shell"; - -// Set up the command-line interface. -fn cli<'a, 'b>() -> App<'a, 'b> { - App::new("Typical") - .version(VERSION) - .version_short("v") - .author("Stephan Boyer ") - .about("Data interchange with algebraic data types.") - .setting(AppSettings::ColoredHelp) - .setting(AppSettings::NextLineHelp) - .setting(AppSettings::SubcommandRequiredElseHelp) // [tag:subcommand_required_else_help] - .setting(AppSettings::UnifiedHelpMessage) - .setting(AppSettings::VersionlessSubcommands) - .subcommand( - SubCommand::with_name(GENERATE_SUBCOMMAND) - .about("Generates code for a schema and its transitive dependencies") - .arg( - Arg::with_name(GENERATE_SUBCOMMAND_PATH_OPTION) - .value_name("SCHEMA_PATH") - .help("Sets the path of the schema") - .required(true), // [tag:generate_subcommand_path_required] - ) - .arg( - Arg::with_name(GENERATE_SUBCOMMAND_LIST_SCHEMAS_OPTION) - .long(GENERATE_SUBCOMMAND_LIST_SCHEMAS_OPTION) - .help( - "Lists the schemas imported by the given schema (and the given schema \ - itself)", - ), - ) - .arg( - Arg::with_name(GENERATE_SUBCOMMAND_RUST_OPTION) - .value_name("PATH") - .long(GENERATE_SUBCOMMAND_RUST_OPTION) - .help("Sets the path of the Rust file to emit"), - ) - .arg( - Arg::with_name(GENERATE_SUBCOMMAND_TYPESCRIPT_OPTION) - .value_name("PATH") - .long(GENERATE_SUBCOMMAND_TYPESCRIPT_OPTION) - .help("Sets the path of the TypeScript file to emit"), - ), - ) - .subcommand( - SubCommand::with_name(FORMAT_SUBCOMMAND) - .about("Formats a schema and its transitive dependencies") - .arg( - Arg::with_name(FORMAT_SUBCOMMAND_PATH_OPTION) - .value_name("SCHEMA_PATH") - .help("Sets the path of the schema") - .required(true), // [tag:format_subcommand_path_required] - ) - .arg( - Arg::with_name(FORMAT_SUBCOMMAND_CHECK_OPTION) - .long(FORMAT_SUBCOMMAND_CHECK_OPTION) - .help("Check the formatting rather than actually doing it"), - ), - ) - .subcommand( - SubCommand::with_name(SHELL_COMPLETION_SUBCOMMAND) - .about( - " \ - Prints a shell completion script. Supports Zsh, Fish, Zsh, PowerShell, and \ - Elvish. \ - " - .trim(), - ) - .arg( - Arg::with_name(SHELL_COMPLETION_SUBCOMMAND_SHELL_OPTION) - .value_name("SHELL") - .help("Bash, Fish, Zsh, PowerShell, or Elvish") - .required(true), // [tag:shell_completion_subcommand_shell_required] - ), - ) +// This struct represents the command-line arguments. +#[derive(Parser)] +#[command( + about = concat!( + env!("CARGO_PKG_DESCRIPTION"), + "\n\n", + "More information can be found at: ", + env!("CARGO_PKG_HOMEPAGE") + ), + version, + disable_version_flag = true, +)] +struct Cli { + #[arg(short, long, help = "Print version", action = ArgAction::Version)] + _version: Option, + + #[command(subcommand)] + command: TypicalCommand, +} + +#[derive(Args)] +struct GenerateArgs { + #[arg(value_name = "SCHEMA_PATH", help = "Set the path to the schema")] + path: String, + + #[arg( + long, + help = "List the schemas imported by the given schema (and the given schema itself)", + action = ArgAction::SetTrue + )] + list_schemas: bool, + + #[arg( + long, + value_name = "PATH", + help = "Set the path to the Rust file to emit" + )] + rust: Option, + + #[arg( + long, + value_name = "PATH", + help = "Set the path to the TypeScript file to emit" + )] + typescript: Option, +} + +#[derive(Args)] +struct FormatArgs { + #[arg(value_name = "SCHEMA_PATH", help = "Set the path to the schema")] + path: String, + + #[arg( + long, + help = "Check the formatting rather than actually doing it", + action = ArgAction::SetTrue + )] + check: bool, +} + +#[derive(Args)] +struct ShellCompletionArgs { + #[arg(help = "Bash, Fish, Zsh, PowerShell, or Elvish")] + shell: String, +} + +#[derive(ClapSubcommand)] +enum TypicalCommand { + #[command(about = "Generate code for a schema and its transitive dependencies")] + Generate(GenerateArgs), + + #[command(about = "Format a schema and its transitive dependencies")] + Format(FormatArgs), + + #[command( + name = "shell-completion", + about = "Print a shell completion script. Supports Bash, Fish, Zsh, PowerShell, and Elvish." + )] + ShellCompletion(ShellCompletionArgs), } // Generate code for a schema and its transitive dependencies. @@ -301,7 +296,8 @@ fn shell_completion(shell: &str) -> Result<(), Error> { }; // Write the script to STDOUT. - cli().gen_completions_to(BIN_NAME, shell_variant, &mut stdout()); + let mut command = Cli::command(); + generate(shell_variant, &mut command, BIN_NAME, &mut stdout()); // If we made it this far, nothing went wrong. Ok(()) @@ -310,80 +306,31 @@ fn shell_completion(shell: &str) -> Result<(), Error> { // Program entrypoint fn entry() -> Result<(), Error> { // Parse command-line arguments. - let matches = cli().get_matches(); + let cli = Cli::parse(); // Decide what to do based on the subcommand. - match matches.subcommand_name() { + match cli.command { // [tag:generate_subcommand] - Some(subcommand) if subcommand == GENERATE_SUBCOMMAND => { - // Get the subcommand matches. The `unwrap` is safe due to [ref:generate_subcommand]. - let subcommand_matches = matches.subcommand_matches(GENERATE_SUBCOMMAND).unwrap(); - - // Determine the path to the schema file. - let path = Path::new( - subcommand_matches - .value_of(GENERATE_SUBCOMMAND_PATH_OPTION) - // [ref:generate_subcommand_path_required] - .unwrap(), - ); - - // Determine if the user wants to list the schemas. - let list_schemas = - subcommand_matches.is_present(GENERATE_SUBCOMMAND_LIST_SCHEMAS_OPTION); - - // Determine the path to the Rust output file, if provided. - let rust = subcommand_matches - .value_of(GENERATE_SUBCOMMAND_RUST_OPTION) - .map(Path::new); - - // Determine the path to the TypeScript output file, if provided. - let typescript = subcommand_matches - .value_of(GENERATE_SUBCOMMAND_TYPESCRIPT_OPTION) - .map(Path::new); - + TypicalCommand::Generate(args) => { // Generate code for the schema and its transitive dependencies. - generate_code(path, list_schemas, rust, typescript)?; + generate_code( + Path::new(&args.path), + args.list_schemas, + args.rust.as_deref().map(Path::new), + args.typescript.as_deref().map(Path::new), + )?; } // [tag:format_subcommand] - Some(subcommand) if subcommand == FORMAT_SUBCOMMAND => { - // Get the subcommand matches. The `unwrap` is safe due to [ref:format_subcommand]. - let subcommand_matches = matches.subcommand_matches(FORMAT_SUBCOMMAND).unwrap(); - - // Determine the path to the schema file. - let path = Path::new( - subcommand_matches - .value_of(FORMAT_SUBCOMMAND_PATH_OPTION) - // [ref:format_subcommand_path_required] - .unwrap(), - ); - - // Determine if the user wants to check the formatting. - let check = subcommand_matches.is_present(FORMAT_SUBCOMMAND_CHECK_OPTION); - + TypicalCommand::Format(args) => { // Format the schema and its transitive dependencies. - format_schema(path, check)?; + format_schema(Path::new(&args.path), args.check)?; } // [tag:shell_completion_subcommand] - Some(subcommand) if subcommand == SHELL_COMPLETION_SUBCOMMAND => { - shell_completion( - matches - .subcommand_matches(SHELL_COMPLETION_SUBCOMMAND) - .unwrap() // [ref:shell_completion_subcommand] - .value_of(SHELL_COMPLETION_SUBCOMMAND_SHELL_OPTION) - // [ref:shell_completion_subcommand_shell_required] - .unwrap(), - )?; + TypicalCommand::ShellCompletion(args) => { + shell_completion(&args.shell)?; } - - // We should never end up in this branch, provided we handled all the subcommands - // above. - Some(_) => panic!("Subcommand not implemented."), - - // If no subcommand was provided, the help message should have been printed - // [ref:subcommand_required_else_help]. - None => panic!("The help message should have been printed."), } // If we made it this far, nothing went wrong. @@ -398,3 +345,14 @@ fn main() { exit(1); } } + +#[cfg(test)] +mod tests { + use super::Cli; + use clap::CommandFactory; + + #[test] + fn verify_cli() { + Cli::command().debug_assert(); + } +}