diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineShellAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineShellAutoConfiguration.java index 198d5a1d..c9789f1e 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineShellAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineShellAutoConfiguration.java @@ -25,6 +25,7 @@ import org.jline.utils.AttributedString; import org.jline.utils.AttributedStyle; import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -41,12 +42,14 @@ import org.springframework.shell.jline.PromptProvider; public class JLineShellAutoConfiguration { @Bean(destroyMethod = "close") - public Terminal terminal() { + public Terminal terminal(ObjectProvider customizers) { try { - return TerminalBuilder.builder().build(); + TerminalBuilder builder = TerminalBuilder.builder(); + customizers.orderedStream().forEach(customizer -> customizer.customize(builder)); + return builder.build(); } catch (IOException e) { - throw new BeanCreationException("Could not create Terminal: " + e.getMessage()); + throw new BeanCreationException("Could not create Terminal", e); } } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/TerminalCustomizer.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/TerminalCustomizer.java new file mode 100644 index 00000000..f14b54f2 --- /dev/null +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/TerminalCustomizer.java @@ -0,0 +1,36 @@ +/* + * 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.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; + +/** + * Callback interface that can be used to customize a {@link Terminal} via its + * {@link TerminalBuilder}. + * + * @author Janne Valkealahti + */ +@FunctionalInterface +public interface TerminalCustomizer { + + /** + * Callback to customize a {@link TerminalBuilder} instance. + * + * @param builder the terminal builder + */ + void customize(TerminalBuilder builder); +} diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/JLineShellAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/JLineShellAutoConfigurationTests.java new file mode 100644 index 00000000..d1de27fb --- /dev/null +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/JLineShellAutoConfigurationTests.java @@ -0,0 +1,50 @@ +/* + * 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.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +class JLineShellAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(JLineShellAutoConfiguration.class)); + + @Test + void canCreatePlainTerminal() { + contextRunner.run(context -> { + assertThat(context).hasSingleBean(Terminal.class); + }); + } + + @Test + void canCustomizeTerminalBuilder() { + TerminalCustomizer customizer = mock(TerminalCustomizer.class); + contextRunner.withBean(TerminalCustomizer.class, () -> customizer) + .run(context -> { + verify(customizer).customize(any(TerminalBuilder.class)); + }); + } +}