Editing pass

for a bunch of new content to support the new version.
This commit is contained in:
Jay Bryant
2022-05-27 14:39:38 -05:00
committed by Janne Valkealahti
parent 9779b5c729
commit 2af4e86925
34 changed files with 307 additions and 311 deletions

View File

@@ -1,8 +1,8 @@
=== Command Catalog
`CommandCatalog` is an interface defining how command registrations exists in
The `CommandCatalog` interface defines how command registrations exist in
a shell application. It is possible to dynamically register and de-register
commands which gives flexibility for a user cases where possible commands will
come and go depending on a states shell is at.
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]
@@ -12,9 +12,9 @@ include::{snippets}/CommandCatalogSnippets.java[tag=snippet1]
====
==== Command Resolver
`CommandResolver` is an interface you can implement and define as a bean to dynamically
resolve mappings from a command names to its `CommandRegistration` instances. Its use
case looks something like:
You can implement the `CommandResolver` interface and define a bean to dynamically
resolve mappings from a command's name to its `CommandRegistration` instances. Consider
the following example:
====
[source, java, indent=0]
@@ -23,18 +23,15 @@ include::{snippets}/CommandCatalogSnippets.java[tag=snippet2]
----
====
[IMPORTANT]
====
Current limitation of a `CommandResolver` is that it is used every time commands are resolved.
Thus it's adviced not to use it if command resolve call takes a long time as it would
make shell feel sluggish.
====
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
make the shell feel sluggish.
==== Command Catalog Customizer
`CommandCatalogCustomizer` is an interface which can be used to customize a `CommandCatalog`.
Its main use case is to modify catalog and within `spring-shell` _auto-configuration_ this
You can use the `CommandCatalogCustomizer` interface to customize a `CommandCatalog`.
Its main use is to modify a catalog. Also, within `spring-shell` auto-configuration, this
interface is used to register existing `CommandRegistration` beans into a catalog.
Its use case looks something like:
Consider the following example:
====
[source, java, indent=0]
@@ -43,4 +40,4 @@ include::{snippets}/CommandCatalogSnippets.java[tag=snippet3]
----
====
Create `CommandCatalogCustomizer` as a bean and `spring-shell` will handle rest.
You can create a `CommandCatalogCustomizer` as a bean, and Spring Shell handles the rest.

View File

@@ -1,6 +1,6 @@
=== Command Context
`CommandContext` is an interface which gives access to a currently executing
context. It can be used to get access to options:
The `CommandContext` interface gives access to a currently running
context. You can use it to get access to options:
====
[source, java, indent=0]
@@ -9,7 +9,7 @@ include::{snippets}/CommandContextSnippets.java[tag=snippet1]
----
====
If you need to print something into a shell you can get `Terminal`
If you need to print something into a shell, you can get a `Terminal`
and use its writer to print something:
====

View File

@@ -1,3 +1,3 @@
=== Command Execution
When _command parsing_ has done its job togethere with resolving _command registration_, execution
will do the hard work and execute a real user level code.
When command parsing has done its job and command registration has been resolved, command execution
does the hard work of running the code.

View File

@@ -1,3 +1,3 @@
=== Command Parser
Before a command can be executed we need to parse commands and options provided by a user. Parsing
sits between _command registration_ and _command execution_.
Before a command can be executed, we need to parse the command and whatever options the user may have provided. Parsing
comes between command registration and command execution.

View File

@@ -2,13 +2,13 @@
=== Command Registration
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Defining a command registation is a first step to introduce a structure of a commands and its options
and parameters. This is loosely decoupled what happens later like parsing command-line and executing
actual target code. Essentially it is a definition of an command API shown to a user.
Defining a command registration is a first step to introducing the structure of a command and its options
and parameters. This is loosely decoupled from what happens later, such as parsing command-line input and running
actual target code. Essentially, it is the definition of a command API that is shown to a user.
==== Commands
Command in a `spring-shell` structure is defined as an array of commands. This will give
you something like:
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]
@@ -20,27 +20,25 @@ command2 sub2 subsub2
----
====
[NOTE]
====
We don't currently support mapping commands to explicit parent if sub-commands are defined.
For example there can't be `command1 sub1` and `command1 sub1 subsub1` registered.
====
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.
==== Interaction Mode
Spring Shell has been designed to work on two modes one being interactive which essentially
is a `REPL` where you have an active shell instance throughout commands and secondly
non-interactive mode where commands are executed one by one from a command line.
Spring Shell has been designed to work on two modes: interactive (which essentially
is a `REPL` where you have an active shell instance throughout a series of commands) and
non-interactive (where commands are executed one by one from a command line).
Differentation between these modes are mostly around limitations what can be done
in each mode as for example it would not be feasible to show what was a previous stacktrace
of a command if shell is not alive anymore and generally things around information
if shell is alive or not.
Differentation between these modes is mostly around limitations about what can be done
in each mode. For example, it would not be feasible to show what was a previous stacktrace
of a command if the shell is no longer active. Generally, whether the shell is still active
dictates the available information.
Also being on an active `REPL` session may provide more info about what user has been
Also, being on an active `REPL` session may provide more information about what the user has been
doing within an active session.
==== Options
Options can be defined as long and short where prefixing is `--` and `-` respectively.
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]
@@ -57,11 +55,12 @@ include::{snippets}/CommandRegistrationSnippets.java[tag=snippet2]
====
==== Target
Target defines what is an execution target of a command. It can be a _method_ in a `POJO`,
`Consumer` or `Function`.
The target defines the execution target of a command. It can be a method in a POJO,
a `Consumer`, or a `Function`.
===== Method
Using a `Method` is a way to define target as a method in an existing pojo.
Using a `Method` in an existing POJO is one way to define a target.
Consider the following class:
====
[source, java, indent=0]
@@ -70,7 +69,7 @@ include::{snippets}/CommandTargetSnippets.java[tag=snippet11]
----
====
Having existing class shown above you can then register its method.
Given the existing class shown in the preceding listing, you can then register its method:
====
[source, java, indent=0]
@@ -81,9 +80,9 @@ include::{snippets}/CommandTargetSnippets.java[tag=snippet12]
===== Function
Using a `Function` as a target gives a lot of flexibility to handle what
happens in a command execution as you can handle many things manually using
a `CommandContext` given to a `Function`. Return type from a `Function` is
then what gets printed into a shell as a result.
happens in a command execution, because you can handle many things manually by using
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]
@@ -93,10 +92,10 @@ include::{snippets}/CommandTargetSnippets.java[tag=snippet2]
====
===== Consumer
Using a `Consumer` is basically same as `Function` with difference being
that there is not return type. If you need to print something into a shell
Using a `Consumer` is basically the same as using a `Function`, with the difference being
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.
through it. Consider the following example:
====
[source, java, indent=0]

View File

@@ -1,8 +1,8 @@
[appendix]
[#appendix-tech-intro]
== Techical Introduction
This section contains information for a developers and others who would like to know more about how _spring-shell_
internally works and what are its design decisions.
== Appendix: Techical Introduction
This appendix contains information for developers and others who would like to know more about how Spring Shell
works internally and what its design decisions are.
include::appendices-techical-intro-registration.adoc[]

View File

@@ -5,8 +5,8 @@ has a simple command to add two numbers.
=== Writing a Simple Boot Application
Starting with version 2, Spring Shell has been rewritten from the ground up with various
enhancements in mind, one of which is easy integration with Spring Boot, although it is
not a strong requirement.
enhancements in mind, one of which is easy integration with Spring Boot.
For the purpose of this tutorial, we create a simple Boot application by
using https://start.spring.io. This minimal application depends only on `spring-boot-starter`
and configures the `spring-boot-maven-plugin` to generate an executable über-jar:
@@ -29,7 +29,7 @@ and configures the `spring-boot-maven-plugin` to generate an executable über-ja
=== Adding a Dependency on Spring Shell
The easiest way to get going with Spring Shell is to depend on the `{starter-artifactId}` artifact.
This comes with everything one needs to use Spring Shell and plays nicely with Boot,
This comes with everything you need to use Spring Shell and plays nicely with Boot,
configuring only the necessary beans as needed:
====
@@ -45,7 +45,7 @@ configuring only the necessary beans as needed:
----
====
CAUTION: Given that Spring Shell starts the REPL by virtue of this dependency being present,
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`) throughout this tutorial or remove the sample integration test
that was generated by https://start.spring.io. If you do not remove it, the integration test creates
the Spring `ApplicationContext` and, depending on your build tool, stays stuck in the eval loop or crashes with a NPE.
@@ -57,7 +57,7 @@ Now we can add our first command. To do so, create a new class (named whatever y
annotate it with `@ShellComponent` (a variation of `@Component` that is used to restrict
the set of classes that are scanned for candidate commands).
Then create an `add` method that takes two ints (`a` and `b`) and returns their sum. Annotate it
Then we can create an `add` method that takes two ints (`a` and `b`) and returns their sum. We need to annotate it
with `@ShellMethod` and provide a description of the command in the annotation (the only piece of
information that is required):
@@ -115,6 +115,6 @@ shell:>add 1 2
----
====
Try to play with the shell (hint: there is a `help` command). When you are done, type `exit` and press `ENTER`.
You should play with the shell (hint: there is a `help` command). When you are done, type `exit` and press `ENTER`.
The rest of this document delves deeper into the whole Spring Shell programming model.

View File

@@ -1,5 +1,5 @@
= Spring Shell Reference Documentation
Eric Bottard; Janne Valkealahti; Jay Bryant, Corneil du Plessis;
Eric Bottard; Janne Valkealahti; Jay Bryant; Corneil du Plessis
:doctype: book
:hide-uri-scheme:
:icons: font

View File

@@ -1,16 +1,14 @@
== Introduction
=== What is Spring Shell?
Not all applications need a fancy web user interface!
== What is Spring Shell?
Not all applications need a fancy web user interface.
Sometimes, interacting with an application through an interactive terminal is
the most appropriate way to get things done.
Spring Shell lets you create such a runnable application, where the
user enters textual commands that are run until the program terminates.
The Spring Shell project provides the infrastructure to create such a REPL (Read, Eval,
Print Loop), letting you concentrate on the commands implementation by using
Print Loop) application, letting you concentrate on implementing commands by using
the familiar Spring programming model.
Advanced features such as parsing, tab completion, colorization of output, fancy ascii-art
table display, input conversion, and validation are all include, freeing you
Spring Shell includes advanced features (such as parsing, tab completion, colorization of
output, fancy ASCII-art table display, input conversion, and validation), freeing you
to focus on core command logic.

View File

@@ -1,28 +1,28 @@
[[using-shell-basics]]
=== Basics
You are here to learn basics of a _spring shell_. Before going forward to define actual _commands_ and _options_
lets take this moment to go trough some fundamental concepts of a _spring shell_.
This section covers the basics of Spring Shell. Before going on to define actual commands and options,
we need to go through some of the fundamental concepts of Spring Shell.
Essentially few things needs to happen before you have a working _spring shell_ app:
Essentially, a few things needs to happen before you have a working Spring Shell application:
- Create a _spring boot_ application
- Define commands and its option
- Package an application
- Execute either interactively or non-interactively
- Create a Spring Boot application.
- Define commands and options.
- Package the application.
- Run the application, either interactively or non-interactively.
You will get a full working _spring shell_ application without defining any user level commands
as some basic build-in commands are provided out of a box like `help` and `history`.
You can get a full working Spring Shell application without defining any user-level commands
as some basic built-in commands (such as `help` and `history`) are provided.
[NOTE]
====
Throughout this documentation we make a references to configuring something using
annotations which mostly relates to use of `@ShellMethod` and `@ShellOption` and
programmatic way which relates to use of `CommandRegistration`.
Throughout this documentation, we make references to configuring something by using
annotations (mostly relates to use of `@ShellMethod` and `@ShellOption`) and to the
programmatic way (which uses `CommandRegistration`).
Programmatic model is how things are actually registered even if you use annotations.
Annotations `@ShellMethod` and `@ShellOption` are considered as legacy feature
which we don't yet want to remove. `CommandRegistration` is a new development
The programmatic model is how things are actually registered, even if you use annotations.
The `@ShellMethod` and `@ShellOption` annotations are a legacy feature
that we do not yet want to remove. `CommandRegistration` is the new development
model where new features are added. We are most likely going to replace existing
annotations with something better order to support new features in a
annotations with something better, to support new features in a
`CommandRegistration` model.
====

View File

@@ -1,15 +1,16 @@
[[using-shell-building]]
=== Building
This section covers how to build a Spring Shell application.
[[native]]
==== Native Support
Re-work with _2.1.x_ brings in an experimental support for compiling shell application
into _native_ application with _GraalVM_ and _spring-native_. As underlying _jline_
library works with _GraalVM_ most of a things should just work.
Version 2.1.x includes experimental support for compiling Spring Shell applications
into native applications with GraalVM and Spring Native. Because the underlying JLine
library works with GraalVM, most things should just work.
Project can be compiled with native profile to get sample compiled as an native
application:
You can compile the project with a native profile to get a native application:
====
----
@@ -17,7 +18,7 @@ $ ./mvnw clean package -Pnative
----
====
You can then run sample either with interactive or non-interactive mode:
You can then run the application in either interactive or non-interactive mode:
====
----

View File

@@ -3,14 +3,14 @@ ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
When you use the standard API, methods on beans are turned into executable commands, provided that:
* The bean class bears the `@ShellComponent` annotation. This is used to restrict the set of beans
that are considered.
* The bean class bears the `@ShellComponent` annotation. (This is used to restrict the set of beans
that are considered.)
* The method bears the `@ShellMethod` annotation.
[TIP]
====
The `@ShellComponent` is a stereotype annotation that is itself meta-annotated with `@Component`. As a result,
you can used it in addition to the filtering mechanism to declare beans (for example, by using `@ComponentScan`).
you can use it in addition to the filtering mechanism to declare beans (for example, by using `@ComponentScan`).
You can customize the name of the created bean by using the `value` attribute of the annotation.
====
@@ -26,15 +26,12 @@ The only required attribute of the `@ShellMethod` annotation is its `value` attr
a short, one-sentence, description of what the command does. This lets your users
get consistent help about your commands without having to leave the shell (see <<help-command>>).
[NOTE]
====
The description of your command should be short -- no more than one or two sentences. For better
consistency, it should starts with a capital letter and end with a period.
====
NOTE: The description of your command should be short -- no more than one or two sentences. For better
consistency, it should start with a capital letter and end with a period.
By default, there is no need to specify the key for your command (that is, the word(s) that should be used
By default, you need not specify the key for your command (that is, the word(s) that should be used
to invoke it in the shell). The name of the method is used as the command key, turning camelCase names into
dashed, gnu-style, names (that is, `sayHello()` becomes `say-hello`).
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:
@@ -45,15 +42,9 @@ include::{snippets}/AnnotationRegistrationSnippets.java[tag=snippet2]
----
====
[NOTE]
====
The `key` attribute accepts multiple values.
NOTE: The `key` attribute accepts multiple values.
If you set multiple keys for a single method, the command is registered with those different aliases.
====
[TIP]
====
The command key can contain pretty much any character, including spaces. When coming up with names though,
keep in mind that consistency is often appreciated by users (that is, you should avoid mixing dashed-names with
spaced names and other inconsistencies).
====
TIP: The command key can contain pretty much any character, including spaces. When coming up with names though,
keep in mind that consistency is often appreciated by users. That is, you should avoid mixing dashed-names with
spaced names and other inconsistencies.

View File

@@ -3,13 +3,13 @@
Registered commands do not always make sense, due to the internal state of the application.
For example, there may be a `download` command, but it only works once the user has used `connect` on a remote
server. Now, if the user tries to use the `download` command, the shell should gracefully explain that
the command exist but that it is not available at the time.
server. Now, if the user tries to use the `download` command, the shell should explain that
the command exists but that it is not available at the time.
Spring Shell lets you do that, even letting you provide a short explanation of the reason for
the command not being available.
There are three possible ways for a command to indicate availability.
They all leverage a no-arg method that returns an instance of `Availability`.
They all use a no-arg method that returns an instance of `Availability`.
Consider the following example:
====
@@ -87,7 +87,7 @@ can provide an explicit name by using the `@ShellMethodAvailability` annotation:
<1> the names have to match
====
Lastly, it is often the case that several commands in the same class share the same internal state and, thus,
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:

View File

@@ -4,26 +4,26 @@
When your shell starts to provide a lot of functionality, you may end up
with a lot of commands, which could be confusing for your users. By typing `help`,
they would see a daunting list of commands, organized in alphabetical order,
which may not always make sense.
which may not always be the best way to show the available commands.
To alleviate this possible confusion, Spring Shell provides the ability to group commands together,
with reasonable defaults. Related commands would then end up in the same group (for example, `User Management Commands`)
and be displayed together in the help screen and other places.
By default, commands are grouped according to the class they are implemented in,
turning the camel case class name into separate words (so `URLRelatedCommands` becomes `URL Related Commands`).
This is a very sensible default, as related commands are often already in the class anyway,
turning the camelCase class name into separate words (so `URLRelatedCommands` becomes `URL Related Commands`).
This is a sensible default, as related commands are often already in the class anyway,
because they need to use the same collaborating objects.
If, however, this behavior does not suit you, you can override the group for a
command in the following ways, in order of priority:
. Specifying a `group()` in the `@ShellMethod` annotation.
. Placing a `@ShellCommandGroup` on the class in which the command is defined. This applies
. Specify a `group()` in the `@ShellMethod` annotation.
. Place a `@ShellCommandGroup` on the class in which the command is defined. This applies
the group for all commands defined in that class (unless overridden, as explained earlier).
. Placing a `@ShellCommandGroup` on the package (through `package-info.java`)
. Place a `@ShellCommandGroup` on the package (through `package-info.java`)
in which the command is defined. This applies to all the commands defined in the
package (unless overridden at the method or class level, as explained earlier)
package (unless overridden at the method or class level, as explained earlier).
The following listing shows an example:

View File

@@ -1,7 +1,7 @@
==== Programmatic Model
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
`CommandRegistration` can be defined as a `@Bean` and it's automatically registered.
In the programmatic model, `CommandRegistration` is defined as a `@Bean`, and it is automatically registered:
====
[source, java, indent=0]

View File

@@ -1,15 +1,15 @@
=== Commands
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
In this section we go through an actual command registration and leave command options
and execution later in a documentation. More detailed info can be found from
In this section, we go through an actual command registration and leave command options
and execution for later in a documentation. You can find more detailed info in
<<appendix-tech-intro-registration>>.
There are two different ways to define a command. Firstly through an annotation model and
secondly through programmatic model. Annotation model if where you define your methods
in a class and annotate class and methods with a spesific annotations. Programmatic model
is where things are done on a more low level ways by defining command registrations either
as beans or registering those with a command catalog dynamically.
There are two different ways to define a command: through an annotation model and
through a programmatic model. In the annotation model, you define your methods
in a class and annotate the class and the methods with specific annotations. In the programmatic model,
you use a more low level approach, defining command registrations (either
as beans or by dynamically registering with a command catalog).
include::using-shell-commands-annotationmodel.adoc[]

View File

@@ -2,17 +2,18 @@
==== Built-In Commands
Any application built by using the `{starter-artifactId}` artifact
(or, to be more precise, the `spring-shell-standard-commands` dependency) comes with a set of built-in commands.
(which equates to the `spring-shell-standard-commands` dependency) comes with a set of built-in commands.
You can override or disable these commands individually (see <<overriding-or-disabling-built-in-commands>>).
However, if they are not overridden or disabled, this section describes their behavior.
[[help-command]]
===== Help
Running a shell application often implies that the user is in a graphically limited environment. Also, while we are
nearly always connected in the era of mobile phones, accessing a web browser or any other rich UI application
(such as a PDF viewer) may not always be possible. This is why it is important that the shell commands are correctly
self documented, and this is where the `help` command comes in.
Running a shell application often implies that the user is in a graphically limited
environment. Also, while we are nearly always connected in the era of mobile phones,
accessing a web browser or any other rich UI application (such as a PDF viewer) may not always
be possible. This is why it is important that the shell commands are correctly self-documented, and this is where the `help`
command comes in.
Typing `help` + `ENTER` lists all the commands known to the shell (including <<dynamic-command-availability,unavailable>> commands)
and a short description of what they do, similar to the following:
@@ -97,7 +98,7 @@ commands to disk, so that they are available again (see <<interacting-with-the-s
When an exception occurs inside command code, it is caught by the shell and a simple, one-line message is displayed
so as not to overflow the user with too much information.
There are cases though when understanding what exactly happened is important (especially if the exception has a nested cause).
There are cases, though, when understanding what exactly happened is important (especially if the exception has a nested cause).
To this end, Spring Shell remembers the last exception that occurred, and the user can later use the `stacktrace`
command to print all the details on the console.
@@ -112,47 +113,44 @@ to be comments and are ignored, while lines ending with `\` trigger line continu
===== History
The `history` command shows history of a commands which has been executed.
The `history` command shows the history of commands that has been executed.
There are few configuration options which can be used to configure behaviour
of a history. History is kept in a log file which is enabled by default and can
be turned off using `spring.shell.history.enabled`. Name of a log file
is resolved from `spring.application.name` and defaults to _spring-shell.log_
which can be changed using `spring.shell.history.name`.
There are a few configuration options that you can use to configure behavior
of a history. History is kept in a log file, which is enabled by default and can
be turned off by setting `spring.shell.history.enabled`. The name of a log file
is resolved from `spring.application.name` and defaults to `spring-shell.log`,
which you can change by setting `spring.shell.history.name`.
On default a log file is generated to a current working directory which can be
changed using `spring.shell.config.location`. This property can contain
a placeholder _{userconfig}_ which resolves to a common shared config directory.
By default, a log file is generated to a current working directory, which you can dictate
by setting `spring.shell.config.location`. This property can contain
a placeholder (`{userconfig}`), which resolves to a common shared config directory.
[TIP]
====
Check how sample app works as it's using these options.
====
TIP: Run the Spring Shell application to see how the sample application works as it uses these options.
===== Completion
The `completion` command set allows you to create _scripts_ files which can be used
with am OS shell implementations to provide completion. This is very usefull when
The `completion` command set lets you create script files that can be used
with am OS shell implementations to provide completion. This is very useful when
working with non-interactive mode.
Currently only implementation is for _bash_ which works with `bash` sub-command.
Currently, the only implementation is for bash, which works with `bash` sub-command.
===== Version
The `version` command shows existing _build_ and _git_ info by integrating into
Boot's `BuildProperties` and `GitProperties` if those exists in a shell app.
On default only version info is shown and other can be enabled via configuration
The `version` command shows existing build and git info by integrating into
Boot's `BuildProperties` and `GitProperties` if those exist in the shell application.
By default, only version information is shown, and you can enable other information through configuration
options.
Settings are under `spring.shell.command.version` where you can use `enabled` to
disable command and optionally define your own template with `template`. Options
The relevant settings are under `spring.shell.command.version`, where you can use `enabled` to
disable a command and, optionally, define your own template with `template`. You can use the
`show-build-artifact`, `show-build-group`, `show-build-name`, `show-build-time`,
`show-build-version`, `show-git-branch`, `show-git-commit-id`,
`show-git-short-commit-id` and `show-git-commit-time` can be used to control
`show-git-short-commit-id` and `show-git-commit-time` commands to control
fields in a default template.
Template default to `classpath:template/version-default.st` and you can define
your own, for example having:
The template defaults to `classpath:template/version-default.st`, and you can define
your own, as the following example shows:
====
[source]
@@ -161,7 +159,7 @@ your own, for example having:
----
====
Which would simply output something like:
This setting would output something like the following:
====
[source]
@@ -170,6 +168,6 @@ X.X.X
----
====
Attributes added to default template rendering are `buildVersion`, `buildGroup`,
You can add the following attributes to the default template rendering: `buildVersion`, `buildGroup`,
`buildGroup`, `buildName`, `buildTime`, `gitShortCommitId`, `gitCommitId`,
`gitBranch` and `gitCommitTime`.
`gitBranch`, and `gitCommitTime`.

View File

@@ -2,13 +2,13 @@
==== Flow
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
When using <<using-shell-components-ui>> to build something which involves
use of a multiple components your implemention may become a bit cluttered.
Nothing wrong with that but to ease these use cases we've build a
`ComponentFlow` which is able to hook multiple component executions together
as a _flow_.
When you use <<using-shell-components-ui>> to build something that involves
use of a multiple components, your implementation may become a bit cluttered.
To ease these use cases, we added a
`ComponentFlow` that can hook multiple component executions together
as a "`flow`".
Here is some examples of a flows and what it looks like in a shell:
The following listings show examples of flows and their output in a shell:
====
[source, java, indent=0]
@@ -29,5 +29,5 @@ include::{snippets}/FlowComponentSnippets.java[tag=snippet2]
image::images/component-flow-conditional-1.svg[text input]
Results from running a flow returns `ComponentFlowResult` which you can
use to do furher actions.
TIP: The result from running a flow returns `ComponentFlowResult`, which you can
use to do further actions.

View File

@@ -2,8 +2,8 @@
===== Confirmation
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Used to ask a simple confirmation from a user and essentially is
yes/no question.
The confirmation component asks a user for a simple confirmation. It is essentially a
yes-or-no question.
====
[source, java, indent=0]
@@ -12,18 +12,20 @@ include::{snippets}/UiComponentSnippets.java[tag=snippet5]
----
====
The following image shows the typical output from a confirmation component:
image::images/component-confirmation-1.svg[text input]
Context object is `ConfirmationInputContext`.
The context object is `ConfirmationInputContext`. The following table describes its context variables:
[[confirmationinputcontext-template-variables]]
.ConfirmationInputContext Template Variables
|===
|Key |Description
|defaultValue
|Default value, either true or false.
|`defaultValue`
|The default value -- either `true` or `false`.
|model
|Parent context variables <<textcomponentcontext-template-variables>>
|`model`
|The parent context variables (see <<textcomponentcontext-template-variables>>).
|===

View File

@@ -2,7 +2,8 @@
===== Multi Select
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Used to ask an items from a list.
The multi select component asks a user to select multiple items from a list.
The following listing shows an example:
====
[source, java, indent=0]
@@ -11,21 +12,23 @@ include::{snippets}/UiComponentSnippets.java[tag=snippet7]
----
====
The following image shows a typical multi-select component:
image::images/component-multi-select-1.svg[text input]
Context object is `MultiItemSelectorContext`.
The context object is `MultiItemSelectorContext`. The following table describes its context variables:
[[multiitemselectorcontext-template-variables]]
.MultiItemSelectorContext Template Variables
|===
|Key |Description
|values
|Returned values when component exists.
|`values`
|The values returned when the component exists.
|rows
|Visible items where rows list contains maps of name, selected, onrow and enabled items.
|`rows`
|The visible items, where rows contain maps of name, selected, on-row, and enabled items.
|model
|Parent context variables <<selectorcomponentcontext-template-variables>>
|`model`
|The parent context variables (see <<selectorcomponentcontext-template-variables>>).
|===

View File

@@ -2,7 +2,7 @@
===== Path Input
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Used to ask a `Path` from a user and gives additional info about a path itself.
The path input component asks a user for a `Path` and gives additional information about a path itself.
====
[source, java, indent=0]
@@ -11,15 +11,17 @@ include::{snippets}/UiComponentSnippets.java[tag=snippet4]
----
====
The following image shows typical output from a path input component:
image::images/component-path-input-1.svg[text input]
Context object is `PathInputContext`.
The context object is `PathInputContext`. The following table describes its context variables:
[[pathinputcontext-template-variables]]
.PathInputContext Template Variables
|===
|Key |Description
|model
|Parent context variables <<textcomponentcontext-template-variables>>
|`model`
|The parent context variables (see <<textcomponentcontext-template-variables>>).
|===

View File

@@ -2,17 +2,17 @@
===== Component Render
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
There are two ways to implement component rendering, firstly fully
programmatically or secondly using a _ANTLR Stringtemplate_. Though
strictly speaking there is just a simple `Function` renderer interface
which takes `Context` as an input and outputs a list of `AttributedString`
but this allows to choose between _templating_ and _code_.
You can implement component rendering in either of two ways: fully
programmatically or by using a _ANTLR Stringtemplate_.
Strictly speaking, there is a simple `Function` renderer interface
that takes `Context` as an input and outputs a list of `AttributedString`.
This lets you choose between templating and code.
Templating is a good choice if you don't need to anything complex or
Templating is a good choice if you do not need to do anything complex or
you just want to slightly modify existing component layouts. Rendering
via code then gives you flexibility to do whatever you need.
through code then gives you flexibility to do whatever you need.
Programmatic way to render is simple as to create a `Function`:
The programmatic way to render is to create a `Function`:
====
[source, java, indent=0]
@@ -21,7 +21,7 @@ include::{snippets}/UiComponentSnippets.java[tag=snippet1]
----
====
And then hook it with a component:
Then you can hook it to a component:
====
[source, java, indent=0]
@@ -30,37 +30,37 @@ include::{snippets}/UiComponentSnippets.java[tag=snippet2]
----
====
Component have their own context but usually shares some functionality
from a parent component types, those context variables are shown below.
Components have their own context but usually share some functionality
from a parent component types. The following tables show those context variables:
[[textcomponentcontext-template-variables]]
.TextComponentContext Template Variables
|===
|Key |Description
|resultValue
|Value after component renders its result.
|`resultValue`
|The value after a component renders its result.
|name
|Name of a component, aka its title.
|`name`
|The name of a component -- that is, its title.
|message
|Possible message set for component.
|`message`
|The possible message set for a component.
|messageLevel
|Level of a message, either INFO, WARN or ERROR
|`messageLevel`
|The level of a message -- one of `INFO`, `WARN`, or `ERROR`.
|hasMessageLevelInfo
|Return true if level is INFO, false otherwise.
|`hasMessageLevelInfo`
|Return `true` if level is `INFO`. Otherwise, false.
|hasMessageLevelWarn
|Return true if level is WARN, false otherwise.
|`hasMessageLevelWarn`
|Return `true` if level is `WARN`. Otherwise, false.
|hasMessageLevelError
|Return true if level is ERROR, false otherwise.
|`hasMessageLevelError`
|Return `true` if level is `ERROR`. Otherwise, false.
|input
|Raw user input.
|`input`
|The raw user input.
|===
@@ -70,22 +70,22 @@ from a parent component types, those context variables are shown below.
|===
|Key |Description
|name
|Name of a component, aka title.
|`name`
|The name of a component -- that is, its title.
|input
|Raw user input, mostly for filter.
|`input`
|The raw user input -- mostly used for filtering.
|itemStates
|Full list of item states.
|`itemStates`
|The full list of item states.
|itemStateView
|Visible list of item states.
|`itemStateView`
|The visible list of item states.
|isResult
|Return if context is in a result mode.
|`isResult`
|Return `true` if the context is in a result mode.
|cursorRow
|Current cursor row in a selector
|`cursorRow`
|The current cursor row in a selector.
|===

View File

@@ -2,8 +2,8 @@
===== Single Select
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Used to ask an item from a list and is essentially similar to simple
dropbox implementation.
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]
@@ -12,27 +12,30 @@ include::{snippets}/UiComponentSnippets.java[tag=snippet6]
----
====
The following image shows typical output for a single select component:
image::images/component-single-select-1.svg[text input]
Context object is `SingleItemSelectorContext`.
The context object is `SingleItemSelectorContext`. The following table describes its context variables:
[[singleitemselectorcontext-template-variables]]
.SingleItemSelectorContext Template Variables
|===
|Key |Description
|value
|Returned value when component exists.
|`value`
|The returned value when the component exists.
|rows
|Visible items where rows list contains maps of name and selected items.
|`rows`
|The visible items, where rows contains maps of name and selected items.
|model
|Parent context variables <<selectorcomponentcontext-template-variables>>
|`model`
|The parent context variables (see <<selectorcomponentcontext-template-variables>>).
|===
It's possible to pre-select an item by defining it to get exposed. This is
useful if default is known and user can then just hit enter.
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]

View File

@@ -2,8 +2,8 @@
===== String Input
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Used to ask a simple text input from a user, optionally masking values
if content contains something sensitive.
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]
@@ -12,31 +12,32 @@ include::{snippets}/UiComponentSnippets.java[tag=snippet3]
----
====
The following image shows typical output from a string input component:
image::images/component-text-input-1.svg[text input]
Context object is `StringInputContext`.
The context object is `StringInputContext`. The following table lists its context variables:
[[stringinputcontext-template-variables]]
.StringInputContext Template Variables
|===
|Key |Description
|defaultValue
|Default value if set, null otherwise.
|`defaultValue`
|The default value, if set. Otherwise, null.
|maskedInput
|Masked input value
|`maskedInput`
|The masked input value
|maskedResultValue
|Masked result value
|`maskedResultValue`
|The masked result value
|maskCharacter
|Mask character if set, null otherwise.
|`maskCharacter`
|The mask character, if set. Otherwise, null.
|hasMaskCharacter
|Is true if mask character is set, false otherwise.
|`hasMaskCharacter`
|`true` if a mask character is set. Otherwise, false.
|model
|Parent context variables <<textcomponentcontext-template-variables>>
|`model`
|The parent context variables (see <<textcomponentcontext-template-variables>>).
|===

View File

@@ -2,27 +2,24 @@
==== Flow Components
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Starting from _2.1.x_ there is a new component model which provides
easier way to create higher level user interaction for usual use cases
like asking input in a various forms. These usually are just plain text
Starting from version 2.1.x, a new component model provides an
easier way to create higher-level user interaction for the usual use cases,
such as asking for input in various forms. These usually are just plain text
input or choosing something from a list.
Templates for build-in components are in classpath under
_org/springframework/shell/component_.
Templates for built-in components are in the
`org/springframework/shell/component` classpath.
Build-in components generally follow logic:
Built-in components generally follow this logic:
* Enter run loop for user input
* Generate component related context
* Render runtime status of a component state
* Exit
* Render final status of a component state
. Enter a run loop for user input.
. Generate component-related context.
. Render the runtime status of a component state.
. Exit.
. Render the final status of a component state.
[NOTE]
====
<<using-shell-components-flow>> gives better interface defining flow of a
components which better suited for defining interactive command flows.
====
NOTE: <<using-shell-components-flow>> gives better interface for defining the flow of
components that are better suited for defining interactive command flows.
include::using-shell-components-ui-render.adoc[]

View File

@@ -1,12 +1,12 @@
[[styling]]
==== Styling
Starting with _2.1.x_ there is a support for centrally handling styling and theming.
There is a default theme named _default_ which can be changed using property
`spring.shell.theme.name`.
Version 2.1.x introduced support for centrally handling styling and theming.
You can change the default theme (named `default`)by setting the
`spring.shell.theme.name` property.
To create a new theme register new `Theme` bean with custom `ThemeSettings` where
you can tweak styles.
To create a new theme, register a new `Theme` bean with custom `ThemeSettings`. This new bean
lets you tweak styles. The following example shows how to do so:
====
[source, java]
@@ -34,8 +34,8 @@ static class MyThemeSettings extends ThemeSettings {
----
====
`ThemeResolver` can be used to resolve styles if you want to create
_jline_ styled strings programmatically.
You can use `ThemeResolver` to resolve styles if you want to create
JLine-styled strings programmatically. The following example shows how to do so:
====
[source, java]

View File

@@ -1,6 +1,8 @@
[[using-shell-customization]]
=== Customization
This section describes how you can customize the shell.
include::using-shell-customization-generic.adoc[]
include::using-shell-customization-styling.adoc[]

View File

@@ -1,18 +1,20 @@
=== Execution
This section describes how to set up a Spring Shell to work in interactive mode.
==== Interaction Mode
Starting from _2.1.x_ a build-in support has been added to distinguish between interactive
and non-interactive modes. This has been added so that it's easier to use shell as a
simple command-line tool without requiring customisation to accomplish that.
Version 2.1.x introduced built-in support to distinguish between interactive
and non-interactive modes. This makes it easier to use the shell as a
simple command-line tool without requiring customization.
Currently interactive mode is entered if any command line options are passed when starting
or running a shell from a command-line. This especially works well when shell application
Currently, interactive mode is entered if any command line options are passed when starting
or running a shell from a command line. This works especially well when a shell application
is compiled with <<native>>.
Some commands may not have any usefull meaning if running on interactive mode
or vice versa on non-interactive mode. For example a build-in `exit` command
have no meaning in non-interactive mode as it's used to exit interactive mode.
Some commands may not have any useful meanings when they run in interactive mode
or (conversely) in non-interactive mode. For example, a built-in `exit` command would
have no meaning in non-interactive mode, because it is used to exit interactive mode.
Annotation `@ShellMethod` has a field `interactionMode` which can be used to instruct
shell when particular command is available.
The `@ShellMethod` annotation has a field called `interactionMode` that you can use to inform
shell about when a particular command is available.

View File

@@ -2,9 +2,9 @@
==== Arity
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 operation happens. Arity is defined as min and max
values where min must be positive integer and max has to be more or equal to min.
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.
====
[source, java, indent=0]
@@ -13,8 +13,8 @@ include::{snippets}/OptionSnippets.java[tag=option-registration-arityints]
----
====
Arity can also be defined as an `OptionArity` enum which are shortcuts
with table shown below.
Arity can also be defined as an `OptionArity` enum, which are shortcuts
within the following table:
====
[source, java, indent=0]
@@ -43,7 +43,7 @@ include::{snippets}/OptionSnippets.java[tag=option-registration-arityenum]
|1 / Integer MAX
|===
Annotation model only supports defining _max_ value of an arity.
The annotation model supports defining only the max value of an arity.
====
[source, java, indent=0]

View File

@@ -3,9 +3,9 @@
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Having a default value for an option is somewhat related to
<<using-shell-options-optional>> as there are cases where you
may want to know if user defined an option and make a difference
based on a default value.
<<using-shell-options-optional>>, as there are cases where you
may want to know if the user defined an option and change behavior
based on a default value:
====
[source, java, indent=0]
@@ -14,7 +14,7 @@ include::{snippets}/OptionSnippets.java[tag=option-registration-default]
----
====
With an annotation model default value can be defined.
The annotation model also supports defining default values:
====
[source, java, indent=0]

View File

@@ -2,8 +2,8 @@
==== Optional Value
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Option is either required or not and it generally speaking depends on
a command target how this behaves.
An option is either required or not and, generally speaking, how it behavesit depends on
a command target:
====
[source, java, indent=0]
@@ -12,8 +12,8 @@ include::{snippets}/OptionSnippets.java[tag=option-registration-optional]
----
====
With an annotation model there is no direct way to define if argument is
optional, instead it's instructed to be _NULL_.
In the annotation model, there is no direct way to define if argument is
optional. Instead, it is instructed to be `NULL`.:
====
[source, java, indent=0]

View File

@@ -2,7 +2,7 @@
==== Positional
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]
Positional information is mostly related to a command target method.
Positional information is mostly related to a command target method:
====
[source, java, indent=0]

View File

@@ -4,7 +4,7 @@
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 as well as annotations at the method level are
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:
====
@@ -31,6 +31,6 @@ The following constraints were not met:
.Applies to All Command Implementations
====
It is important to note that bean validation applies to all command implementations,
whether they use the "standard" API or any other API, through the use of an adapter
(see <<support-for-shell-1-and-jcommander,Supporting Other APIs>>)
whether they use the "`standard`" API or any other API, through the use of an adapter
(see <<support-for-shell-1-and-jcommander,Supporting Other APIs>>).
====

View File

@@ -3,11 +3,11 @@ This section describes how to use Spring Shell.
[IMPORTANT]
====
_Spring Shell 2.1.x_ is a major rework to bring codebase up-to-date with
existing _Spring Boot_ versions, adding new features and especially
making it work with _GraalVM_ which makes command-line applications much
more relevant on a java space. Moving to new major version also allows
us to clean up codebase and make some needed breaking changes.
Spring Shell 2.1.x is a major rework to bring the codebase up to date with
existing Spring Boot versions, adding new features and, especially,
making it work with GraalVM which makes command-line applications much
more relevant in a Java space. Moving to a new major version also lets
us clean up the codebase and make some needed breaking changes.
====
include::using-shell-basics.adoc[]