diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 59118678e..60b20a363 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -26,6 +26,7 @@ Picocli follows [semantic versioning](http://semver.org/). * [#1304] DOC: Manual, chapter '17.9 Inherited Command Attributes': added Kotlin version of code sample. Thanks to [Andreas Deininger](https://github.com/deining) for the pull request. * [#1305] DOC: Document use of `IParameterConsumer` as n-ary type converter. Thanks to [Martin](https://github.com/martlin2cz) for raising this. * [#1307] DOC: Added CAUTION admonitions, Kotlin code sample. Thanks to [Andreas Deininger](https://github.com/deining) for the pull request. +* [#1308] DOC: Add example for Option `converter`. ## Deprecations No features were deprecated in this release. diff --git a/docs/index.html b/docs/index.html index 57d79561e..3fc50436f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3629,41 +3629,46 @@

-

Custom type converters can be registered with the CommandLine.registerConverter(Class<K> cls, ITypeConverter<K> converter) method. All options and positional parameters with the specified type will be converted by the specified converter.

+

For example:

-
- - - - - -
- - -Java 8 lambdas make it easy to register custom converters: -
+
+
+
import javax.crypto.Cipher;
+
+class CipherConverter implements ITypeConverter<Cipher> {
+    public Cipher convert(String value) throws Exception {
+        return Cipher.getInstance(value);
+    }
+}
+
+
+
Java
-
CommandLine cl = new CommandLine(app);
-cl.registerConverter(Locale.class, s -> new Locale.Builder().setLanguageTag(s).build());
-cl.registerConverter(Cipher.class, s -> Cipher.getInstance(s));
+
class App {
+    @Option(names = "-a", converter = CipherConverter.class)
+    javax.crypto.Cipher cipher;
+}
Kotlin
-
val cl = CommandLine(app)
-cl.registerConverter(Locale::class.java) {
-    s: String? -> Locale.Builder().setLanguageTag(s).build()
-}
-cl.registerConverter(Cipher::class.java) {
-    Cipher.getInstance(it)
-}
+
class App {
+    @Option(names = ["-a"], converter = [CipherConverter::class])
+    lateinit var cipher: javax.crypto.Cipher
+}
+

Alternatively, custom type converters can be registered per type in each command with the CommandLine.registerConverter(Class<K> cls, ITypeConverter<K> converter) method. +All options and positional parameters with the specified type will be converted by the specified converter.

+
+

After registering custom converters, call the execute(String…​) or parseArgs(String…​) method on the CommandLine instance where the converters are registered. (The static populateCommand method cannot be used.) For example:

@@ -3691,6 +3696,18 @@

}

+
+ + + + + +
+ + +Java 8 lambdas make it easy to register custom converters: +
+
Java
+
+
Kotlin
+
+
@Command(name = "set-position")
+class SetPositionCommand {
+    @Parameters(parameterConsumer = PointConverter::class)
+    private lateinit var position: Point
+
+    class PointConverter : IParameterConsumer {
+        override fun consumeParameters(args: Stack<String>,
+                                       argSpec: ArgSpec,
+                                       commandSpec: CommandSpec) {
+            if (args.size < 2) {
+                throw ParameterException(commandSpec.commandLine(),
+                    "Missing coordinates for Point. Please specify 2 coordinates.")
+            }
+            val x = args.pop().toInt()
+            val y = args.pop().toInt()
+            argSpec.setValue(Point(x, y))
+        }
+    }
+}
+
+

See the sections on Custom Parameter Processing for more details.

@@ -3925,6 +3966,18 @@

Type converters declared with the converter attribute need to have a public no-argument constructor to be instantiated, unless a Custom Factory is installed to instantiate classes.

+
+ + + + + +
+ + +If your type converter is declared as nested class, make sure you mark this class as static, or picocli will not be able to instantiate your nested converter class without a Custom Factory. +
+

4.5. Arrays, Collections, Maps

@@ -11983,7 +12036,7 @@

description = ["App description"], footerHeading = "Copyright%n", footer = ["(c) Copyright by the authors"], showAtFileInUsageHelp = true) -class AppKt : Runnable { +class App : Runnable { @Option(names = ["-x"]) var x = 0 override fun run() { println("Hello from app!\nx = $x") } @@ -14788,6 +14841,18 @@

All transformers are called once, after the full command hierarchy is constructed, and before any command line arguments are parsed.

+
+ + + + + +
+ + +If your model transformer is declared as nested class, make sure you mark this class as static, or picocli will not be able to instantiate your transformer class without a Custom Factory. +
+

21.7. Automatic Parameter Indexes

@@ -15485,7 +15550,7 @@

This will bring in the info.picocli:picocli and the info.picocli:picocli-spring-boot-starter dependencies.

-

Now open the pre-authored source file SpringBootDemoApplication.java, rename it to MySpringMailer.java and edit and extend it so that it looks like this:

+

Now open the pre-authored source file SpringBootDemoApplication.java, rename it to MySpringMailer.java and edit and extend it so that it looks like this:

Java
@@ -15621,7 +15686,7 @@

1 -We annotate our command with the @org.springframework.stereotype.Component annontation so that Spring can autodetect it for dependency injection. +We annotate our command with the @org.springframework.stereotype.Component annotation so that Spring can autodetect it for dependency injection. 2