diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 2fc7f65586e..21012324d47 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -6,7 +6,7 @@ use std::str::FromStr; use anyhow::{anyhow, Error, Result}; use clap::{ - builder::{EnumValueParser, PossibleValue, PossibleValuesParser}, + builder::{PossibleValue, PossibleValuesParser}, Arg, ArgAction, ArgMatches, Args, Command, FromArgMatches as _, Parser, Subcommand, ValueEnum, }; use clap_complete::Shell; @@ -37,8 +37,8 @@ use crate::{ toolchain::{ distributable::DistributableToolchain, names::{ - partial_toolchain_desc_parser, CustomToolchainName, MaybeResolvableToolchainName, - ResolvableLocalToolchainName, ResolvableToolchainName, ToolchainName, + CustomToolchainName, MaybeResolvableToolchainName, ResolvableLocalToolchainName, + ResolvableToolchainName, ToolchainName, }, toolchain::Toolchain, }, @@ -206,6 +206,24 @@ enum RustupSubcmd { #[command(flatten)] page: DocPage, }, + + /// View the man page for a given command + #[cfg(not(windows))] + Man { + command: String, + + #[arg(long, help = OFFICIAL_TOOLCHAIN_ARG_HELP)] + toolchain: Option, + }, + + /// Generate tab-completion scripts for your shell + #[command(after_help = COMPLETIONS_HELP, arg_required_else_help = true)] + Completions { + shell: Shell, + + #[arg(default_value = "rustup")] + command: CompletionCommand, + }, } #[derive(Debug, Subcommand)] @@ -503,6 +521,11 @@ impl Rustup { topic, page, } => doc(cfg, path, toolchain, topic.as_deref(), &page), + #[cfg(not(windows))] + RustupSubcmd::Man { command, toolchain } => man(cfg, &command, toolchain), + RustupSubcmd::Completions { shell, command } => { + output_completion_script(shell, command) + } } } } @@ -581,10 +604,9 @@ pub fn main() -> Result { ( "dump-testament" | "show" | "update" | "install" | "uninstall" | "toolchain" | "check" | "default" | "target" | "component" | "override" | "run" | "which" - | "doc", + | "doc" | "man" | "completions", _, ) => Rustup::from_arg_matches(&matches)?.dispatch(cfg)?, - ("man", m) => man(cfg, m)?, ("self", c) => match c.subcommand() { Some(s) => match s { ("update", _) => self_update::update(cfg)?, @@ -602,18 +624,6 @@ pub fn main() -> Result { }, None => unreachable!(), }, - ("completions", c) => { - if let Some(&shell) = c.get_one::("shell") { - output_completion_script( - shell, - c.get_one::("command") - .copied() - .unwrap_or(CompletionCommand::Rustup), - )? - } else { - unreachable!() - } - } _ => unreachable!(), }, None => { @@ -624,7 +634,7 @@ pub fn main() -> Result { } pub(crate) fn cli() -> Command { - let mut app = Command::new("rustup") + let app = Command::new("rustup") .version(common::version()) .about("The Rust toolchain installer") .before_help(format!("rustup {}", common::version())) @@ -652,24 +662,7 @@ pub(crate) fn cli() -> Command { Err(Error::raw(ErrorKind::InvalidSubcommand, format!("\"{s}\" is not a valid subcommand, so it was interpreted as a toolchain name, but it is also invalid. {TOOLCHAIN_OVERRIDE_ERROR}"))) } }), - ); - - if cfg!(not(target_os = "windows")) { - app = app.subcommand( - Command::new("man") - .about("View the man page for a given command") - .arg(Arg::new("command").required(true)) - .arg( - Arg::new("toolchain") - .help(OFFICIAL_TOOLCHAIN_ARG_HELP) - .long("toolchain") - .num_args(1) - .value_parser(partial_toolchain_desc_parser), - ), - ); - } - - app = app + ) .subcommand( Command::new("self") .about("Modify the rustup installation") @@ -715,18 +708,6 @@ pub(crate) fn cli() -> Command { .default_value(SelfUpdateMode::default_mode()), ), ), - ) - .subcommand( - Command::new("completions") - .about("Generate tab-completion scripts for your shell") - .after_help(COMPLETIONS_HELP) - .arg_required_else_help(true) - .arg(Arg::new("shell").value_parser(EnumValueParser::::new())) - .arg( - Arg::new("command") - .value_parser(EnumValueParser::::new()) - .default_missing_value("rustup"), - ), ); RustupSubcmd::augment_subcommands(app) @@ -1336,16 +1317,6 @@ fn component_remove( Ok(utils::ExitCode(0)) } -// Make *sure* only to use this for a subcommand whose "toolchain" argument -// has .value_parser(partial_toolchain_desc_parser), or it will panic. -// FIXME: Delete this. -fn explicit_desc_or_dir_toolchain_old<'a>(cfg: &'a Cfg, m: &ArgMatches) -> Result> { - let toolchain = m - .get_one::("toolchain") - .map(Into::into); - explicit_or_dir_toolchain2(cfg, toolchain) -} - fn explicit_desc_or_dir_toolchain( cfg: &Cfg, toolchain: Option, @@ -1580,10 +1551,12 @@ fn doc( } } -fn man(cfg: &Cfg, m: &ArgMatches) -> Result { - let command = m.get_one::("command").unwrap(); - - let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?; +fn man( + cfg: &Cfg, + command: &str, + toolchain: Option, +) -> Result { + let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?; let mut path = toolchain.path().to_path_buf(); path.push("share"); path.push("man"); diff --git a/src/toolchain/names.rs b/src/toolchain/names.rs index 611b0c2c070..5457071cbd2 100644 --- a/src/toolchain/names.rs +++ b/src/toolchain/names.rs @@ -125,15 +125,6 @@ fn validate(candidate: &str) -> Result<&str, InvalidName> { } } -/// Thunk to avoid errors like -/// = note: `fn(&'2 str) -> Result>::Error> {>::try_from}` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... -/// = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` -pub(crate) fn partial_toolchain_desc_parser( - value: &str, -) -> Result { - value.parse::() -} - /// A toolchain name from user input. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub(crate) enum ResolvableToolchainName { diff --git a/tests/suite/cli-ui/rustup/rustup_completions_cmd_help_flag_stdout.toml b/tests/suite/cli-ui/rustup/rustup_completions_cmd_help_flag_stdout.toml index 63ac5221640..d6dcb9cb454 100644 --- a/tests/suite/cli-ui/rustup/rustup_completions_cmd_help_flag_stdout.toml +++ b/tests/suite/cli-ui/rustup/rustup_completions_cmd_help_flag_stdout.toml @@ -1,14 +1,14 @@ bin.name = "rustup" -args = ["completions","--help"] +args = ["completions", "--help"] stdout = """ ... Generate tab-completion scripts for your shell -Usage: rustup[EXE] completions [shell] [command] +Usage: rustup[EXE] completions [COMMAND] Arguments: - [shell] [possible values: bash, elvish, fish, powershell, zsh] - [command] [possible values: rustup, cargo] + [possible values: bash, elvish, fish, powershell, zsh] + [COMMAND] [default: rustup] [possible values: rustup, cargo] Options: -h, --help Print help diff --git a/tests/suite/cli-ui/rustup/rustup_help_cmd_stdout.toml b/tests/suite/cli-ui/rustup/rustup_help_cmd_stdout.toml index f278defd178..a17088cbf38 100644 --- a/tests/suite/cli-ui/rustup/rustup_help_cmd_stdout.toml +++ b/tests/suite/cli-ui/rustup/rustup_help_cmd_stdout.toml @@ -9,10 +9,8 @@ The Rust toolchain installer Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND] Commands: -... self Modify the rustup installation set Alter rustup settings - completions Generate tab-completion scripts for your shell show Show the active and installed toolchains or profiles update Update Rust toolchains and rustup check Check for updates to Rust toolchains and rustup @@ -24,6 +22,8 @@ Commands: run Run a command with an environment configured for a given toolchain which Display which binary will be run for a given command doc Open the documentation for the current toolchain +... + completions Generate tab-completion scripts for your shell help Print this message or the help of the given subcommand(s) Arguments: diff --git a/tests/suite/cli-ui/rustup/rustup_help_flag_stdout.toml b/tests/suite/cli-ui/rustup/rustup_help_flag_stdout.toml index 38a256fdfcc..22c3dcc9024 100644 --- a/tests/suite/cli-ui/rustup/rustup_help_flag_stdout.toml +++ b/tests/suite/cli-ui/rustup/rustup_help_flag_stdout.toml @@ -9,10 +9,8 @@ The Rust toolchain installer Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND] Commands: -... self Modify the rustup installation set Alter rustup settings - completions Generate tab-completion scripts for your shell show Show the active and installed toolchains or profiles update Update Rust toolchains and rustup check Check for updates to Rust toolchains and rustup @@ -24,6 +22,8 @@ Commands: run Run a command with an environment configured for a given toolchain which Display which binary will be run for a given command doc Open the documentation for the current toolchain +... + completions Generate tab-completion scripts for your shell help Print this message or the help of the given subcommand(s) Arguments: diff --git a/tests/suite/cli-ui/rustup/rustup_man_cmd_help_flag_stdout.toml b/tests/suite/cli-ui/rustup/rustup_man_cmd_help_flag_stdout.toml index 5c94c51058d..a35b59460c2 100644 --- a/tests/suite/cli-ui/rustup/rustup_man_cmd_help_flag_stdout.toml +++ b/tests/suite/cli-ui/rustup/rustup_man_cmd_help_flag_stdout.toml @@ -1,16 +1,16 @@ bin.name = "rustup" -args = ["man","--help"] +args = ["man", "--help"] stdout = """ ... View the man page for a given command -Usage: rustup[EXE] man [OPTIONS] +Usage: rustup[EXE] man [OPTIONS] Arguments: - + Options: - --toolchain Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more + --toolchain Toolchain name, such as 'stable', 'nightly', or '1.8.0'. For more information see `rustup help toolchain` -h, --help Print help """ diff --git a/tests/suite/cli-ui/rustup/rustup_only_options_stdout.toml b/tests/suite/cli-ui/rustup/rustup_only_options_stdout.toml index 052a314a1d3..4d3165c8930 100644 --- a/tests/suite/cli-ui/rustup/rustup_only_options_stdout.toml +++ b/tests/suite/cli-ui/rustup/rustup_only_options_stdout.toml @@ -9,10 +9,8 @@ The Rust toolchain installer Usage: rustup[EXE] [OPTIONS] [+toolchain] [COMMAND] Commands: -... self Modify the rustup installation set Alter rustup settings - completions Generate tab-completion scripts for your shell show Show the active and installed toolchains or profiles update Update Rust toolchains and rustup check Check for updates to Rust toolchains and rustup @@ -24,6 +22,8 @@ Commands: run Run a command with an environment configured for a given toolchain which Display which binary will be run for a given command doc Open the documentation for the current toolchain +... + completions Generate tab-completion scripts for your shell help Print this message or the help of the given subcommand(s) Arguments: diff --git a/tests/suite/cli_misc.rs b/tests/suite/cli_misc.rs index 1f511e78e6b..5dccaadd62a 100644 --- a/tests/suite/cli_misc.rs +++ b/tests/suite/cli_misc.rs @@ -798,11 +798,11 @@ fn completion_bad_shell() { setup(&|config| { config.expect_err( &["rustup", "completions", "fake"], - r#"error: invalid value 'fake' for '[shell]'"#, + r#"error: invalid value 'fake' for ''"#, ); config.expect_err( &["rustup", "completions", "fake", "cargo"], - r#"error: invalid value 'fake' for '[shell]'"#, + r#"error: invalid value 'fake' for ''"#, ); }); } @@ -812,7 +812,7 @@ fn completion_bad_tool() { setup(&|config| { config.expect_err( &["rustup", "completions", "bash", "fake"], - r#"error: invalid value 'fake' for '[command]'"#, + r#"error: invalid value 'fake' for '[COMMAND]'"#, ); }); }