11use crate :: { t, VERSION } ;
2+ use std:: fmt:: Write as _;
23use std:: path:: { Path , PathBuf } ;
34use std:: str:: FromStr ;
45use std:: {
@@ -20,7 +21,28 @@ impl Profile {
2021 }
2122
2223 pub fn all ( ) -> impl Iterator < Item = Self > {
23- [ Profile :: Compiler , Profile :: Codegen , Profile :: Library , Profile :: User ] . iter ( ) . copied ( )
24+ use Profile :: * ;
25+ // N.B. these are ordered by how they are displayed, not alphabetically
26+ [ Library , Compiler , Codegen , User ] . iter ( ) . copied ( )
27+ }
28+
29+ pub fn purpose ( & self ) -> String {
30+ use Profile :: * ;
31+ match self {
32+ Library => "Contribute to the standard library" ,
33+ Compiler => "Contribute to the compiler or rustdoc" ,
34+ Codegen => "Contribute to the compiler, and also modify LLVM or codegen" ,
35+ User => "Install Rust from source" ,
36+ }
37+ . to_string ( )
38+ }
39+
40+ pub fn all_for_help ( indent : & str ) -> String {
41+ let mut out = String :: new ( ) ;
42+ for choice in Profile :: all ( ) {
43+ writeln ! ( & mut out, "{}{}: {}" , indent, choice, choice. purpose( ) ) . unwrap ( ) ;
44+ }
45+ out
2446 }
2547}
2648
@@ -29,10 +51,10 @@ impl FromStr for Profile {
2951
3052 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
3153 match s {
32- "a" | " lib" | "library" => Ok ( Profile :: Library ) ,
33- "b" | " compiler" | "rustdoc" => Ok ( Profile :: Compiler ) ,
34- "c" | " llvm" | "codegen" => Ok ( Profile :: Codegen ) ,
35- "d" | " maintainer" | "user" => Ok ( Profile :: User ) ,
54+ "lib" | "library" => Ok ( Profile :: Library ) ,
55+ "compiler" | "rustdoc" => Ok ( Profile :: Compiler ) ,
56+ "llvm" | "codegen" => Ok ( Profile :: Codegen ) ,
57+ "maintainer" | "user" => Ok ( Profile :: User ) ,
3658 _ => Err ( format ! ( "unknown profile: '{}'" , s) ) ,
3759 }
3860 }
@@ -104,19 +126,37 @@ pub fn setup(src_path: &Path, profile: Profile) {
104126
105127// Used to get the path for `Subcommand::Setup`
106128pub fn interactive_path ( ) -> io:: Result < Profile > {
107- let mut input = String :: new ( ) ;
108- println ! (
109- "Welcome to the Rust project! What do you want to do with x.py?
110- a) Contribute to the standard library
111- b) Contribute to the compiler or rustdoc
112- c) Contribute to the compiler, and also modify LLVM or codegen
113- d) Install Rust from source"
114- ) ;
129+ fn abbrev_all ( ) -> impl Iterator < Item = ( String , Profile ) > {
130+ ( 'a' ..) . map ( |c| c. to_string ( ) ) . zip ( Profile :: all ( ) )
131+ }
132+
133+ fn parse_with_abbrev ( input : & str ) -> Result < Profile , String > {
134+ let input = input. trim ( ) . to_lowercase ( ) ;
135+ for ( letter, profile) in abbrev_all ( ) {
136+ if input == letter {
137+ return Ok ( profile) ;
138+ }
139+ }
140+ input. parse ( )
141+ }
142+
143+ println ! ( "Welcome to the Rust project! What do you want to do with x.py?" ) ;
144+ for ( letter, profile) in abbrev_all ( ) {
145+ println ! ( "{}) {}: {}" , letter, profile, profile. purpose( ) ) ;
146+ }
115147 let template = loop {
116- print ! ( "Please choose one (a/b/c/d): " ) ;
148+ print ! (
149+ "Please choose one ({}): " ,
150+ abbrev_all( ) . map( |( l, _) | l) . collect:: <Vec <_>>( ) . join( "/" )
151+ ) ;
117152 io:: stdout ( ) . flush ( ) ?;
153+ let mut input = String :: new ( ) ;
118154 io:: stdin ( ) . read_line ( & mut input) ?;
119- break match input. trim ( ) . to_lowercase ( ) . parse ( ) {
155+ if input == "" {
156+ eprintln ! ( "EOF on stdin, when expecting answer to question. Giving up." ) ;
157+ std:: process:: exit ( 1 ) ;
158+ }
159+ break match parse_with_abbrev ( & input) {
120160 Ok ( profile) => profile,
121161 Err ( err) => {
122162 println ! ( "error: {}" , err) ;
0 commit comments