diff --git a/docs/index.adoc b/docs/index.adoc index bbedd4c2..8efdda8c 100644 --- a/docs/index.adoc +++ b/docs/index.adoc @@ -589,7 +589,7 @@ The documentation for these tools shows further examples. ==== @-files Usage Help -From picocli 4.2, the @filename can be shown in the usage help of a command via the `@Command(showAtFileInUsageHelp=true)` attribute. +From picocli 4.2, an entry for `@` can be shown in the options and parameters list of the usage help message of a command with the `@Command(showAtFileInUsageHelp = true)` annotation. See <> for details. ==== Simplified Format @@ -3039,6 +3039,102 @@ Usage:
[...] files files to transfer ---- +=== Show At Files + +From picocli 4.2, an entry for `@` can be shown in the options and parameters list of the usage help message of a command with the `@Command(showAtFileInUsageHelp = true)` annotation. + +==== Example + +Example command: + +[source,java] +---- +@Command(name = "myapp", showAtFileInUsageHelp = true, + mixinStandardHelpOptions = true, description = "Example command.") +class MyApp { + @Parameters(description = "A file.") File file; +} +---- + +The usage help message for this command looks like this: + +---- +Usage: myapp [-hV] [@...] +Example command. + [@...] One or more argument files containing options. + A file. + -h, --help Show this help message and exit. + -V, --version Print version information and exit. +---- + +==== Changing the At File Entry Location + +By default, the `@` entry is shown before the positional parameters in the synopsis as well as in the parameters list. + +This can be changed with the <> for reordering sections. For example: + +[source,java] +---- +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_AT_FILE_PARAMETER; +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST_HEADING; +import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_OPTION_LIST_HEADING; + +@Command(name = "myapp", showAtFileInUsageHelp = true, + mixinStandardHelpOptions = true, description = "Example command.") +class MyApp { + @Parameters(description = "A file.") File file; + + public static void main(String... args) { + CommandLine cmd = new CommandLine(new MyApp()); + List copy = new ArrayList<>(cmd.getHelpSectionKeys()); + copy.remove(SECTION_KEY_AT_FILE_PARAMETER); + copy.add(copy.indexOf(SECTION_KEY_COMMAND_LIST_HEADING), SECTION_KEY_AT_FILE_PARAMETER); + cmd.setHelpSectionKeys(copy); + + cmd.usage(System.out); + } +} +---- + +The resulting usage help message shows the `@` entry has moved to the bottom, following the options list: + +---- +Usage: myapp [-hV] [@...] +Example command. + A file. + -h, --help Show this help message and exit. + -V, --version Print version information and exit. + [@...] One or more argument files containing options. +---- + +==== Changing the At File Entry Text + +The text of the `@` entry can be changed with the following <>: + +* `picocli.atfile.label` +* `picocli.atfile.description` + +By setting the above variables in either system properties, environment variables or the <> for a command, the text can be customized. + +For example, if we define these system properties: + +[source,java] +---- +System.setProperty("picocli.atfile.label", "my@@@@file"); +System.setProperty("picocli.atfile.description", "@files rock!"); +---- + +then the usage help for our above example changes to this: + +---- +Usage: myapp [-hV] [my@@@@file...] +Example command. + [my@@@@file...] @files rock! + A file. + -h, --help Show this help message and exit. + -V, --version Print version information and exit. +---- + === Show Default Values ==== `${DEFAULT-VALUE}` Variable From picocli 3.2, it is possible to embed the <> in the description for an option or positional parameter by @@ -3482,6 +3578,7 @@ Applications can add, remove or replace sections in this map. The `CommandLine:: . SECTION_KEY_DESCRIPTION_HEADING . SECTION_KEY_DESCRIPTION . SECTION_KEY_PARAMETER_LIST_HEADING +. SECTION_KEY_AT_FILE_PARAMETER . SECTION_KEY_PARAMETER_LIST . SECTION_KEY_OPTION_LIST_HEADING . SECTION_KEY_OPTION_LIST diff --git a/src/test/java/picocli/AtFileTest.java b/src/test/java/picocli/AtFileTest.java index 3f2ef676..bc0a20d7 100644 --- a/src/test/java/picocli/AtFileTest.java +++ b/src/test/java/picocli/AtFileTest.java @@ -1,13 +1,11 @@ package picocli; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.ProvideSystemProperty; import org.junit.contrib.java.lang.system.RestoreSystemProperties; import org.junit.contrib.java.lang.system.SystemErrRule; import org.junit.rules.TestRule; -import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; @@ -28,11 +26,9 @@ import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; -import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.ListResourceBundle; -import java.util.ResourceBundle; import java.util.Set; import static org.hamcrest.CoreMatchers.containsString; @@ -620,15 +616,18 @@ public class AtFileTest { @Test public void testShowAtFileInUsageHelpBasic() { - @Command(name = "A", mixinStandardHelpOptions = true, - showAtFileInUsageHelp = true, description = "... description ...") - class A { } + @Command(name = "myapp", mixinStandardHelpOptions = true, + showAtFileInUsageHelp = true, description = "Example command.") + class MyApp { + @Parameters(description = "A file.") File file; + } - String actual = new CommandLine(new A()).getUsageMessage(); + String actual = new CommandLine(new MyApp()).getUsageMessage(); String expected = String.format("" + - "Usage: A [-hV] [@...]%n" + - "... description ...%n" + + "Usage: myapp [-hV] [@...] %n" + + "Example command.%n" + " [@...] One or more argument files containing options.%n" + + " A file.%n" + " -h, --help Show this help message and exit.%n" + " -V, --version Print version information and exit.%n"); assertEquals(expected, actual); @@ -636,18 +635,21 @@ public class AtFileTest { @Test public void testShowAtFileInUsageHelpSystemProperties() { - @Command(name = "A", mixinStandardHelpOptions = true, - showAtFileInUsageHelp = true, description = "... description ...") - class A { } + @Command(name = "myapp", mixinStandardHelpOptions = true, + showAtFileInUsageHelp = true, description = "Example command.") + class MyApp { + @Parameters(description = "A file.") File file; + } System.setProperty("picocli.atfile.label", "my@@@@file"); System.setProperty("picocli.atfile.description", "@files rock!"); - String actual = new CommandLine(new A()).getUsageMessage(); + String actual = new CommandLine(new MyApp()).getUsageMessage(); String expected = String.format("" + - "Usage: A [-hV] [my@@@@file...]%n" + - "... description ...%n" + + "Usage: myapp [-hV] [my@@@@file...] %n" + + "Example command.%n" + " [my@@@@file...] @files rock!%n" + + " A file.%n" + " -h, --help Show this help message and exit.%n" + " -V, --version Print version information and exit.%n"); assertEquals(expected, actual); @@ -657,8 +659,8 @@ public class AtFileTest { protected Object[][] getContents() { return new Object[][] { {"picocli.atfile", "hi! I amd the @file description from a file"}, - {"@", "BUNDLE@FILE"}, // ignored... - {"my@@@@file", "OTHER@@@"}, // ignored... + {"picocli.atfile.label", "BUNDLE@FILE"}, + {"picocli.atfile.description", "BUNDLE @FILE DESCRIPTION"}, }; } } @@ -690,9 +692,9 @@ public class AtFileTest { String actual = new CommandLine(new A()).getUsageMessage(); String expected = String.format("" + - "Usage: A [-hV] [@...]%n" + + "Usage: A [-hV] [BUNDLE@FILE...]%n" + "... description ...%n" + - " [@...] hi! I amd the @file description from a file%n" + + " [BUNDLE@FILE...] hi! I amd the @file description from a file%n" + " -h, --help Show this help message and exit.%n" + " -V, --version Print version information and exit.%n"); assertEquals(expected, actual); @@ -709,7 +711,7 @@ public class AtFileTest { List helpSectionKeys = commandLine.getHelpSectionKeys(); List copy = new ArrayList(helpSectionKeys); copy.remove(SECTION_KEY_AT_FILE_PARAMETER); - copy.add(helpSectionKeys.indexOf(SECTION_KEY_COMMAND_LIST_HEADING), SECTION_KEY_AT_FILE_PARAMETER); + copy.add(copy.indexOf(SECTION_KEY_COMMAND_LIST_HEADING), SECTION_KEY_AT_FILE_PARAMETER); commandLine.setHelpSectionKeys(copy); String actual = commandLine.getUsageMessage(); @@ -721,6 +723,7 @@ public class AtFileTest { " [@...] One or more argument files containing options.%n" + ""); assertEquals(expected, actual); + commandLine.usage(System.out); } @Test