Skip to content

Commit 24dfa0d

Browse files
fix(clap_mangen): Take into consideration display_order
In #3362 we have an issue where when we configure an arg via .display_order(int), and then generate a manpage, the synposis and options will render the order the args were provided to the App rather than the order they were configured e.g Command::new(name) arg(Arg::new("few").short('b').display_order(2)) arg(Arg::new("bar").short('a').display_order(1)) will show ... SYNOPSIS <name> [-b] [-a] ... ... OPTIONS -b -a instead of ... SYNOPSIS <name> [-a] [-b] ... ... OPTIONS -a -b and so on. This fix adds sorting in the synopsis and options functions responsible for generating the corresponding synopsis and options sections of the manpage. Co-authored-by: ericgumba <ericgumba@gmail.com>
1 parent ef3f77d commit 24dfa0d

File tree

3 files changed

+43
-13
lines changed

3 files changed

+43
-13
lines changed

clap_mangen/src/render.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) {
3333
let name = cmd.get_bin_name().unwrap_or_else(|| cmd.get_name());
3434
let mut line = vec![bold(name), roman(" ")];
3535

36-
for opt in cmd.get_arguments().filter(|i| !i.is_hide_set()) {
36+
let mut opts: Vec<_> = cmd.get_arguments().filter(|i| !i.is_hide_set()).collect();
37+
38+
opts.sort_by_key(|opt| option_sort_key(opt));
39+
40+
for opt in opts {
3741
let (lhs, rhs) = option_markers(opt);
3842
match (opt.get_short(), opt.get_long()) {
3943
(Some(short), Some(long)) => {
@@ -89,7 +93,10 @@ pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) {
8993
}
9094

9195
pub(crate) fn options(roff: &mut Roff, items: &[&Arg]) {
92-
for opt in items.iter().filter(|a| !a.is_positional()) {
96+
let mut sorted_items = items.to_vec();
97+
sorted_items.sort_by_key(|opt| option_sort_key(opt));
98+
99+
for opt in sorted_items.iter().filter(|a| !a.is_positional()) {
93100
let mut header = match (opt.get_short(), opt.get_long()) {
94101
(Some(short), Some(long)) => {
95102
vec![short_option(short), roman(", "), long_option(long)]
@@ -217,7 +224,10 @@ fn possible_options(roff: &mut Roff, arg: &Arg, arg_help_written: bool) {
217224
}
218225

219226
pub(crate) fn subcommands(roff: &mut Roff, cmd: &clap::Command, section: &str) {
220-
for sub in cmd.get_subcommands().filter(|s| !s.is_hide_set()) {
227+
let mut sorted_subcommands: Vec<_> =
228+
cmd.get_subcommands().filter(|s| !s.is_hide_set()).collect();
229+
sorted_subcommands.sort_by_key(|c| subcommand_sort_key(c));
230+
for sub in sorted_subcommands {
221231
roff.control("TP", []);
222232

223233
let name = format!(
@@ -378,3 +388,23 @@ fn format_possible_values(possibles: &Vec<&clap::builder::PossibleValue>) -> (Ve
378388
}
379389
(lines, with_help)
380390
}
391+
392+
fn subcommand_sort_key(command: &clap::Command) -> (usize, &str) {
393+
(command.get_display_order(), command.get_name())
394+
}
395+
396+
/// Note that this function is duplicated from `clap::builder`
397+
fn option_sort_key(arg: &Arg) -> (usize, String) {
398+
let key = if let Some(x) = arg.get_short() {
399+
let mut s = x.to_ascii_lowercase().to_string();
400+
s.push(if x.is_ascii_lowercase() { '0' } else { '1' });
401+
s
402+
} else if let Some(x) = arg.get_long() {
403+
x.to_string()
404+
} else {
405+
let mut s = '{'.to_string();
406+
s.push_str(arg.get_id().as_str());
407+
s
408+
};
409+
(arg.get_display_order(), key)
410+
}

clap_mangen/tests/snapshots/configured_display_order_args.roff

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44
.SH NAME
55
my\-app
66
.SH SYNOPSIS
7-
\fBmy\-app\fR [\fB\-Q\fR|\fB\-\-third\fR] [\fB\-\-fourth\fR] [\fB\-O\fR|\fB\-\-first\fR] [\fB\-P\fR|\fB\-\-second\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fI1st\fR] [\fI2nd\fR] [\fI3rd\fR]
7+
\fBmy\-app\fR [\fB\-O\fR|\fB\-\-first\fR] [\fB\-P\fR|\fB\-\-second\fR] [\fB\-Q\fR|\fB\-\-third\fR] [\fB\-\-fourth\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fI1st\fR] [\fI2nd\fR] [\fI3rd\fR]
88
.SH DESCRIPTION
99
.SH OPTIONS
1010
.TP
11-
\fB\-Q\fR, \fB\-\-third\fR
12-
Should be 3rd
13-
.TP
14-
\fB\-\-fourth\fR
15-
Should be 4th
16-
.TP
1711
\fB\-O\fR, \fB\-\-first\fR
1812
Should be 1st
1913
.TP
2014
\fB\-P\fR, \fB\-\-second\fR
2115
Should be 2nd
2216
.TP
17+
\fB\-Q\fR, \fB\-\-third\fR
18+
Should be 3rd
19+
.TP
20+
\fB\-\-fourth\fR
21+
Should be 4th
22+
.TP
2323
\fB\-h\fR, \fB\-\-help\fR
2424
Print help
2525
.TP

clap_mangen/tests/snapshots/configured_subcmd_order.roff

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ Print help
1515
Print version
1616
.SH SUBCOMMANDS
1717
.TP
18-
my\-app\-b1(1)
19-
blah b1
20-
.TP
2118
my\-app\-a1(1)
2219
blah a1
2320
.TP
21+
my\-app\-b1(1)
22+
blah b1
23+
.TP
2424
my\-app\-help(1)
2525
Print this message or the help of the given subcommand(s)
2626
.SH VERSION

0 commit comments

Comments
 (0)