Revisit positional arguments
- Add better mapping logic - Add better type conversion - More docs for arity and positional option configuration - Fixes #616
This commit is contained in:
@@ -4,7 +4,7 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
|
||||
|
||||
Sometimes, you want to have more fine control of how many parameters with an option
|
||||
are processed when parsing operations happen. Arity is defined as min and max
|
||||
values, where min must be a positive integer and max has to be more or equal to min.
|
||||
values, where min must be zero or a positive integer and max has to be more or equal to min.
|
||||
|
||||
====
|
||||
[source, java, indent=0]
|
||||
@@ -14,7 +14,7 @@ include::{snippets}/OptionSnippets.java[tag=option-registration-arityints]
|
||||
====
|
||||
|
||||
Arity can also be defined as an `OptionArity` enum, which are shortcuts
|
||||
within the following table:
|
||||
shown in below table <<using-shell-options-arity-optionarity-table>>.
|
||||
|
||||
====
|
||||
[source, java, indent=0]
|
||||
@@ -23,6 +23,7 @@ include::{snippets}/OptionSnippets.java[tag=option-registration-arityenum]
|
||||
----
|
||||
====
|
||||
|
||||
[[using-shell-options-arity-optionarity-table]]
|
||||
.OptionArity
|
||||
|===
|
||||
|Value |min/max
|
||||
@@ -51,3 +52,35 @@ The annotation model supports defining only the max value of an arity.
|
||||
include::{snippets}/OptionSnippets.java[tag=option-with-annotation-arity]
|
||||
----
|
||||
====
|
||||
|
||||
One of a use cases to manually define arity is to impose restrictions how
|
||||
many parameters option accepts.
|
||||
|
||||
====
|
||||
[source, java, indent=0]
|
||||
----
|
||||
include::{snippets}/OptionSnippets.java[tag=option-registration-aritystrings-sample]
|
||||
----
|
||||
====
|
||||
|
||||
In above example we have option _arg1_ and it's defined as type _String[]_. Arity
|
||||
defines that it needs at least 1 parameter and not more that 2. As seen in below
|
||||
spesific exceptions _TooManyArgumentsOptionException_ and
|
||||
_NotEnoughArgumentsOptionException_ are thrown to indicate arity mismatch.
|
||||
|
||||
====
|
||||
[source, bash]
|
||||
----
|
||||
shell:>e2e reg arity-errors --arg1
|
||||
Not enough arguments --arg1 requires at least 1.
|
||||
|
||||
shell:>e2e reg arity-errors --arg1 one
|
||||
Hello [one]
|
||||
|
||||
shell:>e2e reg arity-errors --arg1 one two
|
||||
Hello [one, two]
|
||||
|
||||
shell:>e2e reg arity-errors --arg1 one two three
|
||||
Too many arguments --arg1 requires at most 2.
|
||||
----
|
||||
====
|
||||
|
||||
@@ -10,3 +10,61 @@ Positional information is mostly related to a command target method:
|
||||
include::{snippets}/OptionSnippets.java[tag=option-registration-positional]
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: Be careful with positional parameters as it may soon
|
||||
become confusing which options those are mapped to.
|
||||
|
||||
Usually arguments are mapped to an option when those are defined in a
|
||||
command line whether it's a long or short option. Generally speaking
|
||||
there are _options_, _option arguments_ and _arguments_ where latter
|
||||
are the ones which are not mapped to any spesific option.
|
||||
|
||||
Unrecognised arguments can then have a secondary mapping logic where
|
||||
positional information is important. With option position you're
|
||||
essentially telling command parsing how to interpret plain raw
|
||||
ambiguous arguments.
|
||||
|
||||
Let's look what happens when we don't define a position.
|
||||
|
||||
====
|
||||
[source, java, indent=0]
|
||||
----
|
||||
include::{snippets}/OptionSnippets.java[tag=option-registration-aritystrings-noposition]
|
||||
----
|
||||
====
|
||||
|
||||
Option _arg1_ is required and there is no info what to do with argument
|
||||
`one` resulting error for missing option.
|
||||
|
||||
====
|
||||
[source, bash]
|
||||
----
|
||||
shell:>arity-strings-1 one
|
||||
Missing mandatory option --arg1.
|
||||
----
|
||||
====
|
||||
|
||||
Now let's define a position `0`.
|
||||
|
||||
====
|
||||
[source, java, indent=0]
|
||||
----
|
||||
include::{snippets}/OptionSnippets.java[tag=option-registration-aritystrings-position]
|
||||
----
|
||||
====
|
||||
|
||||
Arguments are processed until we get up to 2 arguments.
|
||||
|
||||
====
|
||||
[source, bash]
|
||||
----
|
||||
shell:>arity-strings-2 one
|
||||
Hello [one]
|
||||
|
||||
shell:>arity-strings-2 one two
|
||||
Hello [one, two]
|
||||
|
||||
shell:>arity-strings-2 one two three
|
||||
Hello [one, two]
|
||||
----
|
||||
====
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022 the original author or authors.
|
||||
* Copyright 2022-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.shell.docs;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.shell.command.CommandRegistration;
|
||||
import org.springframework.shell.command.CommandRegistration.OptionArity;
|
||||
import org.springframework.shell.standard.ShellOption;
|
||||
@@ -144,6 +146,61 @@ public class OptionSnippets {
|
||||
.build();
|
||||
// end::option-registration-arityints[]
|
||||
|
||||
// tag::option-registration-aritystrings-sample[]
|
||||
CommandRegistration.builder()
|
||||
.command("arity-errors")
|
||||
.withOption()
|
||||
.longNames("arg1")
|
||||
.type(String[].class)
|
||||
.required()
|
||||
.arity(1, 2)
|
||||
.and()
|
||||
.withTarget()
|
||||
.function(ctx -> {
|
||||
String[] arg1 = ctx.getOptionValue("arg1");
|
||||
return "Hello " + Arrays.asList(arg1);
|
||||
})
|
||||
.and()
|
||||
.build();
|
||||
// end::option-registration-aritystrings-sample[]
|
||||
|
||||
// tag::option-registration-aritystrings-position[]
|
||||
CommandRegistration.builder()
|
||||
.command("arity-strings-2")
|
||||
.withOption()
|
||||
.longNames("arg1")
|
||||
.required()
|
||||
.type(String[].class)
|
||||
.arity(0, 2)
|
||||
.position(0)
|
||||
.and()
|
||||
.withTarget()
|
||||
.function(ctx -> {
|
||||
String[] arg1 = ctx.getOptionValue("arg1");
|
||||
return "Hello " + Arrays.asList(arg1);
|
||||
})
|
||||
.and()
|
||||
.build();
|
||||
// end::option-registration-aritystrings-position[]
|
||||
|
||||
// tag::option-registration-aritystrings-noposition[]
|
||||
CommandRegistration.builder()
|
||||
.command("arity-strings-1")
|
||||
.withOption()
|
||||
.longNames("arg1")
|
||||
.required()
|
||||
.type(String[].class)
|
||||
.arity(0, 2)
|
||||
.and()
|
||||
.withTarget()
|
||||
.function(ctx -> {
|
||||
String[] arg1 = ctx.getOptionValue("arg1");
|
||||
return "Hello " + Arrays.asList(arg1);
|
||||
})
|
||||
.and()
|
||||
.build();
|
||||
// end::option-registration-aritystrings-noposition[]
|
||||
|
||||
// tag::option-registration-optional[]
|
||||
CommandRegistration.builder()
|
||||
.withOption()
|
||||
|
||||
Reference in New Issue
Block a user