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:
commit
c268cc0b4d
2 changed files with 66 additions and 21 deletions
|
@ -125,6 +125,7 @@ Subcommands:
|
||||||
dist Build distribution artifacts
|
dist Build distribution artifacts
|
||||||
install Install distribution artifacts
|
install Install distribution artifacts
|
||||||
run, r Run tools contained in this repository
|
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`",
|
To learn more about a subcommand, run `./x.py <subcommand> -h`",
|
||||||
);
|
);
|
||||||
|
@ -472,15 +473,21 @@ Arguments:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
"setup" => {
|
"setup" => {
|
||||||
subcommand_help.push_str(
|
subcommand_help.push_str(&format!(
|
||||||
"\n
|
"\n
|
||||||
|
x.py setup creates a `config.toml` which changes the defaults for x.py itself.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
This subcommand accepts a 'profile' to use for builds. For example:
|
This subcommand accepts a 'profile' to use for builds. For example:
|
||||||
|
|
||||||
./x.py setup library
|
./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| {
|
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 {
|
||||||
|
|
|
@ -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, choice.purpose()).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,37 @@ 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> {
|
||||||
let mut input = String::new();
|
fn abbrev_all() -> impl Iterator<Item = (String, Profile)> {
|
||||||
println!(
|
('a'..).map(|c| c.to_string()).zip(Profile::all())
|
||||||
"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
|
fn parse_with_abbrev(input: &str) -> Result<Profile, String> {
|
||||||
c) Contribute to the compiler, and also modify LLVM or codegen
|
let input = input.trim().to_lowercase();
|
||||||
d) Install Rust from source"
|
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 {
|
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()?;
|
||||||
|
let mut input = String::new();
|
||||||
io::stdin().read_line(&mut input)?;
|
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,
|
Ok(profile) => profile,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("error: {}", err);
|
println!("error: {}", err);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue