Autoconfigure TerminalUI

- Add TerminalUIBuilder which can be used to build TerminalUI
- Add TerminalUICustomizer which can customize TerminalUI
- What is autoconfigured is TerminalUIBuilder.
- In TerminalUI add configure for views which now allows
  easier way to set needed stuff in views.
- Various changes in a catalog app
- Fixes #900
This commit is contained in:
Janne Valkealahti
2023-10-25 09:10:42 +01:00
parent f3b8bf3de1
commit 82df453cc0
18 changed files with 468 additions and 70 deletions

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2023 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.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.shell.component.view.TerminalUI;
import org.springframework.shell.component.view.TerminalUIBuilder;
import org.springframework.shell.component.view.TerminalUICustomizer;
import org.springframework.shell.style.ThemeActive;
import org.springframework.shell.style.ThemeResolver;
@AutoConfiguration
@ConditionalOnClass(TerminalUI.class)
public class TerminalUIAutoConfiguration {
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
public TerminalUIBuilder terminalUIBuilder(Terminal terminal, ThemeResolver themeResolver, ThemeActive themeActive,
ObjectProvider<TerminalUICustomizer> customizerProvider) {
TerminalUIBuilder builder = new TerminalUIBuilder(terminal);
builder = builder.themeName(themeActive.get());
builder = builder.themeResolver(themeResolver);
builder = builder.customizers(customizerProvider.orderedStream().toList());
return builder;
}
}

View File

@@ -14,3 +14,4 @@ org.springframework.shell.boot.StandardAPIAutoConfiguration
org.springframework.shell.boot.ThemingAutoConfiguration
org.springframework.shell.boot.StandardCommandsAutoConfiguration
org.springframework.shell.boot.ComponentFlowAutoConfiguration
org.springframework.shell.boot.TerminalUIAutoConfiguration

View File

@@ -0,0 +1,108 @@
/*
* Copyright 2023 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 java.util.Set;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.shell.component.view.TerminalUI;
import org.springframework.shell.component.view.TerminalUIBuilder;
import org.springframework.shell.component.view.TerminalUICustomizer;
import org.springframework.shell.style.ThemeActive;
import org.springframework.shell.style.ThemeRegistry;
import org.springframework.shell.style.ThemeResolver;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class TerminalUIAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(TerminalUIAutoConfiguration.class));
@Test
public void terminalUICreated() {
this.contextRunner
.withUserConfiguration(MockConfiguration.class)
.run(context -> {
assertThat(context).hasSingleBean(TerminalUIBuilder.class);
});
}
@Test
@SuppressWarnings("unchecked")
public void canCustomize() {
this.contextRunner
.withUserConfiguration(TestConfiguration.class, MockConfiguration.class)
.run(context -> {
TerminalUIBuilder builder = context.getBean(TerminalUIBuilder.class);
Set<TerminalUICustomizer> customizers = (Set<TerminalUICustomizer>) ReflectionTestUtils
.getField(builder, "customizers");
assertThat(customizers).hasSize(1);
});
}
@Configuration(proxyBeanMethods = false)
static class MockConfiguration {
@Bean
Terminal mockTerminal() {
Terminal terminal = mock(Terminal.class);
when(terminal.getBufferSize()).thenReturn(new Size());
return terminal;
}
@Bean
ThemeResolver mockThemeResolver() {
return new ThemeResolver(new ThemeRegistry(), "default");
}
@Bean
ThemeActive themeActive() {
return () -> {
return "default";
};
}
}
@Configuration(proxyBeanMethods = false)
static class TestConfiguration {
@Bean
TerminalUICustomizer terminalUICustomizer() {
return new TestTerminalUICustomizer();
}
}
static class TestTerminalUICustomizer implements TerminalUICustomizer {
@Override
public void customize(TerminalUI terminalUI) {
terminalUI.setThemeName("test");
}
}
}