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 <ijackson@chiark.greenend.org.uk>
This commit is contained in:
Ian Jackson 2020-10-13 00:07:52 +01:00
parent 5565241f65
commit c4c5653a48
2 changed files with 51 additions and 17 deletions

View File

@ -551,9 +551,7 @@ Arguments:
profile_string.parse().unwrap_or_else(|err| { profile_string.parse().unwrap_or_else(|err| {
eprintln!("error: {}", err); eprintln!("error: {}", err);
eprintln!("help: the available profiles are:"); eprintln!("help: the available profiles are:");
for choice in Profile::all() { eprint!("{}", Profile::all_for_help("- "));
eprintln!("- {}", choice);
}
std::process::exit(1); std::process::exit(1);
}) })
} else { } else {

View File

@ -1,4 +1,5 @@
use crate::{t, VERSION}; use crate::{t, VERSION};
use std::fmt::Write as _;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use std::{ use std::{
@ -20,7 +21,28 @@ impl Profile {
} }
pub fn all() -> impl Iterator<Item = Self> { pub fn all() -> impl Iterator<Item = Self> {
[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<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s { match s {
"a" | "lib" | "library" => Ok(Profile::Library), "lib" | "library" => Ok(Profile::Library),
"b" | "compiler" | "rustdoc" => Ok(Profile::Compiler), "compiler" | "rustdoc" => Ok(Profile::Compiler),
"c" | "llvm" | "codegen" => Ok(Profile::Codegen), "llvm" | "codegen" => Ok(Profile::Codegen),
"d" | "maintainer" | "user" => Ok(Profile::User), "maintainer" | "user" => Ok(Profile::User),
_ => Err(format!("unknown profile: '{}'", s)), _ => 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` // Used to get the path for `Subcommand::Setup`
pub fn interactive_path() -> io::Result<Profile> { pub fn interactive_path() -> io::Result<Profile> {
fn abbrev_all() -> impl Iterator<Item = (String, Profile)> {
('a'..).map(|c| c.to_string()).zip(Profile::all())
}
fn parse_with_abbrev(input: &str) -> Result<Profile, String> {
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(); let mut input = String::new();
println!( println!("Welcome to the Rust project! What do you want to do with x.py?");
"Welcome to the Rust project! What do you want to do with x.py? for (letter, profile) in abbrev_all() {
a) Contribute to the standard library println!("{}) {}", letter, profile.purpose());
b) Contribute to the compiler or rustdoc }
c) Contribute to the compiler, and also modify LLVM or codegen
d) Install Rust from source"
);
let template = loop { let template = loop {
print!("Please choose one (a/b/c/d): "); print!(
"Please choose one ({}): ",
abbrev_all().map(|(l, _)| l).collect::<Vec<_>>().join("/")
);
io::stdout().flush()?; io::stdout().flush()?;
io::stdin().read_line(&mut input)?; io::stdin().read_line(&mut input)?;
break match input.trim().to_lowercase().parse() { break match parse_with_abbrev(&input) {
Ok(profile) => profile, Ok(profile) => profile,
Err(err) => { Err(err) => {
println!("error: {}", err); println!("error: {}", err);