From c4c5653a48fa6871bf2a07dd56cb7f2801115bfb Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 13 Oct 2020 00:07:52 +0100 Subject: [PATCH] x.py: setup: Refactor to centralise list of profiles Put all()'s otuput in the order we want to print things in, and add a comment about why they are in this order. Provide purpose() and all_for_help(). Use these things everywhere. Move all the abbrev character ("a", "b", etc.) processing into interactive_path. No functional change. Signed-off-by: Ian Jackson --- src/bootstrap/flags.rs | 4 +-- src/bootstrap/setup.rs | 64 +++++++++++++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index c10188875fb..f38c6876747 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -551,9 +551,7 @@ Arguments: profile_string.parse().unwrap_or_else(|err| { eprintln!("error: {}", err); eprintln!("help: the available profiles are:"); - for choice in Profile::all() { - eprintln!("- {}", choice); - } + eprint!("{}", Profile::all_for_help("- ")); std::process::exit(1); }) } else { diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 2a9507cfc4c..85b361e16a3 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -1,4 +1,5 @@ use crate::{t, VERSION}; +use std::fmt::Write as _; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{ @@ -20,7 +21,28 @@ impl Profile { } pub fn all() -> impl Iterator { - [Profile::Compiler, Profile::Codegen, Profile::Library, Profile::User].iter().copied() + use Profile::*; + // N.B. these are ordered by how they are displayed, not alphabetically + [Library, Compiler, Codegen, User].iter().copied() + } + + pub fn purpose(&self) -> String { + use Profile::*; + match self { + Library => "Contribute to the standard library", + Compiler => "Contribute to the compiler or rustdoc", + Codegen => "Contribute to the compiler, and also modify LLVM or codegen", + User => "Install Rust from source", + } + .to_string() + } + + pub fn all_for_help(indent: &str) -> String { + let mut out = String::new(); + for choice in Profile::all() { + writeln!(&mut out, "{}{}", indent, choice).unwrap(); + } + out } } @@ -29,10 +51,10 @@ impl FromStr for Profile { fn from_str(s: &str) -> Result { match s { - "a" | "lib" | "library" => Ok(Profile::Library), - "b" | "compiler" | "rustdoc" => Ok(Profile::Compiler), - "c" | "llvm" | "codegen" => Ok(Profile::Codegen), - "d" | "maintainer" | "user" => Ok(Profile::User), + "lib" | "library" => Ok(Profile::Library), + "compiler" | "rustdoc" => Ok(Profile::Compiler), + "llvm" | "codegen" => Ok(Profile::Codegen), + "maintainer" | "user" => Ok(Profile::User), _ => Err(format!("unknown profile: '{}'", s)), } } @@ -104,19 +126,33 @@ pub fn setup(src_path: &Path, profile: Profile) { // Used to get the path for `Subcommand::Setup` pub fn interactive_path() -> io::Result { + fn abbrev_all() -> impl Iterator { + ('a'..).map(|c| c.to_string()).zip(Profile::all()) + } + + fn parse_with_abbrev(input: &str) -> Result { + let input = input.trim().to_lowercase(); + for (letter, profile) in abbrev_all() { + if input == letter { + return Ok(profile); + } + } + input.parse() + } + let mut input = String::new(); - println!( - "Welcome to the Rust project! What do you want to do with x.py? -a) Contribute to the standard library -b) Contribute to the compiler or rustdoc -c) Contribute to the compiler, and also modify LLVM or codegen -d) Install Rust from source" - ); + println!("Welcome to the Rust project! What do you want to do with x.py?"); + for (letter, profile) in abbrev_all() { + println!("{}) {}", letter, profile.purpose()); + } let template = loop { - print!("Please choose one (a/b/c/d): "); + print!( + "Please choose one ({}): ", + abbrev_all().map(|(l, _)| l).collect::>().join("/") + ); io::stdout().flush()?; io::stdin().read_line(&mut input)?; - break match input.trim().to_lowercase().parse() { + break match parse_with_abbrev(&input) { Ok(profile) => profile, Err(err) => { println!("error: {}", err);