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| {
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 {

View File

@ -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<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> {
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<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();
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::<Vec<_>>().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);