==== Invoking your Commands

This section addresses how you can control the way in which your commands are invoked.

===== By Name Versus Positional Parameters

As seen <<documenting-the-command,earlier>>, decorating a method with `@ShellMethod` is the sole requirement for creating a command.

The user can set the value of all the method parameters in either of two ways:

* By using a parameter key (for example, `--arg value`). This approach is called "`by name parameters.`"
* Without a key, by setting parameter values in the order in which they appear in the method signature (called "`positional parameters`").

These two approaches can be mixed and matched, with named parameters always taking precedence (as they are less
prone to ambiguity). Consider the following command definition:

====
[source, java]
----
	@ShellMethod("Display stuff.")
	public String echo(int a, int b, int c) {
		return String.format("You said a=%d, b=%d, c=%d", a, b, c);
	}
----
====

Given the preceding command definiton, the following invocations are all equivalent, as shown in the output:

====
[source, bash]
----
shell:>echo 1 2 3               <1>
You said a=1, b=2, c=3

shell:>echo --a 1 --b 2 --c 3   <2>
You said a=1, b=2, c=3

shell:>echo --b 2 --c 3 --a 1   <3>
You said a=1, b=2, c=3

shell:>echo --a 1 2 3           <4>
You said a=1, b=2, c=3

shell:>echo 1 --c 3 2           <5>
You said a=1, b=2, c=3
----
<1> This uses positional parameters.
<2> This is an example of full by-name parameters.
<3> By-name parameters can be reordered as desired.
<4> You can use a mix of the two approaches.
<5> The non by-name parameters are resolved in the order in which they appear.
====

====== Customizing the Named Parameter Keys

As seen <<your-first-command,earlier>>, the default strategy for deriving the key for a named parameter is to use the Java
name of the method signature and prefix it with two dashes (`--`). You can customize this in two ways:

* Use the `prefix()` attribute of the `@ShellMethod` annotation to change the default prefix for the whole method.
* Annotate the parameter with the `@ShellOption` annotation to override the entire key in a per-parameter fashion.

Consider the following example:

====
[source, java]
----
	@ShellMethod(value = "Display stuff.", prefix="-")
	public String echo(int a, int b, @ShellOption("--third") int c) {
		return String.format("You said a=%d, b=%d, c=%d", a, b, c);
	}
----
====

For such a setup, the possible parameter keys are `-a`, `-b` and `--third`.

[TIP]
=====
You can specify several keys for a single parameter. If you do so, these keys are mutually exclusive (only one of them can be used) ways
to specify the same parameter. The following example shows the signature of the
built-in <<built-in-commands-help,`help`>> command:

====
[source, java]
----
	@ShellMethod("Describe a command.")
	public String help(@ShellOption({"-C", "--command"}) String command) {
		...
	}
----
====
=====

[[optional-parameters-default-values]]
===== Optional Parameters and Default Values

Spring Shell provides the ability to give parameters default values, which lets users omit
those parameters. Consider the following command definition:

====
[source, java]
----
	@ShellMethod("Say hello.")
	public String greet(@ShellOption(defaultValue="World") String who) {
		return "Hello " + who;
	}
----
====

With the preceding definition, the `greet` command can still be invoked as `greet Mother` (or `greet --who Mother`), but the following
is also possible:

====
[source]
----
shell:>greet
Hello World
----
====

===== Parameter Arity
Up to now, it has always been assumed that each parameter maps to a single word entered by the user.
Situations may arise, though, when a parameter value should be multi-valued. This is driven by the `arity()`
attribute of the `@ShellOption` annotation. You can use a collection or array for the parameter type and specify how
many values are expected:

====
[source, java]
----
	@ShellMethod("Add Numbers.")
	public float add(@ShellOption(arity=3) float[] numbers) {
		return numbers[0] + numbers[1] + numbers[2];
	}
----
====

The users can then invoke the command by using any of the following syntax:

====
[source]
----
shell:>add 1 2 3.3
6.3
shell:>add --numbers 1 2 3.3
6.3
----
====

[WARNING]
=====
When using the _by-name_ parameter approach, the key should *not* be repeated. The following does *not* work:

====
[source]
----
shell:>add --numbers 1 --numbers 2 --numbers 3.3
----
====
=====

====== Varying Amount Arity

The above example demonstrates requiring a known, constant arity for a parameter, three in this case. Allowing any number of multiple values of a parameter can be achieved by leaving `arity` unspecified and using Spring's built-in comma separated value parsing for collections and/or arrays:
[source, java]
----
	@ShellMethod("Add a Varying Amount of Numbers.")
	public double add(@ShellOption double[] numbers) {
		return Arrays.stream(numbers).sum();
	}
----

The command may then be invoked with any amount of `numbers`:

====
[source]
----
shell:>add 1,2,3.3
6.3
shell:>add --numbers 42
42.0
shell:>add --numbers 1,2,3.3,4,5
15.3
----
====

====== Special Handling of Boolean Parameters

When it comes to parameter arity, one kind of parameter receives a special treatment by default, as
is often the case in command-line utilities.
Boolean (that is, `boolean` as well as `java.lang.Boolean`) parameters behave like they have an `arity()` of `0` by default, allowing users to set their values by using a "`flag`" approach.
Consider the following command definition:

====
[source, java]
----
	@ShellMethod("Terminate the system.")
	public String shutdown(boolean force) {
		return "You said " + force;
	}
----
====

This preceding command definition allows the following invocations:

====
[source]
----
shell:>shutdown
You said false
shell:>shutdown --force
You said true
----
====

TIP: This special treatment plays well with the <<optional-parameters-default-values,default value>> specification. Although the default
for boolean parameters is to have their default value be `false`, you can specify otherwise (that is,
`@ShellOption(defaultValue="true")`), and the behavior is inverted (that is, not specifying the parameter
results in the value being `true`, and specifying the flag results in the value being `false`)

[WARNING]
=====
Having this behavior of implicit `arity()=0` prevents the user from specifying a value (for example, `shutdown --force true`).
If you would like to allow this behavior (and forego the flag approach), then force an arity of `1` by using the annotation as follows:

====
[source, java]
----
	@ShellMethod("Terminate the system.")
	public String shutdown(@ShellOption(arity=1, defaultValue="false") boolean force) {
		return "You said " + force;
	}
----
====
=====

[[quotes-handling]]
===== Quotes Handling

Spring Shell takes user input and tokenizes it into words, splitting on space characters.
If the user wants to provide a parameter value that contains spaces, that value needs to be quoted.
Both single (`'`) and double (`"`) quotes are supported, and those quotes are not part of the value:
Consider the following command definition:

====
[source, java]
----
	@ShellMethod("Prints what has been entered.")
	public String echo(String what) {
		return "You said " + what;
	}
----
====

The following commands all invoke the preceding command definition:

====
[source]
----
shell:>echo Hello
You said Hello
shell:>echo 'Hello'
You said Hello
shell:>echo 'Hello World'
You said Hello World
shell:>echo "Hello World"
You said Hello World
----
====

Supporting both single and double quotes lets the user embed one type of quotes into
a value:

====
[source]
----
shell:>echo "I'm here!"
You said I'm here!
shell:>echo 'He said "Hi!"'
You said He said "Hi!"
----
====

That way, the user can use a single quote as an apostrophe in a message.

Should the user need to embed the same kind of quote that was used to quote the whole parameter,
the escape sequence uses the backslash (`\`) character:

====
[source]
----
shell:>echo 'I\'m here!'
You said I'm here!
shell:>echo "He said \"Hi!\""
You said He said "Hi!"
shell:>echo I\'m here!
You said I'm here!
----
====

It is also possible to escape space characters when not using enclosing quotes:

====
[source]
----
shell:>echo This\ is\ a\ single\ value
You said This is a single value
----
====

[[interacting-with-the-shell]]
===== Interacting with the Shell

The Spring Shell project builds on top of the https://github.com/jline/jline3[JLine] library and, as a result, brings
a lot of nice interactive features, some of which are detailed in this section.

First and foremost, Spring Shell supports tab completion almost everywhere possible. So, if there
is an `echo` command and the user types `ec` and presses `TAB`, `echo` appears.
Should there be several commands that start with `ec`, then the user is prompted to choose (using `TAB` or
`Shift + TAB` to navigate and `ENTER` to select.)

But completion does not stop at command keys. It also works for parameter keys (`--arg`) and even
parameter values, if the application developer registered the appropriate beans (see <<providing-tab-completion>>).

Another nice feature of Spring Shell applications is support for line continuation. If a command and its parameters
is too long and does not fit nicely on the screen, a user can chunk it by ending a line with a backslash
(`\`) character, pressing `ENTER`, and continuing on the next line. Upon submission of the whole command, this is
parsed as if the user entered a single space on line breaks. The following listing shows an example of this behavior:

====
[source]
----
shell:>register module --type source --name foo  \ <1>
> --uri file:///tmp/bar
Successfully registered module 'source:foo'
----
<1> command continues on next line
====

Line continuation also automatically triggers if the user has opened a quote (see <<quotes-handling>>)
and presses `ENTER` while still in the quotes:

====
[source]
----
shell:>echo "Hello <1>
dquote> World"
You said Hello World
----
<1> The user pressed `ENTER` here.
====

Finally, Spring Shell applications benefit from a lot of keyboard shortcuts (borrowed from Emacs) with which you may
already be familiar from working with your regular OS Shell. Notable shortcuts include `Ctrl+r` to perform
a reverse search, `Ctrl+a`] and `Ctrl+e` to move to the beginning and the end of the current line (respectively),
and `Esc f` and `Esc b` to move forward or backward (respectively) one word at a time.

[[providing-tab-completion]]
// ===== Providing TAB Completion Proposals

// TBD
