Skip to content

Commit 319f931

Browse files
committed
refactor(cli): rewrite rustup show with clap_derive
1 parent 8244acc commit 319f931

File tree

1 file changed

+75
-127
lines changed

1 file changed

+75
-127
lines changed

src/cli/rustup_mode.rs

Lines changed: 75 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use std::str::FromStr;
66
use anyhow::{anyhow, Error, Result};
77
use clap::{
88
builder::{EnumValueParser, PossibleValue, PossibleValuesParser},
9-
Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueEnum,
9+
Arg, ArgAction, ArgGroup, ArgMatches, Command, FromArgMatches as _, Parser, Subcommand,
10+
ValueEnum,
1011
};
1112
use clap_complete::Shell;
1213
use itertools::Itertools;
@@ -86,6 +87,63 @@ where
8687
callee(cfg, matches)
8788
}
8889

90+
#[derive(Debug, Parser)]
91+
#[command(
92+
name = "rustup",
93+
bin_name = "rustup[EXE]",
94+
version = common::version(),
95+
)]
96+
struct Rustup {
97+
#[command(subcommand)]
98+
subcmd: RustupSubcmd,
99+
}
100+
101+
#[derive(Debug, Subcommand)]
102+
enum RustupSubcmd {
103+
/// Show the active and installed toolchains or profiles
104+
#[command(after_help = SHOW_HELP)]
105+
Show {
106+
/// Enable verbose output with rustc information for all installed toolchains
107+
#[arg(short, long)]
108+
verbose: bool,
109+
110+
#[command(subcommand)]
111+
subcmd: Option<ShowSubcmd>,
112+
},
113+
}
114+
115+
#[derive(Debug, Subcommand)]
116+
enum ShowSubcmd {
117+
/// Show the active toolchain
118+
#[command(after_help = SHOW_ACTIVE_TOOLCHAIN_HELP)]
119+
ActiveToolchain {
120+
/// Enable verbose output with rustc information
121+
#[arg(short, long)]
122+
verbose: bool,
123+
},
124+
125+
/// Display the computed value of RUSTUP_HOME
126+
Home,
127+
128+
/// Show the default profile used for the `rustup install` command
129+
Profile,
130+
}
131+
132+
impl Rustup {
133+
fn dispatch(self, cfg: &mut Cfg) -> Result<utils::ExitCode> {
134+
match self.subcmd {
135+
RustupSubcmd::Show { verbose, subcmd } => match subcmd {
136+
None => handle_epipe(show(cfg, verbose)),
137+
Some(ShowSubcmd::ActiveToolchain { verbose }) => {
138+
handle_epipe(show_active_toolchain(cfg, verbose))
139+
}
140+
Some(ShowSubcmd::Home) => handle_epipe(show_rustup_home(cfg)),
141+
Some(ShowSubcmd::Profile) => handle_epipe(show_profile(cfg)),
142+
},
143+
}
144+
}
145+
}
146+
89147
#[cfg_attr(feature = "otel", tracing::instrument(fields(args = format!("{:?}", process().args_os().collect::<Vec<_>>()))))]
90148
pub fn main() -> Result<utils::ExitCode> {
91149
self_update::cleanup_self_updater()?;
@@ -158,15 +216,7 @@ pub fn main() -> Result<utils::ExitCode> {
158216
Ok(match matches.subcommand() {
159217
Some(s) => match s {
160218
("dump-testament", _) => common::dump_testament()?,
161-
("show", c) => match c.subcommand() {
162-
Some(s) => match s {
163-
("active-toolchain", m) => handle_epipe(show_active_toolchain(cfg, m))?,
164-
("home", _) => handle_epipe(show_rustup_home(cfg))?,
165-
("profile", _) => handle_epipe(show_profile(cfg))?,
166-
_ => handle_epipe(show(cfg, c))?,
167-
},
168-
None => handle_epipe(show(cfg, c))?,
169-
},
219+
("show", _) => Rustup::from_arg_matches(&matches)?.dispatch(cfg)?,
170220
("install", m) => deprecated("toolchain install", cfg, m, update)?,
171221
("update", m) => update(cfg, m)?,
172222
("check", _) => check_updates(cfg)?,
@@ -287,106 +337,6 @@ pub(crate) fn cli() -> Command {
287337
.about("Dump information about the build")
288338
.hide(true), // Not for users, only CI
289339
)
290-
.subcommand(
291-
Command::new("show")
292-
.about("Show the active and installed toolchains or profiles")
293-
.after_help(SHOW_HELP)
294-
.arg(
295-
verbose_arg("Enable verbose output with rustc information for all installed toolchains"),
296-
)
297-
.subcommand(
298-
Command::new("active-toolchain")
299-
.about("Show the active toolchain")
300-
.after_help(SHOW_ACTIVE_TOOLCHAIN_HELP)
301-
.arg(
302-
verbose_arg("Enable verbose output with rustc information"),
303-
),
304-
)
305-
.subcommand(
306-
Command::new("home")
307-
.about("Display the computed value of RUSTUP_HOME"),
308-
)
309-
.subcommand(Command::new("profile").about("Show the default profile used for the `rustup install` command"))
310-
)
311-
.subcommand(
312-
Command::new("install")
313-
.about("Update Rust toolchains")
314-
.after_help(INSTALL_HELP)
315-
.hide(true) // synonym for 'toolchain install'
316-
.arg(
317-
Arg::new("toolchain")
318-
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
319-
.required(true)
320-
.value_parser(partial_toolchain_desc_parser)
321-
.num_args(1..)
322-
)
323-
.arg(
324-
Arg::new("profile")
325-
.long("profile")
326-
.value_parser(PossibleValuesParser::new(Profile::names()))
327-
.num_args(1),
328-
)
329-
.arg(
330-
Arg::new("no-self-update")
331-
.help("Don't perform self-update when running the `rustup install` command")
332-
.long("no-self-update")
333-
.action(ArgAction::SetTrue)
334-
)
335-
.arg(
336-
Arg::new("force")
337-
.help("Force an update, even if some components are missing")
338-
.long("force")
339-
.action(ArgAction::SetTrue)
340-
).arg(
341-
Arg::new("force-non-host")
342-
.help("Install toolchains that require an emulator. See https://github.com/rust-lang/rustup/wiki/Non-host-toolchains")
343-
.long("force-non-host")
344-
.action(ArgAction::SetTrue)
345-
),
346-
)
347-
.subcommand(
348-
Command::new("uninstall")
349-
.about("Uninstall Rust toolchains")
350-
.hide(true) // synonym for 'toolchain uninstall'
351-
.arg(
352-
Arg::new("toolchain")
353-
.help(RESOLVABLE_TOOLCHAIN_ARG_HELP)
354-
.required(true)
355-
.value_parser(resolvable_toolchainame_parser)
356-
.num_args(1..)
357-
),
358-
)
359-
.subcommand(
360-
Command::new("update")
361-
.about("Update Rust toolchains and rustup")
362-
.aliases(["upgrade", "up"])
363-
.after_help(UPDATE_HELP)
364-
.arg(
365-
Arg::new("toolchain")
366-
.help(OFFICIAL_TOOLCHAIN_ARG_HELP)
367-
.required(false)
368-
.value_parser(partial_toolchain_desc_parser)
369-
.num_args(1..)
370-
)
371-
.arg(
372-
Arg::new("no-self-update")
373-
.help("Don't perform self update when running the `rustup update` command")
374-
.long("no-self-update")
375-
.action(ArgAction::SetTrue)
376-
)
377-
.arg(
378-
Arg::new("force")
379-
.help("Force an update, even if some components are missing")
380-
.long("force")
381-
.action(ArgAction::SetTrue)
382-
)
383-
.arg(
384-
Arg::new("force-non-host")
385-
.help("Install toolchains that require an emulator. See https://github.com/rust-lang/rustup/wiki/Non-host-toolchains")
386-
.long("force-non-host")
387-
.action(ArgAction::SetTrue)
388-
),
389-
)
390340
.subcommand(Command::new("check").about("Check for updates to Rust toolchains and rustup"))
391341
.subcommand(
392342
Command::new("default")
@@ -804,20 +754,21 @@ pub(crate) fn cli() -> Command {
804754
.default_value(SelfUpdateMode::default_mode()),
805755
),
806756
),
757+
)
758+
.subcommand(
759+
Command::new("completions")
760+
.about("Generate tab-completion scripts for your shell")
761+
.after_help(COMPLETIONS_HELP)
762+
.arg_required_else_help(true)
763+
.arg(Arg::new("shell").value_parser(EnumValueParser::<Shell>::new()))
764+
.arg(
765+
Arg::new("command")
766+
.value_parser(EnumValueParser::<CompletionCommand>::new())
767+
.default_missing_value("rustup"),
768+
),
807769
);
808770

809-
app.subcommand(
810-
Command::new("completions")
811-
.about("Generate tab-completion scripts for your shell")
812-
.after_help(COMPLETIONS_HELP)
813-
.arg_required_else_help(true)
814-
.arg(Arg::new("shell").value_parser(EnumValueParser::<Shell>::new()))
815-
.arg(
816-
Arg::new("command")
817-
.value_parser(EnumValueParser::<CompletionCommand>::new())
818-
.default_missing_value("rustup"),
819-
),
820-
)
771+
RustupSubcmd::augment_subcommands(app)
821772
}
822773

823774
fn verbose_arg(help: &'static str) -> Arg {
@@ -1061,11 +1012,9 @@ fn which(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
10611012
}
10621013

10631014
#[cfg_attr(feature = "otel", tracing::instrument(skip_all))]
1064-
fn show(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1015+
fn show(cfg: &Cfg, verbose: bool) -> Result<utils::ExitCode> {
10651016
common::warn_if_host_is_emulated();
10661017

1067-
let verbose = m.get_flag("verbose");
1068-
10691018
// Print host triple
10701019
{
10711020
let mut t = process().stdout().terminal();
@@ -1201,8 +1150,7 @@ fn show(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
12011150
}
12021151

12031152
#[cfg_attr(feature = "otel", tracing::instrument(skip_all))]
1204-
fn show_active_toolchain(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
1205-
let verbose = m.get_flag("verbose");
1153+
fn show_active_toolchain(cfg: &Cfg, verbose: bool) -> Result<utils::ExitCode> {
12061154
let cwd = utils::current_dir()?;
12071155
match cfg.find_active_toolchain(&cwd)? {
12081156
Some((toolchain_name, reason)) => {

0 commit comments

Comments
 (0)