Migrate to Asciidoctor Tabs

This commit is contained in:
Rob Winch
2023-08-03 11:31:00 -05:00
parent b69312c683
commit 1d7077bf52
50 changed files with 70 additions and 286 deletions

View File

@@ -10,9 +10,6 @@ antora:
- '@antora/atlas-extension'
- require: '@springio/antora-extensions/root-component-extension'
root_component_name: 'shell'
- require: '@springio/antora-extensions/tabs-migration-extension'
unwrap_example_block: always
save_result: true
site:
title: Spring Shell
url: https://docs.spring.io/spring-shell/reference/

View File

@@ -6,12 +6,10 @@ a shell application. It is possible to dynamically register and de-register
commands, which gives flexibility for use cases where possible commands
come and go, depending on a shell's state. Consider the following example:
====
[source, java, indent=0]
----
include::{snippets}/CommandCatalogSnippets.java[tag=snippet1]
----
====
[[command-resolver]]
== Command Resolver
@@ -19,12 +17,10 @@ You can implement the `CommandResolver` interface and define a bean to dynamical
resolve mappings from a command's name to its `CommandRegistration` instances. Consider
the following example:
====
[source, java, indent=0]
----
include::{snippets}/CommandCatalogSnippets.java[tag=snippet2]
----
====
IMPORTANT: A current limitation of a `CommandResolver` is that it is used every time commands are resolved.
Thus, we advise not using it if a command resolution call takes a long time, as it would
@@ -37,11 +33,9 @@ Its main use is to modify a catalog. Also, within `spring-shell` auto-configurat
interface is used to register existing `CommandRegistration` beans into a catalog.
Consider the following example:
====
[source, java, indent=0]
----
include::{snippets}/CommandCatalogSnippets.java[tag=snippet3]
----
====
You can create a `CommandCatalogCustomizer` as a bean, and Spring Shell handles the rest.

View File

@@ -5,19 +5,15 @@
The `CommandContext` interface gives access to a currently running
context. You can use it to get access to options:
====
[source, java, indent=0]
----
include::{snippets}/CommandContextSnippets.java[tag=snippet1]
----
====
If you need to print something into a shell, you can get a `Terminal`
and use its writer to print something:
====
[source, java, indent=0]
----
include::{snippets}/CommandContextSnippets.java[tag=snippet2]
----
====

View File

@@ -12,7 +12,6 @@ actual target code. Essentially, it is the definition of a command API that is s
A command in a `spring-shell` structure is defined as an array of commands. This yields a
structure similar to the following example:
====
[source, bash]
----
command1 sub1
@@ -20,7 +19,6 @@ command2 sub1 subsub1
command2 sub2 subsub1
command2 sub2 subsub2
----
====
NOTE: We do not currently support mapping commands to an explicit parent if sub-commands are defined.
For example, `command1 sub1` and `command1 sub1 subsub1` cannot both be registered.
@@ -44,19 +42,15 @@ doing within an active session.
Options can be defined as long and short, where the prefixing is `--` and `-`, respectively.
The following examples show long and short options:
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationSnippets.java[tag=snippet1]
----
====
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationSnippets.java[tag=snippet2]
----
====
[[target]]
== Target
@@ -68,21 +62,17 @@ a `Consumer`, or a `Function`.
Using a `Method` in an existing POJO is one way to define a target.
Consider the following class:
====
[source, java, indent=0]
----
include::{snippets}/CommandTargetSnippets.java[tag=snippet11]
----
====
Given the existing class shown in the preceding listing, you can then register its method:
====
[source, java, indent=0]
----
include::{snippets}/CommandTargetSnippets.java[tag=snippet12]
----
====
[[function]]
=== Function
@@ -91,12 +81,10 @@ happens in a command execution, because you can handle many things manually by u
a `CommandContext` given to a `Function`. The return type from a `Function` is
then what gets printed into the shell as a result. Consider the following example:
====
[source, java, indent=0]
----
include::{snippets}/CommandTargetSnippets.java[tag=snippet2]
----
====
[[consumer]]
=== Consumer
@@ -105,9 +93,7 @@ that there is no return type. If you need to print something into a shell,
you can get a reference to a `Terminal` from a context and print something
through it. Consider the following example:
====
[source, java, indent=0]
----
include::{snippets}/CommandTargetSnippets.java[tag=snippet3]
----
====

View File

@@ -30,12 +30,10 @@ as we don't want to fully open these until we know API's are good to go
for longer support. You need to construct `SearchMatch` via its
build-in builder.
====
[source, java, indent=0]
----
include::{snippets}/SearchAlgorithmsSnippets.java[tag=builder]
----
====
It's possible to configure _case sensitivity_, on what _direction_ search
happens or if text should be _normilized_ before search happens. Normalization
@@ -61,9 +59,7 @@ below table.
[[examples]]
== Examples
====
[source, java, indent=0]
----
include::{snippets}/SearchAlgorithmsSnippets.java[tag=simple]
----
====

View File

@@ -23,7 +23,6 @@ applied. Prefixing with `~` will resolve from JLine internal bsd color table.
If rgb format is expected and prefixed with either `x` or `#` a normal
hex format is used.
====
[source, text]
----
fg-red
@@ -32,30 +31,25 @@ fg-rgb:red
fg-rgb:xff3333
fg-rgb:#ff3333
----
====
If spec contains special names `default`, `bold`, `faint`, `italic`, `underline`, `blink`,
`inverse`, `inverse-neg`, `inverseneg`, `conceal`, `crossed-out`, `crossedout` or `hidden`
a style is changed accordingly with an existing color.
====
[source, text]
----
bold
bold,fg:red
----
====
If spec is a number or numbers separated with semicolon, format is a plain part of an ansi
ascii codes.
====
[source, text]
----
31
31;1
----
====
NOTE: JLine special mapping format which would resolve spec starting with dot can't be
used as we don't yet map those into Spring Shell styling names.

View File

@@ -19,7 +19,6 @@ NOTE: _Spring Shell_ version on `start.spring.io` is usually latest release.
With _maven_ you're expected to have something like:
====
[source, xml, subs=attributes+]
----
<properties>
@@ -49,11 +48,9 @@ With _maven_ you're expected to have something like:
</dependencies>
</dependencyManagement>
----
====
With _gradle_ you're expected to have something like:
====
[source, groovy, subs=attributes+]
----
dependencies {
@@ -68,7 +65,6 @@ dependencyManagement {
}
}
----
====
CAUTION: Given that Spring Shell starts the REPL (Read-Eval-Print-Loop) because this
dependency is present, you need to either skip tests when you build (`-DskipTests`)
@@ -79,19 +75,15 @@ the eval loop or crashes with a NPE.
Once compiled it can be run either in interactive mode:
====
[source, text, subs=attributes+]
----
----
====
Or in non-interactive mode:
====
[source, text, subs=attributes+]
----
----
====
TIP: Check out xref:using-shell-customization-logging.adoc[Logging] making logging to work
better with shell apps.
@@ -108,7 +100,6 @@ returns it with "Hello world". Add `@ShellMethod` and optionally change command
using `key` parameter. You can use `@ShellOption` to define argument default value
if it's not given when running a command.
====
[source, java]
----
package com.example.demo;
@@ -128,21 +119,17 @@ public class MyCommands {
}
}
----
====
New _hello-world_ command becomes visible to _help_:
====
[source, text]
----
My Commands
hello-world:
----
====
And you can run it:
====
[source, text]
----
shell:>hello-world
@@ -151,6 +138,5 @@ Hello world spring
shell:>hello-world --arg boot
Hello world boot
----
====
The rest of this document delves deeper into the whole Spring Shell programming model.

View File

@@ -23,7 +23,6 @@ _GraalVM_ installed and `JAVA_HOME` pointing to that.
For _gradle_ add graalvm's native plugin and configure metadata repository.
====
[source, groovy, subs=attributes+]
----
plugins {
@@ -36,7 +35,6 @@ graalvmNative {
}
}
----
====
When gradle build is run with `./gradlew nativeCompile` you should get binary
under `build/native/nativeCompile` directory.
@@ -44,7 +42,6 @@ under `build/native/nativeCompile` directory.
For `maven` use `spring-boot-starter-parent` as parent and you'll get `native`
profile which can be used to do a compilation. You need to configure metadata repository
====
[source, xml, subs=attributes+]
----
<build>
@@ -63,7 +60,6 @@ profile which can be used to do a compilation. You need to configure metadata re
</pluginManagement>
</build>
----
====
NOTE: If you rely on `spring-boot-starter-parent` it manages `native-maven-plugin`
version which is kept up to date.

View File

@@ -12,7 +12,6 @@ There are three possible ways for a command to indicate availability.
They all use a no-arg method that returns an instance of `Availability`.
Consider the following example:
====
[source, java]
----
@ShellComponent
@@ -38,7 +37,6 @@ public class MyCommands {
}
}
----
====
The `connect` method is used to connect to the server (details omitted), altering the state
of the command through the `connected` boolean when done.
@@ -48,14 +46,12 @@ The method returns an instance of `Availability`, constructed with one of the tw
If the command is not available, an explanation has to be provided.
Now, if the user tries to invoke the command while not being connected, here is what happens:
====
[source]
----
shell:>download
Command 'download' exists but is not currently available because you are not connected.
Details of the error have been omitted. You can use the stacktrace command to print the full stacktrace.
----
====
Information about currently unavailable commands is also used in the integrated help. See xref:using-shell-commands-builtin-help.adoc[Help].
@@ -69,7 +65,6 @@ You should not start the sentence with a capital or add a final period
If naming the availability method after the name of the command method does not suit you, you
can provide an explicit name by using the `@ShellMethodAvailability` annotation:
====
[source, java]
----
@ShellMethod("Download the nuclear codes.")
@@ -85,14 +80,12 @@ can provide an explicit name by using the `@ShellMethodAvailability` annotation:
}
----
<1> the names have to match
====
Finally, it is often the case that several commands in the same class share the same internal state and, thus,
should all be available or unavailable as a group. Instead of having to stick the `@ShellMethodAvailability`
on all command methods, Spring Shell lets you flip things around and put the `@ShellMethodAvailabilty`
annotation on the availability method, specifying the names of the commands that it controls:
====
[source, java]
----
@ShellMethod("Download the nuclear codes.")
@@ -112,7 +105,6 @@ annotation on the availability method, specifying the names of the commands that
: Availability.unavailable("you are not connected");
}
----
====
[TIP]
=====
@@ -120,7 +112,6 @@ The default value for the `@ShellMethodAvailability.value()` attribute is `*`. T
wildcard matches all command names. This makes it easy to turn all commands of a single class on or off
with a single availability method:
====
[source,java]
----
@ShellComponent
@@ -139,7 +130,6 @@ public class Toggles {
public void bar() {}
}
----
====
=====
TIP: Spring Shell does not impose many constraints on how to write commands and how to organize classes.

View File

@@ -10,7 +10,6 @@ command comes in.
Typing `help` + `ENTER` lists all the commands known to the shell (including xref:using-shell-commands-availability.adoc[unavailable] commands)
and a short description of what they do, similar to the following:
====
[source, bash]
----
my-shell:>help
@@ -27,14 +26,12 @@ Built-In Commands
version: Show version info
script: Read and execute commands from a file.
----
====
Typing `help <command>` shows more detailed information about a command, including the available parameters, their
type, whether they are mandatory or not, and other details.
The following listing shows the `help` command applied to itself:
====
[source, bash]
----
my-shell:>help help
@@ -49,7 +46,6 @@ OPTIONS
The command to obtain help for.
[Optional]
----
====
Help is templated and can be customized if needed. Settings are under `spring.shell.command.help` where you can use
`enabled` to disable command, `grouping-mode` taking `group` or `flat` if you want to hide groups by flattening
@@ -58,7 +54,6 @@ output of a command list.
If `spring.shell.command.help.grouping-mode=flat` is set, then help would show:
====
[source, bash]
----
my-shell:>help help
@@ -74,7 +69,6 @@ completion bash: Generate bash completion script
version: Show version info
script: Read and execute commands from a file.
----
====
Output from `help` and `help <commmand>` are both templated with a default implementation
which can be changed.

View File

@@ -16,21 +16,17 @@ fields in a default template.
The template defaults to `classpath:template/version-default.st`, and you can define
your own, as the following example shows:
====
[source]
----
<buildVersion>
----
====
This setting would output something like the following:
====
[source]
----
X.X.X
----
====
You can add the following attributes to the default template rendering: `buildVersion`, `buildGroup`,
`buildGroup`, `buildName`, `buildTime`, `gitShortCommitId`, `gitCommitId`,

View File

@@ -18,40 +18,32 @@ is used to sort exceptions based on their depth from the thrown exception type.
Alternatively, the annotation declaration may narrow the exception types to match, as the
following example shows:
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=exception-resolver-with-type-in-annotation]
----
====
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=exception-resolver-with-type-in-method]
----
====
`@ExceptionResolver` can also return `String` which is used as an output to console. You can
use `@ExitCode` annotation to define return code.
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=exception-resolver-with-exitcode-annotation]
----
====
`@ExceptionResolver` with `void` return type is automatically handled as handled exception.
You can then also define `@ExitCode` and use `Terminal` if you need to write something
into console.
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=exception-resolver-with-void]
----
====
[[method-arguments]]
== Method Arguments

View File

@@ -15,21 +15,17 @@ integrate into that.
Assuming there is an exception show below which would be thrown from a command:
====
[source, java, indent=0]
----
include::{snippets}/ExitCodeSnippets.java[tag=my-exception-class]
----
====
It is possible to define a mapping function between `Throwable` and exit code. You can also
just configure a _class_ to _exit code_ which is just a syntactic sugar within configurations.
====
[source, java, indent=0]
----
include::{snippets}/ExitCodeSnippets.java[tag=example1]
----
====
NOTE: Exit codes cannot be customized with annotation based configuration

View File

@@ -9,30 +9,24 @@ can be used to resolve exceptions and gives you flexibility to return message to
into console together with exit code which are wrapped within `CommandHandlingResult`.
`CommandHandlingResult` may contain a _message_ and/or _exit code_.
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=my-exception-resolver-class]
----
====
`CommandExceptionResolver` implementations can be defined globally as bean.
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=my-exception-resolver-class-as-bean]
----
====
or defined per `CommandRegistration` if it's applicable only for a particular command itself.
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=example1]
----
====
NOTE: Resolvers defined with a command are handled before global resolvers.
@@ -40,12 +34,10 @@ NOTE: Resolvers defined with a command are handled before global resolvers.
Use you own exception types which can also be an instance of boot's `ExitCodeGenerator` if
you want to define exit code there.
====
[source, java, indent=0]
----
include::{snippets}/ErrorHandlingSnippets.java[tag=my-exception-class]
----
====
Some build in `CommandExceptionResolver` beans are registered to handle common
exceptions thrown from command parsing. These are registered with _order_

View File

@@ -15,16 +15,13 @@ what other command-line options is typed.
Below example shows its default settings.
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationHelpOptionsSnippets.java[tag=defaults]
----
====
It is possible to change default behaviour via configuration options.
====
[source, yaml]
----
spring:
@@ -35,7 +32,6 @@ spring:
short-names: h
command: help
----
====
NOTE: Commands defined programmationally or via annotations will automatically add
help options. With annotation model you can only turn things off globally, programmatic

View File

@@ -18,11 +18,9 @@ from:
Below is an example how to define command as _hidden_. It shows available builder methods
to define _hidden_ state.
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationHiddenSnippets.java[tag=snippet1]
----
====
NOTE: Defining hidden commands is not supported with annotation based configuration

View File

@@ -9,18 +9,14 @@ depending which mode shell is executing. More about that in xref:using-shell-exe
You can define it with `CommandRegisration`.
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationInteractionModeSnippets.java[tag=snippet1]
----
====
Or with `@ShellMethod`.
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationInteractionModeSnippets.java[tag=snippet2]
----
====

View File

@@ -27,7 +27,6 @@ package (unless overridden at the method or class level, as explained earlier).
The following listing shows an example:
====
[source,java]
----
public class UserCommands {
@@ -51,4 +50,3 @@ public class SomeCommands {
public void last() {}
}
----
====

View File

@@ -6,23 +6,19 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
`@Command` annotation when used on a method marks it as a candidate for command registration.
In below example a command `example` is defined.
====
[source, java, indent=0]
----
include::{snippets}/CommandAnnotationSnippets.java[tag=command-anno-in-method]
----
====
`@Command` annotation can be placed on a class which either defines defaults or shared settings
for `@Command` methods defined in a same class. In below example a command `parent example` is
defined.
====
[source, java, indent=0]
----
include::{snippets}/CommandAnnotationSnippets.java[tag=command-anno-in-class]
----
====
Using a `@Command` will not automatically register command targets, instead it is required to use
`@EnableCommand` and/or `@CommandScan` annotations. This model is familiar from other parts
@@ -32,12 +28,10 @@ for command targets.
You can define target classes using `@EnableCommand`. It will get picked from all _Configuration_
classes.
====
[source, java, indent=0]
----
include::{snippets}/CommandAnnotationSnippets.java[tag=enablecommand-with-class]
----
====
You can define target classes using `@CommandScan`. It will get picked from all _Configuration_
classes.
@@ -45,9 +39,7 @@ classes.
TIP: Define `@CommandScan` in Spring Boot `App` class on a top level and it will automatically
scan all command targets from all packages and classes under `App`.
====
[source, java, indent=0]
----
include::{snippets}/CommandAnnotationSnippets.java[tag=commandscan-no-args]
----
====

View File

@@ -17,12 +17,10 @@ you can use it in addition to the filtering mechanism to declare beans (for exam
You can customize the name of the created bean by using the `value` attribute of the annotation.
====
====
[source, java, indent=0]
----
include::{snippets}/AnnotationRegistrationSnippets.java[tag=snippet1]
----
====
The only required attribute of the `@ShellMethod` annotation is its `value` attribute, which should have
a short, one-sentence, description of what the command does. This lets your users
@@ -37,12 +35,10 @@ dashed, gnu-style, names (for example, `sayHello()` becomes `say-hello`).
You can, however, explicitly set the command key, by using the `key` attribute of the annotation:
====
[source, java, indent=0]
----
include::{snippets}/AnnotationRegistrationSnippets.java[tag=snippet2]
----
====
NOTE: The `key` attribute accepts multiple values.
If you set multiple keys for a single method, the command is registered with those different aliases.

View File

@@ -6,12 +6,10 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
In the programmatic model, `CommandRegistration` can be defined as a `@Bean`
and it will be automatically registered.
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationBeanSnippets.java[tag=plain]
----
====
If all your commands have something in common, an instance of
a _CommandRegistration.BuilderSupplier_ is created which can
@@ -24,19 +22,15 @@ add _help options_ mentioned in xref:using-shell-commands-helpoptions.adoc[Help
If bean of this supplier type is defined then auto-configuration
will back off giving you an option to redefine default functionality.
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationBeanSnippets.java[tag=fromsupplier]
----
====
`CommandRegistrationCustomizer` beans can be defined if you want to centrally
modify builder instance given you by supplier mentioned above.
====
[source, java, indent=0]
----
include::{snippets}/CommandRegistrationBeanSnippets.java[tag=customizer]
----
====

View File

@@ -12,18 +12,14 @@ If using target endpoints, i.e. _consumer_ which is not expected
to return anything given `CommandContext` contains reference to
`Terminal` and writer can be accessed from there.
====
[source, java, indent=0]
----
include::{snippets}/WritingSnippets.java[tag=reg-terminal-writer]
----
====
It's possible to autowire `Terminal` to get access to its writer.
====
[source, java, indent=0]
----
include::{snippets}/WritingSnippets.java[tag=anno-terminal-writer]
----
====

View File

@@ -23,43 +23,35 @@ for all commands and scenarious. For example existing completion
implementation `RegistrationOptionsCompletionResolver` handles completions
for a option names.
====
[source, java, indent=0]
----
include::{snippets}/CompletionSnippets.java[tag=resolver-1]
----
====
Option values with builder based command registration can be
defined per option.
====
[source, java, indent=0]
----
include::{snippets}/CompletionSnippets.java[tag=builder-1]
----
====
Option values with annotation based command registration are handled
via `ValueProvider` interface which can be defined with `@ShellOption`
annotation.
====
[source, java, indent=0]
----
include::{snippets}/CompletionSnippets.java[tag=provider-1]
----
====
Actual `ValueProvider` with annotation based command needs to be
registered as a _Bean_.
====
[source, java, indent=0]
----
include::{snippets}/CompletionSnippets.java[tag=anno-method]
----
====
[[command-line]]
== Command-Line

View File

@@ -11,12 +11,10 @@ as a "`flow`".
The following listings show examples of flows and their output in a shell:
====
[source, java, indent=0]
----
include::{snippets}/FlowComponentSnippets.java[tag=snippet1]
----
====
image::component-flow-showcase-1.svg[text input]
@@ -25,12 +23,10 @@ possible to conditionally choose where to jump in a flow by using a `next`
function and returning target _component id_. If this returned id is aither _null_
or doesn't exist flow is essentially stopped right there.
====
[source, java, indent=0]
----
include::{snippets}/FlowComponentSnippets.java[tag=snippet2]
----
====
image::component-flow-conditional-1.svg[text input]

View File

@@ -6,12 +6,10 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
The confirmation component asks a user for a simple confirmation. It is essentially a
yes-or-no question.
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet5]
----
====
The following image shows the typical output from a confirmation component:

View File

@@ -6,12 +6,10 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
The multi select component asks a user to select multiple items from a list.
The following listing shows an example:
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet7]
----
====
The following image shows a typical multi-select component:

View File

@@ -5,12 +5,10 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
The path input component asks a user for a `Path` and gives additional information about a path itself.
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet4]
----
====
The following image shows typical output from a path input component:

View File

@@ -7,12 +7,10 @@ The path search component asks base directory for scan and optional search expre
Results are shown in a single select list where user can pick a path.
`PathSearchConfig` can be used to customise component behaviour.
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet9]
----
====
NOTE: Logic for search is passed as is into algorithms documented
in xref:appendices-techical-intro-searchalgorithm.adoc[Search Algorithms].

View File

@@ -15,21 +15,17 @@ through code then gives you flexibility to do whatever you need.
The programmatic way to render is to create a `Function`:
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet1]
----
====
Then you can hook it to a component:
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet2]
----
====
Components have their own context but usually share some functionality
from a parent component types. The following tables show those context variables:

View File

@@ -6,12 +6,10 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
A single select component asks a user to choose one item from a list. It is similar to a simple
dropbox implementation. The following listing shows an example:
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet6]
----
====
The following image shows typical output for a single select component:
@@ -38,9 +36,7 @@ You can pre-select an item by defining it to get exposed. This is
useful if you know the default and lets the user merely press `Enter` to make a choice.
The following listing sets a default:
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet8]
----
====

View File

@@ -6,12 +6,10 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
The string input component asks a user for simple text input, optionally masking values
if the content contains something sensitive. The following listing shows an example:
====
[source, java, indent=0]
----
include::{snippets}/UiComponentSnippets.java[tag=snippet3]
----
====
The following image shows typical output from a string input component:

View File

@@ -6,40 +6,32 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
On default a missing command is handled via `CommandNotFoundResultHandler`
and outputs a simple message:
====
[source, text]
----
shell:>missing
No command found for 'missing'
----
====
Internally `CommandNotFoundResultHandler` is using `CommandNotFoundMessageProvider`
which is a simple function taking a `ProviderContext` and returning a text
message. Below is an example what a custom message provider might look like.
====
[source, java, indent=0]
----
include::{snippets}/CommandNotFoundSnippets.java[tag=custom-provider]
----
====
It's possible to change this implementation by defining it as a bean.
====
[source, java, indent=0]
----
include::{snippets}/CommandNotFoundSnippets.java[tag=provider-bean-1]
----
====
`CommandNotFoundResultHandler` is a functional interface so it can
be writter as a lambda.
====
[source, java, indent=0]
----
include::{snippets}/CommandNotFoundSnippets.java[tag=provider-bean-2]
----
====

View File

@@ -7,29 +7,24 @@ Fortunately there is a simple way to instruct logging changes via boot propertie
Completely silence console logging by defining its pattern as an empty value.
====
[source, yaml]
----
logging:
pattern:
console:
----
====
If you need log from a shell then write those into a file.
====
[source, yaml]
----
logging:
file:
name: shell.log
----
====
If you need different log levels.
====
[source, yaml]
----
logging:
@@ -38,18 +33,15 @@ logging:
springframework:
shell: debug
----
====
Passing contiguration properties as command line options is not supported but
you can use any other ways supported by boot, for example.
====
[source, bash]
----
$ java -Dlogging.level.root=debug -jar demo.jar
$ LOGGING_LEVEL_ROOT=debug java -jar demo.jar
----
====
NOTE: In a GraalVM image settings are locked during compilation which means
you can't change log levels at runtime.

View File

@@ -10,7 +10,6 @@ command it may be beneficial to configure it for this. Property
runners than `NonInteractiveShellRunner` and configures it to use
defined _Primary Command_.
====
[source, yaml]
----
spring:
@@ -18,7 +17,6 @@ spring:
noninteractive:
primary-command: mycommand
----
====
For example if you have a command `mycommand` with option `arg`
it had to be executed with `<shellapp> mycommand --arg hi`, but with above

View File

@@ -21,49 +21,39 @@ no styling for colors and tries to not use any special figures.
Modify existing style by overriding settings.
====
[source, java, indent=0]
----
include::{snippets}/ThemingSnippets.java[tag=custom-style-class]
----
====
Modify existing figures by overriding settings.
====
[source, java, indent=0]
----
include::{snippets}/ThemingSnippets.java[tag=custom-figure-class]
----
====
To create a new theme, create a `ThemeSettings` and provide your own _style_
and _figure_ implementations.
====
[source, java, indent=0]
----
include::{snippets}/ThemingSnippets.java[tag=custom-theme-class]
----
====
Register a new bean `Theme` where you can return your custom `ThemeSettings`
and a _theme_ name.
====
[source, java, indent=0]
----
include::{snippets}/ThemingSnippets.java[tag=custom-theme-config]
----
====
You can use `ThemeResolver` to resolve _styles_ if you want to create
JLine-styled strings programmatically and _figures_ if you want to
theme characters for being more pretty.
====
[source, java, indent=0]
----
include::{snippets}/ThemingSnippets.java[tag=using-theme-resolver]
----
====

View File

@@ -9,23 +9,29 @@ 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"]
.Programmatic
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zeroorone-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zeroorone-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
.Legacy Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zeroorone-legacyannotation]
----
======
[[using-shell-options-arity-optionarity-table]]
.OptionArity
@@ -51,30 +57,35 @@ include::{snippets}/OptionSnippets.java[tag=option-registration-zeroorone-legacy
NOTE: `legacy annotation` doesn't support defining minimum arity.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
.Programmatic
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zerooronewithminmax-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-registration-zerooronewithminmax-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
.Legacy Annotation
----
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
@@ -89,4 +100,3 @@ Hello [one, two]
shell:>e2e reg arity-errors --arg1 one two three
Too many arguments --arg1 requires at most 2.
----
====

View File

@@ -7,9 +7,7 @@ ifndef::snippets[:snippets: ../../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

@@ -6,29 +6,23 @@ ifndef::snippets[:snippets: ../../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

@@ -8,12 +8,10 @@ ifndef::snippets[:snippets: ../../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`.

View File

@@ -8,20 +8,26 @@ xref:using-shell-options-optional.adoc[Optional Value], as there are cases where
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"]
.Programmatic
----
include::{snippets}/OptionSnippets.java[tag=option-default-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-default-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
.Legacy Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-default-legacyannotation]
----
======

View File

@@ -10,20 +10,24 @@ 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"]
.Programmatic
----
include::{snippets}/OptionSnippets.java[tag=option-label-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-label-annotation]
----
======
Defining label is then shown in `help`.
====
[source, bash]
----
my-shell:>help labelOption
@@ -38,4 +42,3 @@ OPTIONS
[Optional]
----
====

View File

@@ -16,22 +16,18 @@ 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
@@ -46,7 +42,6 @@ default via configuration properies only work if using
pre-configured `Builder` instance. See more
<<using-shell-commands-programmaticmodel>>.
====
[source, yaml]
----
spring:
@@ -59,21 +54,17 @@ spring:
# 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
@@ -89,12 +80,10 @@ OPTIONS
--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
@@ -111,4 +100,3 @@ OPTIONS
[Mandatory]
----
====

View File

@@ -8,40 +8,52 @@ a command target.
Making option optional.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
.Programmatic
----
include::{snippets}/OptionSnippets.java[tag=option-optional-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-optional-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
.Legacy Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-optional-legacyannotation]
----
======
Making option mandatory.
[tabs]
======
Programmatic::
+
[source,java,indent=0,role="primary"]
.Programmatic
----
include::{snippets}/OptionSnippets.java[tag=option-mandatory-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-mandatory-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
.Legacy Annotation
----
include::{snippets}/OptionSnippets.java[tag=option-mandatory-legacyannotation]
----
======

View File

@@ -5,12 +5,10 @@ ifndef::snippets[:snippets: ../../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.
@@ -27,36 +25,29 @@ 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
@@ -68,4 +59,3 @@ Hello [one, two]
shell:>arity-strings-2 one two three
Hello [one, two]
----
====

View File

@@ -6,42 +6,54 @@ ifndef::snippets[:snippets: ../../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"]
.Programmatic
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-string-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-string-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
.Legacy Annotation
----
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"]
.Programmatic
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-multiple-booleans-programmatic]
----
Annotation::
+
[source,java,indent=0,role="secondary"]
.Annotation
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-multiple-booleans-annotation]
----
Legacy Annotation::
+
[source,java,indent=0,role="secondary"]
.Legacy Annotation
----
include::{snippets}/ShortOptionSnippets.java[tag=option-type-multiple-booleans-legacyannotation]
----
======

View File

@@ -11,22 +11,18 @@ This section talks about how particular data type is used as an option value.
`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
@@ -35,14 +31,11 @@ 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
@@ -54,16 +47,12 @@ 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
@@ -75,26 +64,21 @@ 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
@@ -102,42 +86,32 @@ include::{snippets}/OptionTypesSnippets.java[tag=option-type-integer-reg]
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

@@ -7,7 +7,6 @@ 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.")
@@ -15,14 +14,11 @@ honored and trigger validation prior to the command executing. Consider the foll
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')
----
====

View File

@@ -9,18 +9,14 @@ Test support is provided by two modules: `spring-shell-test` contains core items
To test _interactive_ commands.
====
[source, java, indent=0]
----
include::{snippets}/TestingSnippets.java[tag=testing-shelltest-interactive]
----
====
To test _non-interactive_ commands.
====
[source, java, indent=0]
----
include::{snippets}/TestingSnippets.java[tag=testing-shelltest-noninteractive]
----
====

View File

@@ -10,19 +10,15 @@ lines and you don't want to handle those cases in a tests.
These can be changed using properties `spring.shell.test.terminal-width`
or `spring.shell.test.terminal-height`.
====
[source, java, indent=0]
----
include::{snippets}/TestingSnippets.java[tag=testing-shelltest-dimensions-props]
----
====
`ShellTest` annotation have fields `terminalWidth` and `terminalHeight`
which can also be used to change dimensions.
====
[source, java, indent=0]
----
include::{snippets}/TestingSnippets.java[tag=testing-shelltest-dimensions-field]
----
====

View File

@@ -5,12 +5,10 @@
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Lets start with a simple app which prints "hello world" in a view.
====
[source, java, indent=0]
----
include::{snippets}/TerminalUiSnippets.java[tag=snippet1]
----
====
There is not much to see here other than `TerminalUI` is a class handling
all logic aroung views and uses `View` as it's root view.