diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index cfa0a3a66da..d50c11673ea 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -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(()); diff --git a/src/bin/cargo/command_prelude.rs b/src/bin/cargo/command_prelude.rs index fa49bea8639..e40619b300e 100644 --- a/src/bin/cargo/command_prelude.rs +++ b/src/bin/cargo/command_prelude.rs @@ -411,3 +411,18 @@ pub fn values(args: &ArgMatches, name: &str) -> Vec { .map(|s| s.to_string()) .collect() } + +#[derive(PartialEq, PartialOrd, Eq, Ord)] +pub enum CommandInfo { + BuiltIn { name: String, about: Option, }, + 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(), + } + } +} diff --git a/src/bin/cargo/commands/read_manifest.rs b/src/bin/cargo/commands/read_manifest.rs index 1e54c79e87f..300bfe9c952 100644 --- a/src/bin/cargo/commands/read_manifest.rs +++ b/src/bin/cargo/commands/read_manifest.rs @@ -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() } diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index 76efc09094c..18643a97e22 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -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 BTreeSet<(String, Option)> { +fn list_commands(config: &Config) -> BTreeSet { 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)> { } 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 { // 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) diff --git a/tests/testsuite/cargo_command.rs b/tests/testsuite/cargo_command.rs index a754eeefe47..646200a76c3 100644 --- a/tests/testsuite/cargo_command.rs +++ b/tests/testsuite/cargo_command.rs @@ -60,6 +60,24 @@ fn path() -> Vec { 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"), ); }