diff --git a/spring-shell-docs/src/main/asciidoc/using-shell-completion.adoc b/spring-shell-docs/src/main/asciidoc/using-shell-completion.adoc new file mode 100644 index 00000000..d53907c0 --- /dev/null +++ b/spring-shell-docs/src/main/asciidoc/using-shell-completion.adoc @@ -0,0 +1,64 @@ +== Completion +ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs] + +Spring Shell can provide completion proposals for both interactive shell +and a command-line. There are differences however as when shell is in +interactive mode we have an active instance of a shell meaning it's +easier to provide more programmatic ways to provide completion hints. +When shell is purely run as a command-line tool a completion can only +be accomplished with integration into OS level shell's like _bash_. + +=== Interactive + +Hints for completions are calculated with _function_ or _interface_ style +methods which takes `CompletionContext` and returns a list of +`CompletionProposal` instances. `CompletionContext` gives you various +information about a current context like command registration and option. + +NOTE: Generic resolvers can be registered as a beans if those are useful +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 completion currently only support _bash_ and is documented +in a built-in `completion` command <>. diff --git a/spring-shell-docs/src/main/asciidoc/using-shell-components-builtin.adoc b/spring-shell-docs/src/main/asciidoc/using-shell-components-builtin.adoc index b2123677..cdb0474f 100644 --- a/spring-shell-docs/src/main/asciidoc/using-shell-components-builtin.adoc +++ b/spring-shell-docs/src/main/asciidoc/using-shell-components-builtin.adoc @@ -122,6 +122,7 @@ a placeholder (`{userconfig}`), which resolves to a common shared config directo TIP: Run the Spring Shell application to see how the sample application works as it uses these options. +[[built-in-commands-completion]] ==== Completion The `completion` command set lets you create script files that can be used diff --git a/spring-shell-docs/src/main/asciidoc/using-shell.adoc b/spring-shell-docs/src/main/asciidoc/using-shell.adoc index 0dfe966c..9f1249b6 100644 --- a/spring-shell-docs/src/main/asciidoc/using-shell.adoc +++ b/spring-shell-docs/src/main/asciidoc/using-shell.adoc @@ -4,6 +4,8 @@ include::using-shell-commands.adoc[] include::using-shell-options.adoc[] +include::using-shell-completion.adoc[] + include::using-shell-building.adoc[] include::using-shell-components.adoc[] diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CompletionSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CompletionSnippets.java new file mode 100644 index 00000000..60b13fb5 --- /dev/null +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CompletionSnippets.java @@ -0,0 +1,81 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.shell.docs; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.shell.CompletionContext; +import org.springframework.shell.CompletionProposal; +import org.springframework.shell.command.CommandRegistration; +import org.springframework.shell.completion.CompletionResolver; +import org.springframework.shell.standard.ShellMethod; +import org.springframework.shell.standard.ShellOption; +import org.springframework.shell.standard.ValueProvider; + +public class CompletionSnippets { + + // tag::builder-1[] + void dump1() { + CommandRegistration.builder() + .withOption() + .longNames("arg1") + .completion(ctx -> { + return Arrays.asList("val1", "val2").stream() + .map(CompletionProposal::new) + .collect(Collectors.toList()); + }) + .and() + .build(); + } + // end::builder-1[] + + // tag::resolver-1[] + static class MyValuesCompletionResolver implements CompletionResolver { + + @Override + public List apply(CompletionContext t) { + return Arrays.asList("val1", "val2").stream() + .map(CompletionProposal::new) + .collect(Collectors.toList()); + } + } + // end::resolver-1[] + + // tag::provider-1[] + static class MyValuesProvider implements ValueProvider { + + @Override + public List complete(CompletionContext completionContext) { + return Arrays.asList("val1", "val2").stream() + .map(CompletionProposal::new) + .collect(Collectors.toList()); + } + } + // end::provider-1[] + + static class Dump1 { + // tag::anno-method[] + @ShellMethod(value = "complete", key = "complete") + public String complete( + @ShellOption(valueProvider = MyValuesProvider.class) String arg1) + { + return "You said " + arg1; + } + // end::anno-method[] + } +}