Skip to content

Commit d500051

Browse files
committed
WIP: fix(cli): Make --help easier to browse
This mirrors some of the categories from `cargo help` (the man pages).
1 parent e2fbcd9 commit d500051

File tree

33 files changed

+545
-390
lines changed

33 files changed

+545
-390
lines changed

src/bin/cargo/commands/bench.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ pub fn cli() -> Command {
1616
.num_args(0..)
1717
.last(true),
1818
)
19+
.arg_package_spec(
20+
"Package to run benchmarks for",
21+
"Benchmark all packages in the workspace",
22+
"Exclude packages from the benchmark",
23+
)
24+
.arg_features()
1925
.arg_targets_all(
2026
"Benchmark only this package's library",
2127
"Benchmark only the specified binary",
@@ -29,14 +35,8 @@ pub fn cli() -> Command {
2935
"Benchmark all targets",
3036
)
3137
.arg(flag("no-run", "Compile, but don't run benchmarks"))
32-
.arg_package_spec(
33-
"Package to run benchmarks for",
34-
"Benchmark all packages in the workspace",
35-
"Exclude packages from the benchmark",
36-
)
3738
.arg_jobs()
3839
.arg_profile("Build artifacts with the specified profile")
39-
.arg_features()
4040
.arg_target_triple("Build for the target triple")
4141
.arg_target_dir()
4242
.arg_manifest_path()

src/bin/cargo/commands/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub fn cli() -> Command {
1313
"Build all packages in the workspace",
1414
"Exclude packages from the build",
1515
)
16+
.arg_features()
1617
.arg_jobs()
1718
.arg_targets_all(
1819
"Build only this package's library",
@@ -28,7 +29,6 @@ pub fn cli() -> Command {
2829
)
2930
.arg_release("Build artifacts in release mode, with optimizations")
3031
.arg_profile("Build artifacts with the specified profile")
31-
.arg_features()
3232
.arg_target_triple("Build for the target triple")
3333
.arg_target_dir()
3434
.arg(

src/bin/cargo/commands/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub fn cli() -> Command {
1313
"Check all packages in the workspace",
1414
"Exclude packages from the check",
1515
)
16+
.arg_features()
1617
.arg_jobs()
1718
.arg_targets_all(
1819
"Check only this package's library",
@@ -28,7 +29,6 @@ pub fn cli() -> Command {
2829
)
2930
.arg_release("Check artifacts in release mode, with optimizations")
3031
.arg_profile("Check artifacts with the specified profile")
31-
.arg_features()
3232
.arg_target_triple("Check for the target triple")
3333
.arg_target_dir()
3434
.arg_manifest_path()

src/bin/cargo/commands/doc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn cli() -> Command {
1717
"Document all packages in the workspace",
1818
"Exclude packages from the build",
1919
)
20+
.arg_features()
2021
.arg(flag(
2122
"no-deps",
2223
"Don't build documentation for dependencies",
@@ -32,7 +33,6 @@ pub fn cli() -> Command {
3233
)
3334
.arg_release("Build artifacts in release mode, with optimizations")
3435
.arg_profile("Build artifacts with the specified profile")
35-
.arg_features()
3636
.arg_target_triple("Build for the target triple")
3737
.arg_target_dir()
3838
.arg_manifest_path()

src/bin/cargo/commands/fix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub fn cli() -> Command {
1111
"Fix all packages in the workspace",
1212
"Exclude packages from the fixes",
1313
)
14+
.arg_features()
1415
.arg_jobs()
1516
.arg_targets_all(
1617
"Fix only this package's library",
@@ -26,7 +27,6 @@ pub fn cli() -> Command {
2627
)
2728
.arg_release("Fix artifacts in release mode, with optimizations")
2829
.arg_profile("Build artifacts with the specified profile")
29-
.arg_features()
3030
.arg_target_triple("Fix for the target triple")
3131
.arg_target_dir()
3232
.arg_manifest_path()

src/bin/cargo/commands/package.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ pub fn cli() -> Command {
2525
"allow-dirty",
2626
"Allow dirty working directories to be packaged",
2727
))
28-
.arg_target_triple("Build for the target triple")
29-
.arg_target_dir()
30-
.arg_features()
3128
.arg_package_spec_no_all(
3229
"Package(s) to assemble",
3330
"Assemble all packages in the workspace",
3431
"Don't assemble specified packages",
3532
)
33+
.arg_features()
34+
.arg_target_triple("Build for the target triple")
35+
.arg_target_dir()
3636
.arg_manifest_path()
3737
.arg_jobs()
3838
.after_help("Run `cargo help package` for more detailed information.\n")

src/bin/cargo/commands/run.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ pub fn cli() -> Command {
2727
"Name of the example target to run",
2828
)
2929
.arg_package("Package with the target to run")
30+
.arg_features()
3031
.arg_jobs()
3132
.arg_release("Build artifacts in release mode, with optimizations")
3233
.arg_profile("Build artifacts with the specified profile")
33-
.arg_features()
3434
.arg_target_triple("Build for the target triple")
3535
.arg_target_dir()
3636
.arg_manifest_path()

src/bin/cargo/commands/rustc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub fn cli() -> Command {
1616
.trailing_var_arg(true),
1717
)
1818
.arg_package("Package to build")
19+
.arg_features()
1920
.arg_jobs()
2021
.arg_targets_all(
2122
"Build only this package's library",
@@ -31,7 +32,6 @@ pub fn cli() -> Command {
3132
)
3233
.arg_release("Build artifacts in release mode, with optimizations")
3334
.arg_profile("Build artifacts with the specified profile")
34-
.arg_features()
3535
.arg_target_triple("Target triple which compiles will be for")
3636
.arg(
3737
opt(

src/bin/cargo/commands/rustdoc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn cli() -> Command {
1717
"Opens the docs in a browser after the operation",
1818
))
1919
.arg_package("Package to document")
20+
.arg_features()
2021
.arg_jobs()
2122
.arg_targets_all(
2223
"Build only this package's library",
@@ -32,7 +33,6 @@ pub fn cli() -> Command {
3233
)
3334
.arg_release("Build artifacts in release mode, with optimizations")
3435
.arg_profile("Build artifacts with the specified profile")
35-
.arg_features()
3636
.arg_target_triple("Build for the target triple")
3737
.arg_target_dir()
3838
.arg_manifest_path()

src/bin/cargo/commands/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ pub fn cli() -> Command {
4444
"Test all packages in the workspace",
4545
"Exclude packages from the test",
4646
)
47+
.arg_features()
4748
.arg_jobs()
4849
.arg_release("Build artifacts in release mode, with optimizations")
4950
.arg_profile("Build artifacts with the specified profile")
50-
.arg_features()
5151
.arg_target_triple("Build for the target triple")
5252
.arg_target_dir()
5353
.arg_manifest_path()

src/bin/cargo/commands/tree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ pub fn cli() -> Command {
1919
"Display the tree for all packages in the workspace",
2020
"Exclude specific workspace members",
2121
)
22+
.arg_features()
2223
.arg(
2324
flag("all", "Deprecated, use --no-dedupe instead")
2425
.short('a')
2526
.hide(true),
2627
)
2728
.arg(flag("all-targets", "Deprecated, use --target=all instead").hide(true))
28-
.arg_features()
2929
.arg_target_triple(
3030
"Filter dependencies matching the given target-triple (default host platform). \
3131
Pass `all` to include all targets.",

src/cargo/util/command_prelude.rs

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ pub use clap::Command;
2626

2727
use super::config::JobsConfig;
2828

29+
pub mod heading {
30+
pub const PACKAGE_SELECTION: &str = "Package Selection";
31+
pub const TARGET_SELECTION: &str = "Target Selection";
32+
pub const FEATURE_SELECTION: &str = "Feature Selection";
33+
pub const COMPILATION_OPTIONS: &str = "Compilation Options";
34+
}
35+
2936
pub trait CommandExt: Sized {
3037
fn _arg(self, arg: Arg) -> Self;
3138

@@ -37,8 +44,10 @@ pub trait CommandExt: Sized {
3744
all: &'static str,
3845
exclude: &'static str,
3946
) -> Self {
40-
self.arg_package_spec_no_all(package, all, exclude)
41-
._arg(flag("all", "Alias for --workspace (deprecated)"))
47+
self.arg_package_spec_no_all(package, all, exclude)._arg(
48+
flag("all", "Alias for --workspace (deprecated)")
49+
.help_heading(heading::PACKAGE_SELECTION),
50+
)
4251
}
4352

4453
/// Variant of arg_package_spec that does not include the `--all` flag
@@ -51,19 +60,24 @@ pub trait CommandExt: Sized {
5160
exclude: &'static str,
5261
) -> Self {
5362
self.arg_package_spec_simple(package)
54-
._arg(flag("workspace", all))
55-
._arg(multi_opt("exclude", "SPEC", exclude))
63+
._arg(flag("workspace", all).help_heading(heading::PACKAGE_SELECTION))
64+
._arg(multi_opt("exclude", "SPEC", exclude).help_heading(heading::PACKAGE_SELECTION))
5665
}
5766

5867
fn arg_package_spec_simple(self, package: &'static str) -> Self {
59-
self._arg(optional_multi_opt("package", "SPEC", package).short('p'))
68+
self._arg(
69+
optional_multi_opt("package", "SPEC", package)
70+
.short('p')
71+
.help_heading(heading::PACKAGE_SELECTION),
72+
)
6073
}
6174

6275
fn arg_package(self, package: &'static str) -> Self {
6376
self._arg(
6477
optional_opt("package", package)
6578
.short('p')
66-
.value_name("SPEC"),
79+
.value_name("SPEC")
80+
.help_heading(heading::PACKAGE_SELECTION),
6781
)
6882
}
6983

@@ -94,11 +108,13 @@ pub trait CommandExt: Sized {
94108
all: &'static str,
95109
) -> Self {
96110
self.arg_targets_lib_bin_example(lib, bin, bins, example, examples)
97-
._arg(flag("tests", tests))
98-
._arg(optional_multi_opt("test", "NAME", test))
99-
._arg(flag("benches", benches))
100-
._arg(optional_multi_opt("bench", "NAME", bench))
101-
._arg(flag("all-targets", all))
111+
._arg(flag("tests", tests).help_heading(heading::TARGET_SELECTION))
112+
._arg(optional_multi_opt("test", "NAME", test).help_heading(heading::TARGET_SELECTION))
113+
._arg(flag("benches", benches).help_heading(heading::TARGET_SELECTION))
114+
._arg(
115+
optional_multi_opt("bench", "NAME", bench).help_heading(heading::TARGET_SELECTION),
116+
)
117+
._arg(flag("all-targets", all).help_heading(heading::TARGET_SELECTION))
102118
}
103119

104120
fn arg_targets_lib_bin_example(
@@ -109,11 +125,14 @@ pub trait CommandExt: Sized {
109125
example: &'static str,
110126
examples: &'static str,
111127
) -> Self {
112-
self._arg(flag("lib", lib))
113-
._arg(flag("bins", bins))
114-
._arg(optional_multi_opt("bin", "NAME", bin))
115-
._arg(flag("examples", examples))
116-
._arg(optional_multi_opt("example", "NAME", example))
128+
self._arg(flag("lib", lib).help_heading(heading::TARGET_SELECTION))
129+
._arg(flag("bins", bins).help_heading(heading::TARGET_SELECTION))
130+
._arg(optional_multi_opt("bin", "NAME", bin).help_heading(heading::TARGET_SELECTION))
131+
._arg(flag("examples", examples).help_heading(heading::TARGET_SELECTION))
132+
._arg(
133+
optional_multi_opt("example", "NAME", example)
134+
.help_heading(heading::TARGET_SELECTION),
135+
)
117136
}
118137

119138
fn arg_targets_bins_examples(
@@ -123,15 +142,21 @@ pub trait CommandExt: Sized {
123142
example: &'static str,
124143
examples: &'static str,
125144
) -> Self {
126-
self._arg(optional_multi_opt("bin", "NAME", bin))
127-
._arg(flag("bins", bins))
128-
._arg(optional_multi_opt("example", "NAME", example))
129-
._arg(flag("examples", examples))
145+
self._arg(optional_multi_opt("bin", "NAME", bin).help_heading(heading::TARGET_SELECTION))
146+
._arg(flag("bins", bins).help_heading(heading::TARGET_SELECTION))
147+
._arg(
148+
optional_multi_opt("example", "NAME", example)
149+
.help_heading(heading::TARGET_SELECTION),
150+
)
151+
._arg(flag("examples", examples).help_heading(heading::TARGET_SELECTION))
130152
}
131153

132154
fn arg_targets_bin_example(self, bin: &'static str, example: &'static str) -> Self {
133-
self._arg(optional_multi_opt("bin", "NAME", bin))
134-
._arg(optional_multi_opt("example", "NAME", example))
155+
self._arg(optional_multi_opt("bin", "NAME", bin).help_heading(heading::TARGET_SELECTION))
156+
._arg(
157+
optional_multi_opt("example", "NAME", example)
158+
.help_heading(heading::TARGET_SELECTION),
159+
)
135160
}
136161

137162
fn arg_features(self) -> Self {
@@ -141,34 +166,51 @@ pub trait CommandExt: Sized {
141166
"FEATURES",
142167
"Space or comma separated list of features to activate",
143168
)
144-
.short('F'),
169+
.short('F')
170+
.help_heading(heading::FEATURE_SELECTION),
171+
)
172+
._arg(
173+
flag("all-features", "Activate all available features")
174+
.help_heading(heading::FEATURE_SELECTION),
175+
)
176+
._arg(
177+
flag(
178+
"no-default-features",
179+
"Do not activate the `default` feature",
180+
)
181+
.help_heading(heading::FEATURE_SELECTION),
145182
)
146-
._arg(flag("all-features", "Activate all available features"))
147-
._arg(flag(
148-
"no-default-features",
149-
"Do not activate the `default` feature",
150-
))
151183
}
152184

153185
fn arg_release(self, release: &'static str) -> Self {
154-
self._arg(flag("release", release).short('r'))
186+
self._arg(
187+
flag("release", release)
188+
.short('r')
189+
.help_heading(heading::COMPILATION_OPTIONS),
190+
)
155191
}
156192

157193
fn arg_profile(self, profile: &'static str) -> Self {
158-
self._arg(opt("profile", profile).value_name("PROFILE-NAME"))
194+
self._arg(
195+
opt("profile", profile)
196+
.value_name("PROFILE-NAME")
197+
.help_heading(heading::COMPILATION_OPTIONS),
198+
)
159199
}
160200

161201
fn arg_doc(self, doc: &'static str) -> Self {
162202
self._arg(flag("doc", doc))
163203
}
164204

165205
fn arg_target_triple(self, target: &'static str) -> Self {
166-
self._arg(multi_opt("target", "TRIPLE", target))
206+
self._arg(multi_opt("target", "TRIPLE", target).help_heading(heading::COMPILATION_OPTIONS))
167207
}
168208

169209
fn arg_target_dir(self) -> Self {
170210
self._arg(
171-
opt("target-dir", "Directory for all generated artifacts").value_name("DIRECTORY"),
211+
opt("target-dir", "Directory for all generated artifacts")
212+
.value_name("DIRECTORY")
213+
.help_heading(heading::COMPILATION_OPTIONS),
172214
)
173215
}
174216

tests/testsuite/cargo_add/help/stdout.log

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ Options:
4545
--manifest-path <PATH>
4646
Path to Cargo.toml
4747

48-
-p, --package [<SPEC>]
49-
Package to modify
50-
5148
-q, --quiet
5249
Do not print cargo log messages
5350

@@ -78,6 +75,10 @@ Options:
7875
-Z <FLAG>
7976
Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
8077

78+
Package Selection:
79+
-p, --package [<SPEC>]
80+
Package to modify
81+
8182
Source:
8283
--path <PATH>
8384
Filesystem path to local crate to add

0 commit comments

Comments
 (0)