From a068d602d8475495f4d22d670c31d949e58ba19c Mon Sep 17 00:00:00 2001 From: Remko Popma Date: Mon, 14 Dec 2020 12:26:42 +0900 Subject: [PATCH] [#1265] DOC updates for `picocli-shell-jline3` enhancement --- RELEASE-NOTES.md | 2 + picocli-shell-jline3/README.md | 54 +++++++------------ .../picocli/shell/jline3/PicocliCommands.java | 7 ++- .../picocli/shell/jline3/example/Example.java | 3 ++ 4 files changed, 30 insertions(+), 36 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 604138ed3..80918893c 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -9,6 +9,7 @@ This release contains new features, bug fixes and other enhancements. ## Community Contributions * [Andreas Deininger](https://github.com/deining) has been contributing to the documentation and other areas for a while, but recently went into overdrive :-) and contributed many, many new pull requests to improve the documentation. The user manual and Quick Guide now have a "foldable" table of contents, and examples in tabs, with many additional examples in Kotlin, Scala and Groovy. A lot of work went into this! Many thanks, Andreas! +* [Sualeh Fatehi](https://github.com/sualeh) contributed a pull request to `picocli-shell-jline3` that adds a built-in `clear` command and improves the `help` command. * [Daniel Gray](https://github.com/danielthegray) contributed a bug fix to prevent incorrectly defaulting inherited positional params after a subcommand. * [nveeser-google](https://github.com/nveeser-google) contributed a fix for compiler warnings about `Annotation::getClass` and assignment in `if` condition. * [Petr Hála](https://github.com/pehala) contributed a pull request to add a section on Mocking to user manual. @@ -263,6 +264,7 @@ Attributes that are _not_ copied include: * [#1108] Enhancement: Support `Optional` type for options and positional parameters. Thanks to [Max Rydahl Andersen](https://github.com/maxandersen) for raising this. * [#1214] Enhancement: Support Map options with key-only (support `-Dkey` as well as `-Dkey=value`). Thanks to [Max Rydahl Andersen](https://github.com/maxandersen) and [David Walluck](https://github.com/dwalluck) for raising this and subsequent discussion. * [#1260] Enhancement: Support `@Spec`-annotated members in `ArgGroup` classes. Thanks to [Jannick Hemelhof](https://github.com/clone1612) for raising this. +* [#1265] Enhancement in `picocli-shell-jline3`: add built-in `clear` command and improve `help` command. Thanks to [Sualeh Fatehi](https://github.com/sualeh) for the pull request. * [#1236] Enhancement/bugfix: Fix compiler warnings about `Annotation::getClass` and assignment in `if` condition. Thanks to [nveeser-google](https://github.com/nveeser-google) for the pull request. * [#1229] Bugfix: Fix compilation error introduced with fc5ef6de6 (#1184). Thanks to [Andreas Deininger](https://github.com/deining) for the pull request. * [#1225] Bugfix: Error message for unmatched positional argument reports incorrect index when value equals a previously matched argument. Thanks to [Vitaly Shukela](https://github.com/vi) for raising this. diff --git a/picocli-shell-jline3/README.md b/picocli-shell-jline3/README.md index 3304f6587..7c8f0a852 100644 --- a/picocli-shell-jline3/README.md +++ b/picocli-shell-jline3/README.md @@ -107,17 +107,20 @@ import picocli.CommandLine.Command; import picocli.CommandLine.Option; import picocli.CommandLine.ParentCommand; import picocli.shell.jline3.PicocliCommands; +import picocli.shell.jline3.PicocliCommands.PicocliCommandsFactory; -import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; /** * Example that demonstrates how to build an interactive shell with JLine3 and picocli. * This example requires JLine 3.16+ and picocli 4.4+. + *

+ * The {@code PicocliCommands.ClearScreen} was introduced in picocli 4.6. + *

*/ public class Example { @@ -128,22 +131,16 @@ public class Example { description = { "Example interactive shell with completion and autosuggestions. " + "Hit @|magenta |@ to see available commands.", - "Hit @|magenta ALT-S|@ to toggle tailtips.", + "Hit @|magenta ALT-S|@ to toggle tailtips.", ""}, footer = {"", "Press Ctl-D to exit."}, subcommands = { - MyCommand.class, ClearScreen.class, CommandLine.HelpCommand.class}) + MyCommand.class, PicocliCommands.ClearScreen.class, CommandLine.HelpCommand.class}) static class CliCommands implements Runnable { - LineReaderImpl reader; PrintWriter out; CliCommands() {} - public void setReader(LineReader reader){ - this.reader = (LineReaderImpl)reader; - out = reader.getTerminal().writer(); - } - public void run() { out.println(new CommandLine(this).getUsageMessage()); } @@ -218,42 +215,31 @@ public class Example { } } - /** - * Command that clears the screen. - */ - @Command(name = "cls", aliases = "clear", mixinStandardHelpOptions = true, - description = "Clears the screen", version = "1.0") - static class ClearScreen implements Callable { - - @ParentCommand CliCommands parent; - - public Void call() throws IOException { - parent.reader.clearScreen(); - return null; - } - } - - private static Path workDir() { - return Paths.get(System.getProperty("user.dir")); - } - public static void main(String[] args) { AnsiConsole.systemInstall(); try { + Supplier workDir = () -> Paths.get(System.getProperty("user.dir")); // set up JLine built-in commands - Builtins builtins = new Builtins(Example::workDir, null, null); + Builtins builtins = new Builtins(workDir, null, null); builtins.rename(Builtins.Command.TTOP, "top"); builtins.alias("zle", "widget"); builtins.alias("bindkey", "keymap"); // set up picocli commands CliCommands commands = new CliCommands(); - CommandLine cmd = new CommandLine(commands); - PicocliCommands picocliCommands = new PicocliCommands(Example::workDir, cmd); + + PicocliCommandsFactory factory = new PicocliCommandsFactory(); + // Or, if you have your own factory, you can chain them like this: + // MyCustomFactory customFactory = createCustomFactory(); // your application custom factory + // PicocliCommandsFactory factory = new PicocliCommandsFactory(customFactory); // chain the factories + + CommandLine cmd = new CommandLine(commands, factory); + PicocliCommands picocliCommands = new PicocliCommands(cmd); Parser parser = new DefaultParser(); try (Terminal terminal = TerminalBuilder.builder().build()) { - SystemRegistry systemRegistry = new SystemRegistryImpl(parser, terminal, Example::workDir, null); + SystemRegistry systemRegistry = new SystemRegistryImpl(parser, terminal, workDir, null); systemRegistry.setCommandRegistries(builtins, picocliCommands); + systemRegistry.register("help", picocliCommands); LineReader reader = LineReaderBuilder.builder() .terminal(terminal) @@ -262,7 +248,7 @@ public class Example { .variable(LineReader.LIST_MAX, 50) // max tab completion candidates .build(); builtins.setLineReader(reader); - commands.setReader(reader); + factory.setTerminal(terminal); TailTipWidgets widgets = new TailTipWidgets(reader, systemRegistry::commandDescription, 5, TailTipWidgets.TipType.COMPLETER); widgets.enable(); KeyMap keyMap = reader.getKeyMaps().get("main"); diff --git a/picocli-shell-jline3/src/main/java/picocli/shell/jline3/PicocliCommands.java b/picocli-shell-jline3/src/main/java/picocli/shell/jline3/PicocliCommands.java index f3aaafa47..bfb6c5060 100644 --- a/picocli-shell-jline3/src/main/java/picocli/shell/jline3/PicocliCommands.java +++ b/picocli-shell-jline3/src/main/java/picocli/shell/jline3/PicocliCommands.java @@ -49,6 +49,9 @@ public class PicocliCommands implements CommandRegistry { * To accomplish this, construct the {@code CommandLine} with a {@code PicocliCommandsFactory}, * and set the {@code Terminal} on that factory. For example: *
+     * @Command(subcommands = PicocliCommands.ClearScreen.class)
+     * class MyApp //...
+     *
      * PicocliCommandsFactory factory = new PicocliCommandsFactory();
      * CommandLine cmd = new CommandLine(new MyApp(), factory);
      * // create terminal
@@ -73,7 +76,7 @@ public Void call() throws IOException {
 
     /**
      * Command factory that is necessary for applications that want the use the {@code ClearScreen} subcommand.
-     * It allows chaining (or delegating) to a custom factory.
+     * It can be chained with other factories.
      * 

* WARNING: If the application uses the {@code ClearScreen} subcommand, construct the {@code CommandLine} * with a {@code PicocliCommandsFactory}, and set the {@code Terminal} on that factory. Applications need @@ -88,7 +91,7 @@ public Void call() throws IOException { * factory.setTerminal(terminal); *

* - * Custom factories can be chained by passing them in to the constructor like this: + * Other factories can be chained by passing them in to the constructor like this: *
      * MyCustomFactory customFactory = createCustomFactory(); // your application custom factory
      * PicocliCommandsFactory factory = new PicocliCommandsFactory(customFactory); // chain the factories
diff --git a/picocli-shell-jline3/src/test/java/picocli/shell/jline3/example/Example.java b/picocli-shell-jline3/src/test/java/picocli/shell/jline3/example/Example.java
index 0ab01f2c8..4f83e05c3 100644
--- a/picocli-shell-jline3/src/test/java/picocli/shell/jline3/example/Example.java
+++ b/picocli-shell-jline3/src/test/java/picocli/shell/jline3/example/Example.java
@@ -28,6 +28,9 @@
 /**
  * Example that demonstrates how to build an interactive shell with JLine3 and picocli.
  * This example requires JLine 3.16+ and picocli 4.4+.
+ * 

+ * The {@code PicocliCommands.ClearScreen} was introduced in picocli 4.6. + *

*/ public class Example {