Skip to content

Commit

Permalink
feat(help): Add styling to help output
Browse files Browse the repository at this point in the history
Traditionally, cargo has disabled clap's styled output.  My assumed
reason is that cargo mixes custom help output with auto-generated and
you couldn't previously make it all styled.

Clap 4.2 allowed users to pass in strings styled using ANSI escape
codes, allowing us to pass in styled text that matches clap.  In clap
4.4.1, clap gained the ability for the user to override the style.

In this PR, I decided to use the new 4.4.1 feature to style clap's
output to match the rest of cargo's output.  Alternatively, we could use
a more subdue style that clap uses by default.
  • Loading branch information
epage committed Aug 28, 2023
1 parent df644c8 commit 3d0d622
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 27 deletions.
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Expand Up @@ -30,6 +30,7 @@ cargo-test-support = { path = "crates/cargo-test-support" }
cargo-util = { version = "0.2.6", path = "crates/cargo-util" }
cargo_metadata = "0.14.0"
clap = "4.4.1"
color-print = "0.3.4"
core-foundation = { version = "0.9.3", features = ["mac_os_10_7_support"] }
crates-io = { version = "0.39.0", path = "crates/crates-io" }
criterion = { version = "0.5.1", features = ["html_reports"] }
Expand Down Expand Up @@ -130,6 +131,7 @@ cargo-credential-libsecret.workspace = true
cargo-credential-macos-keychain.workspace = true
cargo-credential-wincred.workspace = true
cargo-util.workspace = true
color-print.workspace = true
clap = { workspace = true, features = ["wrap_help"] }
crates-io.workspace = true
curl = { workspace = true, features = ["http2"] }
Expand Down
63 changes: 37 additions & 26 deletions src/bin/cargo/cli.rs
Expand Up @@ -520,48 +520,59 @@ pub fn cli() -> Command {
} else {
"cargo [OPTIONS] [COMMAND]\n cargo [OPTIONS] -Zscript <MANIFEST_RS> [ARGS]..."
};

let styles = {
use clap::builder::styling::*;
Styles::styled()
.header(AnsiColor::Green.on_default() | Effects::BOLD)
.usage(AnsiColor::Green.on_default() | Effects::BOLD)
.literal(AnsiColor::Blue.on_default() | Effects::BOLD)
.placeholder(AnsiColor::Cyan.on_default())
.error(AnsiColor::Red.on_default())
.valid(AnsiColor::Blue.on_default() | Effects::BOLD)
.invalid(AnsiColor::Yellow.on_default())
};

Command::new("cargo")
// Subcommands all count their args' display order independently (from 0),
// which makes their args interspersed with global args. This puts global args last.
//
// We also want these to come before auto-generated `--help`
.next_display_order(800)
.allow_external_subcommands(true)
// Doesn't mix well with our list of common cargo commands. See clap-rs/clap#3108 for
// opening clap up to allow us to style our help template
.disable_colored_help(true)
.styles(styles)
// Provide a custom help subcommand for calling into man pages
.disable_help_subcommand(true)
.override_usage(usage)
.help_template(
.help_template(color_print::cstr!(
"\
Rust's package manager
Usage: {usage}
<green,bold>Usage:</> <blue,bold>{usage}</>
Options:
<green,bold>Options:</>
{options}
Some common cargo commands are (see all commands with --list):
build, b Compile the current package
check, c Analyze the current package and report errors, but don't build object files
clean Remove the target directory
doc, d Build this package's and its dependencies' documentation
new Create a new cargo package
init Create a new cargo package in an existing directory
add Add dependencies to a manifest file
remove Remove dependencies from a manifest file
run, r Run a binary or example of the local package
test, t Run the tests
bench Run the benchmarks
update Update dependencies listed in Cargo.lock
search Search registry for crates
publish Package and upload this package to the registry
install Install a Rust binary. Default location is $HOME/.cargo/bin
uninstall Uninstall a Rust binary
See 'cargo help <command>' for more information on a specific command.\n",
)
Some common cargo commands are (see all commands with '<blue,bold>--list</>'):
<blue,bold>build</>, <blue,bold>b</> Compile the current package
<blue,bold>check</>, <blue,bold>c</> Analyze the current package and report errors, but don't build object files
<blue,bold>clean</> Remove the target directory
<blue,bold>doc</>, <blue,bold>d</> Build this package's and its dependencies' documentation
<blue,bold>new</> Create a new cargo package
<blue,bold>init</> Create a new cargo package in an existing directory
<blue,bold>add</> Add dependencies to a manifest file
<blue,bold>remove</> Remove dependencies from a manifest file
<blue,bold>run</>, <blue,bold>r</> Run a binary or example of the local package
<blue,bold>test</>, <blue,bold>t</> Run the tests
<blue,bold>bench</> Run the benchmarks
<blue,bold>update</> Update dependencies listed in Cargo.lock
<blue,bold>search</> Search registry for crates
<blue,bold>publish</> Package and upload this package to the registry
<blue,bold>install</> Install a Rust binary. Default location is $HOME/.cargo/bin
<blue,bold>uninstall</> Uninstall a Rust binary
See '<blue,bold>cargo help <<command>></>' for more information on a specific command.\n",
))
.arg(flag("version", "Print version info and exit").short('V'))
.arg(flag("list", "List installed commands"))
.arg(opt("explain", "Run `rustc --explain CODE`").value_name("CODE"))
Expand Down
4 changes: 3 additions & 1 deletion src/bin/cargo/commands/run.rs
Expand Up @@ -38,7 +38,9 @@ pub fn cli() -> Command {
.arg_manifest_path()
.arg_unit_graph()
.arg_timings()
.after_help("Run `cargo help run` for more detailed information.\n")
.after_help(color_print::cstr!(
"Run `<blue,bold>cargo help run</>` for more detailed information.\n"
))
}

pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
Expand Down

0 comments on commit 3d0d622

Please sign in to comment.