Add support for global help options
- Essentially this commit registeres on default `--help` and `-h` options to every command and execution short circuits in presense of help options to help command. - Add Supplier<CommandRegistration.Builder> as a bean which can be autowired registration beans. - Make this common bean customisable via CommandRegistrationCustomizer. - Change StandardMethodTargetRegistrar to use supplier so that annotated commands gets common customizations. - Change sample commands to use supplier. - Add new group, spring.shell.help to config props. - Docs changes - Fixes #582 - Fixes #585
This commit is contained in:
@@ -16,19 +16,23 @@
|
||||
package org.springframework.shell.boot;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.shell.MethodTargetRegistrar;
|
||||
import org.springframework.shell.boot.SpringShellProperties.Help;
|
||||
import org.springframework.shell.command.CommandCatalog;
|
||||
import org.springframework.shell.command.CommandCatalogCustomizer;
|
||||
import org.springframework.shell.command.CommandRegistration;
|
||||
import org.springframework.shell.command.CommandResolver;
|
||||
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(SpringShellProperties.class)
|
||||
public class CommandCatalogAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@@ -55,4 +59,29 @@ public class CommandCatalogAutoConfiguration {
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CommandRegistrationCustomizer helpOptionsCommandRegistrationCustomizer(SpringShellProperties properties) {
|
||||
return registration -> {
|
||||
Help help = properties.getHelp();
|
||||
if (help.isEnabled()) {
|
||||
registration.withHelpOptions()
|
||||
.enabled(true)
|
||||
.longNames(help.getLongNames())
|
||||
.shortNames(help.getShortNames())
|
||||
.command(help.getCommand());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Supplier<CommandRegistration.Builder> commandRegistrationBuilderSupplier(
|
||||
ObjectProvider<CommandRegistrationCustomizer> customizerProvider) {
|
||||
return () -> {
|
||||
CommandRegistration.Builder builder = CommandRegistration.builder();
|
||||
customizerProvider.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||
return builder;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.boot;
|
||||
|
||||
import org.springframework.shell.command.CommandRegistration;
|
||||
|
||||
/**
|
||||
* Callback interface that can be used to customize a {@link CommandRegistration.Builder}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface CommandRegistrationCustomizer {
|
||||
|
||||
/**
|
||||
* Callback to customize a {@link CommandRegistration.Builder} instance.
|
||||
*
|
||||
* @param commandRegistrationBuilder the command registration builder to customize
|
||||
*/
|
||||
void customize(CommandRegistration.Builder commandRegistrationBuilder);
|
||||
}
|
||||
@@ -32,6 +32,7 @@ public class SpringShellProperties {
|
||||
private Noninteractive noninteractive = new Noninteractive();
|
||||
private Theme theme = new Theme();
|
||||
private Command command = new Command();
|
||||
private Help help = new Help();
|
||||
|
||||
public void setConfig(Config config) {
|
||||
this.config = config;
|
||||
@@ -89,6 +90,14 @@ public class SpringShellProperties {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void setHelp(Help help) {
|
||||
this.help = help;
|
||||
}
|
||||
|
||||
public Help getHelp() {
|
||||
return help;
|
||||
}
|
||||
|
||||
public static class Config {
|
||||
|
||||
private String env;
|
||||
@@ -495,4 +504,59 @@ public class SpringShellProperties {
|
||||
this.showGitCommitTime = showGitCommitTime;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Help {
|
||||
|
||||
/**
|
||||
* Command to call when presense of help option is detected.
|
||||
*/
|
||||
private String command = "help";
|
||||
|
||||
/**
|
||||
* Long style help option, without a prefix "--".
|
||||
*/
|
||||
private String[] longNames = new String[] { "help" };
|
||||
|
||||
/**
|
||||
* Short style help option, without a prefix "-".
|
||||
*/
|
||||
private Character[] shortNames = new Character[] { 'h' };
|
||||
|
||||
/**
|
||||
* Whether to enable help options for commands.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public void setCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public String[] getLongNames() {
|
||||
return longNames;
|
||||
}
|
||||
|
||||
public void setLongNames(String[] longNames) {
|
||||
this.longNames = longNames;
|
||||
}
|
||||
|
||||
public Character[] getShortNames() {
|
||||
return shortNames;
|
||||
}
|
||||
|
||||
public void setShortNames(Character[] shortNames) {
|
||||
this.shortNames = shortNames;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
|
||||
package org.springframework.shell.boot;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.shell.MethodTargetRegistrar;
|
||||
import org.springframework.shell.command.CommandCatalog;
|
||||
import org.springframework.shell.command.CommandRegistration;
|
||||
import org.springframework.shell.standard.CommandValueProvider;
|
||||
import org.springframework.shell.standard.EnumValueProvider;
|
||||
import org.springframework.shell.standard.FileValueProvider;
|
||||
@@ -50,7 +54,8 @@ public class StandardAPIAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MethodTargetRegistrar standardMethodTargetResolver() {
|
||||
return new StandardMethodTargetRegistrar();
|
||||
public MethodTargetRegistrar standardMethodTargetResolver(ApplicationContext applicationContext,
|
||||
Supplier<CommandRegistration.Builder> builder) {
|
||||
return new StandardMethodTargetRegistrar(applicationContext, builder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,10 @@ public class SpringShellPropertiesTests {
|
||||
assertThat(properties.getCommand().getVersion().isShowGitCommitId()).isFalse();
|
||||
assertThat(properties.getCommand().getVersion().isShowGitShortCommitId()).isFalse();
|
||||
assertThat(properties.getCommand().getVersion().isShowGitCommitTime()).isFalse();
|
||||
assertThat(properties.getHelp().isEnabled()).isTrue();
|
||||
assertThat(properties.getHelp().getCommand()).isEqualTo("help");
|
||||
assertThat(properties.getHelp().getLongNames()).containsExactly("help");
|
||||
assertThat(properties.getHelp().getShortNames()).containsExactly('h');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -99,6 +103,10 @@ public class SpringShellPropertiesTests {
|
||||
.withPropertyValues("spring.shell.command.version.show-git-commit-id=true")
|
||||
.withPropertyValues("spring.shell.command.version.show-git-short-commit-id=true")
|
||||
.withPropertyValues("spring.shell.command.version.show-git-commit-time=true")
|
||||
.withPropertyValues("spring.shell.help.enabled=false")
|
||||
.withPropertyValues("spring.shell.help.command=fake")
|
||||
.withPropertyValues("spring.shell.help.long-names=fake")
|
||||
.withPropertyValues("spring.shell.help.short-names=f")
|
||||
.withUserConfiguration(Config1.class)
|
||||
.run((context) -> {
|
||||
SpringShellProperties properties = context.getBean(SpringShellProperties.class);
|
||||
@@ -132,6 +140,24 @@ public class SpringShellPropertiesTests {
|
||||
assertThat(properties.getCommand().getVersion().isShowGitCommitId()).isTrue();
|
||||
assertThat(properties.getCommand().getVersion().isShowGitShortCommitId()).isTrue();
|
||||
assertThat(properties.getCommand().getVersion().isShowGitCommitTime()).isTrue();
|
||||
assertThat(properties.getHelp().isEnabled()).isFalse();
|
||||
assertThat(properties.getHelp().getCommand()).isEqualTo("fake");
|
||||
assertThat(properties.getHelp().getLongNames()).containsExactly("fake");
|
||||
assertThat(properties.getHelp().getShortNames()).containsExactly('f');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void essentiallyUnset() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.shell.help.long-names=")
|
||||
.withPropertyValues("spring.shell.help.short-names=")
|
||||
.withUserConfiguration(Config1.class)
|
||||
.run((context) -> {
|
||||
SpringShellProperties properties = context.getBean(SpringShellProperties.class);
|
||||
assertThat(properties.getHelp().getLongNames()).isEmpty();
|
||||
assertThat(properties.getHelp().getShortNames()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user