Skip to content

Commit 78da071

Browse files
committed
Document String array option type
- Backport #558 as it brings missing option type docs - Backport #628 - Fixes #629
1 parent b853112 commit 78da071

File tree

5 files changed

+600
-2
lines changed

5 files changed

+600
-2
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
[[using-shell-options-types]]
2+
=== Types
3+
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
4+
5+
This section talks about how particular data type is used as an option value.
6+
7+
==== String
8+
9+
`String` is a most simplest type as there's no conversion involved as what's
10+
coming in from a user is always a string.
11+
12+
====
13+
[source, java, indent=0]
14+
----
15+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-anno]
16+
----
17+
====
18+
19+
While it's not strictly required to define type as a `String` it's always
20+
adviced to do so.
21+
22+
====
23+
[source, java, indent=0]
24+
----
25+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-reg]
26+
----
27+
====
28+
29+
==== Boolean
30+
31+
Using boolean types is a bit more involved as there are `boolean` and
32+
`Boolean` where latter can be _null_. Boolean types are usually used as
33+
flags meaning argument value may not be needed.
34+
35+
====
36+
[source, java, indent=0]
37+
----
38+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-boolean-anno]
39+
----
40+
====
41+
42+
====
43+
[source, bash]
44+
----
45+
shell:>example
46+
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false
47+
48+
shell:>example --arg4
49+
arg1=false arg2=true arg3=false arg4=true arg5=true arg6=false
50+
51+
shell:>example --arg4 false
52+
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false
53+
----
54+
====
55+
56+
====
57+
[source, java, indent=0]
58+
----
59+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-boolean-reg]
60+
----
61+
====
62+
63+
====
64+
[source, bash]
65+
----
66+
shell:>example
67+
arg1=false arg2=true arg3=false arg4=null arg5=true arg6=false
68+
69+
shell:>example --arg4
70+
arg1=false arg2=true arg3=false arg4=true arg5=true arg6=false
71+
72+
shell:>example --arg4 false
73+
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false
74+
----
75+
====
76+
77+
==== Number
78+
79+
Numbers are converted as is.
80+
81+
====
82+
[source, java, indent=0]
83+
----
84+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-integer-anno]
85+
----
86+
====
87+
88+
====
89+
[source, java, indent=0]
90+
----
91+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-integer-reg]
92+
----
93+
====
94+
95+
==== Enum
96+
97+
Conversion to enums is possible if given value is exactly matching enum itself.
98+
Currently you can convert assuming case insensitivity.
99+
100+
====
101+
[source, java, indent=0]
102+
----
103+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-enum-class]
104+
----
105+
====
106+
107+
====
108+
[source, java, indent=0]
109+
----
110+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-enum-anno]
111+
----
112+
====
113+
114+
====
115+
[source, java, indent=0]
116+
----
117+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-enum-reg]
118+
----
119+
====
120+
121+
==== Array
122+
123+
Arrays can be used as is with strings and primitive types.
124+
125+
====
126+
[source, java, indent=0]
127+
----
128+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-array-anno]
129+
----
130+
====
131+
132+
====
133+
[source, java, indent=0]
134+
----
135+
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-array-reg]
136+
----
137+
====

spring-shell-docs/src/main/asciidoc/using-shell-options.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@ include::using-shell-options-default.adoc[]
2020
include::using-shell-options-validation.adoc[]
2121

2222
include::using-shell-options-label.adoc[]
23+
24+
include::using-shell-options-types.adoc[]
25+
26+
include::using-shell-options-naming.adoc[]
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Copyright 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.shell.docs;
17+
18+
import org.springframework.shell.command.CommandRegistration;
19+
import org.springframework.shell.standard.ShellOption;
20+
21+
class OptionTypesSnippets {
22+
23+
class Dump1 {
24+
// tag::option-type-boolean-anno[]
25+
String example(
26+
@ShellOption() boolean arg1,
27+
@ShellOption(defaultValue = "true") boolean arg2,
28+
@ShellOption(defaultValue = "false") boolean arg3,
29+
@ShellOption() Boolean arg4,
30+
@ShellOption(defaultValue = "true") Boolean arg5,
31+
@ShellOption(defaultValue = "false") Boolean arg6
32+
) {
33+
return String.format("arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s",
34+
arg1, arg2, arg3, arg4, arg5, arg6);
35+
}
36+
// end::option-type-boolean-anno[]
37+
void dump() {
38+
// tag::option-type-boolean-reg[]
39+
CommandRegistration.builder()
40+
.command("example")
41+
.withOption()
42+
.longNames("arg1").type(boolean.class).and()
43+
.withOption()
44+
.longNames("arg2").type(boolean.class).defaultValue("true").and()
45+
.withOption()
46+
.longNames("arg3").type(boolean.class).defaultValue("false").and()
47+
.withOption()
48+
.longNames("arg4").type(Boolean.class).and()
49+
.withOption()
50+
.longNames("arg5").type(Boolean.class).defaultValue("true").and()
51+
.withOption()
52+
.longNames("arg6").type(Boolean.class).defaultValue("false").and()
53+
.withTarget()
54+
.function(ctx -> {
55+
boolean arg1 = ctx.hasMappedOption("arg1")
56+
? ctx.getOptionValue("arg1")
57+
: false;
58+
boolean arg2 = ctx.getOptionValue("arg2");
59+
boolean arg3 = ctx.getOptionValue("arg3");
60+
Boolean arg4 = ctx.getOptionValue("arg4");
61+
Boolean arg5 = ctx.getOptionValue("arg5");
62+
Boolean arg6 = ctx.getOptionValue("arg6");
63+
return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s",
64+
arg1, arg2, arg3, arg4, arg5, arg6);
65+
})
66+
.and()
67+
.build();
68+
// end::option-type-boolean-reg[]
69+
}
70+
}
71+
72+
class Dump2 {
73+
// tag::option-type-integer-anno[]
74+
String example(@ShellOption(value = "arg1") int arg1) {
75+
return "Hello " + arg1;
76+
}
77+
// end::option-type-integer-anno[]
78+
void dump() {
79+
// tag::option-type-integer-reg[]
80+
CommandRegistration.builder()
81+
.command("example")
82+
.withOption()
83+
.longNames("arg1")
84+
.type(int.class)
85+
.required()
86+
.and()
87+
.withTarget()
88+
.function(ctx -> {
89+
boolean arg1 = ctx.getOptionValue("arg1");
90+
return "Hello " + arg1;
91+
})
92+
.and()
93+
.build();
94+
// end::option-type-integer-reg[]
95+
}
96+
}
97+
98+
class Dump3 {
99+
// tag::option-type-string-anno[]
100+
String example(@ShellOption(value = "arg1") String arg1) {
101+
return "Hello " + arg1;
102+
}
103+
// end::option-type-string-anno[]
104+
void dump() {
105+
// tag::option-type-string-reg[]
106+
CommandRegistration.builder()
107+
.command("example")
108+
.withOption()
109+
.longNames("arg1")
110+
.type(String.class)
111+
.required()
112+
.and()
113+
.withTarget()
114+
.function(ctx -> {
115+
String arg1 = ctx.getOptionValue("arg1");
116+
return "Hello " + arg1;
117+
})
118+
.and()
119+
.build();
120+
// end::option-type-string-reg[]
121+
}
122+
}
123+
124+
static class Dump4 {
125+
126+
// tag::option-type-enum-class[]
127+
enum OptionTypeEnum {
128+
ONE,TWO,THREE
129+
}
130+
// end::option-type-enum-class[]
131+
132+
// tag::option-type-enum-anno[]
133+
String example(@ShellOption(value = "arg1") OptionTypeEnum arg1) {
134+
return "Hello " + arg1;
135+
}
136+
// end::option-type-enum-anno[]
137+
void dump() {
138+
// tag::option-type-enum-reg[]
139+
CommandRegistration.builder()
140+
.command("example")
141+
.withOption()
142+
.longNames("arg1")
143+
.type(OptionTypeEnum.class)
144+
.required()
145+
.and()
146+
.withTarget()
147+
.function(ctx -> {
148+
OptionTypeEnum arg1 = ctx.getOptionValue("arg1");
149+
return "Hello " + arg1;
150+
})
151+
.and()
152+
.build();
153+
// end::option-type-enum-reg[]
154+
}
155+
}
156+
157+
class Dump5 {
158+
// tag::option-type-string-array-anno[]
159+
String example(@ShellOption(value = "arg1") String[] arg1) {
160+
return "Hello " + arg1;
161+
}
162+
// end::option-type-string-array-anno[]
163+
void dump() {
164+
// tag::option-type-string-array-reg[]
165+
CommandRegistration.builder()
166+
.command("example")
167+
.withOption()
168+
.longNames("arg1")
169+
.type(String[].class)
170+
.required()
171+
.and()
172+
.withTarget()
173+
.function(ctx -> {
174+
String[] arg1 = ctx.getOptionValue("arg1");
175+
return "Hello " + arg1;
176+
})
177+
.and()
178+
.build();
179+
// end::option-type-string-array-reg[]
180+
}
181+
}
182+
}

spring-shell-samples/src/main/java/org/springframework/shell/samples/e2e/BaseE2ECommands.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 the original author or authors.
2+
* Copyright 2022-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,6 +15,11 @@
1515
*/
1616
package org.springframework.shell.samples.e2e;
1717

18+
import java.util.stream.Collectors;
19+
import java.util.stream.IntStream;
20+
21+
import org.springframework.util.StringUtils;
22+
1823
/**
1924
* Base class for all e2e commands.
2025
*
@@ -25,4 +30,26 @@ abstract class BaseE2ECommands {
2530
static final String GROUP = "E2E Commands";
2631
static final String REG = "e2e reg";
2732
static final String LEGACY_ANNO = "e2e anno ";
33+
34+
static String stringOfStrings(String[] values) {
35+
return String.format("[%s]", StringUtils.arrayToCommaDelimitedString(values));
36+
}
37+
38+
static String stringOfInts(int[] values) {
39+
String joined = IntStream.range(0, values.length)
40+
.mapToLong(i -> values[i])
41+
.boxed()
42+
.map(d -> d.toString())
43+
.collect(Collectors.joining(","));
44+
return String.format("[%s]", joined);
45+
}
46+
47+
static String stringOfFloats(float[] values) {
48+
String joined = IntStream.range(0, values.length)
49+
.mapToDouble(i -> values[i])
50+
.boxed()
51+
.map(d -> d.toString())
52+
.collect(Collectors.joining(","));
53+
return String.format("[%s]", joined);
54+
}
2855
}

0 commit comments

Comments
 (0)