@@ -6,7 +6,8 @@ use std::str::FromStr;
66use anyhow:: { anyhow, Error , Result } ;
77use 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} ;
1112use clap_complete:: Shell ;
1213use itertools:: Itertools ;
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 <_>>( ) ) ) ) ) ]
90148pub 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
823774fn 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