diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index 5902fad2973..f9599160003 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -3,12 +3,23 @@ use cargo::core::{features, CliUnstable}; use cargo::{self, drop_print, drop_println, CliResult, Config}; use clap::{AppSettings, Arg, ArgMatches}; use itertools::Itertools; +use std::collections::HashMap; use super::commands; use super::list_commands; use crate::command_prelude::*; use cargo::core::features::HIDDEN; +lazy_static::lazy_static! { + // Maps from commonly known external commands (not builtin to cargo) to their + // description, for the help page. Reserved for external subcommands that are + // core within the rust ecosystem (esp ones that might become internal in the future). + static ref KNOWN_EXTERNAL_COMMAND_DESCRIPTIONS: HashMap<&'static str, &'static str> = vec![ + ("clippy", "Checks a package to catch common mistakes and improve your Rust code."), + ("fmt", "Formats all bin and lib files of the current crate using rustfmt."), + ].into_iter().collect(); +} + pub fn main(config: &mut Config) -> CliResult { // CAUTION: Be careful with using `config` until it is configured below. // In general, try to avoid loading config values unless necessary (like @@ -100,14 +111,22 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'", if args.is_present("list") { drop_println!(config, "Installed Commands:"); for (name, command) in list_commands(config) { + let known_external_desc = KNOWN_EXTERNAL_COMMAND_DESCRIPTIONS.get(name.as_str()); match command { CommandInfo::BuiltIn { about } => { + assert!( + known_external_desc.is_none(), + "KNOWN_EXTERNAL_COMMANDS shouldn't contain builtin \"{}\"", + name + ); let summary = about.unwrap_or_default(); let summary = summary.lines().next().unwrap_or(&summary); // display only the first line drop_println!(config, " {:<20} {}", name, summary); } CommandInfo::External { path } => { - if is_verbose { + if let Some(desc) = known_external_desc { + drop_println!(config, " {:<20} {}", name, desc); + } else if is_verbose { drop_println!(config, " {:<20} {}", name, path.display()); } else { drop_println!(config, " {}", name); diff --git a/tests/testsuite/cargo_command.rs b/tests/testsuite/cargo_command.rs index ceaa4b12bd0..86e53ce757c 100644 --- a/tests/testsuite/cargo_command.rs +++ b/tests/testsuite/cargo_command.rs @@ -101,6 +101,31 @@ fn list_command_looks_at_path() { ); } +#[cargo_test] +fn list_command_handles_known_external_commands() { + let p = project() + .executable(Path::new("path-test").join("cargo-fmt"), "") + .build(); + + let fmt_desc = " fmt Formats all bin and lib files of the current crate using rustfmt."; + + // Without path - fmt isn't there + p.cargo("--list") + .env("PATH", "") + .with_stdout_does_not_contain(fmt_desc) + .run(); + + // With path - fmt is there with known description + let mut path = path(); + path.push(p.root().join("path-test")); + let path = env::join_paths(path.iter()).unwrap(); + + p.cargo("--list") + .env("PATH", &path) + .with_stdout_contains(fmt_desc) + .run(); +} + #[cargo_test] fn list_command_resolves_symlinks() { let proj = project()