Migrate docs to antora

- This is basically copy from main branch minus all
  terminal ui things.
- Relates #971
This commit is contained in:
Janne Valkealahti
2024-01-12 14:02:10 +00:00
parent 09d4bfed51
commit 814ed4958f
108 changed files with 637 additions and 1037 deletions

View File

@@ -0,0 +1,102 @@
[[using-shell-options-arity]]
= Arity
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
Arity defines how many parameters option parsing takes.
NOTE: There are limitations in a `legacy annotation` compared to `annotation`
and `programmatic` use of arity settings. These are mentioned in notes in
below samples.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zeroorone-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zeroorone-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zeroorone-legacyannotation]
----
======
[[using-shell-options-arity-optionarity-table]]
.OptionArity
|===
|Value |min/max
|ZERO
|0 / 0
|ZERO_OR_ONE
|0 / 1
|EXACTLY_ONE
|1 / 1
|ZERO_OR_MORE
| 0 / Integer MAX
|ONE_OR_MORE
|1 / Integer MAX
|===
NOTE: `legacy annotation` doesn't support defining minimum arity.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zerooronewithminmax-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zerooronewithminmax-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zerooronewithminmax-legacyannotation]
----
======
In below 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.
----

View File

@@ -0,0 +1,13 @@
[[using-shell-options-basics-annotation]]
= Annotation
:page-section-summary-toc: 1
ifndef::snippets[:snippets: ../../../../../src/test/java/org/springframework/shell/docs]
`Option` annotation can be used to define an option name if you
don't want it to be same as argument name.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-with-option-annotation]
----

View File

@@ -0,0 +1,12 @@
[[using-shell-options-basics]]
= Basics
:page-section-summary-toc: 1
ifndef::snippets[:snippets: ../../../../../src/test/java/org/springframework/shell/docs]
This section gives a generic idea how an option can be defined. Following
sections, beyond basics, discuss more about how various option behaviour
can be accomplished for a particular use case.

View File

@@ -0,0 +1,28 @@
[[using-shell-options-basics-legacyannotation]]
= Legacy Annotation
ifndef::snippets[:snippets: ../../../../../src/test/java/org/springframework/shell/docs]
Having a target method with argument is automatically registered with a matching
argument name.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-without-annotation]
----
`@ShellOption` annotation can be used to define an option name if you
don't want it to be same as argument name.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-with-annotation]
----
If option name is defined without prefix, either `-` or `--`, it is discovered
from _ShellMethod#prefix_.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-with-annotation-without-prefix]
----

View File

@@ -0,0 +1,19 @@
[[using-shell-options-basics-registration]]
[[using-shell-options-basics-programmatic]]
= Programmatic
:page-section-summary-toc: 1
ifndef::snippets[:snippets: ../../../../../src/test/java/org/springframework/shell/docs]
Programmatic way with `CommandRegistration` is to use `withOption` to define
an option.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-longarg]
----
`CommandRegistration` can be defined as a bean or manually registered
with a `CommandCatalog`.
NOTE: Check below sections for other option types, i.e. short format.

View File

@@ -0,0 +1,33 @@
[[using-shell-options-default]]
= Default Value
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
Having a default value for an option is somewhat related to
xref:options/optional.adoc[Optional Value], as there are cases where you
may want to know if the user defined an option and change behavior
based on a default value:
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/OptionSnippets.java[tag=option-default-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-default-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-default-legacyannotation]
----
======

View File

@@ -0,0 +1,29 @@
[[using-shell-options]]
= Options
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
Command line arguments can be separated into options and positional parameters.
Following sections describes features how options are defined and used. We first
go through some basics about using options and then go into details about
various ways how options and arguments works.
Generally speaking an _option_ is something after a commands prefixed with
either `-` or `--`. An _option_ can either have a value or not depending
on its context.
Options can be defined with a target method using annotations with a method
arguments or with programmatically using `CommandRegistration`.
NOTE: In below sections `@ShellOption` refer to a _legacy annotation model_
and `@Option` refer to an _annotation model_.

View File

@@ -0,0 +1,44 @@
[[using-shell-options-label]]
= Label
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
_Option Label_ has no functional behaviour within a shell itself other than
what a default `help` command outputs. Within a command documentation
a type of an option is documented but this is not always super useful. Thus
you may want to give better descriptive word for an option.
NOTE: Label is not supported with `legacy annotation`.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/OptionSnippets.java[tag=option-label-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-label-annotation]
----
======
Defining label is then shown in `help`.
[source, bash]
----
my-shell:>help labelOption
NAME
labelOption -
SYNOPSIS
labelOption --arg MYLABEL
OPTIONS
--arg MYLABEL
[Optional]
----

View File

@@ -0,0 +1,102 @@
[[using-shell-options-naming]]
= Naming
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
If there is a need to modify option long names that can be done
using `OptionNameModifier` interface which is a simple
`Function<String, String>`. In this interface original option
name goes in and modified name comes out.
Modifier can be defined per `OptionSpec` in `CommandRegistration`,
defaulting globally as bean or via configuration properties.
Modifier defined manually in `OptionSpec` takes takes precedence
over one defined globally. There is no global modifier defined
on default.
You can define one with an option in `CommandRegistration`.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-naming-case-req]
----
Add one _singleton bean_ as type `OptionNameModifier` and that becomes
a global default.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-naming-case-bean]
----
It's also possible to just add configuration property with
`spring.shell.option.naming.case-type` which auto-configures
one based on a type defined.
`noop` is to do nothing, `camel`, `snake`, `kebab`, `pascal`
activates build-in modifiers for `camelCase`, `snake_case`,
`kebab-case` or `PascalCase` respectively.
NOTE: If creating `CommandRegistration` beans directly, global
default via configuration properies only work if using
pre-configured `Builder` instance. See more
<<using-shell-commands-programmaticmodel>>.
[source, yaml]
----
spring:
shell:
option:
naming:
case-type: noop
# case-type: camel
# case-type: snake
# case-type: kebab
# case-type: pascal
----
For example options defined in an annotated method like this.
[source, java, indent=0]
----
include::{snippets}/OptionSnippets.java[tag=option-registration-naming-case-sample1]
----
On default `help` for that command shows names coming
directly from `@ShellOption`.
[source, bash]
----
OPTIONS
--from_snake String
[Mandatory]
--fromCamel String
[Mandatory]
--from-kebab String
[Mandatory]
--FromPascal String
[Mandatory]
----
Define `spring.shell.option.naming.case-type=kebab` and default
modifier is added and option names then look like.
[source, bash]
----
OPTIONS
--from-snake String
[Mandatory]
--from-camel String
[Mandatory]
--from-kebab String
[Mandatory]
--from-pascal String
[Mandatory]
----

View File

@@ -0,0 +1,59 @@
[[using-shell-options-optional]]
= Optional Value
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
An option is either required or not and, generally speaking, how it behaves depends on
a command target.
Making option optional.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/OptionSnippets.java[tag=option-optional-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-optional-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-optional-legacyannotation]
----
======
Making option mandatory.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/OptionSnippets.java[tag=option-mandatory-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-mandatory-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/OptionSnippets.java[tag=option-mandatory-legacyannotation]
----
======

View File

@@ -0,0 +1,61 @@
[[using-shell-options-positional]]
= Positional
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
Positional information is mostly related to a command target method:
[source, java, indent=0]
----
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]
----

View File

@@ -0,0 +1,59 @@
[[using-shell-options-short]]
= Short Format
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
Short style _POSIX_ option is usually just a synonym to long format. As
shown below option `--arg` is equal to `-a`.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-string-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-string-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-string-legacyannotation]
----
======
Short option with combined format is powerful if type is defined as a flag
which means type is a _boolean_. That way you can define a presence of a flags
as `-abc`, `-abc true` or `-abc false`.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-multiple-booleans-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-multiple-booleans-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-multiple-booleans-legacyannotation]
----
======

View File

@@ -0,0 +1,117 @@
[[using-shell-options-types]]
= Types
ifndef::snippets[:snippets: ../../../../src/test/java/org/springframework/shell/docs]
This section talks about how particular data type is used as an option value.
[[string]]
== String
`String` is a most simplest type as there's no conversion involved as what's
coming in from a user is always a string.
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-anno]
----
While it's not strictly required to define type as a `String` it's always
adviced to do so.
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-reg]
----
[[boolean]]
== Boolean
Using boolean types is a bit more involved as there are `boolean` and
`Boolean` where latter can be _null_. Boolean types are usually used as
flags meaning argument value may not be needed.
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-boolean-anno]
----
[source, bash]
----
shell:>example
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false
shell:>example --arg4
arg1=false arg2=true arg3=false arg4=true arg5=true arg6=false
shell:>example --arg4 false
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false
----
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-boolean-reg]
----
[source, bash]
----
shell:>example
arg1=false arg2=true arg3=false arg4=null arg5=true arg6=false
shell:>example --arg4
arg1=false arg2=true arg3=false arg4=true arg5=true arg6=false
shell:>example --arg4 false
arg1=false arg2=true arg3=false arg4=false arg5=true arg6=false
----
[[number]]
== Number
Numbers are converted as is.
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-integer-anno]
----
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-integer-reg]
----
[[enum]]
== Enum
Conversion to enums is possible if given value is exactly matching enum itself.
Currently you can convert assuming case insensitivity.
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-enum-class]
----
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-enum-anno]
----
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-enum-reg]
----
[[array]]
== Array
Arrays can be used as is with strings and primitive types.
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-array-anno]
----
[source, java, indent=0]
----
include::{snippets}/OptionTypesSnippets.java[tag=option-type-string-array-reg]
----

View File

@@ -0,0 +1,24 @@
[[validating-command-arguments]]
= Validation
Spring Shell integrates with the https://beanvalidation.org/[Bean Validation API] to support
automatic and self-documenting constraints on command parameters.
Annotations found on command parameters and annotations at the method level are
honored and trigger validation prior to the command executing. Consider the following command:
[source, java]
----
@ShellMethod("Change password.")
public String changePassword(@Size(min = 8, max = 40) String password) {
return "Password successfully set to " + password;
}
----
From the preceding example, you get the following behavior for free:
----
shell:>change-password hello
The following constraints were not met:
--password string : size must be between 8 and 40 (You passed 'hello')
----