Auto merge of #5807 - dwijnand:cargo-list-summary, r=alexcrichton

Show the command summary when running cargo --list

Fixes #3726
This commit is contained in:
bors 2018-07-27 02:49:04 +00:00
commit dab09a065b
5 changed files with 64 additions and 17 deletions

View File

@ -69,14 +69,19 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
if args.is_present("list") {
println!("Installed Commands:");
for command in list_commands(config) {
let (command, path) = command;
if is_verbose {
match path {
Some(p) => println!(" {:<20} {}", command, p),
None => println!(" {:<20}", command),
match command {
CommandInfo::BuiltIn { name, about } => {
let summary = about.unwrap_or_default();
let summary = summary.lines().next().unwrap_or(&summary); // display only the first line
println!(" {:<20} {}", name, summary)
}
CommandInfo::External { name, path } => {
if is_verbose {
println!(" {:<20} {}", name, path.display())
} else {
println!(" {}", name)
}
}
} else {
println!(" {}", command);
}
}
return Ok(());

View File

@ -411,3 +411,18 @@ pub fn values(args: &ArgMatches, name: &str) -> Vec<String> {
.map(|s| s.to_string())
.collect()
}
#[derive(PartialEq, PartialOrd, Eq, Ord)]
pub enum CommandInfo {
BuiltIn { name: String, about: Option<String>, },
External { name: String, path: PathBuf },
}
impl CommandInfo {
pub fn name(&self) -> String {
match self {
CommandInfo::BuiltIn { name, .. } => name.to_string(),
CommandInfo::External { name, .. } => name.to_string(),
}
}
}

View File

@ -5,8 +5,11 @@ use cargo::print_json;
pub fn cli() -> App {
subcommand("read-manifest")
.about(
"Deprecated, use `cargo metadata --no-deps` instead.
Print a JSON representation of a Cargo.toml manifest.",
"\
Print a JSON representation of a Cargo.toml manifest.
Deprecated, use `cargo metadata --no-deps` instead.\
",
)
.arg_manifest_path()
}

View File

@ -26,6 +26,8 @@ mod cli;
mod command_prelude;
mod commands;
use command_prelude::*;
fn main() {
env_logger::init();
cargo::core::maybe_allow_nightly_features();
@ -81,7 +83,7 @@ fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<Str
}
/// List all runnable commands
fn list_commands(config: &Config) -> BTreeSet<(String, Option<String>)> {
fn list_commands(config: &Config) -> BTreeSet<CommandInfo> {
let prefix = "cargo-";
let suffix = env::consts::EXE_SUFFIX;
let mut commands = BTreeSet::new();
@ -101,16 +103,19 @@ fn list_commands(config: &Config) -> BTreeSet<(String, Option<String>)> {
}
if is_executable(entry.path()) {
let end = filename.len() - suffix.len();
commands.insert((
filename[prefix.len()..end].to_string(),
Some(path.display().to_string()),
));
commands.insert(CommandInfo::External {
name: filename[prefix.len()..end].to_string(),
path: path.clone(),
});
}
}
}
for cmd in commands::builtin() {
commands.insert((cmd.get_name().to_string(), None));
commands.insert(CommandInfo::BuiltIn {
name: cmd.get_name().to_string(),
about: cmd.p.meta.about.map(|s| s.to_string()),
});
}
commands
@ -121,7 +126,8 @@ fn find_closest(config: &Config, cmd: &str) -> Option<String> {
// Only consider candidates with a lev_distance of 3 or less so we don't
// suggest out-of-the-blue options.
cmds.into_iter()
.map(|(c, _)| (lev_distance(&c, cmd), c))
.map(|c| c.name())
.map(|c| (lev_distance(&c, cmd), c))
.filter(|&(d, _)| d < 4)
.min_by_key(|a| a.0)
.map(|slot| slot.1)

View File

@ -60,6 +60,24 @@ fn path() -> Vec<PathBuf> {
env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect()
}
#[test]
fn list_commands_with_descriptions() {
let p = project().build();
let output = p.cargo("--list").exec_with_output().unwrap();
let output = str::from_utf8(&output.stdout).unwrap();
assert!(
output.contains("\n build Compile a local package and all of its dependencies"),
"missing build, with description: {}",
output
);
// assert read-manifest prints the right one-line description followed by another command, indented.
assert!(
output.contains("\n read-manifest Print a JSON representation of a Cargo.toml manifest.\n "),
"missing build, with description: {}",
output
);
}
#[test]
fn list_command_looks_at_path() {
let proj = project().build();
@ -152,7 +170,7 @@ error: no such subcommand: `biuld`
cargo_process().arg("--list"),
execs()
.with_status(0)
.with_stdout_contains(" build\n")
.with_stdout_contains(" build Compile a local package and all of its dependencies\n")
.with_stdout_contains(" biuld\n"),
);
}