-
Notifications
You must be signed in to change notification settings - Fork 391
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 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
- Loading branch information
Showing
18 changed files
with
468 additions
and
70 deletions.
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
...toconfigure/src/main/java/org/springframework/shell/boot/TerminalUIAutoConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
...figure/src/test/java/org/springframework/shell/boot/TerminalUIAutoConfigurationTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
150 changes: 150 additions & 0 deletions
150
...-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUIBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/* | ||
* 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.component.view; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.LinkedHashSet; | ||
import java.util.Set; | ||
|
||
import org.jline.terminal.Terminal; | ||
|
||
import org.springframework.shell.style.ThemeResolver; | ||
import org.springframework.util.Assert; | ||
import org.springframework.util.CollectionUtils; | ||
import org.springframework.util.StringUtils; | ||
|
||
/** | ||
* Builder that can be used to configure and create a {@link TerminalUI}. | ||
* | ||
* @author Janne Valkealahti | ||
*/ | ||
public class TerminalUIBuilder { | ||
|
||
private final Terminal terminal; | ||
private final Set<TerminalUICustomizer> customizers; | ||
private final ThemeResolver themeResolver; | ||
private final String themeName; | ||
|
||
/** | ||
* Create a new {@link TerminalUIBuilder} instance. | ||
* | ||
* @param terminal the terminal | ||
* @param customizers any {@link TerminalUICustomizer TerminalUICustomizers} | ||
* that should be applied when the {@link TerminalUI} is | ||
* built | ||
*/ | ||
public TerminalUIBuilder(Terminal terminal, TerminalUICustomizer... customizers) { | ||
this.terminal = terminal; | ||
this.customizers = copiedSetOf(customizers); | ||
this.themeResolver = null; | ||
this.themeName = null; | ||
} | ||
|
||
/** | ||
* Create a new {@link TerminalUIBuilder} instance. | ||
* | ||
* @param terminal the terminal | ||
* @param customizers any {@link TerminalUICustomizer TerminalUICustomizers} | ||
* that should be applied when the {@link TerminalUI} is | ||
* built | ||
* @param themeResolver the theme resolver | ||
* @param themeName the theme name | ||
*/ | ||
public TerminalUIBuilder(Terminal terminal, Set<TerminalUICustomizer> customizers, ThemeResolver themeResolver, | ||
String themeName) { | ||
this.terminal = terminal; | ||
this.customizers = customizers; | ||
this.themeResolver = themeResolver; | ||
this.themeName = themeName; | ||
} | ||
|
||
/** | ||
* Sets a {@link ThemeResolver} for {@link TerminalUI} to build. | ||
* | ||
* @param themeResolver the theme resolver | ||
* @return a new builder instance | ||
*/ | ||
public TerminalUIBuilder themeResolver(ThemeResolver themeResolver) { | ||
return new TerminalUIBuilder(terminal, customizers, themeResolver, themeName); | ||
} | ||
|
||
/** | ||
* Sets a {@code theme name} for {@link TerminalUI} to build. | ||
* | ||
* @param themeName the theme name | ||
* @return a new builder instance | ||
*/ | ||
public TerminalUIBuilder themeName(String themeName) { | ||
return new TerminalUIBuilder(terminal, customizers, themeResolver, themeName); | ||
} | ||
|
||
/** | ||
* Set the {@link TerminalUICustomizer TerminalUICustomizer} that should be | ||
* applied to the {@link TerminalUI}. Customizers are applied in the order that they | ||
* were added after builder configuration has been applied. Setting this value will | ||
* replace any previously configured customizers. | ||
* | ||
* @param customizers the customizers to set | ||
* @return a new builder instance | ||
*/ | ||
public TerminalUIBuilder customizers(Collection<? extends TerminalUICustomizer> customizers) { | ||
Assert.notNull(customizers, "Customizers must not be null"); | ||
return new TerminalUIBuilder(terminal, copiedSetOf(customizers), themeResolver, themeName); | ||
} | ||
|
||
/** | ||
* Build a new {@link TerminalUI} instance and configure it using this builder. | ||
* | ||
* @return a configured {@link TerminalUI} instance. | ||
*/ | ||
public TerminalUI build() { | ||
return configure(new TerminalUI(terminal)); | ||
} | ||
|
||
/** | ||
* Configure the provided {@link TerminalUI} instance using this builder. | ||
* | ||
* @param <T> the type of terminal ui | ||
* @param terminalUI the {@link TerminalUI} to configure | ||
* @return the terminal ui instance | ||
*/ | ||
public <T extends TerminalUI> T configure(T terminalUI) { | ||
if (themeResolver != null) { | ||
terminalUI.setThemeResolver(themeResolver); | ||
} | ||
if (StringUtils.hasText(themeName)) { | ||
terminalUI.setThemeName(themeName); | ||
} | ||
if (!CollectionUtils.isEmpty(customizers)) { | ||
for (TerminalUICustomizer customizer : customizers) { | ||
customizer.customize(terminalUI); | ||
} | ||
} | ||
return terminalUI; | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
private <T> Set<T> copiedSetOf(T... items) { | ||
return copiedSetOf(Arrays.asList(items)); | ||
} | ||
|
||
private <T> Set<T> copiedSetOf(Collection<? extends T> collection) { | ||
return Collections.unmodifiableSet(new LinkedHashSet<>(collection)); | ||
} | ||
|
||
} |
Oops, something went wrong.