Skip to content

Commit 0ba1e1f

Browse files
committed
refactor(cli): rewrite rustup (man|completions) with clap-derive
1 parent 1764cc8 commit 0ba1e1f

File tree

1 file changed

+34
-62
lines changed

1 file changed

+34
-62
lines changed

src/cli/rustup_mode.rs

Lines changed: 34 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::str::FromStr;
66

77
use anyhow::{anyhow, Error, Result};
88
use clap::{
9-
builder::{EnumValueParser, PossibleValue, PossibleValuesParser},
9+
builder::{PossibleValue, PossibleValuesParser},
1010
Arg, ArgAction, ArgMatches, Args, Command, FromArgMatches as _, Parser, Subcommand, ValueEnum,
1111
};
1212
use clap_complete::Shell;
@@ -37,8 +37,8 @@ use crate::{
3737
toolchain::{
3838
distributable::DistributableToolchain,
3939
names::{
40-
partial_toolchain_desc_parser, CustomToolchainName, MaybeResolvableToolchainName,
41-
ResolvableLocalToolchainName, ResolvableToolchainName, ToolchainName,
40+
CustomToolchainName, MaybeResolvableToolchainName, ResolvableLocalToolchainName,
41+
ResolvableToolchainName, ToolchainName,
4242
},
4343
toolchain::Toolchain,
4444
},
@@ -206,6 +206,24 @@ enum RustupSubcmd {
206206
#[command(flatten)]
207207
page: DocPage,
208208
},
209+
210+
/// View the man page for a given command
211+
#[cfg(not(windows))]
212+
Man {
213+
command: String,
214+
215+
#[arg(long, help = OFFICIAL_TOOLCHAIN_ARG_HELP)]
216+
toolchain: Option<PartialToolchainDesc>,
217+
},
218+
219+
/// Generate tab-completion scripts for your shell
220+
#[command(after_help = COMPLETIONS_HELP, arg_required_else_help = true)]
221+
Completions {
222+
shell: Shell,
223+
224+
#[arg(default_missing_value = "rustup")]
225+
command: CompletionCommand,
226+
},
209227
}
210228

211229
#[derive(Debug, Subcommand)]
@@ -503,6 +521,10 @@ impl Rustup {
503521
topic,
504522
page,
505523
} => doc(cfg, path, toolchain, topic.as_deref(), &page),
524+
RustupSubcmd::Man { command, toolchain } => man(cfg, &command, toolchain),
525+
RustupSubcmd::Completions { shell, command } => {
526+
output_completion_script(shell, command)
527+
}
506528
}
507529
}
508530
}
@@ -581,10 +603,9 @@ pub fn main() -> Result<utils::ExitCode> {
581603
(
582604
"dump-testament" | "show" | "update" | "install" | "uninstall" | "toolchain"
583605
| "check" | "default" | "target" | "component" | "override" | "run" | "which"
584-
| "doc",
606+
| "doc" | "man" | "completions",
585607
_,
586608
) => Rustup::from_arg_matches(&matches)?.dispatch(cfg)?,
587-
("man", m) => man(cfg, m)?,
588609
("self", c) => match c.subcommand() {
589610
Some(s) => match s {
590611
("update", _) => self_update::update(cfg)?,
@@ -602,18 +623,6 @@ pub fn main() -> Result<utils::ExitCode> {
602623
},
603624
None => unreachable!(),
604625
},
605-
("completions", c) => {
606-
if let Some(&shell) = c.get_one::<Shell>("shell") {
607-
output_completion_script(
608-
shell,
609-
c.get_one::<CompletionCommand>("command")
610-
.copied()
611-
.unwrap_or(CompletionCommand::Rustup),
612-
)?
613-
} else {
614-
unreachable!()
615-
}
616-
}
617626
_ => unreachable!(),
618627
},
619628
None => {
@@ -624,7 +633,7 @@ pub fn main() -> Result<utils::ExitCode> {
624633
}
625634

626635
pub(crate) fn cli() -> Command {
627-
let mut app = Command::new("rustup")
636+
let app = Command::new("rustup")
628637
.version(common::version())
629638
.about("The Rust toolchain installer")
630639
.before_help(format!("rustup {}", common::version()))
@@ -652,24 +661,7 @@ pub(crate) fn cli() -> Command {
652661
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}")))
653662
}
654663
}),
655-
);
656-
657-
if cfg!(not(target_os = "windows")) {
658-
app = app.subcommand(
659-
Command::new("man")
660-
.about("View the man page for a given command")
661-
.arg(Arg::new("command").required(true))
662-
.arg(
663-
Arg::new("toolchain")
664-
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
665-
.long("toolchain")
666-
.num_args(1)
667-
.value_parser(partial_toolchain_desc_parser),
668-
),
669-
);
670-
}
671-
672-
app = app
664+
)
673665
.subcommand(
674666
Command::new("self")
675667
.about("Modify the rustup installation")
@@ -715,18 +707,6 @@ pub(crate) fn cli() -> Command {
715707
.default_value(SelfUpdateMode::default_mode()),
716708
),
717709
),
718-
)
719-
.subcommand(
720-
Command::new("completions")
721-
.about("Generate tab-completion scripts for your shell")
722-
.after_help(COMPLETIONS_HELP)
723-
.arg_required_else_help(true)
724-
.arg(Arg::new("shell").value_parser(EnumValueParser::<Shell>::new()))
725-
.arg(
726-
Arg::new("command")
727-
.value_parser(EnumValueParser::<CompletionCommand>::new())
728-
.default_missing_value("rustup"),
729-
),
730710
);
731711

732712
RustupSubcmd::augment_subcommands(app)
@@ -1336,16 +1316,6 @@ fn component_remove(
13361316
Ok(utils::ExitCode(0))
13371317
}
13381318

1339-
// Make *sure* only to use this for a subcommand whose "toolchain" argument
1340-
// has .value_parser(partial_toolchain_desc_parser), or it will panic.
1341-
// FIXME: Delete this.
1342-
fn explicit_desc_or_dir_toolchain_old<'a>(cfg: &'a Cfg, m: &ArgMatches) -> Result<Toolchain<'a>> {
1343-
let toolchain = m
1344-
.get_one::<PartialToolchainDesc>("toolchain")
1345-
.map(Into::into);
1346-
explicit_or_dir_toolchain2(cfg, toolchain)
1347-
}
1348-
13491319
fn explicit_desc_or_dir_toolchain(
13501320
cfg: &Cfg,
13511321
toolchain: Option<PartialToolchainDesc>,
@@ -1580,10 +1550,12 @@ fn doc(
15801550
}
15811551
}
15821552

1583-
fn man(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1584-
let command = m.get_one::<String>("command").unwrap();
1585-
1586-
let toolchain = explicit_desc_or_dir_toolchain_old(cfg, m)?;
1553+
fn man(
1554+
cfg: &Cfg,
1555+
command: &str,
1556+
toolchain: Option<PartialToolchainDesc>,
1557+
) -> Result<utils::ExitCode> {
1558+
let toolchain = explicit_desc_or_dir_toolchain(cfg, toolchain)?;
15871559
let mut path = toolchain.path().to_path_buf();
15881560
path.push("share");
15891561
path.push("man");

0 commit comments

Comments
 (0)