Support modify option names

- New OptionNameModifier which is just a Function<String,String> to
  modify a name.
- Can be defined per option in CommandRegistration.
- Can be defined as global default as bean.
- Default implementation for common case types is enabled via boot's
  config props under spring.shell.option.naming.case-type
- Support facilities for camel, kebab, snake and pascal conversions.
- Fixes #621
This commit is contained in:
Janne Valkealahti
2023-01-15 10:02:55 +00:00
parent 448c507ce9
commit a04091c08f
14 changed files with 747 additions and 5 deletions

View File

@@ -1,3 +1,4 @@
[[using-shell-commands-programmaticmodel]]
==== Programmatic Model
ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs]

View File

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

View File

@@ -22,3 +22,5 @@ include::using-shell-options-validation.adoc[]
include::using-shell-options-label.adoc[]
include::using-shell-options-types.adoc[]
include::using-shell-options-naming.adoc[]

View File

@@ -17,8 +17,11 @@ package org.springframework.shell.docs;
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.shell.command.CommandRegistration;
import org.springframework.shell.command.CommandRegistration.OptionArity;
import org.springframework.shell.command.CommandRegistration.OptionNameModifier;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;
public class OptionSnippets {
@@ -239,6 +242,35 @@ public class OptionSnippets {
.and()
.build();
// end::option-registration-label[]
// tag::option-registration-naming-case-req[]
CommandRegistration.builder()
.withOption()
.longNames("arg1")
.nameModifier(name -> "x" + name)
.and()
.build();
// end::option-registration-naming-case-req[]
}
class Dump8 {
// tag::option-registration-naming-case-bean[]
@Bean
OptionNameModifier sampleOptionNameModifier() {
return name -> "x" + name;
}
// end::option-registration-naming-case-bean[]
// tag::option-registration-naming-case-sample1[]
@ShellMethod(key = "option-naming-sample")
public void optionNamingSample(
@ShellOption("from_snake") String snake,
@ShellOption("fromCamel") String camel,
@ShellOption("from-kebab") String kebab,
@ShellOption("FromPascal") String pascal
) {}
// end::option-registration-naming-case-sample1[]
}
}