From 4b176af4c99e1b70bea8c095adfb4bc79c80babb Mon Sep 17 00:00:00 2001 From: 0xadk <0xadk@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:28:10 -0800 Subject: [PATCH] feat(mangen): split OPTIONS into OPTIONS and GLOBAL OPTIONS --- clap_mangen/src/lib.rs | 28 ++++++++++++++++++--- clap_mangen/src/render.rs | 22 ++++++++++++---- clap_mangen/tests/snapshots/basic.bash.roff | 7 +++--- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/clap_mangen/src/lib.rs b/clap_mangen/src/lib.rs index 7b8d8af7900..185f27e8d58 100644 --- a/clap_mangen/src/lib.rs +++ b/clap_mangen/src/lib.rs @@ -159,6 +159,10 @@ impl Man { self._render_options_section(&mut roff); } + if app_has_global_arguments(&self.cmd) { + self._render_global_options_section(&mut roff); + } + if app_has_subcommands(&self.cmd) { self._render_subcommands_section(&mut roff); } @@ -245,7 +249,18 @@ impl Man { fn _render_options_section(&self, roff: &mut Roff) { roff.control("SH", ["OPTIONS"]); - render::options(roff, &self.cmd); + + let is_not_global = |arg: &clap::Arg| !arg.is_global_set(); + render::options(roff, &self.cmd, is_not_global); + render::options_postional(roff, &self.cmd, is_not_global); + } + + fn _render_global_options_section(&self, roff: &mut Roff) { + roff.control("SH", ["GLOBAL OPTIONS"]); + + let is_global = |arg: &clap::Arg| arg.is_global_set(); + render::options(roff, &self.cmd, is_global); + render::options_postional(roff, &self.cmd, is_global); } /// Render the SUBCOMMANDS section into the writer. @@ -307,9 +322,16 @@ fn app_has_version(cmd: &clap::Command) -> bool { .is_some() } -// Does the application have any command line arguments? +// Does the application have any non-global command line arguments? fn app_has_arguments(cmd: &clap::Command) -> bool { - cmd.get_arguments().any(|i| !i.is_hide_set()) + cmd.get_arguments() + .any(|i| !i.is_hide_set() && !i.is_global_set()) +} + +// Does the application have any global command line arguments? +fn app_has_global_arguments(cmd: &clap::Command) -> bool { + cmd.get_arguments() + .any(|i| !i.is_hide_set() && i.is_global_set()) } // Does the application have any subcommands? diff --git a/clap_mangen/src/render.rs b/clap_mangen/src/render.rs index 81d4e8c6b1c..eb66e16eaee 100644 --- a/clap_mangen/src/render.rs +++ b/clap_mangen/src/render.rs @@ -88,10 +88,12 @@ pub(crate) fn synopsis(roff: &mut Roff, cmd: &clap::Command) { roff.text(line); } -pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) { - let items: Vec<_> = cmd.get_arguments().filter(|i| !i.is_hide_set()).collect(); - - for opt in items.iter().filter(|a| !a.is_positional()) { +pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command, mut filter: impl FnMut(&Arg) -> bool) { + for opt in cmd + .get_arguments() + .filter(|i| !i.is_hide_set() && !i.is_positional()) + .filter(|&arg| filter(arg)) + { let mut header = match (opt.get_short(), opt.get_long()) { (Some(short), Some(long)) => { vec![short_option(short), roman(", "), long_option(long)] @@ -132,8 +134,18 @@ pub(crate) fn options(roff: &mut Roff, cmd: &clap::Command) { roff.control("RE", []); } } +} - for pos in items.iter().filter(|a| a.is_positional()) { +pub(crate) fn options_postional( + roff: &mut Roff, + cmd: &clap::Command, + mut filter: impl FnMut(&Arg) -> bool, +) { + for pos in cmd + .get_arguments() + .filter(|i| !i.is_hide_set() && i.is_positional()) + .filter(|&arg| filter(arg)) + { let mut header = vec![]; let (lhs, rhs) = option_markers(pos); header.push(roman(lhs)); diff --git a/clap_mangen/tests/snapshots/basic.bash.roff b/clap_mangen/tests/snapshots/basic.bash.roff index e9ab64a9d6f..32ff365721c 100644 --- a/clap_mangen/tests/snapshots/basic.bash.roff +++ b/clap_mangen/tests/snapshots/basic.bash.roff @@ -7,15 +7,16 @@ my\-app \fBmy\-app\fR [\fB\-c \fR] [\fB\-v \fR] [\fB\-h\fR|\fB\-\-help\fR] [\fIsubcommands\fR] .SH DESCRIPTION .SH OPTIONS -.TP -\fB\-c\fR - .TP \fB\-v\fR .TP \fB\-h\fR, \fB\-\-help\fR Print help +.SH "GLOBAL OPTIONS" +.TP +\fB\-c\fR + .SH SUBCOMMANDS .TP my\-app\-test(1)