Rollup merge of #77879 - ijackson:x-py, r=jyn514

Provide better documentation and help messages for x.py setup

Closes: #77861

I have split this up into tiny comments because I find it clearer this way.  Feel free to squash it.
This commit is contained in:
Yuki Okushi 2020-10-15 07:32:32 +09:00 committed by GitHub
commit c268cc0b4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 21 deletions

View File

@ -125,6 +125,7 @@ Subcommands:
dist Build distribution artifacts
install Install distribution artifacts
run, r Run tools contained in this repository
setup Create a config.toml (making it easier to use `x.py` itself)
To learn more about a subcommand, run `./x.py <subcommand> -h`",
);
@ -472,15 +473,21 @@ Arguments:
);
}
"setup" => {
subcommand_help.push_str(
subcommand_help.push_str(&format!(
"\n
x.py setup creates a `config.toml` which changes the defaults for x.py itself.
Arguments:
This subcommand accepts a 'profile' to use for builds. For example:
./x.py setup library
The profile is optional and you will be prompted interactively if it is not given.",
);
The profile is optional and you will be prompted interactively if it is not given.
The following profiles are available:
{}",
Profile::all_for_help(" ").trim_end()
));
}
_ => {}
};
@ -551,9 +558,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, choice.purpose()).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,37 @@ pub fn setup(src_path: &Path, profile: Profile) {
// Used to get the path for `Subcommand::Setup`
pub fn interactive_path() -> io::Result<Profile> {
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"
);
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()
}
println!("Welcome to the Rust project! What do you want to do with x.py?");
for (letter, profile) in abbrev_all() {
println!("{}) {}: {}", letter, profile, 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()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
break match input.trim().to_lowercase().parse() {
if input == "" {
eprintln!("EOF on stdin, when expecting answer to question. Giving up.");
std::process::exit(1);
}
break match parse_with_abbrev(&input) {
Ok(profile) => profile,
Err(err) => {
println!("error: {}", err);