From 2f6de1c43618ecdd0b7a1478b3641b6a453309f8 Mon Sep 17 00:00:00 2001 From: Brian Demers Date: Thu, 21 May 2020 14:14:36 -0400 Subject: [PATCH 1/6] Excludes hidden options, params, and subcommands from man page generation Fixes: #1063 --- .../docgen/manpage/ManPageGenerator.java | 33 +++++++--- .../docgen/manpage/ManPageGeneratorTest.java | 51 ++++++++++++++-- .../test/resources/testHidden.manpage.adoc | 60 +++++++++++++++++++ 3 files changed, 133 insertions(+), 11 deletions(-) create mode 100644 picocli-codegen/src/test/resources/testHidden.manpage.adoc diff --git a/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java b/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java index ad3ec9471..c9837dcea 100644 --- a/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java +++ b/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java @@ -193,7 +193,7 @@ static int generateManPage(Config config, CommandSpec... specs) throws IOExcepti // recursively create man pages for subcommands for (CommandLine sub : spec.subcommands().values()) { CommandSpec subSpec = sub.getCommandSpec(); - if (done.contains(subSpec)) {continue;} + if (done.contains(subSpec) || subSpec.usageMessage().hidden()) {continue;} done.add(subSpec); result = generateManPage(config, subSpec); if (result != CommandLine.ExitCode.OK) { @@ -381,6 +381,14 @@ static void genOptions(PrintWriter pw, CommandSpec spec) { IParameterRenderer parameterRenderer = spec.commandLine().getHelp().createDefaultParameterRenderer(); List options = new ArrayList(spec.options()); // options are stored in order of declaration + + // remove hidden options + for (Iterator iter = options.iterator(); iter.hasNext();) { + if (iter.next().hidden()) { + iter.remove(); + } + } + List groups = optionListGroups(spec); for (ArgGroupSpec group : groups) { options.removeAll(group.options()); } @@ -441,12 +449,14 @@ private static void writeOption(PrintWriter pw, IOptionRenderer optionRenderer, } private static void writePositional(PrintWriter pw, PositionalParamSpec positional, IParameterRenderer parameterRenderer, IParamLabelRenderer paramLabelRenderer) { - pw.println(); - Text[][] rows = parameterRenderer.render(positional, paramLabelRenderer, COLOR_SCHEME); - pw.printf("%s::%n", join(", ", rows[0][1], rows[0][3])); - pw.printf(" %s%n", rows[0][4]); - for (int i = 1; i < rows.length; i++) { - pw.printf("+%n%s%n", rows[i][4]); + if (!positional.hidden()) { + pw.println(); + Text[][] rows = parameterRenderer.render(positional, paramLabelRenderer, COLOR_SCHEME); + pw.printf("%s::%n", join(", ", rows[0][1], rows[0][3])); + pw.printf(" %s%n", rows[0][4]); + for (int i = 1; i < rows.length; i++) { + pw.printf("+%n%s%n", rows[i][4]); + } } } @@ -481,6 +491,15 @@ static void genPositionalArgs(PrintWriter pw, CommandSpec spec) { } static void genCommands(PrintWriter pw, CommandSpec spec) { + + // remove hidden subcommands + Map subCommands = new LinkedHashMap(spec.subcommands()); + for (Iterator> iter = subCommands.entrySet().iterator(); iter.hasNext();) { + if (iter.next().getValue().getCommandSpec().usageMessage().hidden()) { + iter.remove(); + } + } + if (spec.subcommands().isEmpty()) { return; } diff --git a/picocli-codegen/src/test/java/picocli/codegen/docgen/manpage/ManPageGeneratorTest.java b/picocli-codegen/src/test/java/picocli/codegen/docgen/manpage/ManPageGeneratorTest.java index afd979399..c6ff29900 100644 --- a/picocli-codegen/src/test/java/picocli/codegen/docgen/manpage/ManPageGeneratorTest.java +++ b/picocli-codegen/src/test/java/picocli/codegen/docgen/manpage/ManPageGeneratorTest.java @@ -21,10 +21,6 @@ public class ManPageGeneratorTest { - @Test - public void main() { - } - @Test public void generateManPage() throws IOException { @Command(name = "myapp", mixinStandardHelpOptions = true, @@ -153,6 +149,53 @@ public void setVerbosity(boolean[] verbosity) { assertEquals(expected, sw.toString()); } + @Test + public void testHidden() throws IOException { + + @Command(name = "a-sub", mixinStandardHelpOptions = true, description = "A sub command") + class ASubCommand { + @Option(names = "input-a") + String inputA; + } + + @Command(name = "hidden-sub", mixinStandardHelpOptions = true, hidden = true) + class HiddenSubCommand { + @Option(names = "input-b") + String inputB; + } + + @Command(name = "testHidden", mixinStandardHelpOptions = true, + version = { + "Versioned Command 1.0", + "Picocli " + picocli.CommandLine.VERSION, + "JVM: ${java.version} (${java.vendor} ${java.vm.name} ${java.vm.version})", + "OS: ${os.name} ${os.version} ${os.arch}"}, + description = "This app does great things.", + subcommands = { ASubCommand.class, HiddenSubCommand.class } + + ) + class MyApp { + @Option(names = {"-o", "--output"}, description = "Output location full path.") + File outputFolder; + + @Option(names = {"--hidden-test"}, hidden = true) + File hidden; + + @Parameters(hidden = true) + List values; + } + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); //System.out, true + ManPageGenerator.writeSingleManPage(pw, new CommandLine(new MyApp()).getCommandSpec()); + pw.flush(); + + String expected = read("/testHidden.manpage.adoc"); + expected = expected.replace("\r\n", "\n"); + expected = expected.replace("\n", System.getProperty("line.separator")); + assertEquals(expected, sw.toString()); + } + private String read(String resource) throws IOException { return readAndClose(getClass().getResourceAsStream(resource)); } diff --git a/picocli-codegen/src/test/resources/testHidden.manpage.adoc b/picocli-codegen/src/test/resources/testHidden.manpage.adoc new file mode 100644 index 000000000..1042cb7e0 --- /dev/null +++ b/picocli-codegen/src/test/resources/testHidden.manpage.adoc @@ -0,0 +1,60 @@ +// tag::picocli-generated-full-manpage[] +// tag::picocli-generated-man-section-header[] +:doctype: manpage +:revnumber: Versioned Command 1.0 +:manmanual: TestHidden Manual +:mansource: Versioned Command 1.0 +:man-linkstyle: pass:[blue R < >] += testHidden(1) + +// end::picocli-generated-man-section-header[] + +// tag::picocli-generated-man-section-name[] +== Name + +testHidden - This app does great things. + +// end::picocli-generated-man-section-name[] + +// tag::picocli-generated-man-section-synopsis[] +== Synopsis + +*testHidden* [*-hV*] [*-o*=__] [COMMAND] + +// end::picocli-generated-man-section-synopsis[] + +// tag::picocli-generated-man-section-description[] +== Description + +This app does great things. + +// end::picocli-generated-man-section-description[] + +// tag::picocli-generated-man-section-options[] +== Options + +*-h*, *--help*:: + Show this help message and exit. + +*-o*, *--output*=__:: + Output location full path. + +*-V*, *--version*:: + Print version information and exit. + +// end::picocli-generated-man-section-options[] + +// tag::picocli-generated-man-section-arguments[] +== Arguments + +// end::picocli-generated-man-section-arguments[] + +// tag::picocli-generated-man-section-commands[] +== Commands + +*a-sub*:: + A sub command + +// end::picocli-generated-man-section-commands[] + +// end::picocli-generated-full-manpage[] From 245ef7fa8e7985d307367c5d7b94aef47405c949 Mon Sep 17 00:00:00 2001 From: Brian Demers Date: Tue, 26 May 2020 12:19:02 -0400 Subject: [PATCH 2/6] Move option.hidden logic to writeOption method --- .../docgen/manpage/ManPageGenerator.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java b/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java index c9837dcea..dad5eeb85 100644 --- a/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java +++ b/picocli-codegen/src/main/java/picocli/codegen/docgen/manpage/ManPageGenerator.java @@ -381,14 +381,6 @@ static void genOptions(PrintWriter pw, CommandSpec spec) { IParameterRenderer parameterRenderer = spec.commandLine().getHelp().createDefaultParameterRenderer(); List options = new ArrayList(spec.options()); // options are stored in order of declaration - - // remove hidden options - for (Iterator iter = options.iterator(); iter.hasNext();) { - if (iter.next().hidden()) { - iter.remove(); - } - } - List groups = optionListGroups(spec); for (ArgGroupSpec group : groups) { options.removeAll(group.options()); } @@ -439,12 +431,14 @@ private static void optionListGroups(List groups, List