From cfdc42f65afcbb58374da991faa66c52390dc693 Mon Sep 17 00:00:00 2001 From: Andrey Litvitski Date: Fri, 3 Oct 2025 19:10:14 +0300 Subject: [PATCH] Add spring code formatting plugin to the build Closes: gh-1185 Signed-off-by: Andrey Litvitski --- pom.xml | 19 + .../ApplicationRunnerAutoConfiguration.java | 4 +- .../boot/CommandCatalogAutoConfiguration.java | 13 +- .../boot/CommandRegistrationCustomizer.java | 2 +- .../boot/CompleterAutoConfiguration.java | 22 +- .../boot/ComponentFlowAutoConfiguration.java | 4 + .../shell/boot/ComponentFlowCustomizer.java | 1 + .../shell/boot/ExitCodeAutoConfiguration.java | 4 + .../shell/boot/JLineAutoConfiguration.java | 2 + .../boot/JLineShellAutoConfiguration.java | 1 + .../boot/LineReaderAutoConfiguration.java | 65 +- .../NonInteractiveShellRunnerCustomizer.java | 1 + .../ParameterResolverAutoConfiguration.java | 3 +- .../boot/ShellContextAutoConfiguration.java | 1 + .../boot/ShellRunnerAutoConfiguration.java | 13 +- .../boot/SpringShellAutoConfiguration.java | 1 + .../shell/boot/SpringShellProperties.java | 66 +- .../boot/StandardAPIAutoConfiguration.java | 3 +- .../StandardCommandsAutoConfiguration.java | 22 +- .../shell/boot/TerminalCustomizer.java | 2 +- .../shell/boot/ThemingAutoConfiguration.java | 1 + .../boot/UserConfigAutoConfiguration.java | 7 + .../OnCompletionCommandCondition.java | 6 +- .../OnNotPrimaryCommandCondition.java | 1 + .../condition/OnPrimaryCommandCondition.java | 2 + ...plicationRunnerAutoConfigurationTests.java | 6 +- .../CommandCatalogAutoConfigurationTests.java | 123 ++- .../JLineShellAutoConfigurationTests.java | 10 +- .../LineReaderAutoConfigurationTests.java | 46 +- ...rameterResolverAutoConfigurationTests.java | 18 +- .../ShellRunnerAutoConfigurationTests.java | 53 +- .../boot/SpringShellPropertiesTests.java | 259 +++--- ...tandardCommandsAutoConfigurationTests.java | 51 +- .../TerminalUIAutoConfigurationTests.java | 26 +- .../boot/ThemingAutoConfigurationTests.java | 42 +- .../UserConfigAutoConfigurationTests.java | 34 +- .../springframework/shell/Availability.java | 35 +- .../shell/AvailabilityProvider.java | 1 + .../AvailabilityReflectiveProcessor.java | 6 +- .../org/springframework/shell/Command.java | 14 +- .../shell/CommandNotCurrentlyAvailable.java | 2 + .../shell/CommandNotFound.java | 11 +- .../shell/CompletingParsedLine.java | 5 +- .../shell/CompletionContext.java | 8 +- .../shell/CompletionProposal.java | 13 +- .../shell/CoreResourcesRuntimeHints.java | 1 + .../shell/DefaultShellApplicationRunner.java | 13 +- .../springframework/shell/ExitRequest.java | 1 + .../java/org/springframework/shell/Input.java | 9 +- .../springframework/shell/InputProvider.java | 8 +- .../shell/JnaRuntimeHints.java | 308 ++----- .../ParameterResolverMissingException.java | 8 +- .../shell/ParameterValidationException.java | 1 + .../springframework/shell/ResultHandler.java | 7 +- .../shell/ResultHandlerService.java | 3 +- .../java/org/springframework/shell/Shell.java | 185 ++-- .../shell/ShellApplicationRunner.java | 1 + .../springframework/shell/ShellRunner.java | 11 +- .../java/org/springframework/shell/Utils.java | 31 +- .../springframework/shell/ValueResult.java | 10 +- .../ArgumentHeaderMethodArgumentResolver.java | 6 +- .../shell/command/CommandAlias.java | 6 +- .../shell/command/CommandCatalog.java | 20 +- .../command/CommandCatalogCustomizer.java | 2 +- .../shell/command/CommandContext.java | 34 +- .../CommandContextMethodArgumentResolver.java | 3 +- .../command/CommandExceptionResolver.java | 13 +- .../shell/command/CommandExecution.java | 108 ++- .../shell/command/CommandExitCode.java | 7 +- .../shell/command/CommandHandlingResult.java | 14 +- .../shell/command/CommandOption.java | 47 +- .../shell/command/CommandParser.java | 38 +- .../CommandParserExceptionResolver.java | 4 +- .../shell/command/CommandRegistration.java | 246 +++--- .../shell/command/CommandResolver.java | 10 +- .../shell/command/annotation/Command.java | 54 +- .../annotation/CommandAvailability.java | 2 +- .../shell/command/annotation/CommandScan.java | 30 +- .../command/annotation/EnableCommand.java | 6 +- .../command/annotation/ExceptionResolver.java | 2 +- .../ExceptionResolverMethodResolver.java | 35 +- .../shell/command/annotation/ExitCode.java | 3 +- .../MethodCommandExceptionResolver.java | 5 +- .../shell/command/annotation/Option.java | 25 +- .../command/annotation/OptionValues.java | 5 +- .../support/CommandAnnotationUtils.java | 65 +- .../CommandRegistrationBeanRegistrar.java | 32 +- .../CommandRegistrationFactoryBean.java | 65 +- .../support/CommandScanRegistrar.java | 4 +- .../support/EnableCommandRegistrar.java | 10 +- .../support/OptionMethodArgumentResolver.java | 2 + .../invocation/InvocableShellMethod.java | 132 +-- .../ShellMethodArgumentResolverComposite.java | 30 +- .../command/parser/AbstractNodeVisitor.java | 25 +- .../shell/command/parser/Ast.java | 23 +- .../shell/command/parser/AstNode.java | 4 +- .../command/parser/CommandArgumentNode.java | 1 + .../shell/command/parser/CommandModel.java | 69 +- .../shell/command/parser/CommandNode.java | 1 + .../shell/command/parser/DirectiveNode.java | 1 + .../shell/command/parser/DirectiveResult.java | 3 +- .../shell/command/parser/Lexer.java | 31 +- .../shell/command/parser/MessageResult.java | 2 - .../shell/command/parser/NodeVisitor.java | 2 +- .../command/parser/NonterminalAstNode.java | 5 +- .../command/parser/OptionArgumentNode.java | 1 + .../shell/command/parser/OptionNode.java | 1 + .../shell/command/parser/Parser.java | 141 +-- .../shell/command/parser/ParserConfig.java | 6 +- .../shell/command/parser/ParserMessage.java | 40 +- .../shell/command/parser/TerminalAstNode.java | 5 +- .../shell/command/parser/Token.java | 4 + .../shell/command/parser/TokenType.java | 7 +- .../support/OptionNameModifierSupport.java | 89 +- .../shell/completion/CompletionProvider.java | 1 + .../shell/completion/CompletionResolver.java | 5 +- ...RegistrationOptionsCompletionResolver.java | 9 +- .../shell/component/ConfirmationInput.java | 16 +- .../shell/component/MultiItemSelector.java | 39 +- .../shell/component/PathInput.java | 9 +- .../shell/component/PathSearch.java | 139 +-- .../shell/component/SingleItemSelector.java | 30 +- .../shell/component/StringInput.java | 18 +- .../shell/component/ViewComponent.java | 27 +- .../shell/component/ViewComponentBuilder.java | 3 +- .../component/ViewComponentExecutor.java | 16 +- .../context/BaseComponentContext.java | 5 +- .../component/context/ComponentContext.java | 23 +- .../component/flow/BaseConfirmationInput.java | 10 + .../shell/component/flow/BaseInput.java | 3 + .../shell/component/flow/BaseInputSpec.java | 3 +- .../component/flow/BaseMultiItemSelector.java | 18 +- .../shell/component/flow/BasePathInput.java | 10 + .../flow/BaseSingleItemSelector.java | 33 +- .../shell/component/flow/BaseStringInput.java | 11 + .../shell/component/flow/ComponentFlow.java | 259 +++--- .../component/flow/ConfirmationInputSpec.java | 13 +- .../flow/DefaultConfirmationInputSpec.java | 1 + .../component/flow/DefaultMultiInputSpec.java | 1 + .../component/flow/DefaultPathInputSpec.java | 1 + .../component/flow/DefaultSelectItem.java | 4 + .../flow/DefaultSingleInputSpec.java | 1 + .../flow/DefaultStringInputSpec.java | 1 + .../component/flow/MultiItemSelectorSpec.java | 19 +- .../shell/component/flow/PathInputSpec.java | 12 +- .../shell/component/flow/ResultMode.java | 11 +- .../shell/component/flow/SelectItem.java | 5 +- .../flow/SingleItemSelectorSpec.java | 20 +- .../shell/component/flow/StringInputSpec.java | 13 +- .../message/ShellMessageBuilder.java | 45 +- .../message/ShellMessageHeaderAccessor.java | 8 +- .../StaticShellMessageHeaderAccessor.java | 11 +- .../component/support/AbstractComponent.java | 47 +- .../support/AbstractSelectorComponent.java | 104 +-- .../support/AbstractTextComponent.java | 29 +- .../shell/component/support/Enableable.java | 1 + .../shell/component/support/Itemable.java | 1 + .../shell/component/support/Matchable.java | 1 + .../shell/component/support/Nameable.java | 3 +- .../shell/component/support/Selectable.java | 1 + .../shell/component/support/SelectorItem.java | 6 + .../shell/component/support/SelectorList.java | 16 +- .../shell/component/view/TerminalUI.java | 107 ++- .../component/view/TerminalUIBuilder.java | 28 +- .../component/view/TerminalUICustomizer.java | 1 - .../view/control/AbstractControl.java | 35 +- .../component/view/control/AbstractView.java | 73 +- .../shell/component/view/control/AppView.java | 17 +- .../shell/component/view/control/BoxView.java | 57 +- .../component/view/control/ButtonView.java | 1 + .../shell/component/view/control/Control.java | 9 +- .../component/view/control/DialogView.java | 20 +- .../component/view/control/GridView.java | 123 +-- .../component/view/control/InputView.java | 5 +- .../component/view/control/ListView.java | 12 +- .../component/view/control/MenuBarView.java | 30 +- .../component/view/control/MenuView.java | 66 +- .../component/view/control/ProgressView.java | 146 ++-- .../shell/component/view/control/Spinner.java | 298 +------ .../component/view/control/StatusBarView.java | 39 +- .../shell/component/view/control/View.java | 27 +- .../component/view/control/ViewCommand.java | 8 +- .../component/view/control/ViewDoneEvent.java | 1 - .../component/view/control/ViewEvent.java | 1 + .../component/view/control/ViewEventArgs.java | 1 + .../component/view/control/ViewService.java | 4 +- .../component/view/control/WindowView.java | 7 +- .../view/control/cell/AbstractCell.java | 3 + .../view/control/cell/AbstractListCell.java | 1 + .../view/control/cell/AbstractTextCell.java | 2 + .../component/view/control/cell/Cell.java | 13 +- .../component/view/control/cell/ListCell.java | 4 +- .../component/view/control/cell/TextCell.java | 7 +- .../view/event/DefaultEventLoop.java | 129 ++- .../shell/component/view/event/EventLoop.java | 61 +- .../shell/component/view/event/KeyBinder.java | 1 - .../view/event/KeyBindingConsumer.java | 1 + .../shell/component/view/event/KeyEvent.java | 115 ++- .../component/view/event/KeyHandler.java | 44 +- .../view/event/MouseBindingConsumer.java | 1 + .../component/view/event/MouseEvent.java | 26 +- .../component/view/event/MouseHandler.java | 39 +- .../AnimationEventLoopProcessor.java | 23 +- .../processor/TaskEventLoopProcessor.java | 9 +- .../shell/component/view/screen/Color.java | 416 +++++++++ .../component/view/screen/DefaultScreen.java | 19 +- .../component/view/screen/DisplayLines.java | 2 +- .../shell/component/view/screen/Screen.java | 45 +- .../component/view/screen/ScreenItem.java | 18 +- .../ShellConversionServiceSupplier.java | 1 + .../shell/config/UserConfigPathProvider.java | 6 +- .../shell/context/DefaultShellContext.java | 2 + .../shell/context/InteractionMode.java | 9 +- .../shell/context/ShellContext.java | 14 +- .../shell/exit/ExitCodeExceptionProvider.java | 5 +- .../shell/exit/ExitCodeMappings.java | 10 +- .../shell/geom/HorizontalAlign.java | 2 + .../springframework/shell/geom/Rectangle.java | 12 +- .../shell/geom/VerticalAlign.java | 2 + .../shell/jline/ExtendedDefaultParser.java | 29 +- .../shell/jline/FileInputProvider.java | 77 +- .../shell/jline/InteractiveShellRunner.java | 16 +- .../jline/NonInteractiveShellRunner.java | 55 +- .../shell/jline/ParsedLineInput.java | 28 +- .../shell/jline/PromptProvider.java | 1 + .../shell/jline/ScriptShellRunner.java | 29 +- .../springframework/shell/package-info.java | 3 +- .../AttributedCharSequenceResultHandler.java | 4 +- .../CommandNotFoundMessageProvider.java | 8 +- .../result/CommandNotFoundResultHandler.java | 13 +- .../shell/result/DefaultResultHandler.java | 1 + .../shell/result/GenericResultHandler.java | 7 +- .../result/GenericResultHandlerService.java | 30 +- ...meterValidationExceptionResultHandler.java | 22 +- .../shell/result/ResultHandlerConfig.java | 3 +- .../ResultHandlerNotFoundException.java | 5 +- .../shell/result/ResultHandlingException.java | 3 +- .../result/TerminalAwareResultHandler.java | 1 + .../TerminalSizeAwareResultHandler.java | 4 +- .../shell/result/ThrowableResultHandler.java | 22 +- .../shell/style/FigureSettings.java | 21 +- .../shell/style/PartsText.java | 3 + .../shell/style/PartsTextRenderer.java | 49 +- .../shell/style/SpinnerSettings.java | 7 +- .../StringToStyleExpressionRenderer.java | 35 +- .../shell/style/StyleSettings.java | 30 +- .../shell/style/TemplateExecutor.java | 14 +- .../springframework/shell/style/Theme.java | 10 +- .../shell/style/ThemeActive.java | 1 + .../shell/style/ThemeRegistry.java | 4 +- .../shell/style/ThemeResolver.java | 32 +- .../shell/style/ThemeSettings.java | 18 +- ...bstractArgumentMethodArgumentResolver.java | 81 +- .../search/AbstractSearchMatchAlgorithm.java | 33 +- .../ExactMatchNaiveSearchMatchAlgorithm.java | 1 + .../FuzzyMatchV1SearchMatchAlgorithm.java | 4 +- .../FuzzyMatchV2SearchMatchAlgorithm.java | 9 +- .../shell/support/search/Normalize.java | 803 +++++++++--------- .../shell/support/search/SearchMatch.java | 21 +- .../support/search/SearchMatchAlgorithm.java | 2 +- .../support/search/SearchMatchResult.java | 12 +- .../AvailabilityReflectiveProcessorTests.java | 22 +- .../shell/JnaRuntimeHintsTests.java | 11 +- .../org/springframework/shell/ShellTests.java | 148 ++-- .../org/springframework/shell/UtilsTests.java | 1 + .../shell/ValueResultAsserts.java | 3 +- .../shell/command/AbstractCommandTests.java | 26 + .../shell/command/CommandCatalogTests.java | 24 +- ...CommandExecutionCustomConversionTests.java | 80 +- .../shell/command/CommandExecutionTests.java | 430 +++++----- .../command/CommandHandlingResultTests.java | 1 + .../CommandParserExceptionResolverTests.java | 1 + .../shell/command/CommandParserTests.java | 11 +- .../command/CommandRegistrationTests.java | 358 ++++---- .../ExceptionResolverMethodResolverTests.java | 10 +- .../MethodCommandExceptionResolverTests.java | 7 + .../support/CommandAnnotationUtilsTests.java | 140 ++- ...CommandRegistrationBeanRegistrarTests.java | 10 +- .../CommandRegistrationFactoryBeanTests.java | 573 +++++++------ .../invocation/InvocableShellMethodTests.java | 2 + .../command/parser/AbstractParsingTests.java | 361 ++++---- .../shell/command/parser/AstTests.java | 125 ++- .../command/parser/CommandModelTests.java | 81 +- .../shell/command/parser/LexerTests.java | 508 ++++------- .../command/parser/ParserAssertions.java | 1 + .../command/parser/ParserConfigTests.java | 1 + .../shell/command/parser/ParserTests.java | 452 ++++------ .../shell/command/parser/TokenAssert.java | 1 + .../OptionNameModifierSupportTests.java | 31 +- ...trationOptionsCompletionResolverTests.java | 32 +- .../shell/component/AbstractShellTests.java | 178 ++-- .../component/ConfirmationInputTests.java | 6 +- .../component/MultiItemSelectorTests.java | 46 +- .../shell/component/PathInputTests.java | 5 + .../shell/component/PathSearchTests.java | 88 +- .../shell/component/ShellAssertions.java | 7 +- .../component/SingleItemSelectorTests.java | 32 +- .../shell/component/StringInputTests.java | 5 + .../context/ComponentContextTests.java | 1 + .../component/flow/AbstractShellTests.java | 178 ++-- .../component/flow/ComponentFlowTests.java | 227 +++-- .../component/support/SelectorListTests.java | 24 +- .../shell/component/view/ScreenAssert.java | 39 +- .../component/view/ScreenAssertTests.java | 10 +- .../view/control/AbstractViewTests.java | 21 +- .../component/view/control/AppViewTests.java | 2 + .../component/view/control/BoxViewTests.java | 1 + .../view/control/ButtonViewTests.java | 23 +- .../view/control/DialogViewTests.java | 16 +- .../component/view/control/GridViewTests.java | 2 +- .../view/control/InputViewTests.java | 9 +- .../component/view/control/ListViewTests.java | 34 +- .../view/control/MenuBarViewTests.java | 15 +- .../component/view/control/MenuViewTests.java | 92 +- .../view/control/ProgressViewTests.java | 16 +- .../view/control/StatusBarViewTests.java | 31 +- .../view/event/DefaultEventLoopTests.java | 93 +- .../component/view/event/KeyEventTests.java | 1 - .../component/view/event/KeyHandlerTests.java | 3 + .../view/event/MouseHandlerTests.java | 2 + .../component/view/geom/RectangleTests.java | 1 + .../jline/ExtendedDefaultParserTests.java | 81 +- .../shell/jline/FileInputProviderTests.java | 15 +- .../GenericResultHandlerServiceTests.java | 7 +- .../jline/InteractiveShellRunnerTests.java | 224 ++--- .../shell/jline/ScriptShellRunnerTests.java | 3 +- .../CommandNotFoundResultHandlerTests.java | 1 + .../shell/style/PartsTextRendererTests.java | 248 ++---- .../StringToStyleExpressionRendererTests.java | 10 +- .../shell/style/TemplateExecutorTests.java | 6 +- .../shell/style/ThemeRegistryTests.java | 1 + .../shell/style/ThemeResolverTests.java | 2 +- .../shell/style/ThemeSettingsTests.java | 21 +- ...ctMatchNaiveSearchMatchAlgorithmTests.java | 40 +- ...FuzzyMatchV1SearchMatchAlgorithmTests.java | 106 +-- ...FuzzyMatchV2SearchMatchAlgorithmTests.java | 137 +-- .../shell/support/search/NormalizeTests.java | 19 +- .../support/search/SearchMatchTests.java | 7 +- .../docs/AnnotationRegistrationSnippets.java | 3 + .../shell/docs/BoxViewSnippets.java | 4 +- .../shell/docs/ButtonViewSnippets.java | 1 + .../shell/docs/CommandAnnotationSnippets.java | 63 +- .../docs/CommandAvailabilitySnippets.java | 118 ++- .../shell/docs/CommandCatalogSnippets.java | 12 +- .../shell/docs/CommandNotFoundSnippets.java | 2 + .../CommandRegistrationAliasSnippets.java | 19 +- .../docs/CommandRegistrationBeanSnippets.java | 15 +- ...ommandRegistrationHelpOptionsSnippets.java | 12 +- ...ndRegistrationInteractionModeSnippets.java | 1 + .../docs/CommandRegistrationSnippets.java | 13 +- .../shell/docs/CommandTargetSnippets.java | 43 +- .../shell/docs/CompletionSnippets.java | 30 +- .../shell/docs/ErrorHandlingSnippets.java | 16 +- .../shell/docs/EventLoopSnippets.java | 9 +- .../shell/docs/ExitCodeSnippets.java | 19 +- .../shell/docs/FlowComponentSnippets.java | 83 +- .../shell/docs/GridViewSnippets.java | 1 + .../shell/docs/InputViewSnippets.java | 1 + .../shell/docs/ListViewSnippets.java | 3 + .../shell/docs/MenuBarViewSnippets.java | 16 +- .../shell/docs/OptionSnippets.java | 277 +++--- .../shell/docs/OptionTypesSnippets.java | 149 ++-- .../shell/docs/ProgressViewSnippets.java | 7 +- .../shell/docs/SearchAlgorithmsSnippets.java | 12 +- .../shell/docs/ShortOptionSnippets.java | 79 +- .../shell/docs/StatusBarViewSnippets.java | 17 +- .../shell/docs/TerminalUiSnippets.java | 21 +- .../shell/docs/TestingSnippets.java | 35 +- .../shell/docs/ThemingSnippets.java | 5 + .../shell/docs/UiComponentSnippets.java | 41 +- .../shell/docs/WritingSnippets.java | 16 +- .../shell/samples/catalog/Catalog.java | 136 +-- .../shell/samples/catalog/CatalogCommand.java | 3 + .../samples/catalog/CatalogConfiguration.java | 3 + .../catalog/scenario/AbstractScenario.java | 5 + .../samples/catalog/scenario/Scenario.java | 23 +- .../catalog/scenario/ScenarioComponent.java | 9 +- .../scenario/box/DrawFunctionScenario.java | 5 +- .../scenario/box/SimpleBoxViewScenario.java | 5 +- .../listview/CheckedListViewScenario.java | 3 +- .../listview/RadioListViewScenario.java | 3 +- .../catalog/scenario/other/ClockScenario.java | 72 +- .../scenario/other/DialogScenario.java | 8 +- .../other/MultiInputViewScenario.java | 3 +- .../scenario/other/SnakeGameScenario.java | 68 +- .../progress/SimpleProgressViewScenario.java | 7 +- .../shell/samples/SpringShellSample.java | 5 +- .../shell/samples/standard/AliasCommands.java | 14 +- .../shell/samples/standard/Commands.java | 1 + .../samples/standard/CompleteCommands.java | 77 +- .../samples/standard/ComponentCommands.java | 40 +- .../standard/ComponentFlowCommands.java | 372 ++++---- .../samples/standard/ComponentUiCommands.java | 39 +- .../samples/standard/ConversionExample.java | 3 + .../samples/standard/DynamicCommands.java | 1 + .../samples/standard/FunctionCommands.java | 77 +- .../samples/standard/RegisterCommands.java | 42 +- .../samples/standard/ResolvedCommands.java | 32 +- .../shell/samples/standard/TableCommands.java | 11 +- .../shell/samples/standard/ThemeCommands.java | 88 +- .../shell/samples/AbstractSampleTests.java | 1 + .../standard/ComponentCommandsTests.java | 11 +- .../shell/samples/SpringShellSample.java | 5 +- .../shell/samples/e2e/AliasCommands.java | 46 +- .../shell/samples/e2e/ArityCommands.java | 157 ++-- .../samples/e2e/AvailabilityCommands.java | 97 +-- .../shell/samples/e2e/BaseE2ECommands.java | 2 + .../samples/e2e/DefaultValueCommands.java | 130 ++- .../samples/e2e/ErrorHandlingCommands.java | 69 +- .../shell/samples/e2e/ExitCodeCommands.java | 45 +- .../shell/samples/e2e/HelpCommands.java | 27 +- .../shell/samples/e2e/HelpOptionCommands.java | 49 +- .../shell/samples/e2e/HiddenCommands.java | 21 +- .../e2e/InteractiveCompletionCommands.java | 63 +- .../samples/e2e/OptionConversionCommands.java | 121 ++- .../samples/e2e/OptionNamingCommands.java | 71 +- .../shell/samples/e2e/OptionTypeCommands.java | 385 ++++----- .../samples/e2e/OptionalValueCommands.java | 32 +- .../e2e/PositionalArgumentsCommands.java | 31 +- .../samples/e2e/RequiredValueCommands.java | 35 +- .../samples/e2e/ShortOptionTypeCommands.java | 108 +-- .../shell/samples/e2e/StdOutTypeCommands.java | 20 +- .../e2e/UnrecognisedOptionCommands.java | 43 +- .../samples/e2e/ValidatedValueCommands.java | 38 +- .../shell/samples/e2e/WriteCommands.java | 30 +- .../shell/samples/AbstractSampleTests.java | 1 + .../shell/samples/e2e/AliasCommandsTests.java | 1 + .../shell/samples/e2e/ArityCommandsTests.java | 1 + .../e2e/DefaultValueCommandsTests.java | 1 + .../samples/e2e/E2EArgumentsProvider.java | 1 + .../shell/samples/e2e/E2ESource.java | 1 + .../e2e/ErrorHandlingCommandsTests.java | 7 +- .../samples/e2e/HelpOptionCommandsTests.java | 1 + .../samples/e2e/HiddenCommandsTests.java | 1 + .../e2e/OptionConversionCommandsTests.java | 1 + .../samples/e2e/OptionTypeCommandsTests.java | 1 + .../e2e/OptionalValueCommandsTests.java | 1 + .../e2e/RequiredValueCommandsTests.java | 1 + .../standard/AbstractShellComponent.java | 109 +-- .../shell/standard/CommandValueProvider.java | 5 +- .../shell/standard/EnumValueProvider.java | 5 +- .../shell/standard/FileValueProvider.java | 10 +- .../shell/standard/ShellCommandGroup.java | 18 +- .../shell/standard/ShellComponent.java | 10 +- .../shell/standard/ShellMethod.java | 30 +- .../standard/ShellMethodAvailability.java | 32 +- .../shell/standard/ShellOption.java | 34 +- .../ShellOptionMethodArgumentResolver.java | 2 + .../StandardMethodTargetRegistrar.java | 97 ++- .../StandardResourcesRuntimeHints.java | 1 + .../shell/standard/ValueProvider.java | 6 +- .../shell/standard/commands/Clear.java | 17 +- .../CommandAvailabilityInfoModel.java | 3 +- .../standard/commands/CommandInfoModel.java | 35 +- .../commands/CommandParameterInfoModel.java | 10 +- .../shell/standard/commands/Completion.java | 3 + .../commands/GroupCommandInfoModel.java | 3 +- .../standard/commands/GroupsInfoModel.java | 52 +- .../shell/standard/commands/Help.java | 35 +- .../shell/standard/commands/History.java | 76 +- .../shell/standard/commands/Quit.java | 19 +- .../shell/standard/commands/Script.java | 53 +- .../shell/standard/commands/Stacktrace.java | 24 +- .../StandardCommandsModelsRuntimeHints.java | 1 + ...StandardCommandsResourcesRuntimeHints.java | 5 +- .../shell/standard/commands/Version.java | 17 +- .../completion/AbstractCompletions.java | 144 ++-- .../standard/completion/BashCompletions.java | 12 +- .../StandardCompletionModelsRuntimeHints.java | 1 + .../standard/completion/ZshCompletions.java | 12 +- .../shell/standard/package-info.java | 3 +- .../standard/CommandValueProviderTests.java | 4 +- .../StandardMethodTargetRegistrarTests.java | 76 +- .../CommandAvailabilityInfoModelTests.java | 1 + .../commands/CommandInfoModelTests.java | 85 +- .../commands/GroupsInfoModelTests.java | 26 +- .../shell/standard/commands/HelpTests.java | 87 +- .../completion/AbstractCompletionsTests.java | 233 +++-- .../completion/BashCompletionsTests.java | 21 +- .../completion/ZshCompletionsTests.java | 21 +- .../shell/TerminalSizeAware.java | 10 +- .../table/AbsoluteWidthSizeConstraints.java | 2 +- .../springframework/shell/table/Aligner.java | 10 +- .../shell/table/ArrayTableModel.java | 1 + .../shell/table/AutoSizeConstraints.java | 5 +- .../shell/table/BeanListTableModel.java | 7 +- .../shell/table/BorderSpecification.java | 27 +- .../shell/table/BorderStyle.java | 35 +- .../shell/table/CellMatcher.java | 5 +- .../shell/table/CellMatchers.java | 6 +- .../shell/table/DebugAligner.java | 5 +- .../shell/table/DebugTextWrapper.java | 7 +- .../shell/table/DefaultFormatter.java | 2 +- .../shell/table/DelimiterTextWrapper.java | 7 +- .../shell/table/Formatter.java | 7 +- .../table/KeyValueHorizontalAligner.java | 10 +- .../shell/table/KeyValueSizeConstraints.java | 10 +- .../shell/table/KeyValueTextWrapper.java | 5 +- .../shell/table/MapFormatter.java | 1 + .../shell/table/NoWrapSizeConstraints.java | 1 + .../shell/table/SizeConstraints.java | 5 +- .../springframework/shell/table/Table.java | 73 +- .../shell/table/TableBuilder.java | 44 +- .../shell/table/TableModel.java | 12 +- .../shell/table/TableModelBuilder.java | 1 + .../springframework/shell/table/Tables.java | 14 +- .../shell/table/TextWrapper.java | 9 +- .../shell/table/AbstractTestWithSample.java | 8 +- .../shell/table/ArrayTableModelTest.java | 5 +- .../shell/table/BeanListTableModelTest.java | 4 +- .../shell/table/BorderFactoryTest.java | 2 +- .../shell/table/BorderStyleTests.java | 72 +- .../shell/table/DelimiterTextWrapperTest.java | 5 +- .../shell/table/KeyValueRenderingTests.java | 11 +- .../shell/table/TableModelBuilderTests.java | 9 +- .../shell/table/TableModelTest.java | 3 +- .../shell/table/TableTest.java | 14 +- .../autoconfigure/AutoConfigureShell.java | 1 + .../AutoConfigureShellTestClient.java | 1 + .../autoconfigure/ShellAutoConfiguration.java | 16 +- .../shell/test/autoconfigure/ShellTest.java | 11 +- .../ShellTestClientAutoConfiguration.java | 2 +- .../ShellTestContextBootstrapper.java | 7 +- .../autoconfigure/ShellTypeExcludeFilter.java | 1 + .../SpringShellTestProperties.java | 1 + .../ShellTestIntegrationTests.java | 11 +- .../ShellTestPropertiesIntegrationTests.java | 1 + ...estTerminalDimensionsIntegrationTests.java | 1 + .../SpringShellTestPropertiesTests.java | 31 +- .../app/ExampleShellApplication.java | 1 + .../test/autoconfigure/app/HelloCommand.java | 1 + .../shell/test/ShellAssertions.java | 6 +- .../shell/test/ShellScreen.java | 23 +- .../shell/test/ShellScreenAssert.java | 2 +- .../shell/test/ShellTestClient.java | 69 +- .../shell/test/ShellWriteSequence.java | 16 +- .../terminal/ArrayTerminalDataStream.java | 3 + .../test/jediterm/terminal/CursorShape.java | 9 +- .../terminal/DataStreamIteratingEmulator.java | 2 + .../test/jediterm/terminal/RequestOrigin.java | 9 +- .../jediterm/terminal/StyledTextConsumer.java | 9 +- .../terminal/StyledTextConsumerAdapter.java | 1 - .../test/jediterm/terminal/Terminal.java | 6 +- .../terminal/TerminalCopyPasteHandler.java | 3 +- .../jediterm/terminal/TerminalDataStream.java | 11 +- .../jediterm/terminal/TerminalDisplay.java | 9 +- .../test/jediterm/terminal/TerminalMode.java | 54 +- .../terminal/TerminalOutputStream.java | 5 +- .../jediterm/terminal/TerminalStarter.java | 6 +- .../test/jediterm/terminal/TextStyle.java | 54 +- .../terminal/TtyBasedArrayDataStream.java | 5 +- .../test/jediterm/terminal/TtyConnector.java | 16 +- .../terminal/emulator/ControlSequence.java | 18 +- .../jediterm/terminal/emulator/Emulator.java | 2 + .../terminal/emulator/JediEmulator.java | 525 ++++++------ .../emulator/SystemCommandSequence.java | 25 +- .../emulator/charset/CharacterSet.java | 686 +++++++-------- .../emulator/charset/CharacterSets.java | 265 +++--- .../terminal/emulator/charset/GraphicSet.java | 43 +- .../emulator/charset/GraphicSetState.java | 19 +- .../jediterm/terminal/model/CharBuffer.java | 10 +- .../jediterm/terminal/model/JediTerminal.java | 274 +++--- .../jediterm/terminal/model/LinesBuffer.java | 53 +- .../jediterm/terminal/model/StoredCursor.java | 26 +- .../jediterm/terminal/model/StyleState.java | 18 +- .../terminal/model/SubCharBuffer.java | 7 +- .../jediterm/terminal/model/Tabulator.java | 30 +- .../jediterm/terminal/model/TerminalLine.java | 113 +-- .../TerminalLineIntervalHighlighting.java | 19 +- .../terminal/model/TerminalModelListener.java | 2 + .../terminal/model/TerminalTextBuffer.java | 188 ++-- .../model/TerminalTypeAheadSettings.java | 10 +- .../shell/test/jediterm/terminal/ui/Cell.java | 3 + .../jediterm/terminal/ui/JediTermWidget.java | 24 +- .../terminal/ui/LineCellInterval.java | 4 + .../terminal/ui/TerminalCoordinates.java | 5 + .../jediterm/terminal/ui/TerminalPanel.java | 22 +- .../terminal/ui/TerminalPanelListener.java | 2 + .../jediterm/terminal/ui/TerminalSession.java | 1 + .../jediterm/terminal/ui/TerminalWidget.java | 1 + .../test/jediterm/terminal/ui/UIUtil.java | 8 + .../jediterm/terminal/util/CharUtils.java | 298 ++++--- .../test/jediterm/terminal/util/Pair.java | 16 +- .../test/jediterm/terminal/util/Util.java | 153 ++-- .../shell/test/jediterm/typeahead/Ascii.java | 87 +- .../shell/test/ShellScreenAssertTests.java | 3 +- 586 files changed, 11535 insertions(+), 11185 deletions(-) diff --git a/pom.xml b/pom.xml index 01596e30d..d2379ec4c 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,8 @@ 1.0.0-alpha.5 + 0.0.43 + false 3.14.0 3.5.3 3.5.3 @@ -86,6 +88,23 @@ + + io.spring.javaformat + spring-javaformat-maven-plugin + ${spring-javaformat-maven-plugin.version} + + + validate + true + + ${disable.format.checks} + + + validate + + + + org.apache.maven.plugins maven-compiler-plugin diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ApplicationRunnerAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ApplicationRunnerAutoConfiguration.java index 0e4aa9549..53973e6b5 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ApplicationRunnerAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ApplicationRunnerAutoConfiguration.java @@ -44,7 +44,7 @@ public ApplicationReadyEventListener applicationReadyEventListener() { return new ApplicationReadyEventListener(); } - static class ApplicationReadyEventListener implements ApplicationListener{ + static class ApplicationReadyEventListener implements ApplicationListener { @Override public void onApplicationEvent(ApplicationReadyEvent event) { @@ -52,5 +52,7 @@ public void onApplicationEvent(ApplicationReadyEvent event) { // shell exits in case that context is kept alive event.getApplicationContext().close(); } + } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandCatalogAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandCatalogAutoConfiguration.java index d38620b10..bd3d4fbea 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandCatalogAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandCatalogAutoConfiguration.java @@ -44,8 +44,7 @@ public class CommandCatalogAutoConfiguration { @ConditionalOnMissingBean(CommandCatalog.class) public CommandCatalog commandCatalog(ObjectProvider methodTargetRegistrars, ObjectProvider commandResolvers, - ObjectProvider commandCatalogCustomizers, - ShellContext shellContext) { + ObjectProvider commandCatalogCustomizers, ShellContext shellContext) { List resolvers = commandResolvers.orderedStream().collect(Collectors.toList()); CommandCatalog catalog = CommandCatalog.of(resolvers, shellContext); methodTargetRegistrars.orderedStream().forEach(resolver -> { @@ -58,7 +57,8 @@ public CommandCatalog commandCatalog(ObjectProvider metho } @Bean - public CommandCatalogCustomizer defaultCommandCatalogCustomizer(ObjectProvider commandRegistrations) { + public CommandCatalogCustomizer defaultCommandCatalogCustomizer( + ObjectProvider commandRegistrations) { return catalog -> { commandRegistrations.orderedStream().forEach(registration -> { catalog.register(registration); @@ -82,7 +82,8 @@ public CommandRegistrationCustomizer helpOptionsCommandRegistrationCustomizer(Sp @Bean @ConditionalOnBean(OptionNameModifier.class) - public CommandRegistrationCustomizer customOptionNameModifierCommandRegistrationCustomizer(OptionNameModifier modifier) { + public CommandRegistrationCustomizer customOptionNameModifierCommandRegistrationCustomizer( + OptionNameModifier modifier) { return builder -> { builder.defaultOptionNameModifier(modifier); }; @@ -91,7 +92,8 @@ public CommandRegistrationCustomizer customOptionNameModifierCommandRegistration @Bean @ConditionalOnMissingBean(OptionNameModifier.class) @ConditionalOnProperty(prefix = "spring.shell.option.naming", name = "case-type") - public CommandRegistrationCustomizer defaultOptionNameModifierCommandRegistrationCustomizer(SpringShellProperties properties) { + public CommandRegistrationCustomizer defaultOptionNameModifierCommandRegistrationCustomizer( + SpringShellProperties properties) { return builder -> { switch (properties.getOption().getNaming().getCaseType()) { case NOOP: @@ -124,4 +126,5 @@ public BuilderSupplier commandRegistrationBuilderSupplier( return builder; }; } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandRegistrationCustomizer.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandRegistrationCustomizer.java index 597312178..12353eac2 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandRegistrationCustomizer.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CommandRegistrationCustomizer.java @@ -27,8 +27,8 @@ public interface CommandRegistrationCustomizer { /** * Callback to customize a {@link CommandRegistration.Builder} instance. - * * @param commandRegistrationBuilder the command registration builder to customize */ void customize(CommandRegistration.Builder commandRegistrationBuilder); + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CompleterAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CompleterAutoConfiguration.java index 5b1a75365..9dddb2818 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CompleterAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/CompleterAutoConfiguration.java @@ -52,19 +52,13 @@ public static class CompleterAdapter implements Completer { public void complete(LineReader reader, ParsedLine line, List candidates) { CompletingParsedLine cpl = (line instanceof CompletingParsedLine) ? ((CompletingParsedLine) line) : t -> t; - CompletionContext context = new CompletionContext(sanitizeInput(line.words()), line.wordIndex(), line.wordCursor(), null, null); + CompletionContext context = new CompletionContext(sanitizeInput(line.words()), line.wordIndex(), + line.wordCursor(), null, null); List proposals = shell.complete(context); proposals.stream() - .map(p -> new Candidate( - p.dontQuote() ? p.value() : cpl.emit(p.value()).toString(), - p.displayText(), - p.category(), - p.description(), - null, - null, - p.complete()) - ) + .map(p -> new Candidate(p.dontQuote() ? p.value() : cpl.emit(p.value()).toString(), p.displayText(), + p.category(), p.description(), null, null, p.complete())) .forEach(candidates::add); } @@ -74,11 +68,15 @@ public void setShell(Shell shell) { static List sanitizeInput(List words) { words = words.stream() - .map(s -> s.replaceAll("^\\n+|\\n+$", "")) // CR at beginning/end of line introduced by backslash continuation - .map(s -> s.replaceAll("\\n+", " ")) // CR in middle of word introduced by return inside a quoted string + .map(s -> s.replaceAll("^\\n+|\\n+$", "")) // CR at beginning/end of line + // introduced by backslash + // continuation + .map(s -> s.replaceAll("\\n+", " ")) // CR in middle of word introduced by + // return inside a quoted string .collect(Collectors.toList()); return words; } + } } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowAutoConfiguration.java index 042127850..1d52a04b8 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowAutoConfiguration.java @@ -65,7 +65,9 @@ public ComponentFlowCustomizer shellCommonComponentFlowCustomizer(ObjectProvider private static class CommonComponentFlowCustomizer implements ComponentFlowCustomizer { private final ObjectProvider terminal; + private final ObjectProvider resourceLoader; + private final ObjectProvider templateExecutor; CommonComponentFlowCustomizer(ObjectProvider terminal, ObjectProvider resourceLoader, @@ -81,5 +83,7 @@ public void customize(Builder componentFlowBuilder) { resourceLoader.ifAvailable(dep -> componentFlowBuilder.resourceLoader(dep)); templateExecutor.ifAvailable(dep -> componentFlowBuilder.templateExecutor(dep)); } + } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowCustomizer.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowCustomizer.java index 533d0bcb5..cb2b40635 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowCustomizer.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ComponentFlowCustomizer.java @@ -30,4 +30,5 @@ public interface ComponentFlowCustomizer { * @param componentFlowBuilder the component flow builder to customize */ void customize(ComponentFlow.Builder componentFlowBuilder); + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ExitCodeAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ExitCodeAutoConfiguration.java index cce07949f..2e7dfd6e9 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ExitCodeAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ExitCodeAutoConfiguration.java @@ -69,6 +69,7 @@ else if (exception.getCause() instanceof CommandExecution.CommandParserException // only map parsing error so that other mappers can do their job return 0; } + } static class ShellExitCodeMappingsExceptionMapper implements ExitCodeExceptionMapper, ExitCodeMappings { @@ -100,6 +101,7 @@ public int getExitCode(Throwable exception) { } return exitCode; } + } static class ShellExitCodeException extends RuntimeException implements ExitCodeGenerator { @@ -115,5 +117,7 @@ static class ShellExitCodeException extends RuntimeException implements ExitCode public int getExitCode() { return code; } + } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineAutoConfiguration.java index cebcf3eba..5f4c7f513 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/JLineAutoConfiguration.java @@ -33,5 +33,7 @@ public static class JLineHistoryConfiguration { public org.jline.reader.History history() { return new DefaultHistory(); } + } + } 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 0ddeeb178..2f6909e04 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 @@ -68,4 +68,5 @@ public Parser parser() { parser.setEofOnEscapedNewLine(true); return parser; } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/LineReaderAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/LineReaderAutoConfiguration.java index bfba557d0..8baef4d95 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/LineReaderAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/LineReaderAutoConfiguration.java @@ -62,6 +62,7 @@ public class LineReaderAutoConfiguration { private String fallbackHistoryFileName; private SpringShellProperties springShellProperties; + private UserConfigPathProvider userConfigPathProvider; public LineReaderAutoConfiguration(Terminal terminal, Completer completer, Parser parser, @@ -84,39 +85,41 @@ public void onContextClosedEvent(ContextClosedEvent event) throws IOException { @Bean public LineReader lineReader() { LineReaderBuilder lineReaderBuilder = LineReaderBuilder.builder() - .terminal(terminal) - .appName("Spring Shell") - .completer(completer) - .history(jLineHistory) - .highlighter(new Highlighter() { - - @Override - public AttributedString highlight(LineReader reader, String buffer) { - int l = 0; - String best = null; - for (String command : commandRegistry.getRegistrations().keySet()) { - if (buffer.startsWith(command) && command.length() > l) { - l = command.length(); - best = command; - } - } - if (best != null) { - return new AttributedStringBuilder(buffer.length()).append(best, AttributedStyle.BOLD).append(buffer.substring(l)).toAttributedString(); - } - else { - return new AttributedString(buffer, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); + .terminal(terminal) + .appName("Spring Shell") + .completer(completer) + .history(jLineHistory) + .highlighter(new Highlighter() { + + @Override + public AttributedString highlight(LineReader reader, String buffer) { + int l = 0; + String best = null; + for (String command : commandRegistry.getRegistrations().keySet()) { + if (buffer.startsWith(command) && command.length() > l) { + l = command.length(); + best = command; } } - - @Override - public void setErrorPattern(Pattern errorPattern) { + if (best != null) { + return new AttributedStringBuilder(buffer.length()).append(best, AttributedStyle.BOLD) + .append(buffer.substring(l)) + .toAttributedString(); } - - @Override - public void setErrorIndex(int errorIndex) { + else { + return new AttributedString(buffer, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)); } - }) - .parser(parser); + } + + @Override + public void setErrorPattern(Pattern errorPattern) { + } + + @Override + public void setErrorIndex(int errorIndex) { + } + }) + .parser(parser); LineReader lineReader = lineReaderBuilder.build(); if (this.springShellProperties.getHistory().isEnabled()) { @@ -133,7 +136,9 @@ public void setErrorIndex(int errorIndex) { // set history file lineReader.setVariable(LineReader.HISTORY_FILE, Paths.get(historyPath)); } - lineReader.unsetOpt(LineReader.Option.INSERT_TAB); // This allows completion on an empty buffer, rather than inserting a tab + lineReader.unsetOpt(LineReader.Option.INSERT_TAB); // This allows completion on an + // empty buffer, rather than + // inserting a tab jLineHistory.attach(lineReader); return lineReader; } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/NonInteractiveShellRunnerCustomizer.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/NonInteractiveShellRunnerCustomizer.java index 23ee3a1d1..c91f6954a 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/NonInteractiveShellRunnerCustomizer.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/NonInteractiveShellRunnerCustomizer.java @@ -11,6 +11,7 @@ */ @FunctionalInterface public interface NonInteractiveShellRunnerCustomizer { + /** * Customize the {@link NonInteractiveShellRunner}. * @param shellRunner the non-interactive shell runner to customize diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ParameterResolverAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ParameterResolverAutoConfiguration.java index 3c8c9c171..7cd9d792b 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ParameterResolverAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ParameterResolverAutoConfiguration.java @@ -41,7 +41,7 @@ public CompletionResolver defaultCompletionResolver() { @Bean public CommandExecutionHandlerMethodArgumentResolvers commandExecutionHandlerMethodArgumentResolvers( - ShellConversionServiceSupplier shellConversionServiceSupplier) { + ShellConversionServiceSupplier shellConversionServiceSupplier) { List resolvers = new ArrayList<>(); resolvers.add(new ArgumentHeaderMethodArgumentResolver(shellConversionServiceSupplier.get(), null)); resolvers.add(new HeadersMethodArgumentResolver()); @@ -50,4 +50,5 @@ public CommandExecutionHandlerMethodArgumentResolvers commandExecutionHandlerMet resolvers.add(new OptionMethodArgumentResolver(shellConversionServiceSupplier.get(), null)); return new CommandExecutionHandlerMethodArgumentResolvers(resolvers); } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellContextAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellContextAutoConfiguration.java index 28b04fd40..95e3e7a0a 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellContextAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellContextAutoConfiguration.java @@ -34,4 +34,5 @@ public ShellContext shellContext(Terminal terminal) { } return new DefaultShellContext(pty); } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellRunnerAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellRunnerAutoConfiguration.java index 491cc3170..2d048069a 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellRunnerAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/ShellRunnerAutoConfiguration.java @@ -43,7 +43,8 @@ public class ShellRunnerAutoConfiguration { public static class PrimaryCommandConfiguration { @Bean - @ConditionalOnProperty(prefix = "spring.shell.noninteractive", value = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.shell.noninteractive", value = "enabled", havingValue = "true", + matchIfMissing = true) public NonInteractiveShellRunner nonInteractiveApplicationRunner(Shell shell, ShellContext shellContext, ObjectProvider customizer, SpringShellProperties properties) { NonInteractiveShellRunner shellRunner = new NonInteractiveShellRunner(shell, shellContext, @@ -59,14 +60,16 @@ public NonInteractiveShellRunner nonInteractiveApplicationRunner(Shell shell, Sh public static class NonePrimaryCommandConfiguration { @Bean - @ConditionalOnProperty(prefix = "spring.shell.interactive", value = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "spring.shell.interactive", value = "enabled", havingValue = "true", + matchIfMissing = false) public InteractiveShellRunner interactiveApplicationRunner(LineReader lineReader, PromptProvider promptProvider, Shell shell, ShellContext shellContext) { return new InteractiveShellRunner(lineReader, promptProvider, shell, shellContext); } @Bean - @ConditionalOnProperty(prefix = "spring.shell.noninteractive", value = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.shell.noninteractive", value = "enabled", havingValue = "true", + matchIfMissing = true) public NonInteractiveShellRunner nonInteractiveApplicationRunner(Shell shell, ShellContext shellContext, ObjectProvider customizer) { NonInteractiveShellRunner shellRunner = new NonInteractiveShellRunner(shell, shellContext); @@ -75,10 +78,12 @@ public NonInteractiveShellRunner nonInteractiveApplicationRunner(Shell shell, Sh } @Bean - @ConditionalOnProperty(prefix = "spring.shell.script", value = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "spring.shell.script", value = "enabled", havingValue = "true", + matchIfMissing = false) public ScriptShellRunner scriptApplicationRunner(Parser parser, Shell shell) { return new ScriptShellRunner(parser, shell); } } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellAutoConfiguration.java index 21c470678..3dbf73b54 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellAutoConfiguration.java @@ -71,4 +71,5 @@ public Shell shell(ResultHandlerService resultHandlerService, CommandCatalog com shell.setConversionService(shellConversionServiceSupplier.get()); return shell; } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellProperties.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellProperties.java index 50b63754d..26f84ae92 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellProperties.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/SpringShellProperties.java @@ -26,14 +26,23 @@ public class SpringShellProperties { private History history = new History(); + private Config config = new Config(); + private Script script = new Script(); + private Interactive interactive = new Interactive(); + private Noninteractive noninteractive = new Noninteractive(); + private Theme theme = new Theme(); + private Command command = new Command(); + private Help help = new Help(); + private Option option = new Option(); + private Context context = new Context(); public void setConfig(Config config) { @@ -119,6 +128,7 @@ public void setContext(Context context) { public static class Config { private String env; + private String location; public String getEnv() { @@ -136,11 +146,13 @@ public String getLocation() { public void setLocation(String location) { this.location = location; } + } public static class History { private String name; + private boolean enabled = true; public String getName() { @@ -158,6 +170,7 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class Script { @@ -171,6 +184,7 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class Interactive { @@ -184,11 +198,13 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class Noninteractive { private boolean enabled = true; + private String primaryCommand; public boolean isEnabled() { @@ -206,6 +222,7 @@ public String getPrimaryCommand() { public void setPrimaryCommand(String primaryCommand) { this.primaryCommand = primaryCommand; } + } public static class Theme { @@ -219,13 +236,17 @@ public String getName() { public void setName(String name) { this.name = name; } + } public static class HelpCommand { private boolean enabled = true; + private String commandTemplate = "classpath:template/help-command-default.stg"; + private String commandsTemplate = "classpath:template/help-commands-default.stg"; + private GroupingMode groupingMode = GroupingMode.GROUP; public boolean isEnabled() { @@ -261,9 +282,11 @@ public void setGroupingMode(GroupingMode groupingMode) { } public enum GroupingMode { - GROUP, - FLAT + + GROUP, FLAT + } + } public static class ClearCommand { @@ -277,6 +300,7 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class QuitCommand { @@ -290,6 +314,7 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class StacktraceCommand { @@ -303,6 +328,7 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class ScriptCommand { @@ -316,6 +342,7 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class HistoryCommand { @@ -329,11 +356,13 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class CompletionCommand { private boolean enabled = true; + private String rootCommand; public boolean isEnabled() { @@ -351,17 +380,25 @@ public String getRootCommand() { public void setRootCommand(String rootCommand) { this.rootCommand = rootCommand; } + } public static class Command { private HelpCommand help = new HelpCommand(); + private ClearCommand clear = new ClearCommand(); + private QuitCommand quit = new QuitCommand(); + private StacktraceCommand stacktrace = new StacktraceCommand(); + private ScriptCommand script = new ScriptCommand(); + private HistoryCommand history = new HistoryCommand(); + private CompletionCommand completion = new CompletionCommand(); + private VersionCommand version = new VersionCommand(); public void setHelp(HelpCommand help) { @@ -427,20 +464,31 @@ public VersionCommand getVersion() { public void setVersion(VersionCommand version) { this.version = version; } + } public static class VersionCommand { private boolean enabled = true; + private String template = "classpath:template/version-default.st"; + private boolean showBuildGroup = false; + private boolean showBuildArtifact = false; + private boolean showBuildName = false; + private boolean showBuildVersion = true; + private boolean showBuildTime = false; + private boolean showGitBranch = false; + private boolean showGitCommitId = false; + private boolean showGitShortCommitId = false; + private boolean showGitCommitTime = false; public boolean isEnabled() { @@ -530,6 +578,7 @@ public boolean isShowGitCommitTime() { public void setShowGitCommitTime(boolean showGitCommitTime) { this.showGitCommitTime = showGitCommitTime; } + } public static class Help { @@ -585,6 +634,7 @@ public boolean isEnabled() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } public static class Option { @@ -598,9 +648,11 @@ public OptionNaming getNaming() { public void setNaming(OptionNaming naming) { this.naming = naming; } + } public static class OptionNaming { + private OptionNamingCase caseType = OptionNamingCase.NOOP; public OptionNamingCase getCaseType() { @@ -610,6 +662,7 @@ public OptionNamingCase getCaseType() { public void setCaseType(OptionNamingCase caseType) { this.caseType = caseType; } + } public static class Context { @@ -623,14 +676,13 @@ public boolean isClose() { public void setClose(boolean close) { this.close = close; } + } public static enum OptionNamingCase { - NOOP, - CAMEL, - SNAKE, - KEBAB, - PASCAL + + NOOP, CAMEL, SNAKE, KEBAB, PASCAL + } } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardAPIAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardAPIAutoConfiguration.java index 3b4685b34..508d33864 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardAPIAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardAPIAutoConfiguration.java @@ -59,7 +59,8 @@ public MethodTargetRegistrar standardMethodTargetResolver(ApplicationContext app } @Bean - public static LazyInitializationExcludeFilter valueProviderLazyInitializationExcludeFilter(){ + public static LazyInitializationExcludeFilter valueProviderLazyInitializationExcludeFilter() { return LazyInitializationExcludeFilter.forBeanTypes(ValueProvider.class); } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardCommandsAutoConfiguration.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardCommandsAutoConfiguration.java index 7aec5430d..bbbe5387a 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardCommandsAutoConfiguration.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/StandardCommandsAutoConfiguration.java @@ -54,7 +54,8 @@ public class StandardCommandsAutoConfiguration { @Bean @ConditionalOnMissingBean(Help.Command.class) - @ConditionalOnProperty(prefix = "spring.shell.command.help", value = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.shell.command.help", value = "enabled", havingValue = "true", + matchIfMissing = true) public Help help(SpringShellProperties properties, ObjectProvider templateExecutor) { Help help = new Help(templateExecutor.getIfAvailable()); if (properties.getCommand().getHelp().getGroupingMode() == GroupingMode.FLAT) { @@ -67,35 +68,40 @@ public Help help(SpringShellProperties properties, ObjectProvider throwableResultHandler) { return new Stacktrace(throwableResultHandler); } @Bean @ConditionalOnMissingBean(Script.Command.class) - @ConditionalOnProperty(prefix = "spring.shell.command.script", value = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.shell.command.script", value = "enabled", havingValue = "true", + matchIfMissing = true) public Script script(Parser parser) { return new Script(parser); } @Bean @ConditionalOnMissingBean(History.Command.class) - @ConditionalOnProperty(prefix = "spring.shell.command.history", value = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.shell.command.history", value = "enabled", havingValue = "true", + matchIfMissing = true) public History historyCommand(org.jline.reader.History jLineHistory) { return new History(jLineHistory); } @@ -109,7 +115,8 @@ public Completion completion(SpringShellProperties properties) { @Bean @ConditionalOnMissingBean(Version.Command.class) - @ConditionalOnProperty(prefix = "spring.shell.command.version", value = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.shell.command.version", value = "enabled", havingValue = "true", + matchIfMissing = true) public Version version(SpringShellProperties properties, ObjectProvider buildProperties, ObjectProvider gitProperties, ObjectProvider templateExecutor) { Version version = new Version(templateExecutor.getIfAvailable()); @@ -128,4 +135,5 @@ public Version version(SpringShellProperties properties, ObjectProvider pathProvider = (path) -> Paths.get(path); + private final String configDirEnv; + private final String configDirLocation; LocationResolver(String configDirEnv, String configDirLocation) { @@ -93,5 +98,7 @@ private boolean isWindows() { String os = System.getProperty("os.name"); return os.startsWith("Windows"); } + } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnCompletionCommandCondition.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnCompletionCommandCondition.java index a82f9b78c..f4bad8f63 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnCompletionCommandCondition.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnCompletionCommandCondition.java @@ -26,9 +26,13 @@ public OnCompletionCommandCondition() { @ConditionalOnProperty(prefix = "spring.shell.command.completion", value = "root-command") static class RootNameCondition { + } - @ConditionalOnProperty(prefix = "spring.shell.command.completion", value = "enabled", havingValue = "true", matchIfMissing = true) + @ConditionalOnProperty(prefix = "spring.shell.command.completion", value = "enabled", havingValue = "true", + matchIfMissing = true) static class EnabledCondition { + } + } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnNotPrimaryCommandCondition.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnNotPrimaryCommandCondition.java index 11a7fb150..4b1742f6f 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnNotPrimaryCommandCondition.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnNotPrimaryCommandCondition.java @@ -26,6 +26,7 @@ public OnNotPrimaryCommandCondition() { @ConditionalOnProperty(prefix = "spring.shell.noninteractive", value = "primary-command", matchIfMissing = false) static class NotPrimaryCommandCondition { + } } diff --git a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnPrimaryCommandCondition.java b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnPrimaryCommandCondition.java index 6f8e7afd5..10d3492ab 100644 --- a/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnPrimaryCommandCondition.java +++ b/spring-shell-autoconfigure/src/main/java/org/springframework/shell/boot/condition/OnPrimaryCommandCondition.java @@ -26,5 +26,7 @@ public OnPrimaryCommandCondition() { @ConditionalOnProperty(prefix = "spring.shell.noninteractive", value = "primary-command", matchIfMissing = false) static class PrimaryCommandCondition { + } + } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ApplicationRunnerAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ApplicationRunnerAutoConfigurationTests.java index 4c8fe3d7e..41ead3abb 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ApplicationRunnerAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ApplicationRunnerAutoConfigurationTests.java @@ -25,18 +25,18 @@ public class ApplicationRunnerAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(ApplicationRunnerAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(ApplicationRunnerAutoConfiguration.class)); @Test void contextCloseDisabledByDefault() { contextRunner.run(context -> assertThat(context) - .doesNotHaveBean(ApplicationRunnerAutoConfiguration.ApplicationReadyEventListener.class)); + .doesNotHaveBean(ApplicationRunnerAutoConfiguration.ApplicationReadyEventListener.class)); } @Test void contextCloseEnabled() { contextRunner.withPropertyValues("spring.shell.context.close:true") - .run(context -> assertThat(context) + .run(context -> assertThat(context) .hasSingleBean(ApplicationRunnerAutoConfiguration.ApplicationReadyEventListener.class)); } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/CommandCatalogAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/CommandCatalogAutoConfigurationTests.java index 5386b805e..cdc706fb2 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/CommandCatalogAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/CommandCatalogAutoConfigurationTests.java @@ -36,8 +36,8 @@ public class CommandCatalogAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(CommandCatalogAutoConfiguration.class, - JLineShellAutoConfiguration.class, ShellContextAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(CommandCatalogAutoConfiguration.class, + JLineShellAutoConfiguration.class, ShellContextAutoConfiguration.class)); @Test void defaultCommandCatalog() { @@ -46,96 +46,83 @@ void defaultCommandCatalog() { @Test void testCommandResolvers() { - this.contextRunner.withUserConfiguration(CustomCommandResolverConfiguration.class) - .run((context) -> { - CommandCatalog commandCatalog = context.getBean(CommandCatalog.class); - assertThat(commandCatalog).extracting("resolvers").asInstanceOf(InstanceOfAssertFactories.LIST) - .hasSize(1); - }); + this.contextRunner.withUserConfiguration(CustomCommandResolverConfiguration.class).run((context) -> { + CommandCatalog commandCatalog = context.getBean(CommandCatalog.class); + assertThat(commandCatalog).extracting("resolvers").asInstanceOf(InstanceOfAssertFactories.LIST).hasSize(1); + }); } @Test void customCommandCatalog() { - this.contextRunner.withUserConfiguration(CustomCommandCatalogConfiguration.class) - .run((context) -> { - CommandCatalog commandCatalog = context.getBean(CommandCatalog.class); - assertThat(commandCatalog).isSameAs(CustomCommandCatalogConfiguration.testCommandCatalog); - }); + this.contextRunner.withUserConfiguration(CustomCommandCatalogConfiguration.class).run((context) -> { + CommandCatalog commandCatalog = context.getBean(CommandCatalog.class); + assertThat(commandCatalog).isSameAs(CustomCommandCatalogConfiguration.testCommandCatalog); + }); } @Test void registerCommandRegistration() { - this.contextRunner.withUserConfiguration(CustomCommandRegistrationConfiguration.class) - .run((context) -> { - CommandCatalog commandCatalog = context.getBean(CommandCatalog.class); - assertThat(commandCatalog.getRegistrations().get("customcommand")).isNotNull(); - }); + this.contextRunner.withUserConfiguration(CustomCommandRegistrationConfiguration.class).run((context) -> { + CommandCatalog commandCatalog = context.getBean(CommandCatalog.class); + assertThat(commandCatalog.getRegistrations().get("customcommand")).isNotNull(); + }); } @Test void builderSupplierIsCreated() { - this.contextRunner - .run(context -> { - BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); - assertThat(builderSupplier).isNotNull(); - }); + this.contextRunner.run(context -> { + BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); + assertThat(builderSupplier).isNotNull(); + }); } @Test void defaultOptionNameModifierIsNull() { - this.contextRunner - .run(context -> { - BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); - Builder builder = builderSupplier.get(); - assertThat(builder).extracting("defaultOptionNameModifier").isNull(); - }); + this.contextRunner.run(context -> { + BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); + Builder builder = builderSupplier.get(); + assertThat(builder).extracting("defaultOptionNameModifier").isNull(); + }); } @Test void defaultOptionNameModifierIsSet() { - this.contextRunner - .withUserConfiguration(CustomOptionNameModifierConfiguration.class) - .run(context -> { - BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); - Builder builder = builderSupplier.get(); - assertThat(builder).extracting("defaultOptionNameModifier").isNotNull(); - }); + this.contextRunner.withUserConfiguration(CustomOptionNameModifierConfiguration.class).run(context -> { + BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); + Builder builder = builderSupplier.get(); + assertThat(builder).extracting("defaultOptionNameModifier").isNotNull(); + }); } @Test void defaultOptionNameModifierIsSetFromProperties() { - this.contextRunner - .withPropertyValues("spring.shell.option.naming.case-type=kebab") - .run(context -> { - BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); - Builder builder = builderSupplier.get(); - assertThat(builder).extracting("defaultOptionNameModifier").isNotNull(); - }); + this.contextRunner.withPropertyValues("spring.shell.option.naming.case-type=kebab").run(context -> { + BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); + Builder builder = builderSupplier.get(); + assertThat(builder).extracting("defaultOptionNameModifier").isNotNull(); + }); } @Test void defaultOptionNameModifierNoopNotSetFromProperties() { - this.contextRunner - .withPropertyValues("spring.shell.option.naming.case-type=noop") - .run(context -> { - BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); - Builder builder = builderSupplier.get(); - assertThat(builder).extracting("defaultOptionNameModifier").isNull(); - // there is customizer but it doesn't do anything - assertThat(context).hasBean("defaultOptionNameModifierCommandRegistrationCustomizer"); - }); + this.contextRunner.withPropertyValues("spring.shell.option.naming.case-type=noop").run(context -> { + BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); + Builder builder = builderSupplier.get(); + assertThat(builder).extracting("defaultOptionNameModifier").isNull(); + // there is customizer but it doesn't do anything + assertThat(context).hasBean("defaultOptionNameModifierCommandRegistrationCustomizer"); + }); } @Test void noCustomizerIfPropertyIsNotSet() { - this.contextRunner - .run(context -> { - BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); - Builder builder = builderSupplier.get(); - assertThat(builder).extracting("defaultOptionNameModifier").isNull(); - // no customizer added without property - assertThat(context).doesNotHaveBean("defaultOptionNameModifierCommandRegistrationCustomizer"); - }); + this.contextRunner.run(context -> { + BuilderSupplier builderSupplier = context.getBean(BuilderSupplier.class); + Builder builder = builderSupplier.get(); + assertThat(builder).extracting("defaultOptionNameModifier").isNull(); + // no customizer added without property + assertThat(context).doesNotHaveBean("defaultOptionNameModifierCommandRegistrationCustomizer"); + }); } // defaultOptionNameModifierCommandRegistrationCustomizer @@ -146,6 +133,7 @@ static class CustomOptionNameModifierConfiguration { OptionNameModifier customOptionNameModifier() { return name -> name; } + } @Configuration @@ -155,6 +143,7 @@ static class CustomCommandResolverConfiguration { CommandResolver customCommandResolver() { return () -> Collections.emptyList(); } + } @Configuration @@ -166,6 +155,7 @@ static class CustomCommandCatalogConfiguration { CommandCatalog customCommandCatalog() { return testCommandCatalog; } + } @Configuration @@ -173,14 +163,11 @@ static class CustomCommandRegistrationConfiguration { @Bean CommandRegistration commandRegistration() { - return CommandRegistration.builder() - .command("customcommand") - .withTarget() - .function(ctx -> { - return null; - }) - .and() - .build(); + return CommandRegistration.builder().command("customcommand").withTarget().function(ctx -> { + return null; + }).and().build(); } + } + } 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 index d1de27fb3..0cffbbda9 100644 --- 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 @@ -30,7 +30,7 @@ class JLineShellAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(JLineShellAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(JLineShellAutoConfiguration.class)); @Test void canCreatePlainTerminal() { @@ -42,9 +42,9 @@ void canCreatePlainTerminal() { @Test void canCustomizeTerminalBuilder() { TerminalCustomizer customizer = mock(TerminalCustomizer.class); - contextRunner.withBean(TerminalCustomizer.class, () -> customizer) - .run(context -> { - verify(customizer).customize(any(TerminalBuilder.class)); - }); + contextRunner.withBean(TerminalCustomizer.class, () -> customizer).run(context -> { + verify(customizer).customize(any(TerminalBuilder.class)); + }); } + } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/LineReaderAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/LineReaderAutoConfigurationTests.java index f4aa0fcfc..26d84a3a9 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/LineReaderAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/LineReaderAutoConfigurationTests.java @@ -39,41 +39,37 @@ public class LineReaderAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(LineReaderAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(LineReaderAutoConfiguration.class)); @Test public void testLineReaderCreated() { - this.contextRunner - .withUserConfiguration(MockConfiguration.class) - .run(context -> { - assertThat(context).hasSingleBean(LineReader.class); - LineReader lineReader = context.getBean(LineReader.class); - assertThat(lineReader.getVariable(LineReader.HISTORY_FILE)).asString().contains("spring-shell.log"); - }); + this.contextRunner.withUserConfiguration(MockConfiguration.class).run(context -> { + assertThat(context).hasSingleBean(LineReader.class); + LineReader lineReader = context.getBean(LineReader.class); + assertThat(lineReader.getVariable(LineReader.HISTORY_FILE)).asString().contains("spring-shell.log"); + }); } @Test public void testLineReaderCreatedNoHistoryFile() { - this.contextRunner - .withUserConfiguration(MockConfiguration.class) - .withPropertyValues("spring.shell.history.enabled=false") - .run(context -> { - assertThat(context).hasSingleBean(LineReader.class); - LineReader lineReader = context.getBean(LineReader.class); - assertThat(lineReader.getVariable(LineReader.HISTORY_FILE)).isNull(); - }); + this.contextRunner.withUserConfiguration(MockConfiguration.class) + .withPropertyValues("spring.shell.history.enabled=false") + .run(context -> { + assertThat(context).hasSingleBean(LineReader.class); + LineReader lineReader = context.getBean(LineReader.class); + assertThat(lineReader.getVariable(LineReader.HISTORY_FILE)).isNull(); + }); } @Test public void testLineReaderCreatedCustomHistoryFile() { - this.contextRunner - .withUserConfiguration(MockConfiguration.class) - .withPropertyValues("spring.shell.history.name=fakehistory.txt") - .run(context -> { - assertThat(context).hasSingleBean(LineReader.class); - LineReader lineReader = context.getBean(LineReader.class); - assertThat(lineReader.getVariable(LineReader.HISTORY_FILE)).asString().contains("fakehistory.txt"); - }); + this.contextRunner.withUserConfiguration(MockConfiguration.class) + .withPropertyValues("spring.shell.history.name=fakehistory.txt") + .run(context -> { + assertThat(context).hasSingleBean(LineReader.class); + LineReader lineReader = context.getBean(LineReader.class); + assertThat(lineReader.getVariable(LineReader.HISTORY_FILE)).asString().contains("fakehistory.txt"); + }); } @Configuration(proxyBeanMethods = false) @@ -110,5 +106,7 @@ History mockHistory() { UserConfigPathProvider mockUserConfigPathProvider() { return () -> Paths.get("mockpath"); } + } + } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ParameterResolverAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ParameterResolverAutoConfigurationTests.java index 44c3c6c65..707d2ac54 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ParameterResolverAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ParameterResolverAutoConfigurationTests.java @@ -31,22 +31,20 @@ public class ParameterResolverAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(ParameterResolverAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(ParameterResolverAutoConfiguration.class)); @Test void defaultCompletionResolverExists() { - this.contextRunner.withUserConfiguration(CustomShellConversionServiceConfiguration.class) - .run((context) -> { - assertThat(context).hasSingleBean(CompletionResolver.class); - }); + this.contextRunner.withUserConfiguration(CustomShellConversionServiceConfiguration.class).run((context) -> { + assertThat(context).hasSingleBean(CompletionResolver.class); + }); } @Test void defaultCommandExecutionHandlerMethodArgumentResolversExists() { - this.contextRunner.withUserConfiguration(CustomShellConversionServiceConfiguration.class) - .run((context) -> { - assertThat(context).hasSingleBean(CommandExecutionHandlerMethodArgumentResolvers.class); - }); + this.contextRunner.withUserConfiguration(CustomShellConversionServiceConfiguration.class).run((context) -> { + assertThat(context).hasSingleBean(CommandExecutionHandlerMethodArgumentResolvers.class); + }); } @Configuration @@ -56,5 +54,7 @@ static class CustomShellConversionServiceConfiguration { ShellConversionServiceSupplier shellConversionServiceSupplier() { return () -> new DefaultConversionService(); } + } + } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ShellRunnerAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ShellRunnerAutoConfigurationTests.java index cb0c2f90a..4067d0a9e 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ShellRunnerAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ShellRunnerAutoConfigurationTests.java @@ -42,14 +42,15 @@ class ShellRunnerAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(ShellRunnerAutoConfiguration.class)) - .withBean(Shell.class, () -> mock(Shell.class)) - .withBean(PromptProvider.class, () -> mock(PromptProvider.class)) - .withBean(LineReader.class, () -> mock(LineReader.class)) - .withBean(Parser.class, () -> mock(Parser.class)) - .withBean(ShellContext.class, () -> mock(ShellContext.class)) - .withBean(CompletionResolver.class, () -> mock(CompletionResolver.class)) - .withBean(CommandExecutionHandlerMethodArgumentResolvers.class, () -> mock(CommandExecutionHandlerMethodArgumentResolvers.class)); + .withConfiguration(AutoConfigurations.of(ShellRunnerAutoConfiguration.class)) + .withBean(Shell.class, () -> mock(Shell.class)) + .withBean(PromptProvider.class, () -> mock(PromptProvider.class)) + .withBean(LineReader.class, () -> mock(LineReader.class)) + .withBean(Parser.class, () -> mock(Parser.class)) + .withBean(ShellContext.class, () -> mock(ShellContext.class)) + .withBean(CompletionResolver.class, () -> mock(CompletionResolver.class)) + .withBean(CommandExecutionHandlerMethodArgumentResolvers.class, + () -> mock(CommandExecutionHandlerMethodArgumentResolvers.class)); @Nested class Interactive { @@ -62,8 +63,9 @@ void disabledByDefault() { @Test void disabledWhenPropertySet() { contextRunner.withPropertyValues("spring.shell.interactive.enabled:false") - .run(context -> assertThat(context).doesNotHaveBean(InteractiveShellRunner.class)); + .run(context -> assertThat(context).doesNotHaveBean(InteractiveShellRunner.class)); } + } @Nested @@ -87,18 +89,18 @@ void primaryCommandNotSet() { @Test void disabledWhenPropertySet() { contextRunner.withPropertyValues("spring.shell.noninteractive.enabled:false") - .run(context -> assertThat(context).doesNotHaveBean(NonInteractiveShellRunner.class)); + .run(context -> assertThat(context).doesNotHaveBean(NonInteractiveShellRunner.class)); } @Test void canBeCustomized() { NonInteractiveShellRunnerCustomizer customizer = mock(NonInteractiveShellRunnerCustomizer.class); - contextRunner.withBean(NonInteractiveShellRunnerCustomizer.class, () -> customizer) - .run(context -> { - NonInteractiveShellRunner runner = context.getBean(NonInteractiveShellRunner.class); - verify(customizer).customize(runner); - }); + contextRunner.withBean(NonInteractiveShellRunnerCustomizer.class, () -> customizer).run(context -> { + NonInteractiveShellRunner runner = context.getBean(NonInteractiveShellRunner.class); + verify(customizer).customize(runner); + }); } + } @Nested @@ -112,8 +114,9 @@ void disabledByDefault() { @Test void disabledWhenPropertySet() { contextRunner.withPropertyValues("spring.shell.script.enabled:false") - .run(context -> assertThat(context).doesNotHaveBean(ScriptShellRunner.class)); + .run(context -> assertThat(context).doesNotHaveBean(ScriptShellRunner.class)); } + } @Nested @@ -121,16 +124,16 @@ class PrimaryCommand { @Test void primaryCommandDisablesOtherRunners() { - contextRunner.withPropertyValues("spring.shell.noninteractive.primary-command:fake") - .run(context -> { - assertThat(context).doesNotHaveBean(InteractiveShellRunner.class); - assertThat(context).doesNotHaveBean(ScriptShellRunner.class); - assertThat(context).hasSingleBean(NonInteractiveShellRunner.class); - NonInteractiveShellRunner runner = context.getBean(NonInteractiveShellRunner.class); - String command = (String) ReflectionTestUtils.getField(runner, "primaryCommand"); - assertThat(command).isEqualTo("fake"); - }); + contextRunner.withPropertyValues("spring.shell.noninteractive.primary-command:fake").run(context -> { + assertThat(context).doesNotHaveBean(InteractiveShellRunner.class); + assertThat(context).doesNotHaveBean(ScriptShellRunner.class); + assertThat(context).hasSingleBean(NonInteractiveShellRunner.class); + NonInteractiveShellRunner runner = context.getBean(NonInteractiveShellRunner.class); + String command = (String) ReflectionTestUtils.getField(runner, "primaryCommand"); + assertThat(command).isEqualTo("fake"); + }); } } + } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/SpringShellPropertiesTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/SpringShellPropertiesTests.java index 462dc3202..824e3eda8 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/SpringShellPropertiesTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/SpringShellPropertiesTests.java @@ -30,148 +30,145 @@ public class SpringShellPropertiesTests { @Test public void defaultNoPropertiesSet() { - this.contextRunner - .withUserConfiguration(Config1.class) - .run((context) -> { - SpringShellProperties properties = context.getBean(SpringShellProperties.class); - assertThat(properties.getHistory().isEnabled()).isTrue(); - assertThat(properties.getHistory().getName()).isNull(); - assertThat(properties.getConfig().getLocation()).isNull(); - assertThat(properties.getConfig().getEnv()).isNull(); - assertThat(properties.getScript().isEnabled()).isFalse(); - assertThat(properties.getInteractive().isEnabled()).isFalse(); - assertThat(properties.getNoninteractive().isEnabled()).isTrue(); - assertThat(properties.getNoninteractive().getPrimaryCommand()).isNull(); - assertThat(properties.getTheme().getName()).isNull(); - assertThat(properties.getCommand().getClear().isEnabled()).isTrue(); - assertThat(properties.getCommand().getHelp().isEnabled()).isTrue(); - assertThat(properties.getCommand().getHelp().getGroupingMode()).isEqualTo(GroupingMode.GROUP); - assertThat(properties.getCommand().getHelp().getCommandTemplate()).isNotNull(); - assertThat(properties.getCommand().getHelp().getCommandsTemplate()).isNotNull(); - assertThat(properties.getCommand().getHistory().isEnabled()).isTrue(); - assertThat(properties.getCommand().getQuit().isEnabled()).isTrue(); - assertThat(properties.getCommand().getScript().isEnabled()).isTrue(); - assertThat(properties.getCommand().getStacktrace().isEnabled()).isTrue(); - assertThat(properties.getCommand().getCompletion().isEnabled()).isTrue(); - assertThat(properties.getCommand().getCompletion().getRootCommand()).isNull(); - assertThat(properties.getCommand().getVersion().isEnabled()).isTrue(); - assertThat(properties.getCommand().getVersion().getTemplate()).isNotNull(); - assertThat(properties.getCommand().getVersion().isShowBuildArtifact()).isFalse(); - assertThat(properties.getCommand().getVersion().isShowBuildGroup()).isFalse(); - assertThat(properties.getCommand().getVersion().isShowBuildName()).isFalse(); - assertThat(properties.getCommand().getVersion().isShowBuildTime()).isFalse(); - assertThat(properties.getCommand().getVersion().isShowBuildVersion()).isTrue(); - assertThat(properties.getCommand().getVersion().isShowGitBranch()).isFalse(); - 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'); - assertThat(properties.getOption().getNaming().getCaseType()).isEqualTo(OptionNamingCase.NOOP); - assertThat(properties.getContext().isClose()).isFalse(); - }); + this.contextRunner.withUserConfiguration(Config1.class).run((context) -> { + SpringShellProperties properties = context.getBean(SpringShellProperties.class); + assertThat(properties.getHistory().isEnabled()).isTrue(); + assertThat(properties.getHistory().getName()).isNull(); + assertThat(properties.getConfig().getLocation()).isNull(); + assertThat(properties.getConfig().getEnv()).isNull(); + assertThat(properties.getScript().isEnabled()).isFalse(); + assertThat(properties.getInteractive().isEnabled()).isFalse(); + assertThat(properties.getNoninteractive().isEnabled()).isTrue(); + assertThat(properties.getNoninteractive().getPrimaryCommand()).isNull(); + assertThat(properties.getTheme().getName()).isNull(); + assertThat(properties.getCommand().getClear().isEnabled()).isTrue(); + assertThat(properties.getCommand().getHelp().isEnabled()).isTrue(); + assertThat(properties.getCommand().getHelp().getGroupingMode()).isEqualTo(GroupingMode.GROUP); + assertThat(properties.getCommand().getHelp().getCommandTemplate()).isNotNull(); + assertThat(properties.getCommand().getHelp().getCommandsTemplate()).isNotNull(); + assertThat(properties.getCommand().getHistory().isEnabled()).isTrue(); + assertThat(properties.getCommand().getQuit().isEnabled()).isTrue(); + assertThat(properties.getCommand().getScript().isEnabled()).isTrue(); + assertThat(properties.getCommand().getStacktrace().isEnabled()).isTrue(); + assertThat(properties.getCommand().getCompletion().isEnabled()).isTrue(); + assertThat(properties.getCommand().getCompletion().getRootCommand()).isNull(); + assertThat(properties.getCommand().getVersion().isEnabled()).isTrue(); + assertThat(properties.getCommand().getVersion().getTemplate()).isNotNull(); + assertThat(properties.getCommand().getVersion().isShowBuildArtifact()).isFalse(); + assertThat(properties.getCommand().getVersion().isShowBuildGroup()).isFalse(); + assertThat(properties.getCommand().getVersion().isShowBuildName()).isFalse(); + assertThat(properties.getCommand().getVersion().isShowBuildTime()).isFalse(); + assertThat(properties.getCommand().getVersion().isShowBuildVersion()).isTrue(); + assertThat(properties.getCommand().getVersion().isShowGitBranch()).isFalse(); + 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'); + assertThat(properties.getOption().getNaming().getCaseType()).isEqualTo(OptionNamingCase.NOOP); + assertThat(properties.getContext().isClose()).isFalse(); + }); } @Test public void setProperties() { - this.contextRunner - .withPropertyValues("spring.shell.history.enabled=false") - .withPropertyValues("spring.shell.history.name=fakename") - .withPropertyValues("spring.shell.config.location=fakelocation") - .withPropertyValues("spring.shell.config.env=FAKE_ENV") - .withPropertyValues("spring.shell.script.enabled=true") - .withPropertyValues("spring.shell.interactive.enabled=true") - .withPropertyValues("spring.shell.noninteractive.enabled=false") - .withPropertyValues("spring.shell.noninteractive.primary-command=fakecommand") - .withPropertyValues("spring.shell.theme.name=fake") - .withPropertyValues("spring.shell.command.clear.enabled=false") - .withPropertyValues("spring.shell.command.help.enabled=false") - .withPropertyValues("spring.shell.command.help.grouping-mode=flat") - .withPropertyValues("spring.shell.command.help.command-template=fake1") - .withPropertyValues("spring.shell.command.help.commands-template=fake2") - .withPropertyValues("spring.shell.command.history.enabled=false") - .withPropertyValues("spring.shell.command.quit.enabled=false") - .withPropertyValues("spring.shell.command.script.enabled=false") - .withPropertyValues("spring.shell.command.stacktrace.enabled=false") - .withPropertyValues("spring.shell.command.completion.enabled=false") - .withPropertyValues("spring.shell.command.completion.root-command=fake") - .withPropertyValues("spring.shell.command.version.enabled=false") - .withPropertyValues("spring.shell.command.version.template=fake") - .withPropertyValues("spring.shell.command.version.show-build-artifact=true") - .withPropertyValues("spring.shell.command.version.show-build-group=true") - .withPropertyValues("spring.shell.command.version.show-build-name=true") - .withPropertyValues("spring.shell.command.version.show-build-time=true") - .withPropertyValues("spring.shell.command.version.show-build-version=false") - .withPropertyValues("spring.shell.command.version.show-git-branch=true") - .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") - .withPropertyValues("spring.shell.option.naming.case-type=camel") - .withPropertyValues("spring.shell.context.close=true") - .withUserConfiguration(Config1.class) - .run((context) -> { - SpringShellProperties properties = context.getBean(SpringShellProperties.class); - assertThat(properties.getHistory().isEnabled()).isFalse(); - assertThat(properties.getHistory().getName()).isEqualTo("fakename"); - assertThat(properties.getConfig().getLocation()).isEqualTo("fakelocation"); - assertThat(properties.getConfig().getEnv()).isEqualTo("FAKE_ENV"); - assertThat(properties.getScript().isEnabled()).isTrue(); - assertThat(properties.getInteractive().isEnabled()).isTrue(); - assertThat(properties.getNoninteractive().isEnabled()).isFalse(); - assertThat(properties.getNoninteractive().getPrimaryCommand()).isEqualTo("fakecommand"); - assertThat(properties.getTheme().getName()).isEqualTo("fake"); - assertThat(properties.getCommand().getClear().isEnabled()).isFalse(); - assertThat(properties.getCommand().getHelp().isEnabled()).isFalse(); - assertThat(properties.getCommand().getHelp().getGroupingMode()).isEqualTo(GroupingMode.FLAT); - assertThat(properties.getCommand().getHelp().getCommandTemplate()).isEqualTo("fake1"); - assertThat(properties.getCommand().getHelp().getCommandsTemplate()).isEqualTo("fake2"); - assertThat(properties.getCommand().getHistory().isEnabled()).isFalse(); - assertThat(properties.getCommand().getQuit().isEnabled()).isFalse(); - assertThat(properties.getCommand().getScript().isEnabled()).isFalse(); - assertThat(properties.getCommand().getStacktrace().isEnabled()).isFalse(); - assertThat(properties.getCommand().getCompletion().isEnabled()).isFalse(); - assertThat(properties.getCommand().getCompletion().getRootCommand()).isEqualTo("fake"); - assertThat(properties.getCommand().getVersion().isEnabled()).isFalse(); - assertThat(properties.getCommand().getVersion().getTemplate()).isEqualTo("fake"); - assertThat(properties.getCommand().getVersion().isShowBuildArtifact()).isTrue(); - assertThat(properties.getCommand().getVersion().isShowBuildGroup()).isTrue(); - assertThat(properties.getCommand().getVersion().isShowBuildName()).isTrue(); - assertThat(properties.getCommand().getVersion().isShowBuildTime()).isTrue(); - assertThat(properties.getCommand().getVersion().isShowBuildVersion()).isFalse(); - assertThat(properties.getCommand().getVersion().isShowGitBranch()).isTrue(); - 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'); - assertThat(properties.getOption().getNaming().getCaseType()).isEqualTo(OptionNamingCase.CAMEL); - assertThat(properties.getContext().isClose()).isTrue(); - }); + this.contextRunner.withPropertyValues("spring.shell.history.enabled=false") + .withPropertyValues("spring.shell.history.name=fakename") + .withPropertyValues("spring.shell.config.location=fakelocation") + .withPropertyValues("spring.shell.config.env=FAKE_ENV") + .withPropertyValues("spring.shell.script.enabled=true") + .withPropertyValues("spring.shell.interactive.enabled=true") + .withPropertyValues("spring.shell.noninteractive.enabled=false") + .withPropertyValues("spring.shell.noninteractive.primary-command=fakecommand") + .withPropertyValues("spring.shell.theme.name=fake") + .withPropertyValues("spring.shell.command.clear.enabled=false") + .withPropertyValues("spring.shell.command.help.enabled=false") + .withPropertyValues("spring.shell.command.help.grouping-mode=flat") + .withPropertyValues("spring.shell.command.help.command-template=fake1") + .withPropertyValues("spring.shell.command.help.commands-template=fake2") + .withPropertyValues("spring.shell.command.history.enabled=false") + .withPropertyValues("spring.shell.command.quit.enabled=false") + .withPropertyValues("spring.shell.command.script.enabled=false") + .withPropertyValues("spring.shell.command.stacktrace.enabled=false") + .withPropertyValues("spring.shell.command.completion.enabled=false") + .withPropertyValues("spring.shell.command.completion.root-command=fake") + .withPropertyValues("spring.shell.command.version.enabled=false") + .withPropertyValues("spring.shell.command.version.template=fake") + .withPropertyValues("spring.shell.command.version.show-build-artifact=true") + .withPropertyValues("spring.shell.command.version.show-build-group=true") + .withPropertyValues("spring.shell.command.version.show-build-name=true") + .withPropertyValues("spring.shell.command.version.show-build-time=true") + .withPropertyValues("spring.shell.command.version.show-build-version=false") + .withPropertyValues("spring.shell.command.version.show-git-branch=true") + .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") + .withPropertyValues("spring.shell.option.naming.case-type=camel") + .withPropertyValues("spring.shell.context.close=true") + .withUserConfiguration(Config1.class) + .run((context) -> { + SpringShellProperties properties = context.getBean(SpringShellProperties.class); + assertThat(properties.getHistory().isEnabled()).isFalse(); + assertThat(properties.getHistory().getName()).isEqualTo("fakename"); + assertThat(properties.getConfig().getLocation()).isEqualTo("fakelocation"); + assertThat(properties.getConfig().getEnv()).isEqualTo("FAKE_ENV"); + assertThat(properties.getScript().isEnabled()).isTrue(); + assertThat(properties.getInteractive().isEnabled()).isTrue(); + assertThat(properties.getNoninteractive().isEnabled()).isFalse(); + assertThat(properties.getNoninteractive().getPrimaryCommand()).isEqualTo("fakecommand"); + assertThat(properties.getTheme().getName()).isEqualTo("fake"); + assertThat(properties.getCommand().getClear().isEnabled()).isFalse(); + assertThat(properties.getCommand().getHelp().isEnabled()).isFalse(); + assertThat(properties.getCommand().getHelp().getGroupingMode()).isEqualTo(GroupingMode.FLAT); + assertThat(properties.getCommand().getHelp().getCommandTemplate()).isEqualTo("fake1"); + assertThat(properties.getCommand().getHelp().getCommandsTemplate()).isEqualTo("fake2"); + assertThat(properties.getCommand().getHistory().isEnabled()).isFalse(); + assertThat(properties.getCommand().getQuit().isEnabled()).isFalse(); + assertThat(properties.getCommand().getScript().isEnabled()).isFalse(); + assertThat(properties.getCommand().getStacktrace().isEnabled()).isFalse(); + assertThat(properties.getCommand().getCompletion().isEnabled()).isFalse(); + assertThat(properties.getCommand().getCompletion().getRootCommand()).isEqualTo("fake"); + assertThat(properties.getCommand().getVersion().isEnabled()).isFalse(); + assertThat(properties.getCommand().getVersion().getTemplate()).isEqualTo("fake"); + assertThat(properties.getCommand().getVersion().isShowBuildArtifact()).isTrue(); + assertThat(properties.getCommand().getVersion().isShowBuildGroup()).isTrue(); + assertThat(properties.getCommand().getVersion().isShowBuildName()).isTrue(); + assertThat(properties.getCommand().getVersion().isShowBuildTime()).isTrue(); + assertThat(properties.getCommand().getVersion().isShowBuildVersion()).isFalse(); + assertThat(properties.getCommand().getVersion().isShowGitBranch()).isTrue(); + 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'); + assertThat(properties.getOption().getNaming().getCaseType()).isEqualTo(OptionNamingCase.CAMEL); + assertThat(properties.getContext().isClose()).isTrue(); + }); } - @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(); - }); + 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(); + }); } @EnableConfigurationProperties({ SpringShellProperties.class }) private static class Config1 { + } + } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/StandardCommandsAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/StandardCommandsAutoConfigurationTests.java index f674b25e1..cbf135223 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/StandardCommandsAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/StandardCommandsAutoConfigurationTests.java @@ -31,39 +31,39 @@ public class StandardCommandsAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(StandardCommandsAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(StandardCommandsAutoConfiguration.class)); @Test public void testCompletionCommand() { + this.contextRunner.with(disableCommands("help", "clear", "quit", "stacktrace", "script", "history")) + .run((context) -> { + assertThat(context).doesNotHaveBean(Completion.class); + }); this.contextRunner - .with(disableCommands("help", "clear", "quit", "stacktrace", "script", "history")) - .run((context) -> {assertThat(context).doesNotHaveBean(Completion.class); - }); - this.contextRunner - .with(disableCommands("help", "clear", "quit", "stacktrace", "script", "history", "completion")) - .withPropertyValues("spring.shell.command.completion.root-command=fake") - .run((context) -> {assertThat(context).doesNotHaveBean(Completion.class); - }); - this.contextRunner - .with(disableCommands("help", "clear", "quit", "stacktrace", "script", "history")) - .withPropertyValues("spring.shell.command.completion.root-command=fake") - .run((context) -> {assertThat(context).hasSingleBean(Completion.class); - }); + .with(disableCommands("help", "clear", "quit", "stacktrace", "script", "history", "completion")) + .withPropertyValues("spring.shell.command.completion.root-command=fake") + .run((context) -> { + assertThat(context).doesNotHaveBean(Completion.class); + }); + this.contextRunner.with(disableCommands("help", "clear", "quit", "stacktrace", "script", "history")) + .withPropertyValues("spring.shell.command.completion.root-command=fake") + .run((context) -> { + assertThat(context).hasSingleBean(Completion.class); + }); } @Test public void testHelpCommand() { - this.contextRunner - .with(disableCommands("clear", "quit", "stacktrace", "script", "history", "completion")) - .withPropertyValues("spring.shell.command.help.grouping-mode=flat") - .run(context -> { - assertThat(context).hasSingleBean(Help.class); - Help help = context.getBean(Help.class); - Field showGroupsField = ReflectionUtils.findField(Help.class, "showGroups"); - ReflectionUtils.makeAccessible(showGroupsField); - ReflectionUtils.getField(showGroupsField, help); - assertThat(ReflectionUtils.getField(showGroupsField, help)).isEqualTo(false); - }); + this.contextRunner.with(disableCommands("clear", "quit", "stacktrace", "script", "history", "completion")) + .withPropertyValues("spring.shell.command.help.grouping-mode=flat") + .run(context -> { + assertThat(context).hasSingleBean(Help.class); + Help help = context.getBean(Help.class); + Field showGroupsField = ReflectionUtils.findField(Help.class, "showGroups"); + ReflectionUtils.makeAccessible(showGroupsField); + ReflectionUtils.getField(showGroupsField, help); + assertThat(ReflectionUtils.getField(showGroupsField, help)).isEqualTo(false); + }); } private static Function disableCommands(String... commands) { @@ -74,4 +74,5 @@ private static Function disa return cr; }; } + } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/TerminalUIAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/TerminalUIAutoConfigurationTests.java index c8ccb03d1..541719528 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/TerminalUIAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/TerminalUIAutoConfigurationTests.java @@ -40,28 +40,24 @@ class TerminalUIAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(TerminalUIAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(TerminalUIAutoConfiguration.class)); @Test public void terminalUICreated() { - this.contextRunner - .withUserConfiguration(MockConfiguration.class) - .run(context -> { - assertThat(context).hasSingleBean(TerminalUIBuilder.class); - }); + 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 customizers = (Set) ReflectionTestUtils - .getField(builder, "customizers"); - assertThat(customizers).hasSize(1); - }); + this.contextRunner.withUserConfiguration(TestConfiguration.class, MockConfiguration.class).run(context -> { + TerminalUIBuilder builder = context.getBean(TerminalUIBuilder.class); + Set customizers = (Set) ReflectionTestUtils.getField(builder, + "customizers"); + assertThat(customizers).hasSize(1); + }); } @Configuration(proxyBeanMethods = false) @@ -95,6 +91,7 @@ static class TestConfiguration { TerminalUICustomizer terminalUICustomizer() { return new TestTerminalUICustomizer(); } + } static class TestTerminalUICustomizer implements TerminalUICustomizer { @@ -103,6 +100,7 @@ static class TestTerminalUICustomizer implements TerminalUICustomizer { public void customize(TerminalUI terminalUI) { terminalUI.setThemeName("test"); } + } } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ThemingAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ThemingAutoConfigurationTests.java index 8ff0f344a..e6240330c 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ThemingAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/ThemingAutoConfigurationTests.java @@ -40,33 +40,30 @@ public class ThemingAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(ThemingAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(ThemingAutoConfiguration.class)); @Test void createsDefaultBeans() { - this.contextRunner - .run(context -> { - assertThat(context).hasSingleBean(TemplateExecutor.class); - assertThat(context).hasSingleBean(ThemeRegistry.class); - ThemeRegistry registry = context.getBean(ThemeRegistry.class); - assertThat(registry.get("default")).isNotNull(); - assertThat(registry.get("dump")).isNotNull(); - assertThat(context).hasSingleBean(ThemeResolver.class); - ThemeResolver resolver = context.getBean(ThemeResolver.class); - assertThat(resolver).extracting("theme").asInstanceOf(THEME).hasName("default", "dump"); - }); + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(TemplateExecutor.class); + assertThat(context).hasSingleBean(ThemeRegistry.class); + ThemeRegistry registry = context.getBean(ThemeRegistry.class); + assertThat(registry.get("default")).isNotNull(); + assertThat(registry.get("dump")).isNotNull(); + assertThat(context).hasSingleBean(ThemeResolver.class); + ThemeResolver resolver = context.getBean(ThemeResolver.class); + assertThat(resolver).extracting("theme").asInstanceOf(THEME).hasName("default", "dump"); + }); } @Test public void canRegisterCustomTheme() { - this.contextRunner - .withUserConfiguration(CustomThemeConfig.class) - .run(context -> { - assertThat(context).hasSingleBean(ThemeRegistry.class); - ThemeRegistry registry = context.getBean(ThemeRegistry.class); - assertThat(registry.get("default")).isNotNull(); - assertThat(registry.get("mytheme")).isNotNull(); - }); + this.contextRunner.withUserConfiguration(CustomThemeConfig.class).run(context -> { + assertThat(context).hasSingleBean(ThemeRegistry.class); + ThemeRegistry registry = context.getBean(ThemeRegistry.class); + assertThat(registry.get("default")).isNotNull(); + assertThat(registry.get("mytheme")).isNotNull(); + }); } @Configuration @@ -87,12 +84,15 @@ public ThemeSettings getSettings() { } }; } + } static class MyThemeSettings extends ThemeSettings { + MyThemeSettings() { super(StyleSettings.defaults(), FigureSettings.defaults(), SpinnerSettings.defaults()); } + } InstanceOfAssertFactory THEME = new InstanceOfAssertFactory<>(Theme.class, @@ -103,6 +103,7 @@ static class ThemeAssertions { public static ThemeAssert assertThat(Theme actual) { return new ThemeAssert(actual); } + } static class ThemeAssert extends AbstractAssert { @@ -120,6 +121,7 @@ public ThemeAssert hasName(String... names) { } return this; } + } } diff --git a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/UserConfigAutoConfigurationTests.java b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/UserConfigAutoConfigurationTests.java index c32b50715..33091afa9 100644 --- a/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/UserConfigAutoConfigurationTests.java +++ b/spring-shell-autoconfigure/src/test/java/org/springframework/shell/boot/UserConfigAutoConfigurationTests.java @@ -32,30 +32,28 @@ public class UserConfigAutoConfigurationTests { private final static Logger log = LoggerFactory.getLogger(UserConfigAutoConfigurationTests.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(UserConfigAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(UserConfigAutoConfiguration.class)); @Test public void testDefaults() { - this.contextRunner - .run(context -> { - assertThat(context).hasSingleBean(UserConfigPathProvider.class); - UserConfigPathProvider provider = context.getBean(UserConfigPathProvider.class); - Path path = provider.provide(); - assertThat(path).isNotNull(); - log.info("Path testDefaults: {}", path.toAbsolutePath()); - }); + this.contextRunner.run(context -> { + assertThat(context).hasSingleBean(UserConfigPathProvider.class); + UserConfigPathProvider provider = context.getBean(UserConfigPathProvider.class); + Path path = provider.provide(); + assertThat(path).isNotNull(); + log.info("Path testDefaults: {}", path.toAbsolutePath()); + }); } @Test public void testUserConfig() { - this.contextRunner - .withPropertyValues("spring.shell.config.location={userconfig}/test") - .run(context -> { - assertThat(context).hasSingleBean(UserConfigPathProvider.class); - UserConfigPathProvider provider = context.getBean(UserConfigPathProvider.class); - Path path = provider.provide(); - assertThat(path).isNotNull(); - log.info("Path testUserConfig: {}", path.toAbsolutePath()); - }); + this.contextRunner.withPropertyValues("spring.shell.config.location={userconfig}/test").run(context -> { + assertThat(context).hasSingleBean(UserConfigPathProvider.class); + UserConfigPathProvider provider = context.getBean(UserConfigPathProvider.class); + Path path = provider.provide(); + assertThat(path).isNotNull(); + log.info("Path testUserConfig: {}", path.toAbsolutePath()); + }); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/Availability.java b/spring-shell-core/src/main/java/org/springframework/shell/Availability.java index 0175eba61..0a3281fea 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/Availability.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/Availability.java @@ -26,26 +26,27 @@ */ public class Availability { - private final String reason; + private final String reason; - private Availability(String reason) { - this.reason = reason; - } + private Availability(String reason) { + this.reason = reason; + } - public static Availability available() { - return new Availability(null); - } + public static Availability available() { + return new Availability(null); + } - public static Availability unavailable(String reason) { - Assert.notNull(reason, "Reason for not being available must be provided"); - return new Availability(reason); - } + public static Availability unavailable(String reason) { + Assert.notNull(reason, "Reason for not being available must be provided"); + return new Availability(reason); + } - public boolean isAvailable() { - return reason == null; - } + public boolean isAvailable() { + return reason == null; + } + + public String getReason() { + return reason; + } - public String getReason() { - return reason; - } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityProvider.java index 7eebb0b58..31e18c291 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityProvider.java @@ -24,4 +24,5 @@ */ @FunctionalInterface public interface AvailabilityProvider extends Supplier { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityReflectiveProcessor.java b/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityReflectiveProcessor.java index b7467e7f6..bd050b7d1 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityReflectiveProcessor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/AvailabilityReflectiveProcessor.java @@ -25,8 +25,8 @@ import org.springframework.util.ReflectionUtils; /** - * A {@link ReflectiveProcessor} implementation that registers methods of a - * return type {@link Availability} from a target which is a class. + * A {@link ReflectiveProcessor} implementation that registers methods of a return type + * {@link Availability} from a target which is a class. * * @author Janne Valkealahti */ @@ -46,11 +46,11 @@ public void registerReflectionHints(ReflectionHints hints, AnnotatedElement elem /** * Register {@link ReflectionHints} against the specified {@link Method}. - * * @param hints the reflection hints instance to use * @param method the method to process */ protected void registerMethodHint(ReflectionHints hints, Method method) { hints.registerMethod(method, ExecutableMode.INVOKE); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/Command.java b/spring-shell-core/src/main/java/org/springframework/shell/Command.java index f571a6f26..080a0be55 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/Command.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/Command.java @@ -36,8 +36,8 @@ class Help { private final String group; /** - * A required, short one sentence description of the command. Should start with a capital and end with a dot - * for consistency. + * A required, short one sentence description of the command. Should start with a + * capital and end with a dot for consistency. */ private final String description; @@ -61,17 +61,19 @@ public String getGroup() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; Help help = (Help) o; - return Objects.equals(group, help.group) && - Objects.equals(description, help.description); + return Objects.equals(group, help.group) && Objects.equals(description, help.description); } @Override public int hashCode() { return Objects.hash(group, description); } + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/CommandNotCurrentlyAvailable.java b/spring-shell-core/src/main/java/org/springframework/shell/CommandNotCurrentlyAvailable.java index 11df2d3c6..fd6b090da 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/CommandNotCurrentlyAvailable.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/CommandNotCurrentlyAvailable.java @@ -23,6 +23,7 @@ public class CommandNotCurrentlyAvailable extends RuntimeException { private final String command; + private final Availability availability; public CommandNotCurrentlyAvailable(String command, Availability availability) { @@ -39,4 +40,5 @@ public String getCommand() { public Availability getAvailability() { return availability; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/CommandNotFound.java b/spring-shell-core/src/main/java/org/springframework/shell/CommandNotFound.java index 61ba13cea..89be8dc73 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/CommandNotFound.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/CommandNotFound.java @@ -23,12 +23,15 @@ import org.springframework.shell.command.CommandRegistration; /** - * A result to be handled by the {@link ResultHandler} when no command could be mapped to user input + * A result to be handled by the {@link ResultHandler} when no command could be mapped to + * user input */ public class CommandNotFound extends RuntimeException { private final List words; + private final Map registrations; + private final String text; public CommandNotFound(List words) { @@ -48,16 +51,14 @@ public String getMessage() { /** * Gets a {@code words} in this exception. - * * @return a words */ - public List getWords(){ + public List getWords() { return new ArrayList<>(words); } /** * Gets command registrations known when this error was created. - * * @return known command registrations */ public Map getRegistrations() { @@ -66,10 +67,10 @@ public Map getRegistrations() { /** * Gets a raw text input. - * * @return raw text input */ public String getText() { return text; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/CompletingParsedLine.java b/spring-shell-core/src/main/java/org/springframework/shell/CompletingParsedLine.java index 30d5c0788..d6891b7c3 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/CompletingParsedLine.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/CompletingParsedLine.java @@ -20,8 +20,8 @@ /** * An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules - * of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion candidate - * should be escaped/quoted. + * of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion + * candidate should be escaped/quoted. * * @author Eric Bottard */ @@ -29,4 +29,5 @@ public interface CompletingParsedLine { public CharSequence emit(CharSequence candidate); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/CompletionContext.java b/spring-shell-core/src/main/java/org/springframework/shell/CompletionContext.java index 5a42c1232..3f5499cb9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/CompletionContext.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/CompletionContext.java @@ -41,12 +41,12 @@ public class CompletionContext { private final CommandRegistration commandRegistration; /** - * * @param words words in the buffer, excluding words for the command name * @param wordIndex the index of the word the cursor is in * @param position the position inside the current word where the cursor is */ - public CompletionContext(List words, int wordIndex, int position, CommandRegistration commandRegistration, CommandOption commandOption) { + public CompletionContext(List words, int wordIndex, int position, CommandRegistration commandRegistration, + CommandOption commandOption) { this.words = words; this.wordIndex = wordIndex; this.position = position; @@ -86,7 +86,8 @@ public String upToCursor() { } /** - * Return the whole word the cursor is in, or {@code null} if the cursor is past the last word. + * Return the whole word the cursor is in, or {@code null} if the cursor is past the + * last word. */ public String currentWord() { return wordIndex >= 0 && wordIndex < words.size() ? words.get(wordIndex) : null; @@ -118,4 +119,5 @@ public CompletionContext commandOption(CommandOption commandOption) { public CompletionContext commandRegistration(CommandRegistration commandRegistration) { return new CompletionContext(words, wordIndex, position, commandRegistration, commandOption); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/CompletionProposal.java b/spring-shell-core/src/main/java/org/springframework/shell/CompletionProposal.java index 6a13c0b91..d8f6ded55 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/CompletionProposal.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/CompletionProposal.java @@ -17,7 +17,8 @@ package org.springframework.shell; /** - * Represents a proposal for TAB completion, made not only of the text to append, but also metadata about the proposal. + * Represents a proposal for TAB completion, made not only of the text to append, but also + * metadata about the proposal. * * @author Eric Bottard */ @@ -44,14 +45,14 @@ public class CompletionProposal { private String category; /** - * Whether the proposal should bypass escaping and quoting rules. This is useful for command proposals, which can - * appear as true multi-word Strings. + * Whether the proposal should bypass escaping and quoting rules. This is useful for + * command proposals, which can appear as true multi-word Strings. */ private boolean dontQuote = false; /** - * Whether the proposal cant be completed further. By setting complete to false then it will not append an space - * making it easier to continue tab completion + * Whether the proposal cant be completed further. By setting complete to false then + * it will not append an space making it easier to continue tab completion */ private boolean complete = true; @@ -104,7 +105,6 @@ public boolean complete() { return complete; } - public CompletionProposal dontQuote(boolean dontQuote) { this.dontQuote = dontQuote; return this; @@ -118,4 +118,5 @@ public boolean dontQuote() { public String toString() { return value; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/CoreResourcesRuntimeHints.java b/spring-shell-core/src/main/java/org/springframework/shell/CoreResourcesRuntimeHints.java index b2107d9b9..eb301f5cf 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/CoreResourcesRuntimeHints.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/CoreResourcesRuntimeHints.java @@ -29,4 +29,5 @@ class CoreResourcesRuntimeHints implements RuntimeHintsRegistrar { public void registerHints(RuntimeHints hints, ClassLoader classLoader) { hints.resources().registerPattern("org/springframework/shell/component/*.stg"); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/DefaultShellApplicationRunner.java b/spring-shell-core/src/main/java/org/springframework/shell/DefaultShellApplicationRunner.java index e22d740c2..17137b629 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/DefaultShellApplicationRunner.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/DefaultShellApplicationRunner.java @@ -27,8 +27,8 @@ import org.springframework.core.annotation.Order; /** - * Default {@link ShellApplicationRunner} which dispatches to the first ordered {@link ShellRunner} able to handle - * the shell. + * Default {@link ShellApplicationRunner} which dispatches to the first ordered + * {@link ShellRunner} able to handle the shell. * * @author Janne Valkealahti * @author Chris Bono @@ -37,11 +37,13 @@ public class DefaultShellApplicationRunner implements ShellApplicationRunner { /** - * The precedence at which this runner is executed with respect to other ApplicationRunner beans + * The precedence at which this runner is executed with respect to other + * ApplicationRunner beans */ public static final int PRECEDENCE = 0; private final static Logger log = LoggerFactory.getLogger(DefaultShellApplicationRunner.class); + private final List shellRunners; public DefaultShellApplicationRunner(List shellRunners) { @@ -75,13 +77,12 @@ public void run(ApplicationArguments args) throws Exception { } // Handle old deprecated ShellRunner api - Optional optional = shellRunners.stream() - .filter(sh -> sh.canRun(args)) - .findFirst(); + Optional optional = shellRunners.stream().filter(sh -> sh.canRun(args)).findFirst(); ShellRunner shellRunner = optional.orElse(null); log.debug("Using shell runner {}", shellRunner); if (shellRunner != null) { shellRunner.run(args); } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/ExitRequest.java b/spring-shell-core/src/main/java/org/springframework/shell/ExitRequest.java index a3db97301..85012d823 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/ExitRequest.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/ExitRequest.java @@ -39,4 +39,5 @@ public ExitRequest(int code) { public int status() { return code; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/Input.java b/spring-shell-core/src/main/java/org/springframework/shell/Input.java index 574659204..851032d40 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/Input.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/Input.java @@ -36,8 +36,11 @@ public interface Input { /** * Return the input as a list of parsed "words", having split the raw input according - * to parsing rules (for example, handling quoted portions of the readInput as a single - * "word") + * to parsing rules (for example, handling quoted portions of the readInput as a + * single "word") */ - default List words() {return "".equals(rawText()) ? Collections.emptyList() : Arrays.asList(rawText().split(" "));} + default List words() { + return "".equals(rawText()) ? Collections.emptyList() : Arrays.asList(rawText().split(" ")); + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/InputProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/InputProvider.java index aa888e07c..a0e6c752d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/InputProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/InputProvider.java @@ -1,7 +1,8 @@ package org.springframework.shell; /** - * To be implemented by components able to provide a "line" of user input, whether interactively or by batch. + * To be implemented by components able to provide a "line" of user input, whether + * interactively or by batch. * * @author Eric Bottard */ @@ -10,7 +11,10 @@ public interface InputProvider { /** * Return text entered by user to invoke commands. * - *

Returning {@literal null} indicates end of input, requesting shell exit.

+ *

+ * Returning {@literal null} indicates end of input, requesting shell exit. + *

*/ Input readInput(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/JnaRuntimeHints.java b/spring-shell-core/src/main/java/org/springframework/shell/JnaRuntimeHints.java index 8db5fa9f4..9fe8ab03d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/JnaRuntimeHints.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/JnaRuntimeHints.java @@ -79,12 +79,11 @@ private void registerProxies(ProxyHints proxy, String... classNames) { } private void registerForMostReflection(ReflectionHints reflection, String... classNames) { - reflection.registerTypes(typeReferences(classNames), - hint -> { - hint.withMembers(MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS, + reflection.registerTypes(typeReferences(classNames), hint -> { + hint.withMembers(MemberCategory.DECLARED_CLASSES, MemberCategory.DECLARED_FIELDS, MemberCategory.PUBLIC_CLASSES, MemberCategory.PUBLIC_FIELDS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS); - }); + }); } private List typeReferences(String... classNames) { @@ -94,249 +93,129 @@ private List typeReferences(String... classNames) { private void registerJni(ReflectionHints jni) { TypeReference reachableType = TypeReference.of("org.jline.terminal.impl.jna.win.Kernel32"); - registerForJni(jni, reachableType, "com.sun.jna.Callback", - Methods.of(), - Fields.of()); + registerForJni(jni, reachableType, "com.sun.jna.Callback", Methods.of(), Fields.of()); registerForJni(jni, reachableType, "com.sun.jna.CallbackReference", - Methods.of( - Method.of("getCallback", "java.lang.Class", "com.sun.jna.Pointer", "boolean"), - Method.of("getFunctionPointer", "com.sun.jna.Callback", "boolean"), - Method.of("getNativeString", "java.lang.Object", "boolean"), - Method.of("initializeThread", "com.sun.jna.Callback", - "com.sun.jna.CallbackReference$AttachOptions")), - Fields.of()); - - registerForJni(jni, reachableType, "com.sun.jna.CallbackReference$AttachOptions", - Methods.of(), - Fields.of()); - - registerForJni(jni, reachableType, "com.sun.jna.FromNativeConverter", - Methods.of( - Method.of("nativeType") - ), - Fields.of()); - - registerForJni(jni, reachableType, "com.sun.jna.IntegerType", - Methods.of(), - Fields.of("value")); - - registerForJni(jni, reachableType, "com.sun.jna.JNIEnv", - Methods.of(), - Fields.of()); - - registerForJni(jni, reachableType, "com.sun.jna.Native", - Methods.of( - Method.of("dispose"), + Methods + .of(Method.of("getCallback", "java.lang.Class", "com.sun.jna.Pointer", "boolean"), + Method.of("getFunctionPointer", "com.sun.jna.Callback", "boolean"), + Method.of("getNativeString", "java.lang.Object", "boolean"), Method.of("initializeThread", + "com.sun.jna.Callback", "com.sun.jna.CallbackReference$AttachOptions")), + Fields.of()); + + registerForJni(jni, reachableType, "com.sun.jna.CallbackReference$AttachOptions", Methods.of(), Fields.of()); + + registerForJni(jni, reachableType, "com.sun.jna.FromNativeConverter", Methods.of(Method.of("nativeType")), + Fields.of()); + + registerForJni(jni, reachableType, "com.sun.jna.IntegerType", Methods.of(), Fields.of("value")); + + registerForJni(jni, reachableType, "com.sun.jna.JNIEnv", Methods.of(), Fields.of()); + + registerForJni(jni, reachableType, "com.sun.jna.Native", Methods.of(Method.of("dispose"), Method.of("fromNative", "com.sun.jna.FromNativeConverter", "java.lang.Object", "java.lang.reflect.Method"), Method.of("fromNative", "java.lang.Class", "java.lang.Object"), Method.of("fromNative", "java.lang.reflect.Method", "java.lang.Object"), Method.of("nativeType", "java.lang.Class"), - Method.of("toNative", "com.sun.jna.ToNativeConverter","java.lang.Object") - ), - Fields.of()); + Method.of("toNative", "com.sun.jna.ToNativeConverter", "java.lang.Object")), Fields.of()); registerForJni(jni, reachableType, "com.sun.jna.Native$ffi_callback", - Methods.of( - Method.of("invoke", "long", "long", "long") - ), - Fields.of()); - - registerForJni(jni, reachableType, "com.sun.jna.NativeMapped", - Methods.of( - Method.of("toNative") - ), - Fields.of()); - - registerForJni(jni, reachableType, "com.sun.jna.Pointer", - Methods.of( - Method.of("", "long") - ), - Fields.of("peer")); - - registerForJni(jni, reachableType, "com.sun.jna.PointerType", - Methods.of(), - Fields.of("pointer")); - - registerForJni(jni, reachableType, "com.sun.jna.Structure", - Methods.of( - Method.of("autoRead"), - Method.of("autoWrite"), - Method.of("getTypeInfo"), - Method.of("newInstance", "java.lang.Class", "long") - ), - Fields.of("memory", "typeInfo")); - - registerForJni(jni, reachableType, "com.sun.jna.Structure$ByValue", - Methods.of(), - Fields.of()); - - registerForJni(jni, reachableType, "com.sun.jna.Structure$FFIType$FFITypes", - Methods.of(), - Fields.of("ffi_type_double", "ffi_type_float", "ffi_type_longdouble", "ffi_type_pointer", - "ffi_type_sint16", "ffi_type_sint32", "ffi_type_sint64", "ffi_type_sint8", "ffi_type_uint16", - "ffi_type_uint32", "ffi_type_uint64", "ffi_type_uint8", - "ffi_type_void")); - - registerForJni(jni, reachableType, "com.sun.jna.WString", - Methods.of( - Method.of("", "java.lang.String") - ), - Fields.of()); - - registerForJni(jni, reachableType, "java.lang.Boolean", - Methods.of( - Method.of("", "boolean") - ), - Fields.of("TYPE", "value")); - - registerForJni(jni, reachableType, "java.lang.Byte", - Methods.of( - Method.of("", "byte") - ), - Fields.of("TYPE", "value")); - - registerForJni(jni, reachableType, "java.lang.Character", - Methods.of( - Method.of("", "char") - ), - Fields.of("TYPE", "value")); - - registerForJni(jni, reachableType, "java.lang.Class", - Methods.of( - Method.of("getComponentType") - ), - Fields.of()); - - registerForJni(jni, reachableType, "java.lang.Double", - Methods.of( - Method.of("", "double") - ), - Fields.of("TYPE", "value")); - - registerForJni(jni, reachableType, "java.lang.Float", - Methods.of( - Method.of("", "float") - ), - Fields.of("TYPE", "value")); - - registerForJni(jni, reachableType, "java.lang.Integer", - Methods.of( - Method.of("", "int") - ), - Fields.of("TYPE", "value")); - - registerForJni(jni, reachableType, "java.lang.Long", - Methods.of( - Method.of("", "long") - ), - Fields.of("TYPE", "value")); - - registerForJni(jni, reachableType, "java.lang.Object", - Methods.of( - Method.of("toString") - ), - Fields.of()); - - registerForJni(jni, reachableType, "java.lang.Short", - Methods.of( - Method.of("", "short") - ), - Fields.of("TYPE", "value")); + Methods.of(Method.of("invoke", "long", "long", "long")), Fields.of()); + + registerForJni(jni, reachableType, "com.sun.jna.NativeMapped", Methods.of(Method.of("toNative")), Fields.of()); + + registerForJni(jni, reachableType, "com.sun.jna.Pointer", Methods.of(Method.of("", "long")), + Fields.of("peer")); + + registerForJni(jni, reachableType, "com.sun.jna.PointerType", Methods.of(), Fields.of("pointer")); + + registerForJni( + jni, reachableType, "com.sun.jna.Structure", Methods.of(Method.of("autoRead"), Method.of("autoWrite"), + Method.of("getTypeInfo"), Method.of("newInstance", "java.lang.Class", "long")), + Fields.of("memory", "typeInfo")); + + registerForJni(jni, reachableType, "com.sun.jna.Structure$ByValue", Methods.of(), Fields.of()); + + registerForJni(jni, reachableType, "com.sun.jna.Structure$FFIType$FFITypes", Methods.of(), + Fields.of("ffi_type_double", "ffi_type_float", "ffi_type_longdouble", "ffi_type_pointer", + "ffi_type_sint16", "ffi_type_sint32", "ffi_type_sint64", "ffi_type_sint8", "ffi_type_uint16", + "ffi_type_uint32", "ffi_type_uint64", "ffi_type_uint8", "ffi_type_void")); + + registerForJni(jni, reachableType, "com.sun.jna.WString", Methods.of(Method.of("", "java.lang.String")), + Fields.of()); + + registerForJni(jni, reachableType, "java.lang.Boolean", Methods.of(Method.of("", "boolean")), + Fields.of("TYPE", "value")); + + registerForJni(jni, reachableType, "java.lang.Byte", Methods.of(Method.of("", "byte")), + Fields.of("TYPE", "value")); + + registerForJni(jni, reachableType, "java.lang.Character", Methods.of(Method.of("", "char")), + Fields.of("TYPE", "value")); + + registerForJni(jni, reachableType, "java.lang.Class", Methods.of(Method.of("getComponentType")), Fields.of()); + + registerForJni(jni, reachableType, "java.lang.Double", Methods.of(Method.of("", "double")), + Fields.of("TYPE", "value")); + + registerForJni(jni, reachableType, "java.lang.Float", Methods.of(Method.of("", "float")), + Fields.of("TYPE", "value")); + + registerForJni(jni, reachableType, "java.lang.Integer", Methods.of(Method.of("", "int")), + Fields.of("TYPE", "value")); + + registerForJni(jni, reachableType, "java.lang.Long", Methods.of(Method.of("", "long")), + Fields.of("TYPE", "value")); + + registerForJni(jni, reachableType, "java.lang.Object", Methods.of(Method.of("toString")), Fields.of()); + + registerForJni(jni, reachableType, "java.lang.Short", Methods.of(Method.of("", "short")), + Fields.of("TYPE", "value")); registerForJni(jni, reachableType, "java.lang.String", - Methods.of( - Method.of("", "byte[]"), - Method.of("", "byte[]", "java.lang.String"), - Method.of("getBytes"), - Method.of("getBytes", "java.lang.String"), - Method.of("toCharArray") - ), - Fields.of()); - - registerForJni(jni, reachableType, "java.lang.System", - Methods.of( - Method.of("getProperty", "java.lang.String") - ), - Fields.of()); + Methods.of(Method.of("", "byte[]"), Method.of("", "byte[]", "java.lang.String"), + Method.of("getBytes"), Method.of("getBytes", "java.lang.String"), Method.of("toCharArray")), + Fields.of()); + + registerForJni(jni, reachableType, "java.lang.System", Methods.of(Method.of("getProperty", "java.lang.String")), + Fields.of()); registerForJni(jni, reachableType, "java.lang.UnsatisfiedLinkError", - Methods.of( - Method.of("","java.lang.String") - ), - Fields.of()); + Methods.of(Method.of("", "java.lang.String")), Fields.of()); - registerForJni(jni, reachableType, "java.lang.Void", - Methods.of(), - Fields.of("TYPE")); + registerForJni(jni, reachableType, "java.lang.Void", Methods.of(), Fields.of("TYPE")); registerForJni(jni, reachableType, "java.lang.reflect.Method", - Methods.of( - Method.of("getParameterTypes"), - Method.of("getReturnType") - ), - Fields.of()); - - registerForJni(jni, reachableType, "java.nio.Buffer", - Methods.of( - Method.of("position") - ), - Fields.of()); + Methods.of(Method.of("getParameterTypes"), Method.of("getReturnType")), Fields.of()); + + registerForJni(jni, reachableType, "java.nio.Buffer", Methods.of(Method.of("position")), Fields.of()); registerForJni(jni, reachableType, "java.nio.ByteBuffer", - Methods.of( - Method.of("array"), - Method.of("arrayOffset") - ), - Fields.of()); + Methods.of(Method.of("array"), Method.of("arrayOffset")), Fields.of()); registerForJni(jni, reachableType, "java.nio.CharBuffer", - Methods.of( - Method.of("array"), - Method.of("arrayOffset") - ), - Fields.of()); + Methods.of(Method.of("array"), Method.of("arrayOffset")), Fields.of()); registerForJni(jni, reachableType, "java.nio.DoubleBuffer", - Methods.of( - Method.of("array"), - Method.of("arrayOffset") - ), - Fields.of()); + Methods.of(Method.of("array"), Method.of("arrayOffset")), Fields.of()); registerForJni(jni, reachableType, "java.nio.FloatBuffer", - Methods.of( - Method.of("array"), - Method.of("arrayOffset") - ), - Fields.of()); + Methods.of(Method.of("array"), Method.of("arrayOffset")), Fields.of()); registerForJni(jni, reachableType, "java.nio.IntBuffer", - Methods.of( - Method.of("array"), - Method.of("arrayOffset") - ), - Fields.of()); + Methods.of(Method.of("array"), Method.of("arrayOffset")), Fields.of()); registerForJni(jni, reachableType, "java.nio.LongBuffer", - Methods.of( - Method.of("array"), - Method.of("arrayOffset") - ), - Fields.of()); + Methods.of(Method.of("array"), Method.of("arrayOffset")), Fields.of()); registerForJni(jni, reachableType, "java.nio.ShortBuffer", - Methods.of( - Method.of("array"), - Method.of("arrayOffset") - ), - Fields.of()); + Methods.of(Method.of("array"), Method.of("arrayOffset")), Fields.of()); } - private void registerForJni(ReflectionHints jni, TypeReference reachableType, String type, - Methods methods, Fields fields) { + private void registerForJni(ReflectionHints jni, TypeReference reachableType, String type, Methods methods, + Fields fields) { jni.registerType(TypeReference.of(type), hint -> { hint.onReachableType(reachableType); methods.withHints(hint); @@ -380,4 +259,5 @@ void withHints(TypeHint.Builder hint) { Stream.of(methods()).forEach(m -> m.withHints(hint)); } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/ParameterResolverMissingException.java b/spring-shell-core/src/main/java/org/springframework/shell/ParameterResolverMissingException.java index 39dfc740e..e965c2f3e 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/ParameterResolverMissingException.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/ParameterResolverMissingException.java @@ -18,13 +18,15 @@ import org.springframework.core.MethodParameter; /** - * Thrown when no ParameterResolver is found for a parameter during a resolve - * operation. + * Thrown when no ParameterResolver is found for a parameter during a resolve operation. * * @author Camilo Gonzalez */ public class ParameterResolverMissingException extends RuntimeException { + public ParameterResolverMissingException(MethodParameter parameter) { - super(String.format("No parameter resolver found for parameter with index %d (named '%s') of %s ", parameter.getParameterIndex(), parameter.getParameterName(), parameter.getMethod())); + super(String.format("No parameter resolver found for parameter with index %d (named '%s') of %s ", + parameter.getParameterIndex(), parameter.getParameterName(), parameter.getMethod())); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/ParameterValidationException.java b/spring-shell-core/src/main/java/org/springframework/shell/ParameterValidationException.java index 684aefee0..69460e039 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/ParameterValidationException.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/ParameterValidationException.java @@ -36,4 +36,5 @@ public ParameterValidationException(Set> constraintV public Set> getConstraintViolations() { return constraintViolations; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/ResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/ResultHandler.java index e0a5e6bee..192ddb94b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/ResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/ResultHandler.java @@ -17,15 +17,16 @@ package org.springframework.shell; /** - * Implementations know how to deal with results of method invocations, whether normal results or exceptions thrown. + * Implementations know how to deal with results of method invocations, whether normal + * results or exceptions thrown. * * @author Eric Bottard */ public interface ResultHandler { /** - * Deal with some method execution result, whether it was the normal return value, or some kind - * of {@link Throwable}. + * Deal with some method execution result, whether it was the normal return value, or + * some kind of {@link Throwable}. */ void handleResult(T result); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/ResultHandlerService.java b/spring-shell-core/src/main/java/org/springframework/shell/ResultHandlerService.java index 4f3e91306..bb3b9f8d1 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/ResultHandlerService.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/ResultHandlerService.java @@ -27,16 +27,15 @@ public interface ResultHandlerService { /** * Handle result. - * * @param result the result */ void handle(@Nullable Object result); /** * Handle result to the specified {@link TypeDescriptor}. - * * @param result the result * @param resultType the result type */ void handle(@Nullable Object result, @Nullable TypeDescriptor resultType); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/Shell.java b/spring-shell-core/src/main/java/org/springframework/shell/Shell.java index c5c867cf2..eb5407696 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/Shell.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/Shell.java @@ -62,6 +62,7 @@ public class Shell { private final static Logger log = LoggerFactory.getLogger(Shell.class); + private final ResultHandlerService resultHandlerService; /** @@ -71,22 +72,31 @@ public class Shell { public static final Object NO_INPUT = new Object(); private final Terminal terminal; + private final CommandCatalog commandRegistry; + protected List completionResolvers = new ArrayList<>(); + private CommandExecutionHandlerMethodArgumentResolvers argumentResolvers; + private ConversionService conversionService = new DefaultConversionService(); + private final ShellContext shellContext; + private final ExitCodeMappings exitCodeMappings; + private Exception handlingResultNonInt = null; + private CommandHandlingResult processExceptionNonInt = null; /** - * Marker object to distinguish unresolved arguments from {@code null}, which is a valid - * value. + * Marker object to distinguish unresolved arguments from {@code null}, which is a + * valid value. */ protected static final Object UNRESOLVED = new Object(); private Validator validator = Utils.defaultValidator(); + private List exceptionResolvers = new ArrayList<>(); public Shell(ResultHandlerService resultHandlerService, CommandCatalog commandRegistry, Terminal terminal, @@ -131,8 +141,9 @@ public void setExitCodeExceptionProvider(ExitCodeExceptionProvider exitCodeExcep } /** - * The main program loop: acquire input, try to match it to a command and evaluate. Repeat - * until a {@link ResultHandler} causes the process to exit or there is no input. + * The main program loop: acquire input, try to match it to a command and evaluate. + * Repeat until a {@link ResultHandler} causes the process to exit or there is no + * input. *

* This method has public visibility so that it can be invoked by actual commands * (e.g. a {@literal script} command). @@ -140,13 +151,15 @@ public void setExitCodeExceptionProvider(ExitCodeExceptionProvider exitCodeExcep */ public void run(InputProvider inputProvider) throws Exception { Object result = null; - while (!(result instanceof ExitRequest)) { // Handles ExitRequest thrown from Quit command + while (!(result instanceof ExitRequest)) { // Handles ExitRequest thrown from Quit + // command Input input; try { input = inputProvider.readInput(); } catch (Exception e) { - if (e instanceof ExitRequest) { // Handles ExitRequest thrown from hitting CTRL-C + if (e instanceof ExitRequest) { // Handles ExitRequest thrown from hitting + // CTRL-C break; } resultHandlerService.handle(e); @@ -183,12 +196,12 @@ else if (processExceptionNonInt != null && processExceptionNonInt.exitCode() != } /** - * Evaluate a single "line" of input from the user by trying to map words to a command and - * arguments. + * Evaluate a single "line" of input from the user by trying to map words to a command + * and arguments. * *

- * This method does not throw exceptions, it catches them and returns them as a regular - * result + * This method does not throw exceptions, it catches them and returns them as a + * regular result *

*/ protected Object evaluate(Input input) { @@ -209,27 +222,26 @@ protected Object evaluate(Input input) { log.debug("Evaluate input with line=[{}], command=[{}]", line, command); - Optional commandRegistration = registrations.values().stream() - .filter(r -> { - if (r.getCommand().equals(command)) { + Optional commandRegistration = registrations.values().stream().filter(r -> { + if (r.getCommand().equals(command)) { + return true; + } + for (CommandAlias a : r.getAliases()) { + if (a.getCommand().equals(command)) { return true; } - for (CommandAlias a : r.getAliases()) { - if (a.getCommand().equals(command)) { - return true; - } - } - return false; - }) - .findFirst(); + } + return false; + }).findFirst(); if (commandRegistration.isEmpty()) { return new CommandNotFound(words, new HashMap<>(registrations), input.rawText()); } if (this.exitCodeMappings != null) { - List> mappingFunctions = commandRegistration.get().getExitCode() - .getMappingFunctions(); + List> mappingFunctions = commandRegistration.get() + .getExitCode() + .getMappingFunctions(); this.exitCodeMappings.reset(mappingFunctions); } @@ -237,8 +249,8 @@ protected Object evaluate(Input input) { Object sh = Signals.register("INT", () -> commandThread.interrupt()); CommandExecution execution = CommandExecution.of( - argumentResolvers != null ? argumentResolvers.getResolvers() : null, validator, terminal, - shellContext, conversionService, commandRegistry); + argumentResolvers != null ? argumentResolvers.getResolvers() : null, validator, terminal, shellContext, + conversionService, commandRegistry); List commandExceptionResolvers = commandRegistration.get().getExceptionResolvers(); @@ -248,7 +260,8 @@ protected Object evaluate(Input input) { evaluate = execution.evaluate(words.toArray(new String[0])); } catch (UndeclaredThrowableException ute) { - if (ute.getCause() instanceof InterruptedException || ute.getCause() instanceof ClosedByInterruptException) { + if (ute.getCause() instanceof InterruptedException + || ute.getCause() instanceof ClosedByInterruptException) { Thread.interrupted(); // to reset interrupted flag } return ute.getCause(); @@ -281,7 +294,8 @@ protected Object evaluate(Input input) { } return null; } - } catch (Exception e1) { + } + catch (Exception e1) { e = e1; } } @@ -291,8 +305,8 @@ protected Object evaluate(Input input) { return evaluate; } - private CommandHandlingResult processException(List commandExceptionResolvers, Exception e) - throws Exception { + private CommandHandlingResult processException(List commandExceptionResolvers, + Exception e) throws Exception { CommandHandlingResult r = null; for (CommandExceptionResolver resolver : commandExceptionResolvers) { r = resolver.resolve(e); @@ -315,24 +329,23 @@ private CommandHandlingResult processException(List co } /** - * Return true if the parsed input ends up being empty (e.g. hitting ENTER on an - * empty line or blank space). + * Return true if the parsed input ends up being empty (e.g. hitting ENTER on + * an empty line or blank space). * *

- * Also returns true (i.e. ask to ignore) when input starts with {@literal //}, - * which is used for comments. + * Also returns true (i.e. ask to ignore) when input starts with + * {@literal //}, which is used for comments. *

*/ private boolean noInput(Input input) { - return input.words().isEmpty() - || (input.words().size() == 1 && input.words().get(0).trim().isEmpty()) + return input.words().isEmpty() || (input.words().size() == 1 && input.words().get(0).trim().isEmpty()) || (input.words().iterator().next().matches("\\s*//.*")); } /** - * Gather completion proposals given some (incomplete) input the user has already typed - * in. When and how this method is invoked is implementation specific and decided by the - * actual user interface. + * Gather completion proposals given some (incomplete) input the user has already + * typed in. When and how this method is invoked is implementation specific and + * decided by the actual user interface. */ public List complete(CompletionContext context) { @@ -354,20 +367,20 @@ public List complete(CompletionContext context) { // Try to complete arguments List matchedArgOptions = new ArrayList<>(); - if (argsContext.getWords().size() > 0 && argsContext.getWordIndex() > 0 && argsContext.getWords().size() > argsContext.getWordIndex()) { - matchedArgOptions.addAll(matchOptions(registration.getOptions(), argsContext.getWords().get(argsContext.getWordIndex() - 1))); + if (argsContext.getWords().size() > 0 && argsContext.getWordIndex() > 0 + && argsContext.getWords().size() > argsContext.getWordIndex()) { + matchedArgOptions.addAll(matchOptions(registration.getOptions(), + argsContext.getWords().get(argsContext.getWordIndex() - 1))); } - List argProposals = matchedArgOptions.stream() - .flatMap(o -> { - Function> completion = o.getCompletion(); - if (completion != null) { - List apply = completion.apply(argsContext.commandOption(o)); - return apply.stream(); - } - return Stream.empty(); - }) - .collect(Collectors.toList()); + List argProposals = matchedArgOptions.stream().flatMap(o -> { + Function> completion = o.getCompletion(); + if (completion != null) { + List apply = completion.apply(argsContext.commandOption(o)); + return apply.stream(); + } + return Stream.empty(); + }).collect(Collectors.toList()); candidates.addAll(argProposals); } @@ -381,43 +394,36 @@ private List matchOptions(List options, String arg if (count == 1) { if (trimmed.length() == 1) { Character trimmedChar = trimmed.charAt(0); - options.stream() - .filter(o -> { - for (Character sn : o.getShortNames()) { - if (trimmedChar.equals(sn)) { - return true; - } + options.stream().filter(o -> { + for (Character sn : o.getShortNames()) { + if (trimmedChar.equals(sn)) { + return true; } - return false; - }) - .findFirst() - .ifPresent(o -> matched.add(o)); + } + return false; + }).findFirst().ifPresent(o -> matched.add(o)); } else if (trimmed.length() > 1) { - trimmed.chars().mapToObj(i -> (char)i) - .forEach(c -> { - options.stream().forEach(o -> { - for (Character sn : o.getShortNames()) { - if (c.equals(sn)) { - matched.add(o); - } + trimmed.chars().mapToObj(i -> (char) i).forEach(c -> { + options.stream().forEach(o -> { + for (Character sn : o.getShortNames()) { + if (c.equals(sn)) { + matched.add(o); } - }); + } }); + }); } } else if (count == 2) { - options.stream() - .filter(o -> { - for (String ln : o.getLongNames()) { - if (trimmed.equals(ln)) { - return true; - } + options.stream().filter(o -> { + for (String ln : o.getLongNames()) { + if (trimmed.equals(ln)) { + return true; } - return false; - }) - .findFirst() - .ifPresent(o -> matched.add(o)); + } + return false; + }).findFirst().ifPresent(o -> matched.add(o)); } return matched; } @@ -426,7 +432,9 @@ private List commandsStartingWith(String prefix) { // Workaround for https://github.com/spring-projects/spring-shell/issues/150 // (sadly, this ties this class to JLine somehow) int lastWordStart = prefix.lastIndexOf(' ') + 1; - return Utils.removeHiddenCommands(commandRegistry.getRegistrations()).entrySet().stream() + return Utils.removeHiddenCommands(commandRegistry.getRegistrations()) + .entrySet() + .stream() .filter(e -> e.getKey().startsWith(prefix)) .map(e -> { String c = e.getKey(); @@ -437,15 +445,14 @@ private List commandsStartingWith(String prefix) { } private CompletionProposal toCommandProposal(String command, CommandRegistration registration) { - return new CompletionProposal(command) - .dontQuote(true) - .category("Available commands") - .description(registration.getDescription()); + return new CompletionProposal(command).dontQuote(true) + .category("Available commands") + .description(registration.getDescription()); } /** - * Returns the longest command that can be matched as first word(s) in the given buffer. - * + * Returns the longest command that can be matched as first word(s) in the given + * buffer. * @return a valid command name, or {@literal null} if none matched */ private String findLongestCommand(String prefix, boolean filterHidden) { @@ -453,9 +460,11 @@ private String findLongestCommand(String prefix, boolean filterHidden) { if (filterHidden) { registrations = Utils.removeHiddenCommands(registrations); } - String result = registrations.keySet().stream() - .filter(command -> prefix.equals(command) || prefix.startsWith(command + " ")) - .reduce("", (c1, c2) -> c1.length() > c2.length() ? c1 : c2); + String result = registrations.keySet() + .stream() + .filter(command -> prefix.equals(command) || prefix.startsWith(command + " ")) + .reduce("", (c1, c2) -> c1.length() > c2.length() ? c1 : c2); return "".equals(result) ? null : result; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/ShellApplicationRunner.java b/spring-shell-core/src/main/java/org/springframework/shell/ShellApplicationRunner.java index 2fabc371b..525605d7e 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/ShellApplicationRunner.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/ShellApplicationRunner.java @@ -23,4 +23,5 @@ * @author Janne Valkealahti */ public interface ShellApplicationRunner extends ApplicationRunner { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/ShellRunner.java b/spring-shell-core/src/main/java/org/springframework/shell/ShellRunner.java index 6792ae3b3..7cc26639c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/ShellRunner.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/ShellRunner.java @@ -27,9 +27,8 @@ public interface ShellRunner { /** * Checks if a particular shell runner can execute. * - * For {@link #canRun(ApplicationArguments)} and - * {@link #run(ApplicationArguments)} prefer {@link #run(String[])}. - * + * For {@link #canRun(ApplicationArguments)} and {@link #run(ApplicationArguments)} + * prefer {@link #run(String[])}. * @param args the application arguments * @return true if shell runner can execute */ @@ -41,9 +40,8 @@ default boolean canRun(ApplicationArguments args) { /** * Execute application. * - * For {@link #canRun(ApplicationArguments)} and - * {@link #run(ApplicationArguments)} prefer {@link #run(String[])}. - * + * For {@link #canRun(ApplicationArguments)} and {@link #run(ApplicationArguments)} + * prefer {@link #run(String[])}. * @param args the application argumets * @throws Exception in errors */ @@ -55,7 +53,6 @@ default void run(ApplicationArguments args) throws Exception { /** * Execute {@code ShellRunner} with given args. Return value indicates if run * operation happened and no further runners should be used. - * * @param args the raw arguments * @return true if run execution happened * @throws Exception possible error during run diff --git a/spring-shell-core/src/main/java/org/springframework/shell/Utils.java b/spring-shell-core/src/main/java/org/springframework/shell/Utils.java index b108ff298..4f67e98a3 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/Utils.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/Utils.java @@ -74,6 +74,7 @@ public static MethodParameter createMethodParameter(Parameter parameter) { } throw new AssertionError("Can't happen"); } + /** * Return a properly initialized MethodParameter for the given executable and index. */ @@ -81,9 +82,11 @@ public static MethodParameter createMethodParameter(Executable executable, int i MethodParameter methodParameter; if (executable instanceof Method) { methodParameter = new MethodParameter((Method) executable, i); - } else if (executable instanceof Constructor){ + } + else if (executable instanceof Constructor) { methodParameter = new MethodParameter((Constructor) executable, i); - } else { + } + else { throw new IllegalArgumentException("Unsupported Executable: " + executable); } methodParameter.initParameterNameDiscovery(new DefaultParameterNameDiscoverer()); @@ -94,24 +97,26 @@ public static MethodParameter createMethodParameter(Executable executable, int i * Return MethodParameters for each parameter of the given method/constructor. */ public static Stream createMethodParameters(Executable executable) { - return IntStream.range(0, executable.getParameterCount()) - .mapToObj(i -> createMethodParameter(executable, i)); + return IntStream.range(0, executable.getParameterCount()).mapToObj(i -> createMethodParameter(executable, i)); } /** - * Sanitize the buffer input given the customizations applied to the JLine - * parser (e.g. support for - * line continuations, etc.) + * Sanitize the buffer input given the customizations applied to the JLine parser + * (e.g. support for line continuations, etc.) */ public static List sanitizeInput(List words) { words = words.stream() - .map(s -> s.replaceAll("^\\n+|\\n+$", "")) // CR at beginning/end of line introduced by backslash continuation - .map(s -> s.replaceAll("\\n+", " ")) // CR in middle of word introduced by return inside a quoted string + .map(s -> s.replaceAll("^\\n+|\\n+$", "")) // CR at beginning/end of line + // introduced by backslash + // continuation + .map(s -> s.replaceAll("\\n+", " ")) // CR in middle of word introduced by + // return inside a quoted string .collect(Collectors.toList()); return words; } private final static ValidatorFactory DEFAULT_VALIDATOR_FACTORY; + private final static Validator DEFAULT_VALIDATOR; static { @@ -121,7 +126,6 @@ public static List sanitizeInput(List words) { /** * Gets a default shared validation factory. - * * @return default validation factory */ public static ValidatorFactory defaultValidatorFactory() { @@ -130,7 +134,6 @@ public static ValidatorFactory defaultValidatorFactory() { /** * Gets a default shared validator. - * * @return default validator */ public static Validator defaultValidator() { @@ -139,7 +142,6 @@ public static Validator defaultValidator() { /** * Split array into list of lists by predicate - * * @param array the array * @param predicate the predicate * @return the list of lists @@ -172,11 +174,11 @@ public static List> split(T[] array, Predicate predicate) { /** * Takes a map of command registrations and removes hidden commands from it. - * * @param registrations a command registrations * @return same map with removed hidden commands */ - public static Map removeHiddenCommands(Map registrations) { + public static Map removeHiddenCommands( + Map registrations) { Iterator> iter = registrations.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -186,4 +188,5 @@ public static Map removeHiddenCommands(Map m @Override protected void handleMissingValue(List headerName, MethodParameter parameter, Message message) { - throw new MessageHandlingException(message, "Missing header '" + headerName + - "' for method parameter type [" + parameter.getParameterType() + "]"); + throw new MessageHandlingException(message, + "Missing header '" + headerName + "' for method parameter type [" + parameter.getParameterType() + "]"); } private static final class HeaderNamedValueInfo extends NamedValueInfo { @@ -75,5 +75,7 @@ private static final class HeaderNamedValueInfo extends NamedValueInfo { private HeaderNamedValueInfo(Header annotation) { super(Arrays.asList(annotation.name()), annotation.required(), annotation.defaultValue()); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandAlias.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandAlias.java index 3895c37fc..658c9a3c2 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandAlias.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandAlias.java @@ -24,21 +24,18 @@ public interface CommandAlias { /** * Gets a command an alias. - * * @return command */ String getCommand(); /** * Get group for an alias. - * * @return the group */ String getGroup(); /** * Gets an instance of a default {@link CommandAlias}. - * * @param command the command * @param group the group * @return default command alias @@ -53,6 +50,7 @@ public static CommandAlias of(String command, String group) { public static class DefaultCommandAlias implements CommandAlias { private final String command; + private final String group; public DefaultCommandAlias(String command, String group) { @@ -69,5 +67,7 @@ public String getCommand() { public String getGroup() { return group; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalog.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalog.java index 7e1c38a9c..f406a3613 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalog.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalog.java @@ -35,36 +35,31 @@ public interface CommandCatalog { /** * Register a {@link CommandRegistration}. - * * @param registration the command registration */ void register(CommandRegistration... registration); /** * Unregister a {@link CommandRegistration}. - * * @param registration the command registration */ void unregister(CommandRegistration... registration); /** * Unregister a {@link CommandRegistration} by its command name. - * * @param commandName the command name */ void unregister(String... commandName); /** - * Gets all {@link CommandRegistration}s mapped with their names. - * Returned map is a copy and cannot be used to register new commands. - * + * Gets all {@link CommandRegistration}s mapped with their names. Returned map is a + * copy and cannot be used to register new commands. * @return all command registrations */ Map getRegistrations(); /** * Gets an instance of a default {@link CommandCatalog}. - * * @return default command catalog */ static CommandCatalog of() { @@ -73,7 +68,6 @@ static CommandCatalog of() { /** * Gets an instance of a default {@link CommandCatalog}. - * * @param resolvers the command resolvers * @param shellContext the shell context * @return default command catalog @@ -88,7 +82,9 @@ static CommandCatalog of(Collection resolvers, ShellContext she static class DefaultCommandCatalog implements CommandCatalog { private final Map commandRegistrations = new HashMap<>(); + private final Collection resolvers = new ArrayList<>(); + private final ShellContext shellContext; DefaultCommandCatalog(Collection resolvers, ShellContext shellContext) { @@ -136,7 +132,8 @@ public Map getRegistrations() { regs.put(r.getCommand(), r); }); } - return regs.entrySet().stream() + return regs.entrySet() + .stream() .filter(filterByInteractionMode(shellContext)) .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } @@ -146,7 +143,8 @@ public Map getRegistrations() { * effectively disables filtering as as we only care if mode is set to interactive * or non-interactive. */ - private static Predicate> filterByInteractionMode(ShellContext shellContext) { + private static Predicate> filterByInteractionMode( + ShellContext shellContext) { return e -> { InteractionMode mim = e.getValue().getInteractionMode(); InteractionMode cim = shellContext != null ? shellContext.getInteractionMode() : InteractionMode.ALL; @@ -162,5 +160,7 @@ else if (mim == InteractionMode.NONINTERACTIVE) { return true; }; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalogCustomizer.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalogCustomizer.java index 4bf2a678c..04c22879c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalogCustomizer.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandCatalogCustomizer.java @@ -25,8 +25,8 @@ public interface CommandCatalogCustomizer { /** * Customize a command catalog. - * * @param commandCatalog a command catalog */ void customize(CommandCatalog commandCatalog); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContext.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContext.java index 17daa5a32..00d430bd2 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContext.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContext.java @@ -35,14 +35,12 @@ public interface CommandContext { /** * Gets a raw args passed into a currently executing command. - * * @return raw command arguments */ String[] getRawArgs(); /** * Gets if option has been mapped. - * * @param name the option name * @return true if option has been mapped, false otherwise */ @@ -50,21 +48,18 @@ public interface CommandContext { /** * Gets a command option parser results. - * * @return the command option parser results */ CommandParserResults getParserResults(); /** * Gets a command registration. - * * @return the command registration */ CommandRegistration getCommandRegistration(); /** * Gets an mapped option value. - * * @param the type to map to * @param name the option name * @return mapped value @@ -73,21 +68,18 @@ public interface CommandContext { /** * Gets a terminal. - * * @return a terminal */ Terminal getTerminal(); /** * Gets a {@link ShellContext} associated with {@link CommandContext}. - * * @return a shell context */ ShellContext getShellContext(); /** * Gets an instance of a default {@link CommandContext}. - * * @param args the arguments * @param results the results * @param terminal the terminal @@ -105,9 +97,13 @@ static CommandContext of(String[] args, CommandParserResults results, Terminal t static class DefaultCommandContext implements CommandContext { private final String[] args; + private final CommandParserResults results; + private final Terminal terminal; + private final CommandRegistration commandRegistration; + private final ShellContext shellContext; DefaultCommandContext(String[] args, CommandParserResults results, Terminal terminal, @@ -160,17 +156,17 @@ public ShellContext getShellContext() { } private Optional find(String name) { - return results.results().stream() - .filter(r -> { - Stream l = Arrays.asList(r.option().getLongNames()).stream(); - Stream lm = Arrays.asList(r.option().getLongNamesModified()).stream(); - Stream s = Arrays.asList(r.option().getShortNames()).stream().map(n -> Character.toString(n)); - return Stream.concat(Stream.concat(l, lm), s) - .filter(o -> ObjectUtils.nullSafeEquals(o, name)) - .findFirst() - .isPresent(); - }) - .findFirst(); + return results.results().stream().filter(r -> { + Stream l = Arrays.asList(r.option().getLongNames()).stream(); + Stream lm = Arrays.asList(r.option().getLongNamesModified()).stream(); + Stream s = Arrays.asList(r.option().getShortNames()).stream().map(n -> Character.toString(n)); + return Stream.concat(Stream.concat(l, lm), s) + .filter(o -> ObjectUtils.nullSafeEquals(o, name)) + .findFirst() + .isPresent(); + }).findFirst(); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContextMethodArgumentResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContextMethodArgumentResolver.java index b4a4957b7..5fb1ba622 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContextMethodArgumentResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandContextMethodArgumentResolver.java @@ -39,8 +39,9 @@ public boolean supportsParameter(MethodParameter parameter) { } @Override - public Object resolveArgument(MethodParameter parameter, Message message){ + public Object resolveArgument(MethodParameter parameter, Message message) { CommandContext commandContext = message.getHeaders().get(HEADER_COMMAND_CONTEXT, CommandContext.class); return parameter.isOptional() ? Optional.ofNullable(commandContext) : commandContext; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExceptionResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExceptionResolver.java index d29a54a2b..1662dc78d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExceptionResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExceptionResolver.java @@ -19,10 +19,9 @@ import org.springframework.core.annotation.Order; /** - * Interface to be implemented by objects that can resolve exceptions thrown - * during command processing, in the typical case error response. Implementors - * are typically registered as beans in the application context or directly - * with command. + * Interface to be implemented by objects that can resolve exceptions thrown during + * command processing, in the typical case error response. Implementors are typically + * registered as beans in the application context or directly with command. * * @author Janne Valkealahti */ @@ -35,10 +34,10 @@ public interface CommandExceptionResolver { /** * Try to resolve the given exception that got thrown during command processing. - * * @param ex the exception - * @return a corresponding {@code HandlingResult} framework to handle, or - * {@code null} for default processing in the resolution chain + * @return a corresponding {@code HandlingResult} framework to handle, or {@code null} + * for default processing in the resolution chain */ CommandHandlingResult resolve(Exception ex); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExecution.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExecution.java index 34bd7aa24..47c8a1a3b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExecution.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExecution.java @@ -53,15 +53,13 @@ public interface CommandExecution { /** * Evaluate a command with a given arguments. - * - * @param args the command args + * @param args the command args * @return evaluated execution */ Object evaluate(String[] args); /** * Gets an instance of a default {@link CommandExecution}. - * * @param resolvers the handler method argument resolvers * @return default command execution */ @@ -71,7 +69,6 @@ public static CommandExecution of(List /** * Gets an instance of a default {@link CommandExecution}. - * * @param resolvers the handler method argument resolvers * @param validator the validator * @param terminal the terminal @@ -85,7 +82,6 @@ public static CommandExecution of(List /** * Gets an instance of a default {@link CommandExecution}. - * * @param resolvers the handler method argument resolvers * @param validator the validator * @param terminal the terminal @@ -93,8 +89,10 @@ public static CommandExecution of(List * @return default command execution */ public static CommandExecution of(List resolvers, Validator validator, - Terminal terminal, ShellContext shellContext, ConversionService conversionService, CommandCatalog commandCatalog) { - return new DefaultCommandExecution(resolvers, validator, terminal, shellContext, conversionService, commandCatalog); + Terminal terminal, ShellContext shellContext, ConversionService conversionService, + CommandCatalog commandCatalog) { + return new DefaultCommandExecution(resolvers, validator, terminal, shellContext, conversionService, + commandCatalog); } /** @@ -103,14 +101,20 @@ public static CommandExecution of(List static class DefaultCommandExecution implements CommandExecution { private List resolvers; + private Validator validator; + private Terminal terminal; + private ShellContext shellContext; + private ConversionService conversionService; + private CommandCatalog commandCatalog; public DefaultCommandExecution(List resolvers, Validator validator, - Terminal terminal, ShellContext shellContext, ConversionService conversionService, CommandCatalog commandCatalog) { + Terminal terminal, ShellContext shellContext, ConversionService conversionService, + CommandCatalog commandCatalog) { this.resolvers = resolvers; this.validator = validator; this.terminal = terminal; @@ -120,7 +124,8 @@ public DefaultCommandExecution(List res } public Object evaluate(String[] args) { - CommandParser parser = CommandParser.of(conversionService, commandCatalog.getRegistrations(), new ParserConfig()); + CommandParser parser = CommandParser.of(conversionService, commandCatalog.getRegistrations(), + new ParserConfig()); CommandParserResults results = parser.parse(args); CommandRegistration registration = results.registration(); @@ -133,29 +138,30 @@ public Object evaluate(String[] args) { // check help options to short circuit boolean handleHelpOption = false; HelpOptionInfo helpOption = registration.getHelpOption(); - if (helpOption.isEnabled() && helpOption.getCommand() != null && (!ObjectUtils.isEmpty(helpOption.getLongNames()) || !ObjectUtils.isEmpty(helpOption.getShortNames()))) { - handleHelpOption = results.results().stream() - .filter(cpr -> { - boolean present = false; - if (helpOption.getLongNames() != null) { - present = Arrays.asList(cpr.option().getLongNames()).stream() - .filter(ln -> ObjectUtils.containsElement(helpOption.getLongNames(), ln)) - .findFirst() - .isPresent(); - } - if (present) { - return true; - } - if (helpOption.getShortNames() != null) { - present = Arrays.asList(cpr.option().getShortNames()).stream() - .filter(sn -> ObjectUtils.containsElement(helpOption.getShortNames(), sn)) - .findFirst() - .isPresent(); - } - return present; - }) - .findFirst() - .isPresent(); + if (helpOption.isEnabled() && helpOption.getCommand() != null + && (!ObjectUtils.isEmpty(helpOption.getLongNames()) + || !ObjectUtils.isEmpty(helpOption.getShortNames()))) { + handleHelpOption = results.results().stream().filter(cpr -> { + boolean present = false; + if (helpOption.getLongNames() != null) { + present = Arrays.asList(cpr.option().getLongNames()) + .stream() + .filter(ln -> ObjectUtils.containsElement(helpOption.getLongNames(), ln)) + .findFirst() + .isPresent(); + } + if (present) { + return true; + } + if (helpOption.getShortNames() != null) { + present = Arrays.asList(cpr.option().getShortNames()) + .stream() + .filter(sn -> ObjectUtils.containsElement(helpOption.getShortNames(), sn)) + .findFirst() + .isPresent(); + } + return present; + }).findFirst().isPresent(); } // if needed switch registration to help command if we're short circuiting @@ -165,7 +171,7 @@ public Object evaluate(String[] args) { CommandParser helpParser = CommandParser.of(conversionService, commandCatalog.getRegistrations(), new ParserConfig()); CommandRegistration helpCommandRegistration = commandCatalog.getRegistrations() - .get(registration.getHelpOption().getCommand()); + .get(registration.getHelpOption().getCommand()); CommandParserResults helpResults = helpParser.parse(new String[] { "help", "--command", command }); results = helpResults; usedRegistration = helpCommandRegistration; @@ -198,24 +204,29 @@ else if (targetInfo.getTargetType() == TargetType.METHOD) { results.results().stream().forEach(r -> { if (r.option().getLongNames() != null) { for (String n : r.option().getLongNames()) { - messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, r.value()); + messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, + r.value()); paramValues.put(n, r.value()); } - // need to provide backmapping for orinal names which were modified + // need to provide backmapping for orinal names which were + // modified for (String n : r.option().getLongNamesModified()) { - messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, r.value()); + messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n, + r.value()); paramValues.put(n, r.value()); } } if (r.option().getShortNames() != null) { for (Character n : r.option().getShortNames()) { - messageBuilder.setHeader(ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n.toString(), r.value()); + messageBuilder.setHeader( + ArgumentHeaderMethodArgumentResolver.ARGUMENT_PREFIX + n.toString(), r.value()); } } }); messageBuilder.setHeader(CommandContextMethodArgumentResolver.HEADER_COMMAND_CONTEXT, ctx); - InvocableShellMethod invocableShellMethod = new InvocableShellMethod(targetInfo.getBean(), targetInfo.getMethod()); + InvocableShellMethod invocableShellMethod = new InvocableShellMethod(targetInfo.getBean(), + targetInfo.getMethod()); invocableShellMethod.setConversionService(conversionService); invocableShellMethod.setValidator(validator); ShellMethodArgumentResolverComposite argumentResolvers = new ShellMethodArgumentResolverComposite(); @@ -223,25 +234,29 @@ else if (targetInfo.getTargetType() == TargetType.METHOD) { argumentResolvers.addResolvers(resolvers); } if (!paramValues.isEmpty()) { - argumentResolvers.addResolver(new ParamNameHandlerMethodArgumentResolver(paramValues, conversionService)); + argumentResolvers + .addResolver(new ParamNameHandlerMethodArgumentResolver(paramValues, conversionService)); } invocableShellMethod.setMessageMethodArgumentResolvers(argumentResolvers); - res = invocableShellMethod.invoke(messageBuilder.build(), (Object[])null); + res = invocableShellMethod.invoke(messageBuilder.build(), (Object[]) null); - } catch (Exception e) { + } + catch (Exception e) { throw new CommandExecutionException(e); } } return res; } + } @Order(100) static class ParamNameHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { private final Map paramValues = new HashMap<>(); + private final ConversionService conversionService; ParamNameHandlerMethodArgumentResolver(Map paramValues, ConversionService conversionService) { @@ -257,8 +272,8 @@ public boolean supportsParameter(MethodParameter parameter) { } Class sourceType = paramValues.get(parameterName) != null ? paramValues.get(parameterName).getClass() : null; - return paramValues.containsKey(parameterName) && conversionService - .canConvert(sourceType, parameter.getParameterType()); + return paramValues.containsKey(parameterName) + && conversionService.canConvert(sourceType, parameter.getParameterType()); } @Override @@ -279,6 +294,7 @@ static class CommandExecutionException extends RuntimeException { public CommandExecutionException(Throwable cause) { super(cause); } + } public static class CommandParserExceptionsException extends RuntimeException { @@ -290,13 +306,15 @@ public CommandParserExceptionsException(String message, List parserExceptions) { + public static CommandParserExceptionsException of(String message, + List parserExceptions) { return new CommandParserExceptionsException(message, parserExceptions); } public List getParserExceptions() { return parserExceptions; } + } static class CommandExecutionHandlerMethodArgumentResolvers { @@ -310,5 +328,7 @@ public CommandExecutionHandlerMethodArgumentResolvers(List getResolvers() { return resolvers; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExitCode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExitCode.java index e2de9c8b0..c8d29c6dd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExitCode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandExitCode.java @@ -28,14 +28,12 @@ public interface CommandExitCode { /** * Gets a function mappings from exceptions to exit codes. - * * @return function mappings */ List> getMappingFunctions(); /** * Gets an instance of a default {@link CommandExitCode}. - * * @return a command exit code */ public static CommandExitCode of() { @@ -44,7 +42,6 @@ public static CommandExitCode of() { /** * Gets an instance of a default {@link CommandExitCode}. - * * @param functions the function mappings * @return a command exit code */ @@ -56,7 +53,7 @@ static class DefaultCommandExitCode implements CommandExitCode { private final List> functions; - DefaultCommandExitCode( List> functions) { + DefaultCommandExitCode(List> functions) { this.functions = functions; } @@ -64,5 +61,7 @@ static class DefaultCommandExitCode implements CommandExitCode { public List> getMappingFunctions() { return functions; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandHandlingResult.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandHandlingResult.java index 000565a06..37c7c3865 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandHandlingResult.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandHandlingResult.java @@ -26,37 +26,32 @@ public interface CommandHandlingResult { /** * Gets a message for this {@code CommandHandlingResult}. - * * @return a message */ @Nullable String message(); /** - * Gets an exit code for this {@code CommandHandlingResult}. Exit code only has meaning - * if shell is in non-interactive mode. - * + * Gets an exit code for this {@code CommandHandlingResult}. Exit code only has + * meaning if shell is in non-interactive mode. * @return an exit code */ Integer exitCode(); /** * Indicate whether this {@code CommandHandlingResult} has a result. - * * @return true if result exist */ public boolean isPresent(); /** * Indicate whether this {@code CommandHandlingResult} does not have a result. - * * @return true if result doesn't exist */ public boolean isEmpty(); /** * Gets an empty instance of {@code CommandHandlingResult}. - * * @return empty instance of {@code CommandHandlingResult} */ public static CommandHandlingResult empty() { @@ -65,7 +60,6 @@ public static CommandHandlingResult empty() { /** * Gets an instance of {@code CommandHandlingResult}. - * * @param message the message * @return instance of {@code CommandHandlingResult} */ @@ -75,7 +69,6 @@ public static CommandHandlingResult of(@Nullable String message) { /** * Gets an instance of {@code CommandHandlingResult}. - * * @param message the message * @param exitCode the exit code * @return instance of {@code CommandHandlingResult} @@ -87,6 +80,7 @@ public static CommandHandlingResult of(@Nullable String message, Integer exitCod static class DefaultHandlingResult implements CommandHandlingResult { private final String message; + private final Integer exitCode; DefaultHandlingResult(String message) { @@ -117,5 +111,7 @@ public boolean isPresent() { public boolean isEmpty() { return !isPresent(); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandOption.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandOption.java index 396db9526..8bfb42810 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandOption.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandOption.java @@ -27,7 +27,6 @@ public interface CommandOption { /** * Gets a long names of an option. - * * @return long names of an option */ String[] getLongNames(); @@ -35,84 +34,72 @@ public interface CommandOption { /** * Gets a modified long names of an option. Set within a command registration if * option name modifier were used to have an info about original names. - * * @return modified long names of an option */ String[] getLongNamesModified(); /** * Gets a short names of an option. - * * @return short names of an option */ Character[] getShortNames(); /** * Gets a description of an option. - * * @return description of an option */ String getDescription(); /** * Gets a {@link ResolvableType} of an option. - * * @return type of an option */ ResolvableType getType(); /** * Gets a flag if option is required. - * * @return the required flag */ boolean isRequired(); /** * Gets a default value of an option. - * * @return the default value */ String getDefaultValue(); /** * Gets a positional value. - * * @return the positional value */ int getPosition(); /** * Gets a minimum arity. - * * @return the minimum arity */ int getArityMin(); /** * Gets a maximum arity. - * * @return the maximum arity */ int getArityMax(); /** * Gets a label. - * * @return the label */ String getLabel(); /** * Gets a completion function. - * * @return the completion function */ CompletionResolver getCompletion(); /** * Gets an instance of a default {@link CommandOption}. - * * @param longNames the long names * @param shortNames the short names * @param description the description @@ -124,7 +111,6 @@ public static CommandOption of(String[] longNames, Character[] shortNames, Strin /** * Gets an instance of a default {@link CommandOption}. - * * @param longNames the long names * @param shortNames the short names * @param description the description @@ -138,7 +124,6 @@ public static CommandOption of(String[] longNames, Character[] shortNames, Strin /** * Gets an instance of a default {@link CommandOption}. - * * @param longNames the long names * @param longNamesModified the modified long names * @param shortNames the short names @@ -153,11 +138,11 @@ public static CommandOption of(String[] longNames, Character[] shortNames, Strin * @param completion the completion * @return default command option */ - public static CommandOption of(String[] longNames, String[] longNamesModified, Character[] shortNames, String description, - ResolvableType type, boolean required, String defaultValue, Integer position, Integer arityMin, - Integer arityMax, String label, CompletionResolver completion) { - return new DefaultCommandOption(longNames, longNamesModified, shortNames, description, type, required, defaultValue, position, - arityMin, arityMax, label, completion); + public static CommandOption of(String[] longNames, String[] longNamesModified, Character[] shortNames, + String description, ResolvableType type, boolean required, String defaultValue, Integer position, + Integer arityMin, Integer arityMax, String label, CompletionResolver completion) { + return new DefaultCommandOption(longNames, longNamesModified, shortNames, description, type, required, + defaultValue, position, arityMin, arityMax, label, completion); } /** @@ -166,22 +151,32 @@ public static CommandOption of(String[] longNames, String[] longNamesModified, C public static class DefaultCommandOption implements CommandOption { private String[] longNames; + private String[] longNamesModified; + private Character[] shortNames; + private String description; + private ResolvableType type; + private boolean required; + private String defaultValue; + private int position; + private int arityMin; + private int arityMax; + private String label; + private CompletionResolver completion; - public DefaultCommandOption(String[] longNames, String[] longNamesModified, Character[] shortNames, String description, - ResolvableType type, boolean required, String defaultValue, Integer position, - Integer arityMin, Integer arityMax, String label, - CompletionResolver completion) { + public DefaultCommandOption(String[] longNames, String[] longNamesModified, Character[] shortNames, + String description, ResolvableType type, boolean required, String defaultValue, Integer position, + Integer arityMin, Integer arityMax, String label, CompletionResolver completion) { this.longNames = longNames != null ? longNames : new String[0]; this.longNamesModified = longNamesModified != null ? longNamesModified : new String[0]; this.shortNames = shortNames != null ? shortNames : new Character[0]; @@ -189,7 +184,7 @@ public DefaultCommandOption(String[] longNames, String[] longNamesModified, Char this.type = type; this.required = required; this.defaultValue = defaultValue; - this.position = position != null && position > -1 ? position : -1 ; + this.position = position != null && position > -1 ? position : -1; this.arityMin = arityMin != null ? arityMin : -1; this.arityMax = arityMax != null ? arityMax : -1; this.label = label; @@ -255,5 +250,7 @@ public String getLabel() { public CompletionResolver getCompletion() { return completion; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java index 58af7fa35..532211909 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java @@ -30,10 +30,10 @@ import org.springframework.shell.command.parser.ParserConfig; /** - * Interface parsing arguments for a {@link CommandRegistration}. A command is - * always identified by a set of words like - * {@code command subcommand1 subcommand2} and remaining part of it are options - * which this interface intercepts and translates into format we can understand. + * Interface parsing arguments for a {@link CommandRegistration}. A command is always + * identified by a set of words like {@code command subcommand1 subcommand2} and remaining + * part of it are options which this interface intercepts and translates into format we + * can understand. * * @author Janne Valkealahti */ @@ -46,21 +46,18 @@ interface CommandParserResult { /** * Gets the {@link CommandOption}. - * * @return the command option */ CommandOption option(); /** * Gets the value. - * * @return the value */ Object value(); /** * Gets an instance of a default {@link CommandParserResult}. - * * @param option the command option * @param value the value * @return a result @@ -68,44 +65,41 @@ interface CommandParserResult { static CommandParserResult of(CommandOption option, Object value) { return new DefaultCommandParserResult(option, value); } + } /** - * Results of a {@link CommandParser}. Basically contains a list of {@link CommandParserResult}s. + * Results of a {@link CommandParser}. Basically contains a list of + * {@link CommandParserResult}s. */ interface CommandParserResults { /** * Gets the registration. - * * @return the registration */ CommandRegistration registration(); /** * Gets the results. - * * @return the results */ List results(); /** * Gets the unmapped positional arguments. - * * @return the unmapped positional arguments */ List positional(); /** * Gets parsing errors. - * * @return the parsing errors */ List errors(); /** * Gets an instance of a default {@link CommandParserResults}. - * * @param registration the registration * @param results the results * @param positional the list of positional arguments @@ -116,14 +110,14 @@ static CommandParserResults of(CommandRegistration registration, List positional, List errors) { return new DefaultCommandParserResults(registration, results, positional, errors); } + } /** * Parse options with a given arguments. * - * May throw various runtime exceptions depending how parser is configure. - * For example if required option is missing an exception is thrown. - * + * May throw various runtime exceptions depending how parser is configure. For example + * if required option is missing an exception is thrown. * @param args the arguments * @return parsed results */ @@ -131,7 +125,6 @@ static CommandParserResults of(CommandRegistration registration, List results; + private List positional; + private List errors; DefaultCommandParserResults(CommandRegistration registration, List results, @@ -179,6 +175,7 @@ public List positional() { public List errors() { return errors; } + } /** @@ -187,6 +184,7 @@ public List errors() { static class DefaultCommandParserResult implements CommandParserResult { private CommandOption option; + private Object value; DefaultCommandParserResult(CommandOption option, Object value) { @@ -203,6 +201,7 @@ public CommandOption option() { public Object value() { return value; } + } /** @@ -211,7 +210,9 @@ public Object value() { static class AstCommandParser implements CommandParser { private final Map registrations; + private final ParserConfig configuration; + private final ConversionService conversionService; public AstCommandParser(Map registrations, ParserConfig configuration, @@ -248,6 +249,7 @@ public CommandParserResults parse(String[] args) { return new DefaultCommandParserResults(result.commandRegistration(), results, positional, errors); } + } public static class CommandParserException extends RuntimeException { @@ -263,5 +265,7 @@ public CommandParserException(String message, Throwable cause) { public static CommandParserException of(String message) { return new CommandParserException(message); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParserExceptionResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParserExceptionResolver.java index ecc7fbdc2..cc599ff8b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParserExceptionResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParserExceptionResolver.java @@ -33,7 +33,8 @@ public CommandHandlingResult resolve(Exception ex) { if (ex instanceof CommandParserExceptionsException cpee) { AttributedStringBuilder builder = new AttributedStringBuilder(); cpee.getParserExceptions().stream().forEach(e -> { - builder.append(new AttributedString(e.getMessage(), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED))); + builder.append( + new AttributedString(e.getMessage(), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED))); builder.append("\n"); }); String as = builder.toAttributedString().toAnsi(); @@ -41,4 +42,5 @@ public CommandHandlingResult resolve(Exception ex) { } return null; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandRegistration.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandRegistration.java index 2f1b0edc1..3f1c5b440 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandRegistration.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandRegistration.java @@ -46,91 +46,78 @@ public interface CommandRegistration { /** * Gets a command for this registration. - * * @return command */ String getCommand(); /** * Gets an {@link InteractionMode}. - * * @return the interaction mode */ InteractionMode getInteractionMode(); /** * Get group for a command. - * * @return the group */ String getGroup(); /** * Returns if command is hidden. - * * @return true if command is hidden */ boolean isHidden(); /** * Get description for a command. - * * @return the description */ String getDescription(); /** * Get {@link Availability} for a command - * * @return the availability */ Availability getAvailability(); /** * Gets target info. - * * @return the target info */ TargetInfo getTarget(); /** * Gets an options. - * * @return the options */ List getOptions(); /** * Gets an aliases. - * * @return the aliases */ List getAliases(); /** * Gets an exit code. - * * @return the exit code */ CommandExitCode getExitCode(); /** * Gets an exception resolvers. - * * @return the exception resolvers */ List getExceptionResolvers(); /** * Gets a help option info. - * * @return the help option info */ HelpOptionInfo getHelpOption(); /** * Gets a new instance of a {@link Builder}. - * * @return a new builder instance */ public static Builder builder() { @@ -138,19 +125,21 @@ public static Builder builder() { } /** - * Interface used to supply instance of a {@link Builder}. Meant to be a single - * point access to centrally configured builder in an application context. + * Interface used to supply instance of a {@link Builder}. Meant to be a single point + * access to centrally configured builder in an application context. */ @FunctionalInterface public interface BuilderSupplier extends Supplier { + } /** - * Interface used to modify option long name. Usual use case is i.e. making - * conversion from a {@code camelCase} to {@code snake-case}. + * Interface used to modify option long name. Usual use case is i.e. making conversion + * from a {@code camelCase} to {@code snake-case}. */ @FunctionalInterface public interface OptionNameModifier extends Function { + } /** @@ -160,7 +149,6 @@ public interface OptionSpec { /** * Define long option names. - * * @param names the long option names * @return option spec for chaining */ @@ -168,7 +156,6 @@ public interface OptionSpec { /** * Define short option names. - * * @param names the long option names * @return option spec for chaining */ @@ -176,10 +163,8 @@ public interface OptionSpec { /** * Define a type for an option. This method is a shortcut for - * {@link #type(ResolvableType)} which is a preferred way to - * define type with generics. Will override one from - * {@link #type(ResolvableType)}. - * + * {@link #type(ResolvableType)} which is a preferred way to define type with + * generics. Will override one from {@link #type(ResolvableType)}. * @param type the type * @return option spec for chaining * @see #type(ResolvableType) @@ -187,10 +172,8 @@ public interface OptionSpec { OptionSpec type(Type type); /** - * Define a {@link ResolvableType} for an option. This method is - * a preferred way to define type with generics. Will override one - * from {@link #type(Type)}. - * + * Define a {@link ResolvableType} for an option. This method is a preferred way + * to define type with generics. Will override one from {@link #type(Type)}. * @param type the resolvable type * @return option spec for chaining */ @@ -198,7 +181,6 @@ public interface OptionSpec { /** * Define a {@code description} for an option. - * * @param description the option description * @return option spec for chaining */ @@ -206,23 +188,20 @@ public interface OptionSpec { /** * Define if option is required. - * * @param required the required flag * @return option spec for chaining */ OptionSpec required(boolean required); /** - * Define option to be required. Syntatic sugar calling - * {@link #required(boolean)} with {@code true}. - * + * Define option to be required. Syntatic sugar calling {@link #required(boolean)} + * with {@code true}. * @return option spec for chaining */ OptionSpec required(); /** * Define a {@code defaultValue} for an option. - * * @param defaultValue the option default value * @return option spec for chaining */ @@ -230,7 +209,6 @@ public interface OptionSpec { /** * Define an optional hint for possible positional mapping. - * * @param position the position * @return option spec for chaining */ @@ -238,7 +216,6 @@ public interface OptionSpec { /** * Define an {@code arity} for an option. - * * @param min the min arity * @param max the max arity * @return option spec for chaining @@ -247,7 +224,6 @@ public interface OptionSpec { /** * Define an {@code arity} for an option. - * * @param arity the arity * @return option spec for chaining */ @@ -255,7 +231,6 @@ public interface OptionSpec { /** * Define a {@code label} for an option. - * * @param label the label * @return option spec for chaining */ @@ -263,7 +238,6 @@ public interface OptionSpec { /** * Define a {@code completion function} for an option. - * * @param completion the completion function * @return option spec for chaining */ @@ -271,7 +245,6 @@ public interface OptionSpec { /** * Define an option name modifier. - * * @param modifier the option name modifier function * @return option spec for chaining */ @@ -279,10 +252,10 @@ public interface OptionSpec { /** * Return a builder for chaining. - * * @return a builder for chaining */ Builder and(); + } /** @@ -291,8 +264,8 @@ public interface OptionSpec { public enum OptionArity { /** - * Used to indicate that arity is not set. Exists as a workaround for a case - * where it's not possible to use null values. + * Used to indicate that arity is not set. Exists as a workaround for a case where + * it's not possible to use null values. */ NONE, @@ -320,6 +293,7 @@ public enum OptionArity { * Define min(1), max(MAXINTEGER). */ ONE_OR_MORE; + } /** @@ -329,35 +303,30 @@ public interface TargetInfo { /** * Get target type - * * @return the target type */ TargetType getTargetType(); /** * Get the bean. - * * @return the bean */ Object getBean(); /** * Get the bean method - * * @return the bean method */ Method getMethod(); /** * Get the function - * * @return the function */ Function getFunction(); /** * Get the consumer - * * @return the consumer */ Consumer getConsumer(); @@ -375,15 +344,21 @@ static TargetInfo of(Consumer consumer) { } enum TargetType { + METHOD, FUNCTION, CONSUMER; + } static class DefaultTargetInfo implements TargetInfo { private final TargetType targetType; + private final Object bean; + private final Method method; + private final Function function; + private final Consumer consumer; public DefaultTargetInfo(TargetType targetType, Object bean, Method method, @@ -419,7 +394,9 @@ public Method getMethod() { public Consumer getConsumer() { return consumer; } + } + } /** @@ -429,7 +406,6 @@ public interface TargetSpec { /** * Register a method target. - * * @param bean the bean * @param method the method * @param paramTypes the parameter types @@ -439,7 +415,6 @@ public interface TargetSpec { /** * Register a method target. - * * @param bean the bean * @param method the method * @return a target spec for chaining @@ -448,7 +423,6 @@ public interface TargetSpec { /** * Register a function target. - * * @param function the function to register * @return a target spec for chaining */ @@ -456,7 +430,6 @@ public interface TargetSpec { /** * Register a consumer target. - * * @param consumer the consumer to register * @return a target spec for chaining */ @@ -464,10 +437,10 @@ public interface TargetSpec { /** * Return a builder for chaining. - * * @return a builder for chaining */ Builder and(); + } /** @@ -477,7 +450,6 @@ public interface AliasSpec { /** * Define commands for an alias. - * * @param commands the commands * @return a target spec for chaining */ @@ -485,7 +457,6 @@ public interface AliasSpec { /** * Define group for an alias. - * * @param group the group * @return a target spec for chaining */ @@ -493,10 +464,10 @@ public interface AliasSpec { /** * Return a builder for chaining. - * * @return a builder for chaining */ Builder and(); + } /** @@ -506,7 +477,6 @@ public interface ExitCodeSpec { /** * Define mapping from exception to code. - * * @param e the exception * @param code the exit code * @return a target spec for chaining @@ -514,7 +484,6 @@ public interface ExitCodeSpec { ExitCodeSpec map(Class e, int code); /** - * * @param function * @return */ @@ -522,10 +491,10 @@ public interface ExitCodeSpec { /** * Return a builder for chaining. - * * @return a builder for chaining */ Builder and(); + } /** @@ -535,7 +504,6 @@ public interface ErrorHandlingSpec { /** * Add {@link CommandExceptionResolver}. - * * @param resolver the resolver * @return a error handling for chaining */ @@ -543,38 +511,34 @@ public interface ErrorHandlingSpec { /** * Return a builder for chaining. - * * @return a builder for chaining */ Builder and(); + } public interface HelpOptionInfo { /** * Gets whether help options are enabled. - * * @return whether help options are enabled */ boolean isEnabled(); /** * Gets long names options for help. - * * @return long names options for help */ String[] getLongNames(); /** * Gets short names options for help. - * * @return short names options for help */ Character[] getShortNames(); /** * Gets command for help. - * * @return command for help */ String getCommand(); @@ -590,8 +554,11 @@ static HelpOptionInfo of(boolean enabled, String[] longNames, Character[] shortN static class DefaultHelpOptionInfo implements HelpOptionInfo { private final String command; + private final String[] longNames; + private final Character[] shortNames; + private final boolean enabled; public DefaultHelpOptionInfo(boolean enabled, String[] longNames, Character[] shortNames, String command) { @@ -620,7 +587,9 @@ public Character[] getShortNames() { public String getCommand() { return command; } + } + } /** @@ -630,7 +599,6 @@ public interface HelpOptionsSpec { /** * Whether help options are enabled. - * * @param enabled the enabled flag * @return a help option for chaining */ @@ -638,7 +606,6 @@ public interface HelpOptionsSpec { /** * Sets long names options for help. - * * @param longNames the long names * @return a help option for chaining */ @@ -646,7 +613,6 @@ public interface HelpOptionsSpec { /** * Sets short names options for help. - * * @param shortNames the short names * @return a help option for chaining */ @@ -654,7 +620,6 @@ public interface HelpOptionsSpec { /** * Sets command used for help. - * * @param command the command * @return a help option for chaining */ @@ -662,10 +627,10 @@ public interface HelpOptionsSpec { /** * Return a builder for chaining. - * * @return a builder for chaining */ Builder and(); + } /** @@ -674,11 +639,10 @@ public interface HelpOptionsSpec { public interface Builder { /** - * Define commands this registration uses. Essentially defines a full set of - * main and sub commands. It doesn't matter if full command is defined in one - * string or multiple strings as "words" are splitted and trimmed with - * whitespaces. You will get result of {@code command subcommand1 subcommand2, ...}. - * + * Define commands this registration uses. Essentially defines a full set of main + * and sub commands. It doesn't matter if full command is defined in one string or + * multiple strings as "words" are splitted and trimmed with whitespaces. You will + * get result of {@code command subcommand1 subcommand2, ...}. * @param commands the commands * @return builder for chaining */ @@ -686,7 +650,6 @@ public interface Builder { /** * Define {@link InteractionMode} for a command. - * * @param mode the interaction mode * @return builder for chaining */ @@ -694,7 +657,6 @@ public interface Builder { /** * Define a description text for a command. - * * @param description the description text * @return builder for chaining */ @@ -702,7 +664,6 @@ public interface Builder { /** * Define an {@link Availability} suppliear for a command. - * * @param availability the availability * @return builder for chaining */ @@ -710,7 +671,6 @@ public interface Builder { /** * Define a group for a command. - * * @param group the group * @return builder for chaining */ @@ -718,7 +678,6 @@ public interface Builder { /** * Define a command to be hidden. - * * @return builder for chaining * @see #hidden(boolean) */ @@ -726,87 +685,90 @@ public interface Builder { /** * Define a command to be hidden by a given flag. - * * @param hidden the hidden flag * @return builder for chaining */ Builder hidden(boolean hidden); /** - * Provides a global option name modifier. Will be used with all options to - * modify long names. Usual use case is to enforce naming convention i.e. to - * have {@code snake-case} for all names. - * + * Provides a global option name modifier. Will be used with all options to modify + * long names. Usual use case is to enforce naming convention i.e. to have + * {@code snake-case} for all names. * @param modifier to modifier to change option name * @return builder for chaining */ Builder defaultOptionNameModifier(Function modifier); /** - * Define an option what this command should user for. Can be used multiple - * times. - * + * Define an option what this command should user for. Can be used multiple times. * @return option spec for chaining */ OptionSpec withOption(); /** * Define a target what this command should execute - * * @return target spec for chaining */ TargetSpec withTarget(); /** * Define an alias what this command should execute - * * @return alias spec for chaining */ AliasSpec withAlias(); /** * Define an exit code what this command should execute - * * @return exit code spec for chaining */ ExitCodeSpec withExitCode(); /** * Define an error handling what this command should use - * * @return error handling spec for chaining */ ErrorHandlingSpec withErrorHandling(); /** * Define help options what this command should use. - * * @return help options spec for chaining */ HelpOptionsSpec withHelpOptions(); /** * Builds a {@link CommandRegistration}. - * * @return a command registration */ CommandRegistration build(); + } static class DefaultOptionSpec implements OptionSpec { private BaseBuilder builder; + private String[] longNames; + private Character[] shortNames; + private ResolvableType type; + private String description; + private boolean required; + private String defaultValue; + private Integer position; + private Integer arityMin; + private Integer arityMax; + private String label; + private CompletionResolver completion; + private Function optionNameModifier; DefaultOptionSpec(BaseBuilder builder) { @@ -987,14 +949,19 @@ public Function getOptionNameModifier() { } return null; } + } static class DefaultTargetSpec implements TargetSpec { private BaseBuilder builder; + private Object bean; + private Method method; + private Function function; + private Consumer consumer; DefaultTargetSpec(BaseBuilder builder) { @@ -1032,12 +999,15 @@ public TargetSpec consumer(Consumer consumer) { public Builder and() { return builder; } + } static class DefaultAliasSpec implements AliasSpec { private BaseBuilder builder; + private String[] commands; + private String group; DefaultAliasSpec(BaseBuilder builder) { @@ -1047,7 +1017,8 @@ static class DefaultAliasSpec implements AliasSpec { @Override public AliasSpec command(String... commands) { Assert.notNull(commands, "commands must be set"); - this.commands = Arrays.asList(commands).stream() + this.commands = Arrays.asList(commands) + .stream() .flatMap(c -> Stream.of(c.split(" "))) .filter(c -> StringUtils.hasText(c)) .map(c -> c.trim()) @@ -1066,11 +1037,13 @@ public AliasSpec group(String group) { public Builder and() { return builder; } + } static class DefaultExitCodeSpec implements ExitCodeSpec { private BaseBuilder builder; + private final List> functions = new ArrayList<>(); DefaultExitCodeSpec(BaseBuilder builder) { @@ -1099,11 +1072,13 @@ public ExitCodeSpec map(Function function) { public Builder and() { return builder; } + } static class DefaultErrorHandlingSpec implements ErrorHandlingSpec { private BaseBuilder builder; + private final List resolvers = new ArrayList<>(); DefaultErrorHandlingSpec(BaseBuilder builder) { @@ -1120,14 +1095,19 @@ public ErrorHandlingSpec resolver(CommandExceptionResolver resolver) { public Builder and() { return builder; } + } static class DefaultHelpOptionsSpec implements HelpOptionsSpec { private BaseBuilder builder; + private String command; + private String[] longNames; + private Character[] shortNames; + private boolean enabled = true; DefaultHelpOptionsSpec(BaseBuilder builder) { @@ -1151,7 +1131,7 @@ public HelpOptionsSpec command(String command) { @Override public HelpOptionsSpec longNames(String... longNames) { - this.longNames = longNames; + this.longNames = longNames; return this; } @@ -1171,28 +1151,42 @@ public HelpOptionsSpec enabled(boolean enabled) { public Builder and() { return builder; } + } static class DefaultCommandRegistration implements CommandRegistration { private String command; + private InteractionMode interactionMode; + private String group; + private boolean hidden; + private String description; + private Supplier availability; + private List options; + private List optionSpecs; + private DefaultTargetSpec targetSpec; + private List aliasSpecs; + private DefaultExitCodeSpec exitCodeSpec; + private DefaultErrorHandlingSpec errorHandlingSpec; + private DefaultHelpOptionsSpec helpOptionsSpec; public DefaultCommandRegistration(String[] commands, InteractionMode interactionMode, String group, - boolean hidden, String description, Supplier availability, + boolean hidden, String description, Supplier availability, List optionSpecs, DefaultTargetSpec targetSpec, List aliasSpecs, - DefaultExitCodeSpec exitCodeSpec, DefaultErrorHandlingSpec errorHandlingSpec, DefaultHelpOptionsSpec helpOptionsSpec) { + DefaultExitCodeSpec exitCodeSpec, DefaultErrorHandlingSpec errorHandlingSpec, + DefaultHelpOptionsSpec helpOptionsSpec) { this.command = commandArrayToName(commands); this.interactionMode = interactionMode; this.group = group; @@ -1242,20 +1236,18 @@ public List getOptions() { if (options != null) { return options; } - options = optionSpecs.stream() - .map(o -> { - String[] longNames = o.getLongNames(); - String[] longNamesModified = null; - Function modifier = o.getOptionNameModifier(); - if (modifier != null) { - longNamesModified = Arrays.copyOf(longNames, longNames.length); - longNames = Arrays.stream(longNames).map(modifier).toArray(String[]::new); - } - return CommandOption.of(longNames, longNamesModified, o.getShortNames(), o.getDescription(), o.getType(), - o.isRequired(), o.getDefaultValue(), o.getPosition(), o.getArityMin(), o.getArityMax(), - o.getLabel(), o.getCompletion()); - }) - .collect(Collectors.toList()); + options = optionSpecs.stream().map(o -> { + String[] longNames = o.getLongNames(); + String[] longNamesModified = null; + Function modifier = o.getOptionNameModifier(); + if (modifier != null) { + longNamesModified = Arrays.copyOf(longNames, longNames.length); + longNames = Arrays.stream(longNames).map(modifier).toArray(String[]::new); + } + return CommandOption.of(longNames, longNamesModified, o.getShortNames(), o.getDescription(), + o.getType(), o.isRequired(), o.getDefaultValue(), o.getPosition(), o.getArityMin(), + o.getArityMax(), o.getLabel(), o.getCompletion()); + }).collect(Collectors.toList()); if (helpOptionsSpec != null) { String[] longNames = helpOptionsSpec.longNames != null ? helpOptionsSpec.longNames : null; Character[] shortNames = helpOptionsSpec.shortNames != null ? helpOptionsSpec.shortNames : null; @@ -1281,11 +1273,9 @@ public TargetInfo getTarget() { @Override public List getAliases() { - return this.aliasSpecs.stream() - .map(spec -> { - return CommandAlias.of(commandArrayToName(spec.commands), spec.group); - }) - .collect(Collectors.toList()); + return this.aliasSpecs.stream().map(spec -> { + return CommandAlias.of(commandArrayToName(spec.commands), spec.group); + }).collect(Collectors.toList()); } @Override @@ -1320,37 +1310,53 @@ public HelpOptionInfo getHelpOption() { } private static String commandArrayToName(String[] commands) { - return Arrays.asList(commands).stream() + return Arrays.asList(commands) + .stream() .flatMap(c -> Stream.of(c.split(" "))) .filter(c -> StringUtils.hasText(c)) .map(c -> c.trim()) .collect(Collectors.joining(" ")); } + } static class DefaultBuilder extends BaseBuilder { + } static abstract class BaseBuilder implements Builder { private String[] commands; + private InteractionMode interactionMode = InteractionMode.ALL; + private String group; + private boolean hidden; + private String description; + private Supplier availability; + private List optionSpecs = new ArrayList<>(); + private List aliasSpecs = new ArrayList<>(); + private DefaultTargetSpec targetSpec; + private DefaultExitCodeSpec exitCodeSpec; + private DefaultErrorHandlingSpec errorHandlingSpec; + private DefaultHelpOptionsSpec helpOptionsSpec; + private Function defaultOptionNameModifier; @Override public Builder command(String... commands) { Assert.notNull(commands, "commands must be set"); - this.commands = Arrays.asList(commands).stream() + this.commands = Arrays.asList(commands) + .stream() .flatMap(c -> Stream.of(c.split(" "))) .filter(c -> StringUtils.hasText(c)) .map(c -> c.trim()) @@ -1395,7 +1401,7 @@ public Builder availability(Supplier availability) { } @Override - public Builder defaultOptionNameModifier(Function modifier) { + public Builder defaultOptionNameModifier(Function modifier) { this.defaultOptionNameModifier = modifier; return this; } @@ -1451,5 +1457,7 @@ public CommandRegistration build() { return new DefaultCommandRegistration(commands, interactionMode, group, hidden, description, availability, optionSpecs, targetSpec, aliasSpecs, exitCodeSpec, errorHandlingSpec, helpOptionsSpec); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandResolver.java index acf629e5c..88f34243a 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandResolver.java @@ -18,10 +18,10 @@ import java.util.List; /** - * Interface to resolve currently existing commands. It is useful to have fully - * dynamic set of commands which may exists only if some conditions in a running - * shell are met. For example if shell is targeting arbitrary server environment - * some commands may or may not exist depending on a runtime state. + * Interface to resolve currently existing commands. It is useful to have fully dynamic + * set of commands which may exists only if some conditions in a running shell are met. + * For example if shell is targeting arbitrary server environment some commands may or may + * not exist depending on a runtime state. * * @author Janne Valkealahti */ @@ -30,8 +30,8 @@ public interface CommandResolver { /** * Resolve command registrations. - * * @return command registrations */ List resolve(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Command.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Command.java index 31de5fd28..6eaf16097 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Command.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Command.java @@ -36,8 +36,8 @@ public @interface Command { /** - * Define command as an array. Given that command should be - * {@code command1 sub1} it can be defined as: + * Define command as an array. Given that command should be {@code command1 sub1} it + * can be defined as: * *
 	 * command = { "command1", "sub1" }
@@ -47,9 +47,9 @@
 	 * Values are split and trimmed meaning spaces doesn't matter.
 	 *
 	 * 

- * Supported at the type level as well as at the method level! - * When used at the type level, all method-level mappings inherit this primary - * command to use it as a prefix. + * Supported at the type level as well as at the method level! When used at the + * type level, all method-level mappings inherit this primary command to use it as a + * prefix. * *

 	 * @Command(command = "command1")
@@ -59,14 +59,13 @@
 	 *   void sub1(){}
 	 * }
 	 * 
- * * @return the command as an array */ String[] command() default {}; /** - * Define alias as an array. Given that alias should be - * {@code alias1 sub1} it can be defined as: + * Define alias as an array. Given that alias should be {@code alias1 sub1} it can be + * defined as: * *
 	 * alias = { "alias1", "sub1" }
@@ -76,9 +75,9 @@
 	 * Values are split and trimmed meaning spaces doesn't matter.
 	 *
 	 * 

- * Supported at the type level as well as at the method level! - * When used at the type level, all method-level mappings inherit this primary - * alias to use it as a prefix. + * Supported at the type level as well as at the method level! When used at the + * type level, all method-level mappings inherit this primary alias to use it as a + * prefix. * *

 	 * @Command(alias = "alias1")
@@ -88,7 +87,6 @@
 	 *   void sub1(){}
 	 * }
 	 * 
- * * @return the aliases as an array */ String[] alias() default {}; @@ -97,10 +95,9 @@ * Define a command group. * *

- * Supported at the type level as well as at the method level! - * When used at the type level, all method-level group inherit this primary - * group. Can be overridden on method-level. - * + * Supported at the type level as well as at the method level! When used at the + * type level, all method-level group inherit this primary group. Can be overridden on + * method-level. * @return the command group */ String group() default ""; @@ -109,10 +106,9 @@ * Define a command description. * *

- * Supported at the type level as well as at the method level! - * When used at the type level, all method-level descriptions inherit this primary - * field. Can be overridden on method-level. - * + * Supported at the type level as well as at the method level! When used at the + * type level, all method-level descriptions inherit this primary field. Can be + * overridden on method-level. * @return the command description */ String description() default ""; @@ -121,9 +117,8 @@ * Define command to be hidden. * *

- * Supported at the type level as well as at the method level! - * When used at the type level, all method-level mappings inherit this primary - * hidden field. + * Supported at the type level as well as at the method level! When used at the + * type level, all method-level mappings inherit this primary hidden field. * *

 	 * @Command(hidden = true)
@@ -135,23 +130,20 @@
 	 *   }
 	 * }
 	 * 
- * * @return true if command should be hidden */ boolean hidden() default false; /** - * Define interaction mode for a command as a hint when command should be - * available. For example presense of some commands doesn't make sense if shell - * is running as non-interactive mode and vice versa. + * Define interaction mode for a command as a hint when command should be available. + * For example presense of some commands doesn't make sense if shell is running as + * non-interactive mode and vice versa. * *

- * Supported at the type level as well as at the method level! - * When used at the type level, all method-level mappings inherit this primary - * field. + * Supported at the type level as well as at the method level! When used at the + * type level, all method-level mappings inherit this primary field. * * Type is an array to be able to indicate that default don't have anyting defined. - * * @return interaction modes */ InteractionMode[] interactionMode() default {}; diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandAvailability.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandAvailability.java index 431667e4d..36f2b05e4 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandAvailability.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandAvailability.java @@ -35,8 +35,8 @@ /** * Names of provider beans for {@link Availability}. - * * @return names of supplier beans */ String[] provider() default {}; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandScan.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandScan.java index bf137fbb8..74778da0c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandScan.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/CommandScan.java @@ -26,11 +26,11 @@ import org.springframework.shell.command.annotation.support.CommandScanRegistrar; /** - * Configures the base packages used when scanning for {@link Command @Comamnd} - * classes. One of {@link #basePackageClasses()}, {@link #basePackages()} or its - * alias {@link #value()} may be specified to define specific packages to scan. - * If specific packages are not defined scanning will occur from the package of - * the class with this annotation. + * Configures the base packages used when scanning for {@link Command @Comamnd} classes. + * One of {@link #basePackageClasses()}, {@link #basePackages()} or its alias + * {@link #value()} may be specified to define specific packages to scan. If specific + * packages are not defined scanning will occur from the package of the class with this + * annotation. * * @author Janne Valkealahti */ @@ -42,35 +42,33 @@ public @interface CommandScan { /** - * Alias for the {@link #basePackages()} attribute. Allows for more concise - * annotation declarations e.g.: {@code @CommandScan("org.my.pkg")} instead of + * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation + * declarations e.g.: {@code @CommandScan("org.my.pkg")} instead of * {@code @CommandScan(basePackages="org.my.pkg")}. - * * @return the base packages to scan */ @AliasFor("basePackages") String[] value() default {}; /** - * Base packages to scan for commands. {@link #value()} is an alias for (and - * mutually exclusive with) this attribute. + * Base packages to scan for commands. {@link #value()} is an alias for (and mutually + * exclusive with) this attribute. *

* Use {@link #basePackageClasses()} for a type-safe alternative to String-based * package names. - * * @return the base packages to scan */ @AliasFor("value") String[] basePackages() default {}; /** - * Type-safe alternative to {@link #basePackages()} for specifying the packages - * to scan for commands. The package of each class specified will be scanned. + * Type-safe alternative to {@link #basePackages()} for specifying the packages to + * scan for commands. The package of each class specified will be scanned. *

- * Consider creating a special no-op marker class or interface in each package - * that serves no purpose other than being referenced by this attribute. - * + * Consider creating a special no-op marker class or interface in each package that + * serves no purpose other than being referenced by this attribute. * @return classes from the base packages to scan */ Class[] basePackageClasses() default {}; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/EnableCommand.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/EnableCommand.java index 36dd66ff7..1b572b8c8 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/EnableCommand.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/EnableCommand.java @@ -25,8 +25,8 @@ import org.springframework.shell.command.annotation.support.EnableCommandRegistrar; /** - * Enable support for {@link Command @Command} annotated classes. - * {@code @Command} classes can be registered directly on this annotation. + * Enable support for {@link Command @Command} annotated classes. {@code @Command} classes + * can be registered directly on this annotation. * * @author Janne Valkealahti */ @@ -38,8 +38,8 @@ /** * Defines candicate classes for shell commands. - * * @return candidate classes for shell commands */ Class[] value() default {}; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolver.java index 87630fc2d..c2b814c0c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolver.java @@ -34,8 +34,8 @@ /** * Exceptions handled by the annotated method. If empty, will default to any * exceptions listed in the method argument list. - * * @return Exceptions handled by annotated method */ Class[] value() default {}; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolver.java index 7c8e60e90..e2bccfadb 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolver.java @@ -31,21 +31,23 @@ import org.springframework.util.ReflectionUtils.MethodFilter; /** - * * @author Janne Valkealahti */ public class ExceptionResolverMethodResolver { - private static final MethodFilter EXCEPTION_HANDLER_METHODS = method -> - AnnotatedElementUtils.hasAnnotation(method, ExceptionResolver.class); + private static final MethodFilter EXCEPTION_HANDLER_METHODS = method -> AnnotatedElementUtils.hasAnnotation(method, + ExceptionResolver.class); + private static final Method NO_MATCHING_EXCEPTION_HANDLER_METHOD; + private final Map, Method> mappedMethods = new HashMap<>(16); + private final Map, Method> exceptionLookupCache = new ConcurrentReferenceHashMap<>(16); static { try { - NO_MATCHING_EXCEPTION_HANDLER_METHOD = - ExceptionResolverMethodResolver.class.getDeclaredMethod("noMatchingExceptionHandler"); + NO_MATCHING_EXCEPTION_HANDLER_METHOD = ExceptionResolverMethodResolver.class + .getDeclaredMethod("noMatchingExceptionHandler"); } catch (NoSuchMethodException ex) { throw new IllegalStateException("Expected method not found: " + ex); @@ -54,7 +56,6 @@ public class ExceptionResolverMethodResolver { /** * A constructor that finds {@link ExceptionResolver} methods in the given type. - * * @param handlerType the type to introspect */ public ExceptionResolverMethodResolver(Class handlerType) { @@ -95,8 +96,8 @@ private void detectAnnotationExceptionMappings(Method method, List exceptionType, Method method) { Method oldMethod = this.mappedMethods.put(exceptionType, method); if (oldMethod != null && !oldMethod.equals(method)) { - throw new IllegalStateException("Ambiguous @ExceptionResolver method mapped for [" + - exceptionType + "]: {" + oldMethod + ", " + method + "}"); + throw new IllegalStateException("Ambiguous @ExceptionResolver method mapped for [" + exceptionType + "]: {" + + oldMethod + ", " + method + "}"); } } @@ -109,7 +110,8 @@ public boolean hasExceptionMappings() { /** * Find a {@link Method} to handle the given exception. - *

Uses {@link ExceptionDepthComparator} if more than one match is found. + *

+ * Uses {@link ExceptionDepthComparator} if more than one match is found. * @param exception the exception * @return a Method to handle the exception, or {@code null} if none found */ @@ -120,8 +122,8 @@ public Method resolveMethod(Exception exception) { /** * Find a {@link Method} to handle the given Throwable. - *

Uses {@link ExceptionDepthComparator} if more than one match is found. - * + *

+ * Uses {@link ExceptionDepthComparator} if more than one match is found. * @param exception the exception * @return a Method to handle the exception, or {@code null} if none found */ @@ -138,10 +140,10 @@ public Method resolveMethodByThrowable(Throwable exception) { } /** - * Find a {@link Method} to handle the given exception type. This can be - * useful if an {@link Exception} instance is not available (e.g. for tools). - *

Uses {@link ExceptionDepthComparator} if more than one match is found. - * + * Find a {@link Method} to handle the given exception type. This can be useful if an + * {@link Exception} instance is not available (e.g. for tools). + *

+ * Uses {@link ExceptionDepthComparator} if more than one match is found. * @param exceptionType the exception type * @return a Method to handle the exception, or {@code null} if none found */ @@ -179,8 +181,9 @@ private Method getMappedMethod(Class exceptionType) { /** * For the {@link #NO_MATCHING_EXCEPTION_HANDLER_METHOD} constant. - */ + */ @SuppressWarnings("unused") private void noMatchingExceptionHandler() { } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExitCode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExitCode.java index 70a252881..9d71905f1 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExitCode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/ExitCode.java @@ -37,7 +37,6 @@ /** * Exit code value. - * * @return exit code * @see #code() */ @@ -46,10 +45,10 @@ /** * Exit code value. - * * @return exit code * @see #value() */ @AliasFor("value") int code() default 0; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolver.java index f5d03f4c8..9f83eec6f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolver.java @@ -36,7 +36,9 @@ public class MethodCommandExceptionResolver implements CommandExceptionResolver { private final static Logger log = LoggerFactory.getLogger(MethodCommandExceptionResolver.class); + private final Object bean; + private final Terminal terminal; public MethodCommandExceptionResolver(Object bean) { @@ -97,7 +99,7 @@ else if (invoke instanceof CommandHandlingResult result) { if (ecFromAnn != null) { return CommandHandlingResult.of(result.message(), ecFromAnn); } - return (CommandHandlingResult)invoke; + return (CommandHandlingResult) invoke; } else if (invoke instanceof String msg) { if (ecFromAnn != null) { @@ -127,4 +129,5 @@ public Object resolveArgument(MethodParameter parameter, Message message) thr } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Option.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Option.java index cdce438eb..91d08250b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Option.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/Option.java @@ -34,52 +34,45 @@ public @interface Option { /** - * Long names of an option. There can be multiple names where first is primary - * one and other are aliases. - * + * Long names of an option. There can be multiple names where first is primary one and + * other are aliases. * @return Option long names, defaults to empty. */ String[] longNames() default {}; /** - * Short names of an option. There can be multiple names where first is primary - * one and other are aliases. - * + * Short names of an option. There can be multiple names where first is primary one + * and other are aliases. * @return Option short names, defaults to empty. */ char[] shortNames() default {}; /** * Mark option required. - * * @return true if option is required, defaults to false. */ boolean required() default false; /** * Define option default value. - * * @return default value */ String defaultValue() default ""; /** * Return a short description of the option. - * * @return description of the option */ String description() default ""; /** * Return a label of the option. - * * @return label of the option */ String label() default ""; /** * Define option arity. - * * @return option arity * @see #arityMin() * @see #arityMax() @@ -88,9 +81,8 @@ /** * Define option arity min. If Defined non-negative will be used instead of - * {@link #arity()}. If {@code arityMax} is not set non-negative it is set to - * same as this. - * + * {@link #arity()}. If {@code arityMax} is not set non-negative it is set to same as + * this. * @return option arity min * @see #arity() */ @@ -98,11 +90,10 @@ /** * Define option arity max. If Defined non-negative will be used instead of - * {@link #arity()}. If {@code arityMin} is not set non-negative it is set to - * zero. - * + * {@link #arity()}. If {@code arityMin} is not set non-negative it is set to zero. * @return option arity max * @see #arity() */ int arityMax() default -1; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/OptionValues.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/OptionValues.java index 3caa2e14b..245edb4a9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/OptionValues.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/OptionValues.java @@ -24,8 +24,7 @@ import org.springframework.shell.completion.CompletionProvider; /** - * Annotation marking a method parameter which completion proposals should be - * used. + * Annotation marking a method parameter which completion proposals should be used. * * @author Janne Valkealahti */ @@ -36,8 +35,8 @@ /** * Names of beans for {@link CompletionProvider}. - * * @return names of CompletionProvider beans */ String[] provider() default {}; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java index f4f669fd7..d77ca550e 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtils.java @@ -26,25 +26,29 @@ import org.springframework.util.StringUtils; /** - * Utilities to merge {@link Command} annotations using opinionated logic. In - * this class {@code left} is meant for annotation on a class level and - * {@code right} annotation on a method level. Class level is meant to provide - * defaults and every field may have its own logic. + * Utilities to merge {@link Command} annotations using opinionated logic. In this class + * {@code left} is meant for annotation on a class level and {@code right} annotation on a + * method level. Class level is meant to provide defaults and every field may have its own + * logic. * * @author Janne Valkealahti */ class CommandAnnotationUtils { private final static String COMMAND = "command"; + private final static String ALIAS = "alias"; + private final static String HIDDEN = "hidden"; + private final static String GROUP = "group"; + private final static String DESCRIPTION = "description"; + private final static String INTERACTION_MODE = "interactionMode"; /** * Deduce {@link Command#hidden()} from annotations. - * * @param left the left side annotation * @param right the right side annotation * @return deduced boolean for hidden field @@ -68,11 +72,10 @@ static boolean deduceHidden(MergedAnnotation left, MergedAnnotation right) } /** - * Deduce {@link Command#command()} from annotations. Command array is supposed - * to contain commands without leading or trailing white spaces, so strip, split - * and assume that class level defines prefix for array. - * - * @param left the left side annotation + * Deduce {@link Command#command()} from annotations. Command array is supposed to + * contain commands without leading or trailing white spaces, so strip, split and + * assume that class level defines prefix for array. + * @param left the left side annotation * @param right the right side annotation * @return deduced boolean for command field */ @@ -81,11 +84,10 @@ static String[] deduceCommand(MergedAnnotation left, MergedAnnotation righ } /** - * Deduce {@link Command#alias()} from annotations. Alias array is supposed - * to contain commands without leading or trailing white spaces, so strip, split - * and assume that class level defines prefix for array. - * - * @param left the left side annotation + * Deduce {@link Command#alias()} from annotations. Alias array is supposed to contain + * commands without leading or trailing white spaces, so strip, split and assume that + * class level defines prefix for array. + * @param left the left side annotation * @param right the right side annotation * @return deduced arrays for alias field */ @@ -94,10 +96,9 @@ static String[][] deduceAlias(MergedAnnotation left, MergedAnnotation righ } /** - * Deduce {@link Command#group()} from annotations. Right side overrides if it - * has value. - * - * @param left the left side annotation + * Deduce {@link Command#group()} from annotations. Right side overrides if it has + * value. + * @param left the left side annotation * @param right the right side annotation * @return deduced String for group field */ @@ -108,8 +109,7 @@ static String deduceGroup(MergedAnnotation left, MergedAnnotation right) { /** * Deduce {@link Command#description()} from annotations. Right side overrides if it * has value. - * - * @param left the left side annotation + * @param left the left side annotation * @param right the right side annotation * @return deduced String for description field */ @@ -120,8 +120,7 @@ static String deduceDescription(MergedAnnotation left, MergedAnnotation ri /** * Deduce {@link Command#interactionMode()} from annotations. Right side overrides if. * Returns {@code null} if nothing defined. - * - * @param left the left side annotation + * @param left the left side annotation * @param right the right side annotation * @return deduced InteractionMode for interaction mode field */ @@ -151,7 +150,8 @@ static String deduceDescription(MergedAnnotation left, MergedAnnotation ri return mode; } - private static String[][] deduceStringArrayLeftPrefixes(String field, MergedAnnotation left, MergedAnnotation right) { + private static String[][] deduceStringArrayLeftPrefixes(String field, MergedAnnotation left, + MergedAnnotation right) { List prefix = Stream.of(left.getStringArray(field)) .flatMap(command -> Stream.of(command.split(" "))) .filter(command -> StringUtils.hasText(command)) @@ -160,9 +160,7 @@ private static String[][] deduceStringArrayLeftPrefixes(String field, MergedAnno return Stream.of(right.getStringArray(field)) .map(command -> command.strip()) - .map(command -> Stream.concat( - prefix.stream(), - Stream.of(command).filter(c -> StringUtils.hasText(c))) + .map(command -> Stream.concat(prefix.stream(), Stream.of(command).filter(c -> StringUtils.hasText(c))) .collect(Collectors.toList())) .map(arr -> arr.toArray(String[]::new)) .toArray(String[][]::new); @@ -170,14 +168,15 @@ private static String[][] deduceStringArrayLeftPrefixes(String field, MergedAnno private static String[] deduceStringArray(String field, MergedAnnotation left, MergedAnnotation right) { return Stream.of(left.getStringArray(field), right.getStringArray(field)) - .flatMap(commands -> Stream.of(commands)) - .flatMap(command -> Stream.of(command.split(" "))) - .filter(command -> StringUtils.hasText(command)) - .map(command -> command.strip()) - .toArray(String[]::new); + .flatMap(commands -> Stream.of(commands)) + .flatMap(command -> Stream.of(command.split(" "))) + .filter(command -> StringUtils.hasText(command)) + .map(command -> command.strip()) + .toArray(String[]::new); } - private static String deduceStringRightOverrides(String field, MergedAnnotation left, MergedAnnotation right) { + private static String deduceStringRightOverrides(String field, MergedAnnotation left, + MergedAnnotation right) { String r = right.getString(field); if (StringUtils.hasText(r)) { return r; diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrar.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrar.java index c71a0aa96..d9c656d8d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrar.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrar.java @@ -37,18 +37,19 @@ import org.springframework.util.ReflectionUtils.MethodFilter; /** - * Delegate used by {@link EnableCommandRegistrar} and - * {@link CommandScanRegistrar} to register a bean definition(s) for a - * {@link Command @Command} class. + * Delegate used by {@link EnableCommandRegistrar} and {@link CommandScanRegistrar} to + * register a bean definition(s) for a {@link Command @Command} class. * * @author Janne Valkealahti */ public final class CommandRegistrationBeanRegistrar { private final BeanDefinitionRegistry registry; + private final BeanFactory beanFactory; - private static final MethodFilter COMMAND_METHODS = method -> - AnnotatedElementUtils.hasAnnotation(method, Command.class); + + private static final MethodFilter COMMAND_METHODS = method -> AnnotatedElementUtils.hasAnnotation(method, + Command.class); public CommandRegistrationBeanRegistrar(BeanDefinitionRegistry registry) { this.registry = registry; @@ -57,7 +58,7 @@ public CommandRegistrationBeanRegistrar(BeanDefinitionRegistry registry) { public void register(Class type) { MergedAnnotation annotation = MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY) - .get(Command.class); + .get(Command.class); register(type, annotation); } @@ -75,9 +76,10 @@ void scanMethods(Class type, String containerBean, MergedAnnotation String name = type.getName(); String methodName = m.getName(); Class[] methodParameterTypes = m.getParameterTypes(); - String postfix = Stream.of(methodParameterTypes).map(clazz -> ClassUtils.getShortName(clazz)) - .collect(Collectors.joining()); - name = name + "/" + methodName + postfix; + String postfix = Stream.of(methodParameterTypes) + .map(clazz -> ClassUtils.getShortName(clazz)) + .collect(Collectors.joining()); + name = name + "/" + methodName + postfix; if (!containsBeanDefinition(name)) { registerCommandMethodBeanDefinition(type, name, containerBean, methodName, methodParameterTypes); @@ -88,13 +90,13 @@ void scanMethods(Class type, String containerBean, MergedAnnotation private void registerCommandClassBeanDefinition(String beanName, Class type, MergedAnnotation annotation) { - Assert.state(annotation.isPresent(), () -> "No " + Command.class.getSimpleName() - + " annotation found on '" + type.getName() + "'."); + Assert.state(annotation.isPresent(), + () -> "No " + Command.class.getSimpleName() + " annotation found on '" + type.getName() + "'."); this.registry.registerBeanDefinition(beanName, createCommandClassBeanDefinition(type)); } - private void registerCommandMethodBeanDefinition(Class commandBeanType, String commandBeanName, String containerBean, String methodName, - Class[] methodParameterTypes) { + private void registerCommandMethodBeanDefinition(Class commandBeanType, String commandBeanName, + String containerBean, String methodName, Class[] methodParameterTypes) { this.registry.registerBeanDefinition(commandBeanName, createCommandMethodBeanDefinition(commandBeanType, containerBean, methodName, methodParameterTypes)); } @@ -110,7 +112,8 @@ private BeanDefinition createCommandMethodBeanDefinition(Class commandBeanTyp definition.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_BEAN_TYPE, commandBeanType); definition.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_BEAN_NAME, commandBeanName); definition.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_METHOD_NAME, commandMethodName); - definition.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_METHOD_PARAMETERS, commandMethodParameters); + definition.getPropertyValues() + .add(CommandRegistrationFactoryBean.COMMAND_METHOD_PARAMETERS, commandMethodParameters); return definition; } @@ -128,4 +131,5 @@ private boolean containsBeanDefinition(BeanFactory beanFactory, String name) { } return false; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java index 5426a4571..df9dc734f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBean.java @@ -61,13 +61,12 @@ import org.springframework.util.StringUtils; /** - * Factory bean used in {@link CommandRegistrationBeanRegistrar} to build - * instance of {@link CommandRegistration}. Main logic of constructing - * {@link CommandRegistration} out from annotated command target is - * in this factory. + * Factory bean used in {@link CommandRegistrationBeanRegistrar} to build instance of + * {@link CommandRegistration}. Main logic of constructing {@link CommandRegistration} out + * from annotated command target is in this factory. * - * This factory needs a name of a {@code commandBeanName} which is a name of bean - * hosting command methods, {@code commandBeanType} which is type of a bean, + * This factory needs a name of a {@code commandBeanName} which is a name of bean hosting + * command methods, {@code commandBeanType} which is type of a bean, * {@code commandMethodName} which is a name of {@link Method} in a bean, * {@code commandMethodParameters} for method parameter types and optionally * {@code BuilderSupplier} if context provides pre-configured builder. @@ -76,20 +75,31 @@ * * @author Janne Valkealahti */ -class CommandRegistrationFactoryBean implements FactoryBean, ApplicationContextAware, InitializingBean { +class CommandRegistrationFactoryBean + implements FactoryBean, ApplicationContextAware, InitializingBean { private final Logger log = LoggerFactory.getLogger(CommandRegistrationFactoryBean.class); + public static final String COMMAND_BEAN_TYPE = "commandBeanType"; + public static final String COMMAND_BEAN_NAME = "commandBeanName"; + public static final String COMMAND_METHOD_NAME = "commandMethodName"; + public static final String COMMAND_METHOD_PARAMETERS = "commandMethodParameters"; private ObjectProvider supplier; + private ApplicationContext applicationContext; + private Object commandBean; + private Class commandBeanType; + private String commandBeanName; + private String commandMethodName; + private Class[] commandMethodParameters; @Override @@ -137,9 +147,9 @@ private CommandRegistration.Builder getBuilder() { private CommandRegistration buildRegistration() { Method method = ReflectionUtils.findMethod(commandBeanType, commandMethodName, commandMethodParameters); MergedAnnotation classAnn = MergedAnnotations.from(commandBeanType, SearchStrategy.TYPE_HIERARCHY) - .get(Command.class); + .get(Command.class); MergedAnnotation methodAnn = MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY) - .get(Command.class); + .get(Command.class); Builder builder = getBuilder(); @@ -168,14 +178,12 @@ private CommandRegistration buildRegistration() { // availability MergedAnnotation caAnn = MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY) - .get(CommandAvailability.class); + .get(CommandAvailability.class); if (caAnn.isPresent()) { String[] refs = caAnn.getStringArray("provider"); - List avails = Stream.of(refs) - .map(r -> { - return this.applicationContext.getBean(r, AvailabilityProvider.class); - }) - .collect(Collectors.toList()); + List avails = Stream.of(refs).map(r -> { + return this.applicationContext.getBean(r, AvailabilityProvider.class); + }).collect(Collectors.toList()); if (!avails.isEmpty()) { builder.availability(() -> { for (AvailabilityProvider avail : avails) { @@ -205,7 +213,8 @@ private CommandRegistration buildRegistration() { } // error handling - ExceptionResolverMethodResolver exceptionResolverMethodResolver = new ExceptionResolverMethodResolver(commandBean.getClass()); + ExceptionResolverMethodResolver exceptionResolverMethodResolver = new ExceptionResolverMethodResolver( + commandBean.getClass()); MethodCommandExceptionResolver methodCommandExceptionResolver = new MethodCommandExceptionResolver(); methodCommandExceptionResolver.bean = commandBean; methodCommandExceptionResolver.exceptionResolverMethodResolver = exceptionResolverMethodResolver; @@ -218,18 +227,18 @@ private CommandRegistration buildRegistration() { private void onCommandParameter(MethodParameter mp, Builder builder) { MergedAnnotation

The class may be created with a bean instance or with a bean name - * (e.g. lazy-init bean, prototype bean). Use {@link #createWithResolvedBean()} - * to obtain a {@code HandlerMethod} instance with a bean instance resolved - * through the associated {@link BeanFactory}. + *

+ * The class may be created with a bean instance or with a bean name (e.g. lazy-init bean, + * prototype bean). Use {@link #createWithResolvedBean()} to obtain a + * {@code HandlerMethod} instance with a bean instance resolved through the associated + * {@link BeanFactory}. * * @author Janne Valkealahti */ @@ -113,7 +114,8 @@ public InvocableShellMethod(Object bean, Method method) { * Create an instance from a bean instance, method name, and parameter types. * @throws NoSuchMethodException when the method cannot be found */ - public InvocableShellMethod(Object bean, String methodName, Class... parameterTypes) throws NoSuchMethodException { + public InvocableShellMethod(Object bean, String methodName, Class... parameterTypes) + throws NoSuchMethodException { Assert.notNull(bean, "Bean is required"); Assert.notNull(methodName, "Method name is required"); this.bean = bean; @@ -126,9 +128,9 @@ public InvocableShellMethod(Object bean, String methodName, Class... paramete } /** - * Create an instance from a bean name, a method, and a {@code BeanFactory}. - * The method {@link #createWithResolvedBean()} may be used later to - * re-create the {@code HandlerMethod} with an initialized bean. + * Create an instance from a bean name, a method, and a {@code BeanFactory}. The + * method {@link #createWithResolvedBean()} may be used later to re-create the + * {@code HandlerMethod} with an initialized bean. */ public InvocableShellMethod(String beanName, BeanFactory beanFactory, Method method) { Assert.hasText(beanName, "Bean name is required"); @@ -149,7 +151,6 @@ public InvocableShellMethod(String beanName, BeanFactory beanFactory, Method met /** * Sets a conversion service - * * @param conversionService the conversion service */ public void setConversionService(ConversionService conversionService) { @@ -192,34 +193,38 @@ public void setValidator(Validator validator) { } /** - * Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use to use for resolving method argument values. + * Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use to + * use for resolving method argument values. */ public void setMessageMethodArgumentResolvers(ShellMethodArgumentResolverComposite argumentResolvers) { this.resolvers = argumentResolvers; } /** - * Set the ParameterNameDiscoverer for resolving parameter names when needed - * (e.g. default request attribute name). - *

Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}. + * Set the ParameterNameDiscoverer for resolving parameter names when needed (e.g. + * default request attribute name). + *

+ * Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}. */ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { this.parameterNameDiscoverer = parameterNameDiscoverer; } /** - * Invoke the method after resolving its argument values in the context of the given message. - *

Argument values are commonly resolved through - * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}. - * The {@code providedArgs} parameter however may supply argument values to be used directly, - * i.e. without argument resolution. - *

Delegates to {@link #getMethodArgumentValues} and calls {@link #doInvoke} with the + * Invoke the method after resolving its argument values in the context of the given + * message. + *

+ * Argument values are commonly resolved through {@link HandlerMethodArgumentResolver + * HandlerMethodArgumentResolvers}. The {@code providedArgs} parameter however may + * supply argument values to be used directly, i.e. without argument resolution. + *

+ * Delegates to {@link #getMethodArgumentValues} and calls {@link #doInvoke} with the * resolved arguments. * @param message the current message being processed * @param providedArgs "given" arguments matched by type, not resolved * @return the raw value returned by the invoked method - * @throws Exception raised if no suitable argument resolver can be found, - * or if the method raised an exception + * @throws Exception raised if no suitable argument resolver can be found, or if the + * method raised an exception * @see #getMethodArgumentValues * @see #doInvoke */ @@ -235,7 +240,8 @@ public Object invoke(Message message, Object... providedArgs) throws Exceptio /** * Get the method argument values for the current message, checking the provided * argument values and falling back to the configured argument resolvers. - *

The resulting array will be passed into {@link #doInvoke}. + *

+ * The resulting array will be passed into {@link #doInvoke}. */ protected Object[] getMethodArgumentValues(Message message, Object... providedArgs) throws Exception { MethodParameter[] parameters = getMethodParameters(); @@ -265,8 +271,10 @@ protected Object[] getMethodArgumentValues(Message message, Object... provide for (int i = 0; i < parameters.length; i++) { if (!holders[i].resolved) { if (providedArgs != null && unresolvedCount <= providedArgs.length) { - if (conversionService.canConvert(providedArgs[providedArgsIndex].getClass(), holders[i].parameter.getParameterType())) { - holders[i].arg = conversionService.convert(providedArgs[providedArgsIndex], holders[i].parameter.getParameterType()); + if (conversionService.canConvert(providedArgs[providedArgsIndex].getClass(), + holders[i].parameter.getParameterType())) { + holders[i].arg = conversionService.convert(providedArgs[providedArgsIndex], + holders[i].parameter.getParameterType()); providedArgsIndex++; } } @@ -278,8 +286,11 @@ protected Object[] getMethodArgumentValues(Message message, Object... provide } private static class ResolvedHolder { + boolean resolved; + MethodParameter parameter; + Object arg; public ResolvedHolder(boolean resolved, MethodParameter parameter, Object arg) { @@ -287,6 +298,7 @@ public ResolvedHolder(boolean resolved, MethodParameter parameter, Object arg) { this.parameter = parameter; this.arg = arg; } + } /** @@ -298,7 +310,7 @@ protected Object doInvoke(Object... args) throws Exception { if (validator != null) { Method bridgedMethod = getBridgedMethod(); Set> constraintViolations = validator.forExecutables() - .validateParameters(getBean(), bridgedMethod, args); + .validateParameters(getBean(), bridgedMethod, args); if (constraintViolations.size() > 0) { throw new ParameterValidationException(constraintViolations); } @@ -328,7 +340,6 @@ else if (targetException instanceof Exception) { } } - MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) { return new AsyncResultMethodParameter(returnValue); } @@ -358,8 +369,9 @@ public Method getMethod() { /** * This method returns the type of the handler for this handler method. - *

Note that if the bean type is a CGLIB-generated class, the original - * user-defined class is returned. + *

+ * Note that if the bean type is a CGLIB-generated class, the original user-defined + * class is returned. */ public Class getBeanType() { return this.beanType; @@ -367,7 +379,8 @@ public Class getBeanType() { /** * If the bean method is a bridge method, this method returns the bridged - * (user-defined) method. Otherwise it returns the same method as {@link #getMethod()}. + * (user-defined) method. Otherwise it returns the same method as + * {@link #getMethod()}. */ protected Method getBridgedMethod() { return this.bridgedMethod; @@ -402,10 +415,10 @@ public boolean isVoid() { } /** - * Return a single annotation on the underlying method traversing its super methods - * if no annotation can be found on the given method itself. - *

Also supports merged composed annotations with attribute - * overrides. + * Return a single annotation on the underlying method traversing its super methods if + * no annotation can be found on the given method itself. + *

+ * Also supports merged composed annotations with attribute overrides. * @param annotationType the type of annotation to introspect the method for * @return the annotation, or {@code null} if none found * @see AnnotatedElementUtils#findMergedAnnotation @@ -425,8 +438,8 @@ public boolean hasMethodAnnotation(Class annotationTyp } /** - * Return the HandlerMethod from which this HandlerMethod instance was - * resolved via {@link #createWithResolvedBean()}. + * Return the HandlerMethod from which this HandlerMethod instance was resolved via + * {@link #createWithResolvedBean()}. */ @Nullable public InvocableShellMethod getResolvedFromHandlerMethod() { @@ -434,8 +447,8 @@ public InvocableShellMethod getResolvedFromHandlerMethod() { } /** - * If the provided instance contains a bean name rather than an object instance, - * the bean name is resolved before a {@link InvocableShellMethod} is created and + * If the provided instance contains a bean name rather than an object instance, the + * bean name is resolved before a {@link InvocableShellMethod} is created and * returned. */ public InvocableShellMethod createWithResolvedBean() { @@ -456,7 +469,6 @@ public String getShortLogMessage() { return getBeanType().getSimpleName() + "#" + this.method.getName() + "[" + args + " args]"; } - @Override public boolean equals(@Nullable Object other) { if (this == other) { @@ -479,7 +491,6 @@ public String toString() { return this.method.toGenericString(); } - // Support methods for use in "InvocableHandlerMethod" sub-class variants.. @Nullable @@ -495,25 +506,25 @@ protected static Object findProvidedArgument(MethodParameter parameter, @Nullabl } protected static String formatArgumentError(MethodParameter param, String message) { - return "Could not resolve parameter [" + param.getParameterIndex() + "] in " + - param.getExecutable().toGenericString() + (StringUtils.hasText(message) ? ": " + message : ""); + return "Could not resolve parameter [" + param.getParameterIndex() + "] in " + + param.getExecutable().toGenericString() + (StringUtils.hasText(message) ? ": " + message : ""); } /** * Assert that the target bean class is an instance of the class where the given * method is declared. In some cases the actual endpoint instance at request- - * processing time may be a JDK dynamic proxy (lazy initialization, prototype - * beans, and others). Endpoint classes that require proxying should prefer - * class-based proxy mechanisms. + * processing time may be a JDK dynamic proxy (lazy initialization, prototype beans, + * and others). Endpoint classes that require proxying should prefer class-based proxy + * mechanisms. */ protected void assertTargetBean(Method method, Object targetBean, Object[] args) { Class methodDeclaringClass = method.getDeclaringClass(); Class targetBeanClass = targetBean.getClass(); if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) { - String text = "The mapped handler method class '" + methodDeclaringClass.getName() + - "' is not an instance of the actual endpoint bean class '" + - targetBeanClass.getName() + "'. If the endpoint requires proxying " + - "(e.g. due to @Transactional), please use class-based proxying."; + String text = "The mapped handler method class '" + methodDeclaringClass.getName() + + "' is not an instance of the actual endpoint bean class '" + targetBeanClass.getName() + + "'. If the endpoint requires proxying " + + "(e.g. due to @Transactional), please use class-based proxying."; throw new IllegalStateException(formatInvokeError(text, args)); } } @@ -521,18 +532,15 @@ protected void assertTargetBean(Method method, Object targetBean, Object[] args) protected String formatInvokeError(String text, Object[] args) { String formattedArgs = IntStream.range(0, args.length) - .mapToObj(i -> (args[i] != null ? - "[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" : - "[" + i + "] [null]")) - .collect(Collectors.joining(",\n", " ", " ")); + .mapToObj(i -> (args[i] != null + ? "[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" + : "[" + i + "] [null]")) + .collect(Collectors.joining(",\n", " ", " ")); - return text + "\n" + - "Endpoint [" + getBeanType().getName() + "]\n" + - "Method [" + getBridgedMethod().toGenericString() + "] " + - "with argument values:\n" + formattedArgs; + return text + "\n" + "Endpoint [" + getBeanType().getName() + "]\n" + "Method [" + + getBridgedMethod().toGenericString() + "] " + "with argument values:\n" + formattedArgs; } - /** * A MethodParameter with HandlerMethod-specific behavior. */ @@ -565,8 +573,8 @@ public boolean hasMethodAnnotation(Class annotationTyp public HandlerMethodParameter clone() { return new HandlerMethodParameter(this); } - } + } /** * A MethodParameter for a HandlerMethod return type based on an actual return value. @@ -595,6 +603,7 @@ public Class getParameterType() { public ReturnValueMethodParameter clone() { return new ReturnValueMethodParameter(this); } + } private class AsyncResultMethodParameter extends HandlerMethodParameter { @@ -636,6 +645,7 @@ public Type getGenericParameterType() { public AsyncResultMethodParameter clone() { return new AsyncResultMethodParameter(this); } + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/invocation/ShellMethodArgumentResolverComposite.java b/spring-shell-core/src/main/java/org/springframework/shell/command/invocation/ShellMethodArgumentResolverComposite.java index ef3afcd35..32caa8ed2 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/invocation/ShellMethodArgumentResolverComposite.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/invocation/ShellMethodArgumentResolverComposite.java @@ -29,8 +29,8 @@ /** * Resolves method parameters by delegating to a list of registered - * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}. - * Previously resolved method parameters are cached for faster lookups. + * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}. Previously + * resolved method parameters are cached for faster lookups. * * @author Rossen Stoyanchev * @author Juergen Hoeller @@ -39,9 +39,8 @@ public class ShellMethodArgumentResolverComposite implements HandlerMethodArgume private final List argumentResolvers = new ArrayList<>(); - private final Map argumentResolverCache = - new ConcurrentHashMap<>(256); - + private final Map argumentResolverCache = new ConcurrentHashMap<>( + 256); /** * Add the given {@link HandlerMethodArgumentResolver}. @@ -56,8 +55,7 @@ public ShellMethodArgumentResolverComposite addResolver(HandlerMethodArgumentRes * Add the given {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}. * @since 4.3 */ - public ShellMethodArgumentResolverComposite addResolvers( - @Nullable HandlerMethodArgumentResolver... resolvers) { + public ShellMethodArgumentResolverComposite addResolvers(@Nullable HandlerMethodArgumentResolver... resolvers) { if (resolvers != null) { Collections.addAll(this.argumentResolvers, resolvers); @@ -94,10 +92,9 @@ public void clear() { this.argumentResolverCache.clear(); } - /** - * Whether the given {@linkplain MethodParameter method parameter} is - * supported by any registered {@link HandlerMethodArgumentResolver}. + * Whether the given {@linkplain MethodParameter method parameter} is supported by any + * registered {@link HandlerMethodArgumentResolver}. */ @Override public boolean supportsParameter(MethodParameter parameter) { @@ -105,9 +102,8 @@ public boolean supportsParameter(MethodParameter parameter) { } /** - * Iterate over registered - * {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} - * and invoke the one that supports it. + * Iterate over registered {@link HandlerMethodArgumentResolver + * HandlerMethodArgumentResolvers} and invoke the one that supports it. * @throws IllegalArgumentException if no suitable argument resolver is found */ @Override @@ -115,15 +111,15 @@ public boolean supportsParameter(MethodParameter parameter) { public Object resolveArgument(MethodParameter parameter, Message message) throws Exception { HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { - throw new IllegalArgumentException("Unsupported parameter type [" + - parameter.getParameterType().getName() + "]. supportsParameter should be called first."); + throw new IllegalArgumentException("Unsupported parameter type [" + parameter.getParameterType().getName() + + "]. supportsParameter should be called first."); } return resolver.resolveArgument(parameter, message); } /** - * Find a registered {@link HandlerMethodArgumentResolver} that supports - * the given method parameter. + * Find a registered {@link HandlerMethodArgumentResolver} that supports the given + * method parameter. */ @Nullable private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AbstractNodeVisitor.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AbstractNodeVisitor.java index fa79ec5cd..46f982368 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AbstractNodeVisitor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AbstractNodeVisitor.java @@ -23,8 +23,8 @@ import org.springframework.shell.command.parser.Parser.ParseResult; /** - * Base abstract {@link NodeVisitor} which visits all nodes allowing user to - * implement callback methods. + * Base abstract {@link NodeVisitor} which visits all nodes allowing user to implement + * callback methods. * * @author Janne Valkealahti */ @@ -33,8 +33,7 @@ public abstract class AbstractNodeVisitor implements NodeVisitor { private final static Logger log = LoggerFactory.getLogger(AbstractNodeVisitor.class); @Override - public final ParseResult visit(List nonterminalNodes, - List terminalNodes) { + public final ParseResult visit(List nonterminalNodes, List terminalNodes) { for (NonterminalAstNode ntn : nonterminalNodes) { log.debug("visit {}", ntn); if (ntn instanceof CommandNode node) { @@ -56,15 +55,13 @@ public final ParseResult visit(List nonterminalNodes, /** * Called after all nodes has been visited to build results. - * * @return the results from this visit operation */ protected abstract ParseResult buildResult(); /** - * Called when {@link CommandNode} for root is entered. When node is fully - * visited, {@link #onExitRootCommandNode(CommandNode)} is called. - * + * Called when {@link CommandNode} for root is entered. When node is fully visited, + * {@link #onExitRootCommandNode(CommandNode)} is called. * @param node the command node * @see #onExitRootCommandNode(CommandNode) */ @@ -72,7 +69,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link CommandNode} for root is exited. - * * @param node the command node * @see #onEnterRootCommandNode(CommandNode) */ @@ -81,7 +77,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link CommandNode} is entered. When node is fully visited, * {@link #onExitCommandNode(CommandNode)} is called. - * * @param node the command node * @see #onExitCommandNode(CommandNode) */ @@ -89,7 +84,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link CommandNode} is exited. - * * @param node the command node * @see #onEnterCommandNode(CommandNode) */ @@ -98,7 +92,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link OptionNode} is entered. When node is fully visited, * {@link #onExitOptionNode(OptionNode)} is called. - * * @param node the option node * @see #onExitOptionNode(OptionNode) */ @@ -106,7 +99,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link OptionNode} is exited. - * * @param node the option node * @see #onEnterOptionNode(OptionNode) */ @@ -115,7 +107,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link CommandArgumentNode} is entered. When node is fully visited, * {@link #onExitCommandArgumentNode(CommandArgumentNode)} is called. - * * @param node the command argument node * @see #onExitCommandArgumentNode(CommandArgumentNode) */ @@ -123,7 +114,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link CommandArgumentNode} is exited. - * * @param node the command argument node * @see #onEnterCommandArgumentNode(CommandArgumentNode) */ @@ -132,7 +122,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link OptionArgumentNode} is entered. When node is fully visited, * {@link #onExitOptionArgumentNode(OptionArgumentNode)} is called. - * * @param node the option argument node * @see #onExitOptionArgumentNode(OptionArgumentNode) */ @@ -140,7 +129,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link OptionArgumentNode} is exited. - * * @param node the command argument node * @see #onEnterOptionArgumentNode(OptionArgumentNode) */ @@ -149,7 +137,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link DirectiveNode} is entered. When node is fully visited, * {@link #onExitDirectiveNode(DirectiveNode)} is called. - * * @param node the option node * @see #onExitDirectiveNode(DirectiveNode) */ @@ -157,7 +144,6 @@ public final ParseResult visit(List nonterminalNodes, /** * Called when {@link DirectiveNode} is exited. - * * @param node the option node * @see #onEnterDirectiveNode(DirectiveNode) */ @@ -241,4 +227,5 @@ else if (node instanceof OptionArgumentNode n) { exitOptionArgumentNode(n); } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Ast.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Ast.java index a9c108c44..e24bb81f2 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Ast.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Ast.java @@ -19,23 +19,21 @@ import java.util.List; /** - * Interface to generate abstract syntax tree from tokens. Generic language - * parser usually contains lexing and parsing where this {@code Ast} represents - * the latter parsing side. + * Interface to generate abstract syntax tree from tokens. Generic language parser usually + * contains lexing and parsing where this {@code Ast} represents the latter parsing side. * - * Parsing looks tokens and combines those together into nodes and we get - * closer to understand commands, its options and arguments whether those - * belong to command or option. Parser don't look if for example option - * arguments makes sense which happen later when ast tree is visited. + * Parsing looks tokens and combines those together into nodes and we get closer to + * understand commands, its options and arguments whether those belong to command or + * option. Parser don't look if for example option arguments makes sense which happen + * later when ast tree is visited. * * @author Janne Valkealahti */ public interface Ast { /** - * Generate ast result from a tokens. {@link AstResult} contains info about - * token to ast tree generation. - * + * Generate ast result from a tokens. {@link AstResult} contains info about token to + * ast tree generation. * @param tokens the tokens * @return a result containing further syntax info */ @@ -86,7 +84,8 @@ public AstResult generate(List tokens) { break; case ARGUMENT: if (optionNode != null) { - OptionArgumentNode optionArgumentNode = new OptionArgumentNode(token, optionNode, token.getValue()); + OptionArgumentNode optionArgumentNode = new OptionArgumentNode(token, optionNode, + token.getValue()); optionNode.addChildNode(optionArgumentNode); } else { @@ -114,5 +113,7 @@ public AstResult generate(List tokens) { return new AstResult(nonterminalNodes, terminalNodes); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AstNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AstNode.java index a3fc8ed7e..12e7c16af 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AstNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/AstNode.java @@ -16,8 +16,7 @@ package org.springframework.shell.command.parser; /** - * Represents a node in an {@code abstract syntax tree} and knows about - * {@link Token}. + * Represents a node in an {@code abstract syntax tree} and knows about {@link Token}. * * @author Janne Valkealahti */ @@ -32,4 +31,5 @@ public AstNode(Token token) { public Token getToken() { return token; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandArgumentNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandArgumentNode.java index 0f009ee28..f5eb21698 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandArgumentNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandArgumentNode.java @@ -32,4 +32,5 @@ public CommandArgumentNode(Token token, CommandNode parent) { public CommandNode getParentCommandNode() { return parent; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandModel.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandModel.java index 8a65e51e5..247a14474 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandModel.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandModel.java @@ -26,14 +26,15 @@ import org.springframework.shell.command.parser.ParserConfig.Feature; /** - * Helper class to make it easier to work with command registrations and how - * those are used with parser model. + * Helper class to make it easier to work with command registrations and how those are + * used with parser model. * * @author Janne Valkealahti */ public class CommandModel { private final Map rootCommands = new HashMap<>(); + private final ParserConfig configuration; public CommandModel(Map registrations, ParserConfig configuration) { @@ -50,13 +51,15 @@ CommandInfo resolve(List commands) { CommandInfo info = null; boolean onRoot = true; for (String commandx : commands) { - String command = configuration.isEnabled(Feature.CASE_SENSITIVE_COMMANDS) ? commandx : commandx.toLowerCase(); + String command = configuration.isEnabled(Feature.CASE_SENSITIVE_COMMANDS) ? commandx + : commandx.toLowerCase(); if (onRoot) { info = rootCommands.get(command); onRoot = false; } else { - Optional nextInfo = info.getChildren().stream() + Optional nextInfo = info.getChildren() + .stream() .filter(i -> i.command.equals(command)) .findFirst(); if (nextInfo.isEmpty()) { @@ -82,13 +85,13 @@ Map getValidRootTokens() { }); // rootCommands.entrySet().forEach(e -> { - // tokens.put(e.getKey(), new Token(e.getKey(), TokenType.COMMAND)); - // if (e.getValue().registration != null) { - // e.getValue().registration.getAliases().forEach(alias -> { - // String[] commands = alias.getCommand().split(" "); - // tokens.put(commands[0], new Token(commands[0], TokenType.COMMAND)); - // }); - // } + // tokens.put(e.getKey(), new Token(e.getKey(), TokenType.COMMAND)); + // if (e.getValue().registration != null) { + // e.getValue().registration.getAliases().forEach(alias -> { + // String[] commands = alias.getCommand().split(" "); + // tokens.put(commands[0], new Token(commands[0], TokenType.COMMAND)); + // }); + // } // }); return tokens; } @@ -129,7 +132,8 @@ private CommandInfo getOrCreate(String[] commands, CommandRegistration registrat } parent = children; ret = parent; - // CommandInfo asdf = new CommandInfo(key, i < commands.length - 1 ? null : registration, parent); + // CommandInfo asdf = new CommandInfo(key, i < commands.length - 1 ? null : + // registration, parent); // parent.addChildred(command, asdf); // parent = asdf; @@ -149,18 +153,20 @@ private void buildModel(Map registrations) { // String[] commands = e.getKey().split(" "); // CommandInfo parent = null; // for (int i = 0; i < commands.length; i++) { - // CommandRegistration registration = i + 1 == commands.length ? e.getValue() : null; - // String key = configuration.isCommandsCaseSensitive() ? commands[i] : commands[i].toLowerCase(); - // if (parent == null) { - // CommandInfo info = new CommandInfo(commands[i], registration, parent); - // rootCommands.computeIfAbsent(key, command -> info); - // parent = info; - // } - // else { - // CommandInfo info = new CommandInfo(key, registration, parent); - // parent.children.add(info); - // parent = info; - // } + // CommandRegistration registration = i + 1 == commands.length ? e.getValue() + // : null; + // String key = configuration.isCommandsCaseSensitive() ? commands[i] : + // commands[i].toLowerCase(); + // if (parent == null) { + // CommandInfo info = new CommandInfo(commands[i], registration, parent); + // rootCommands.computeIfAbsent(key, command -> info); + // parent = info; + // } + // else { + // CommandInfo info = new CommandInfo(key, registration, parent); + // parent.children.add(info); + // parent = info; + // } // } }); } @@ -169,9 +175,13 @@ private void buildModel(Map registrations) { * Contains info about a command, its registration, its parent and childs. */ static class CommandInfo { + String command; + CommandRegistration registration; + CommandInfo parent; + // private List children = new ArrayList<>(); private Map children = new HashMap<>(); @@ -183,7 +193,6 @@ static class CommandInfo { /** * Get valid tokens for this {@code CommandInfo}. - * * @return mapping from raw value to a token */ Map getValidTokens() { @@ -215,10 +224,12 @@ public void addChildred(String command, CommandInfo children) { CommandInfo getChildren(String command) { return children.get(command); // return children.stream() - // .filter(c -> c.command.equals(command)) - // .findFirst() - // .orElse(null) - // ; + // .filter(c -> c.command.equals(command)) + // .findFirst() + // .orElse(null) + // ; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandNode.java index de3d1d7ad..f0da3b4e7 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/CommandNode.java @@ -37,4 +37,5 @@ public String getCommand() { public String toString() { return "CommandNode [command=" + command + ", children=" + getChildren() + ", token=" + getToken() + "]"; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveNode.java index 433e93f55..b99970f5c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveNode.java @@ -23,6 +23,7 @@ public final class DirectiveNode extends TerminalAstNode { private final String name; + private final String value; public DirectiveNode(Token token, String name, String value) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveResult.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveResult.java index da9709947..d7a8b4b02 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveResult.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/DirectiveResult.java @@ -18,8 +18,7 @@ import org.springframework.lang.Nullable; /** - * Encapsulating {@code Directive} with its fields, {@code name} and - * {@code value}. + * Encapsulating {@code Directive} with its fields, {@code name} and {@code value}. * * @author Janne Valkealahti */ diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Lexer.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Lexer.java index 04a002cc4..c161bfaf0 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Lexer.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Lexer.java @@ -30,14 +30,12 @@ import org.springframework.shell.command.parser.ParserConfig.Feature; /** - * Interface to tokenize arguments into tokens. Generic language parser usually - * contains lexing and parsing where this {@code Lexer} represents the former - * lexing side. + * Interface to tokenize arguments into tokens. Generic language parser usually contains + * lexing and parsing where this {@code Lexer} represents the former lexing side. * - * Lexing takes a first step to analyse basic construct of elements out from - * given arguments. We get rough idea what each argument represents but don't - * look deeper if any of it is correct which happens later when tokens go - * through parsing operation. + * Lexing takes a first step to analyse basic construct of elements out from given + * arguments. We get rough idea what each argument represents but don't look deeper if any + * of it is correct which happens later when tokens go through parsing operation. * * @author Janne Valkealahti */ @@ -45,7 +43,6 @@ public interface Lexer { /** * Tokenize given command line arguments into a list of tokens. - * * @param arguments the command line arguments * @return lexer result having tokens and operation messages */ @@ -66,7 +63,9 @@ public record LexerResult(List tokens, List messageResults public class DefaultLexer implements Lexer { private final static Logger log = LoggerFactory.getLogger(DefaultLexer.class); + private final CommandModel commandModel; + private final ParserConfig config; public DefaultLexer(CommandModel commandModel, ParserConfig config) { @@ -149,7 +148,8 @@ public LexerResult tokenize(List arguments) { } else { if (!config.isEnabled(Feature.IGNORE_DIRECTIVES) && beforeArguments.size() > 0) { - errorResults.add(MessageResult.of(ParserMessage.ILLEGAL_CONTENT_BEFORE_COMMANDS, 0, beforeArguments)); + errorResults + .add(MessageResult.of(ParserMessage.ILLEGAL_CONTENT_BEFORE_COMMANDS, 0, beforeArguments)); } } @@ -162,7 +162,7 @@ public LexerResult tokenize(List arguments) { int i2 = i1; for (String argument : afterArguments) { // if (!configuration.isEnabled(Feature.CASE_SENSITIVE_COMMANDS)) { - // argument = argument.toLowerCase(); + // argument = argument.toLowerCase(); // } i2++; @@ -173,9 +173,9 @@ public LexerResult tokenize(List arguments) { continue; } if (!foundDoubleDash && "--".equals(argument)) { - tokenList.add(Token.of(argument, TokenType.DOUBLEDASH, i2)); - foundDoubleDash = true; - continue; + tokenList.add(Token.of(argument, TokenType.DOUBLEDASH, i2)); + foundDoubleDash = true; + continue; } String argumentToCheck = argument; @@ -188,7 +188,8 @@ public LexerResult tokenize(List arguments) { Token token = validTokens.get(argumentToCheck); switch (token.getType()) { case COMMAND: - currentCommand = currentCommand == null ? commandModel.getRootCommands().get(argumentToCheck) + currentCommand = currentCommand == null + ? commandModel.getRootCommands().get(argumentToCheck) : currentCommand.getChildren(argument); tokenList.add(Token.of(argument, TokenType.COMMAND, i2)); validTokens = currentCommand.getValidTokens(); @@ -277,5 +278,7 @@ private static int decuceArgumentStyle(String str) { } return ret; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/MessageResult.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/MessageResult.java index 1300efbe2..75e838198 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/MessageResult.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/MessageResult.java @@ -24,7 +24,6 @@ public record MessageResult(ParserMessage parserMessage, int position, Object[] /** * Constructs {@code MessageResult} with parser message, position and inserts. - * * @param parserMessage the parser message * @param position the position * @param inserts the inserts @@ -36,7 +35,6 @@ public static MessageResult of(ParserMessage parserMessage, int position, Object /** * Gets a formatted message using position and inserts. - * * @return a formatted message */ public String getMessage() { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NodeVisitor.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NodeVisitor.java index f1a268d0d..6142563ca 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NodeVisitor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NodeVisitor.java @@ -28,10 +28,10 @@ public interface NodeVisitor { /** * Visit lists of non terminal and terminal nodes. - * * @param nonterminalNodes non terminal nodes * @param terminalNodes terminal nodes * @return parser result */ ParseResult visit(List nonterminalNodes, List terminalNodes); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NonterminalAstNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NonterminalAstNode.java index 518ae3706..2501e5b54 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NonterminalAstNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/NonterminalAstNode.java @@ -19,8 +19,8 @@ import java.util.List; /** - * {@code Nonterminal} node means that it can have children and doesn't - * necessarily terminal {@code ast tree branch}. + * {@code Nonterminal} node means that it can have children and doesn't necessarily + * terminal {@code ast tree branch}. * * @author Janne Valkealahti */ @@ -39,4 +39,5 @@ public List getChildren() { void addChildNode(AstNode node) { this.children.add(node); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionArgumentNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionArgumentNode.java index 7915c091c..ff408bd27 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionArgumentNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionArgumentNode.java @@ -23,6 +23,7 @@ public final class OptionArgumentNode extends TerminalAstNode { private final OptionNode parentOptionNode; + private final String value; public OptionArgumentNode(Token token, OptionNode parentOptionNode, String value) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionNode.java index 64093a994..f54bb3715 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/OptionNode.java @@ -37,4 +37,5 @@ public String getName() { public String toString() { return "OptionNode [name=" + name + ", children=" + getChildren() + ", token=" + getToken() + "]"; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Parser.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Parser.java index 84284546e..ba5305587 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Parser.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Parser.java @@ -47,17 +47,15 @@ public interface Parser { /** * Parse given arguments into a {@link ParseResult}. - * * @param arguments the command line arguments * @return a parsed results */ ParseResult parse(List arguments); - /** * Results from a {@link Parser} containing needed information like resolved - * {@link CommandRegistration}, list of {@link CommandOption} instances, errors - * and directive. + * {@link CommandRegistration}, list of {@link CommandOption} instances, errors and + * directive. * * @param commandRegistration command registration * @param optionResults option results @@ -85,15 +83,18 @@ public static ArgumentResult of(String value, int position) { } /** - * Default implementation of a {@link Parser}. Uses {@link Lexer} and - * {@link Ast}. + * Default implementation of a {@link Parser}. Uses {@link Lexer} and {@link Ast}. */ public class DefaultParser implements Parser { private final ParserConfig config; + private final CommandModel commandModel; + private final Lexer lexer; + private final Ast ast; + private ConversionService conversionService; public DefaultParser(CommandModel commandModel, Lexer lexer, Ast ast) { @@ -120,17 +121,18 @@ public ParseResult parse(List arguments) { List tokens = lexerResult.tokens(); // 2. generate syntax tree results from tokens - // result from it is then feed into node visitor + // result from it is then feed into node visitor AstResult astResult = ast.generate(tokens); // 3. visit nodes - // whoever uses this parser can then do further - // things with final parsing results + // whoever uses this parser can then do further + // things with final parsing results NodeVisitor visitor = new DefaultNodeVisitor(commandModel, conversionService, config); ParseResult parseResult = visitor.visit(astResult.nonterminalNodes(), astResult.terminalNodes()); parseResult.messageResults().addAll(lexerResult.messageResults()); return parseResult; } + } /** @@ -139,17 +141,29 @@ public ParseResult parse(List arguments) { class DefaultNodeVisitor extends AbstractNodeVisitor { private final CommandModel commandModel; + private final ConversionService conversionService; + private final ParserConfig config; + private final List commonMessageResults = new ArrayList<>(); + private List resolvedCommmand = new ArrayList<>(); + private List optionResults = new ArrayList<>(); + private List currentOptionArgument = new ArrayList<>(); + private List directiveResults = new ArrayList<>(); + private List invalidOptionNodes = new ArrayList<>(); + private List argumentResults = new ArrayList<>(); + private int commandArgumentPos = 0; + private int optionPos = -1; + private long expectedOptionCount; DefaultNodeVisitor(CommandModel commandModel, ConversionService conversionService, ParserConfig config) { @@ -176,7 +190,8 @@ protected ParseResult buildResult() { .collect(Collectors.toSet()); // get sorted list by position as we later match by order - List optionsForArguments = registration.getOptions().stream() + List optionsForArguments = registration.getOptions() + .stream() .filter(o -> !resolvedOptions.contains(o)) .filter(o -> o.getPosition() > -1) .sorted(Comparator.comparingInt(o -> o.getPosition())) @@ -221,7 +236,8 @@ protected ParseResult buildResult() { } // possibly fill in from default values - registration.getOptions().stream() + registration.getOptions() + .stream() .filter(o -> o.getDefaultValue() != null) .filter(o -> !resolvedOptions.contains(o)) .forEach(o -> { @@ -279,7 +295,8 @@ protected void onEnterOptionNode(OptionNode node) { String name = node.getName(); if (name.startsWith("--")) { info.registration.getOptions().forEach(option -> { - Set longNames = Arrays.asList(option.getLongNames()).stream() + Set longNames = Arrays.asList(option.getLongNames()) + .stream() .map(n -> "--" + n) .collect(Collectors.toSet()); String nameToMatch = config.isEnabled(Feature.CASE_SENSITIVE_OPTIONS) ? name : name.toLowerCase(); @@ -292,9 +309,10 @@ protected void onEnterOptionNode(OptionNode node) { else if (name.startsWith("-")) { if (name.length() == 2) { info.registration.getOptions().forEach(option -> { - Set shortNames = Arrays.asList(option.getShortNames()).stream() - .map(n -> "-" + Character.toString(n)) - .collect(Collectors.toSet()); + Set shortNames = Arrays.asList(option.getShortNames()) + .stream() + .map(n -> "-" + Character.toString(n)) + .collect(Collectors.toSet()); boolean match = shortNames.contains(name); if (match) { currentOptions.add(option); @@ -303,9 +321,10 @@ else if (name.startsWith("-")) { } else if (name.length() > 2) { info.registration.getOptions().forEach(option -> { - Set shortNames = Arrays.asList(option.getShortNames()).stream() - .map(n -> "-" + Character.toString(n)) - .collect(Collectors.toSet()); + Set shortNames = Arrays.asList(option.getShortNames()) + .stream() + .map(n -> "-" + Character.toString(n)) + .collect(Collectors.toSet()); for (int i = 1; i < name.length(); i++) { boolean match = shortNames.contains("-" + name.charAt(i)); if (match) { @@ -336,12 +355,14 @@ protected void onExitOptionNode(OptionNode node) { // because number of argument to eat dependes on arity // and rest would go back to positional args. if (optionPos + 1 < expectedOptionCount) { - if (currentOption.getArityMin() > -1 && currentOptionArgument.size() < currentOption.getArityMin()) { + if (currentOption.getArityMin() > -1 + && currentOptionArgument.size() < currentOption.getArityMin()) { String arg = currentOption.getLongNames()[0]; commonMessageResults.add(MessageResult.of(ParserMessage.NOT_ENOUGH_OPTION_ARGUMENTS, 0, arg, currentOptionArgument.size())); } - else if (currentOption.getArityMax() > -1 && currentOptionArgument.size() > currentOption.getArityMax()) { + else if (currentOption.getArityMax() > -1 + && currentOptionArgument.size() > currentOption.getArityMax()) { String arg = currentOption.getLongNames()[0]; commonMessageResults.add(MessageResult.of(ParserMessage.TOO_MANY_OPTION_ARGUMENTS, 0, arg, currentOption.getArityMax())); @@ -370,8 +391,10 @@ else if (toUse.size() > 1) { try { value = convertOptionType(currentOption, value); - } catch (Exception e) { - commonMessageResults.add(MessageResult.of(ParserMessage.ILLEGAL_OPTION_VALUE, 0, value, e.getMessage())); + } + catch (Exception e) { + commonMessageResults + .add(MessageResult.of(ParserMessage.ILLEGAL_OPTION_VALUE, 0, value, e.getMessage())); } optionResults.add(new OptionResult(currentOption, value)); } @@ -416,52 +439,46 @@ private Object convertOptionType(CommandOption option, Object value) { } private List validateOptionNotMissing(CommandRegistration registration) { - HashSet requiredOptions = registration.getOptions().stream() + HashSet requiredOptions = registration.getOptions() + .stream() .filter(o -> o.isRequired()) .collect(Collectors.toCollection(() -> new HashSet<>())); - List argumentResultValues = argumentResults.stream().map(ar -> ar.value).collect(Collectors.toList()); - optionResults.stream() - .filter(or -> or.value() != null) - .map(or -> or.option()) - .forEach(o -> { - requiredOptions.remove(o); - }); - Set requiredOptions2 = requiredOptions.stream() - .filter(o -> { - if (argumentResultValues.isEmpty()) { - return true; - } - List longNames = Arrays.asList(o.getLongNames()); - return !Collections.disjoint(argumentResultValues, longNames); - }) - .collect(Collectors.toSet()); - - return requiredOptions2.stream() - .map(o -> { - String ins0 = ""; - if (o.getLongNames().length > 0) { - ins0 = "--" + o.getLongNames()[0]; - } - else if (o.getShortNames().length > 0) { - ins0 = "-" + o.getShortNames()[0]; - } - - String ins1 = ""; - if (StringUtils.hasText(o.getDescription())) { - ins1 = ", " + o.getDescription(); - } - return MessageResult.of(ParserMessage.MANDATORY_OPTION_MISSING, 0, ins0, ins1); - }) + List argumentResultValues = argumentResults.stream() + .map(ar -> ar.value) .collect(Collectors.toList()); + optionResults.stream().filter(or -> or.value() != null).map(or -> or.option()).forEach(o -> { + requiredOptions.remove(o); + }); + Set requiredOptions2 = requiredOptions.stream().filter(o -> { + if (argumentResultValues.isEmpty()) { + return true; + } + List longNames = Arrays.asList(o.getLongNames()); + return !Collections.disjoint(argumentResultValues, longNames); + }).collect(Collectors.toSet()); + + return requiredOptions2.stream().map(o -> { + String ins0 = ""; + if (o.getLongNames().length > 0) { + ins0 = "--" + o.getLongNames()[0]; + } + else if (o.getShortNames().length > 0) { + ins0 = "-" + o.getShortNames()[0]; + } + + String ins1 = ""; + if (StringUtils.hasText(o.getDescription())) { + ins1 = ", " + o.getDescription(); + } + return MessageResult.of(ParserMessage.MANDATORY_OPTION_MISSING, 0, ins0, ins1); + }).collect(Collectors.toList()); } private List validateOptionIsValid(CommandRegistration registration) { - return invalidOptionNodes.stream() - .map(on -> { - return MessageResult.of(ParserMessage.UNRECOGNISED_OPTION, 0, on.getName()); - }) - .collect(Collectors.toList()); + return invalidOptionNodes.stream().map(on -> { + return MessageResult.of(ParserMessage.UNRECOGNISED_OPTION, 0, on.getName()); + }).collect(Collectors.toList()); } private static long optionCountInCommand(CommandNode node) { @@ -470,5 +487,7 @@ private static long optionCountInCommand(CommandNode node) { } return node.getChildren().stream().filter(n -> n instanceof OptionNode).count(); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserConfig.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserConfig.java index 3ecec5090..a657c714c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserConfig.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserConfig.java @@ -62,10 +62,10 @@ public static enum Feature { /** * Defines if options are parsed using case-sensitivity, enabled on default. */ - CASE_SENSITIVE_OPTIONS(true) - ; + CASE_SENSITIVE_OPTIONS(true); private final boolean defaultState; + private final long mask; private Feature(boolean defaultState) { @@ -94,5 +94,7 @@ public boolean enabledIn(int flags) { public long getMask() { return mask; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserMessage.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserMessage.java index 9eb22488c..96df72be5 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserMessage.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/ParserMessage.java @@ -18,21 +18,19 @@ import java.text.MessageFormat; /** - * Contains all the messages that can be produced during parsing. Each message - * has a kind (WARNING, ERROR) and a code number. Code is used to identify - * particular message and makes it easier to test what messages are produced. - * Code numbers are split so that ones within {@code 1xxx} are from lexer - * and {@code 2xxx} from parser. + * Contains all the messages that can be produced during parsing. Each message has a kind + * (WARNING, ERROR) and a code number. Code is used to identify particular message and + * makes it easier to test what messages are produced. Code numbers are split so that ones + * within {@code 1xxx} are from lexer and {@code 2xxx} from parser. * - * Messages with {@code ERROR} should be treated as terminating messages because - * those are most likely hard errors based on manual validation or exception - * thrown within lexing or parsing. + * Messages with {@code ERROR} should be treated as terminating messages because those are + * most likely hard errors based on manual validation or exception thrown within lexing or + * parsing. * - * Messages with {@code WARNING} can be ignored but can be used to provide - * info to user. For example parsing may detect some ambiguities with a command - * and option model related to what user tries to use as an input. This - * because there are limits how clever a parser can be as command model - * is beyond its control. + * Messages with {@code WARNING} can be ignored but can be used to provide info to user. + * For example parsing may detect some ambiguities with a command and option model related + * to what user tries to use as an input. This because there are limits how clever a + * parser can be as command model is beyond its control. * * @author Janne Valkealahti */ @@ -43,11 +41,12 @@ public enum ParserMessage { UNRECOGNISED_OPTION(Type.ERROR, 2001, "Unrecognised option ''{0}''"), ILLEGAL_OPTION_VALUE(Type.ERROR, 2002, "Illegal option value ''{0}'', reason ''{1}''"), NOT_ENOUGH_OPTION_ARGUMENTS(Type.ERROR, 2003, "Not enough arguments for option ''{0}'', requires at least ''{1}''"), - TOO_MANY_OPTION_ARGUMENTS(Type.ERROR, 2004, "Too many arguments for option ''{0}'', requires at most ''{1}''") - ; + TOO_MANY_OPTION_ARGUMENTS(Type.ERROR, 2004, "Too many arguments for option ''{0}'', requires at most ''{1}''"); private Type type; + private int code; + private String message; ParserMessage(Type type, int code, String message) { @@ -66,7 +65,6 @@ public Type getType() { /** * Format message without code and position parts. - * * @param inserts the inserts * @return formatted message */ @@ -77,8 +75,8 @@ public String formatMessage(Object... inserts) { /** * Format message. * - *

For example code and position 2000E:(pos 0): - * + *

+ * For example code and position 2000E:(pos 0): * @param useCode Add code part * @param position position info, not printed if negative * @param inserts the inserts @@ -106,7 +104,9 @@ public String formatMessage(boolean useCode, int position, Object... inserts) { } public enum Type { - WARNING, - ERROR + + WARNING, ERROR + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TerminalAstNode.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TerminalAstNode.java index 4a7f1e034..451d97fa5 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TerminalAstNode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TerminalAstNode.java @@ -20,10 +20,11 @@ * * @author Janne Valkealahti */ -public abstract sealed class TerminalAstNode - extends AstNode permits DirectiveNode, OptionArgumentNode, CommandArgumentNode { +public abstract sealed class TerminalAstNode extends AstNode + permits DirectiveNode, OptionArgumentNode, CommandArgumentNode { public TerminalAstNode(Token token) { super(token); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Token.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Token.java index 187bcb910..6cfca3cb3 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Token.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/Token.java @@ -18,8 +18,11 @@ public class Token { private final static int IMPLICIT_POSITION = -1; + private final String value; + private final TokenType type; + private final int position; public Token(String value, TokenType type) { @@ -56,4 +59,5 @@ public int getPosition() { public String toString() { return "Token [type=" + type + ", position=" + position + ", value=" + value + "]"; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TokenType.java b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TokenType.java index 3312716a0..6d09ab3ea 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TokenType.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/parser/TokenType.java @@ -17,9 +17,6 @@ public enum TokenType { - ARGUMENT, - COMMAND, - OPTION, - DOUBLEDASH, - DIRECTIVE + ARGUMENT, COMMAND, OPTION, DOUBLEDASH, DIRECTIVE + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/support/OptionNameModifierSupport.java b/spring-shell-core/src/main/java/org/springframework/shell/command/support/OptionNameModifierSupport.java index 2ea618430..1368fcfe6 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/support/OptionNameModifierSupport.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/support/OptionNameModifierSupport.java @@ -28,25 +28,27 @@ import org.springframework.util.StringUtils; /** - * Support facilities for {@link OptionNameModifier} providing common naming - * types. + * Support facilities for {@link OptionNameModifier} providing common naming types. * * @author Janne Valkealahti */ public abstract class OptionNameModifierSupport { public static final OptionNameModifier NOOP = name -> name; + public static final OptionNameModifier CAMELCASE = name -> toCamelCase(name); + public static final OptionNameModifier SNAKECASE = name -> toSnakeCase(name); + public static final OptionNameModifier KEBABCASE = name -> toKebabCase(name); + public static final OptionNameModifier PASCALCASE = name -> toPascalCase(name); private static final Pattern PATTERN = Pattern - .compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+"); + .compile("[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+"); /** * Convert given name to {@code camelCase}. - * * @param name the name to modify * @return a modified name as camel case */ @@ -56,7 +58,6 @@ public static String toCamelCase(String name) { /** * Convert given name to {@code snake_case}. - * * @param name the name to modify * @return a modified name as snake case */ @@ -66,7 +67,6 @@ public static String toSnakeCase(String name) { /** * Convert given name to {@code kebab-case}. - * * @param name the name to modify * @return a modified name as kebab case */ @@ -76,7 +76,6 @@ public static String toKebabCase(String name) { /** * Convert given name to {@code PascalCase}. - * * @param name the name to modify * @return a modified name as pascal case */ @@ -95,37 +94,39 @@ private static String matchJoin(String name, String delimiter) { } private static String toCapitalizeCase(String name, final boolean capitalizeFirstLetter, final char... delimiters) { - if (!StringUtils.hasText(name)) { - return name; - } - String nameL = name.toLowerCase(); + if (!StringUtils.hasText(name)) { + return name; + } + String nameL = name.toLowerCase(); final int strLen = nameL.length(); - final int[] newCodePoints = new int[strLen]; - final Set delimiterSet = toDelimiterSet(delimiters); + final int[] newCodePoints = new int[strLen]; + final Set delimiterSet = toDelimiterSet(delimiters); int outOffset = 0; - boolean capitalizeNext = capitalizeFirstLetter; + boolean capitalizeNext = capitalizeFirstLetter; boolean delimiterFound = false; for (int index = 0; index < strLen;) { - final int codePoint = nameL.codePointAt(index); - - if (delimiterSet.contains(codePoint)) { - capitalizeNext = outOffset != 0; - index += Character.charCount(codePoint); - delimiterFound = true; - } else if (capitalizeNext || outOffset == 0 && capitalizeFirstLetter) { - final int titleCaseCodePoint = Character.toTitleCase(codePoint); - newCodePoints[outOffset++] = titleCaseCodePoint; - index += Character.charCount(titleCaseCodePoint); - capitalizeNext = false; - } else { - newCodePoints[outOffset++] = codePoint; - index += Character.charCount(codePoint); - } - } + final int codePoint = nameL.codePointAt(index); + + if (delimiterSet.contains(codePoint)) { + capitalizeNext = outOffset != 0; + index += Character.charCount(codePoint); + delimiterFound = true; + } + else if (capitalizeNext || outOffset == 0 && capitalizeFirstLetter) { + final int titleCaseCodePoint = Character.toTitleCase(codePoint); + newCodePoints[outOffset++] = titleCaseCodePoint; + index += Character.charCount(titleCaseCodePoint); + capitalizeNext = false; + } + else { + newCodePoints[outOffset++] = codePoint; + index += Character.charCount(codePoint); + } + } if (!delimiterFound) { if (capitalizeFirstLetter) { @@ -136,28 +137,28 @@ private static String toCapitalizeCase(String name, final boolean capitalizeFirs } } - return new String(newCodePoints, 0, outOffset); - } + return new String(newCodePoints, 0, outOffset); + } - /** + /** * Converts an array of delimiters to a hash set of code points. Code point of * space(32) is added as the default value. The generated hash set provides O(1) * lookup time. - * * @param delimiters set of characters to determine capitalization, null means - * whitespace + * whitespace * @return Integers of code points */ - private static Set toDelimiterSet(final char[] delimiters) { - final Set delimiterHashSet = new HashSet<>(); - delimiterHashSet.add(Character.codePointAt(new char[]{' '}, 0)); + private static Set toDelimiterSet(final char[] delimiters) { + final Set delimiterHashSet = new HashSet<>(); + delimiterHashSet.add(Character.codePointAt(new char[] { ' ' }, 0)); if (ObjectUtils.isEmpty(delimiters)) { - return delimiterHashSet; + return delimiterHashSet; + } + + for (int index = 0; index < delimiters.length; index++) { + delimiterHashSet.add(Character.codePointAt(delimiters, index)); } + return delimiterHashSet; + } - for (int index = 0; index < delimiters.length; index++) { - delimiterHashSet.add(Character.codePointAt(delimiters, index)); - } - return delimiterHashSet; - } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionProvider.java index c4a1bf62e..8c05cc9c5 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionProvider.java @@ -28,4 +28,5 @@ */ @FunctionalInterface public interface CompletionProvider extends Function> { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionResolver.java index 1bb618d07..8b13ce73c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/completion/CompletionResolver.java @@ -16,12 +16,13 @@ package org.springframework.shell.completion; /** - * Interface resolving completion proposals. This is same as - * {@link CompletionProvider} but mean to be autowired globally. + * Interface resolving completion proposals. This is same as {@link CompletionProvider} + * but mean to be autowired globally. * * @author Janne Valkealahti * @see CompletionProvider */ @FunctionalInterface public interface CompletionResolver extends CompletionProvider { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolver.java index fa33ba387..c18553f92 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolver.java @@ -36,13 +36,17 @@ public List apply(CompletionContext context) { return Collections.emptyList(); } List candidates = new ArrayList<>(); - context.getCommandRegistration().getOptions().stream() + context.getCommandRegistration() + .getOptions() + .stream() .flatMap(o -> Stream.of(o.getLongNames())) .map(ln -> "--" + ln) .filter(ln -> !context.getWords().contains(ln)) .map(CompletionProposal::new) .forEach(candidates::add); - context.getCommandRegistration().getOptions().stream() + context.getCommandRegistration() + .getOptions() + .stream() .flatMap(o -> Stream.of(o.getShortNames())) .map(ln -> "-" + ln) .filter(ln -> !context.getWords().contains(ln)) @@ -50,4 +54,5 @@ public List apply(CompletionContext context) { .forEach(candidates::add); return candidates; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/ConfirmationInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/ConfirmationInput.java index 94d328582..8c7c0db7a 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/ConfirmationInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/ConfirmationInput.java @@ -42,7 +42,9 @@ public class ConfirmationInput extends AbstractTextComponent { private final static Logger log = LoggerFactory.getLogger(ConfirmationInput.class); + private final boolean defaultValue; + private ConfirmationInputContext currentContext; public ConfirmationInput(Terminal terminal) { @@ -147,7 +149,7 @@ private void checkInput(String input, ConfirmationInputContext context) { context.setMessage(null); return; } - Boolean yesno = parseBoolean(input); + Boolean yesno = parseBoolean(input); if (yesno == null) { String msg = String.format("Sorry, your input is invalid: '%s', try again", input); context.setMessage(msg, MessageLevel.ERROR); @@ -161,21 +163,18 @@ public interface ConfirmationInputContext extends TextComponentContext - implements ConfirmationInputContext { + private static class DefaultConfirmationInputContext + extends BaseTextComponentContext implements ConfirmationInputContext { private Boolean defaultValue; @@ -219,6 +218,7 @@ public Map toTemplateModel() { model.put("model", attributes); return model; } + } private class DefaultRenderer implements Function> { @@ -227,5 +227,7 @@ private class DefaultRenderer implements Function apply(ConfirmationInputContext context) { return renderTemplateResource(context.toTemplateModel()); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/MultiItemSelector.java b/spring-shell-core/src/main/java/org/springframework/shell/component/MultiItemSelector.java index 4b40fe64b..aaf95664b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/MultiItemSelector.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/MultiItemSelector.java @@ -89,14 +89,12 @@ public interface MultiItemSelectorContext getValues(); /** * Creates an empty {@link MultiItemSelectorContext}. - * * @return empty context */ static > MultiItemSelectorContext empty() { @@ -105,16 +103,18 @@ static > MultiItemSelectorContex /** * Creates an {@link MultiItemSelectorContext}. - * * @return context */ - static > MultiItemSelectorContext empty(Function itemMapper) { + static > MultiItemSelectorContext empty( + Function itemMapper) { return new DefaultMultiItemSelectorContext<>(itemMapper); } + } - private static class DefaultMultiItemSelectorContext> extends - BaseSelectorComponentContext> implements MultiItemSelectorContext { + private static class DefaultMultiItemSelectorContext> + extends BaseSelectorComponentContext> + implements MultiItemSelectorContext { private Function itemMapper = item -> item.toString(); @@ -131,25 +131,23 @@ public List getValues() { return Collections.emptyList(); } return getResultItems().stream() - .map(i -> i.getItem()) - .map(i -> itemMapper.apply(i)) - .collect(Collectors.toList()); + .map(i -> i.getItem()) + .map(i -> itemMapper.apply(i)) + .collect(Collectors.toList()); } @Override public Map toTemplateModel() { Map attributes = super.toTemplateModel(); attributes.put("values", getValues()); - List> rows = getItemStateView().stream() - .map(is -> { - Map map = new HashMap<>(); - map.put("name", is.getName()); - map.put("selected", is.isSelected()); - map.put("onrow", getCursorRow().intValue() == is.getIndex()); - map.put("enabled", is.isEnabled()); - return map; - }) - .collect(Collectors.toList()); + List> rows = getItemStateView().stream().map(is -> { + Map map = new HashMap<>(); + map.put("name", is.getName()); + map.put("selected", is.isSelected()); + map.put("onrow", getCursorRow().intValue() == is.getIndex()); + map.put("enabled", is.isEnabled()); + return map; + }).collect(Collectors.toList()); attributes.put("rows", rows); // finally wrap it into 'model' as that's what // we expect in stg template. @@ -157,6 +155,7 @@ public Map toTemplateModel() { model.put("model", attributes); return model; } + } private class DefaultRenderer implements Function, List> { @@ -165,5 +164,7 @@ private class DefaultRenderer implements Function public List apply(MultiItemSelectorContext context) { return renderTemplateResource(context.toTemplateModel()); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/PathInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/PathInput.java index e1006355c..c6f75ccc5 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/PathInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/PathInput.java @@ -45,7 +45,9 @@ public class PathInput extends AbstractTextComponent { private final static Logger log = LoggerFactory.getLogger(PathInput.class); + private PathInputContext currentContext; + private Function pathProvider = (path) -> Paths.get(path); public PathInput(Terminal terminal) { @@ -119,7 +121,6 @@ protected boolean read(BindingReader bindingReader, KeyMap keyMap, PathI /** * Sets a path provider. - * * @param pathProvider the path provider */ public void setPathProvider(Function pathProvider) { @@ -128,7 +129,6 @@ public void setPathProvider(Function pathProvider) { /** * Resolves a {@link Path} from a given raw {@code path}. - * * @param path the raw path * @return a resolved path */ @@ -155,12 +155,12 @@ public interface PathInputContext extends TextComponentContext @@ -173,6 +173,7 @@ public Map toTemplateModel() { model.put("model", attributes); return model; } + } private class DefaultRenderer implements Function> { @@ -181,5 +182,7 @@ private class DefaultRenderer implements Function apply(PathInputContext context) { return renderTemplateResource(context.toTemplateModel()); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/PathSearch.java b/spring-shell-core/src/main/java/org/springframework/shell/component/PathSearch.java index 577a5b06b..e6c22b650 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/PathSearch.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/PathSearch.java @@ -66,22 +66,25 @@ import static org.jline.keymap.KeyMap.key; /** - * Component resolving {@link Path} based on base path and optional search term. - * User is expected to type a base path and then delimited by space and a search - * term. + * Component resolving {@link Path} based on base path and optional search term. User is + * expected to type a base path and then delimited by space and a search term. * - * Based on algorithms i.e. from https://github.com/junegunn/fzf and other - * sources. + * Based on algorithms i.e. from https://github.com/junegunn/fzf and other sources. * * @author Janne Valkealahti */ public class PathSearch extends AbstractTextComponent { private final static Logger log = LoggerFactory.getLogger(PathSearch.class); + private final static String DEFAULT_TEMPLATE_LOCATION = "classpath:org/springframework/shell/component/path-search-default.stg"; + private final PathSearchConfig config; + private PathSearchContext currentContext; + private Function pathProvider = (path) -> Paths.get(path); + private final SelectorList selectorList; public PathSearch(Terminal terminal) { @@ -183,7 +186,6 @@ protected boolean read(BindingReader bindingReader, KeyMap keyMap, PathS /** * Sets a path provider. - * * @param pathProvider the path provider */ public void setPathProvider(Function pathProvider) { @@ -192,7 +194,6 @@ public void setPathProvider(Function pathProvider) { /** * Resolves a {@link Path} from a given raw {@code path}. - * * @param path the raw path * @return a resolved path */ @@ -207,11 +208,9 @@ private void inputUpdated(PathSearchContext context, String input) { } private void selectorListUpdated(PathSearchContext context) { - List pathViews = selectorList.getProjection().stream() - .map(i -> { - return new PathViewItem(i.getItem().getPath(), i.getItem().getPartsText(), i.isSelected()); - }) - .collect(Collectors.toList()); + List pathViews = selectorList.getProjection().stream().map(i -> { + return new PathViewItem(i.getItem().getPath(), i.getItem().getPartsText(), i.isSelected()); + }).collect(Collectors.toList()); context.setPathViewItems(pathViews); } @@ -222,26 +221,23 @@ private void updateSelectorList(String path, PathSearchContext context) { return; } PathScannerResult result = this.config.pathScanner.get().apply(path, context); - List items = result.getScoredPaths().stream() - .filter(scoredPath -> { - if (result.hasFilter()) { - return scoredPath.result.getScore() > 0; - } - else { - return true; - } - }) - .map(scoredPath -> { - int[] positions = scoredPath.getResult().getPositions(); - String text = scoredPath.getPath().toString(); - if (!StringUtils.hasText(text)) { - text = "."; - } - PartsText partsText = PathSearchContext.ofPositions(text, positions); - PathViewItem item = new PathViewItem(scoredPath.getPath(), partsText, false); - return item; - }) - .collect(Collectors.toList()); + List items = result.getScoredPaths().stream().filter(scoredPath -> { + if (result.hasFilter()) { + return scoredPath.result.getScore() > 0; + } + else { + return true; + } + }).map(scoredPath -> { + int[] positions = scoredPath.getResult().getPositions(); + String text = scoredPath.getPath().toString(); + if (!StringUtils.hasText(text)) { + text = "."; + } + PartsText partsText = PathSearchContext.ofPositions(text, positions); + PathViewItem item = new PathViewItem(scoredPath.getPath(), partsText, false); + return item; + }).collect(Collectors.toList()); long total = result.getDirCount() + result.getFileCount(); if (total > -1) { @@ -259,11 +255,17 @@ private void updateSelectorList(String path, PathSearchContext context) { public static class PathSearchConfig { private int maxPathsShow = 5; + private int maxPathsSearch = 20; + private boolean searchForward = true; + private boolean searchCaseSensitive = false; + private boolean searchNormalize = false; - private Supplier> pathScanner = () -> DefaultPathScanner.of(); + + private Supplier> pathScanner = () -> DefaultPathScanner + .of(); public int getMaxPathsShow() { return this.maxPathsShow; @@ -311,6 +313,7 @@ public boolean isSearchNormalize() { public void setSearchNormalize(boolean searchNormalize) { this.searchNormalize = searchNormalize; } + } /** @@ -319,8 +322,11 @@ public void setSearchNormalize(boolean searchNormalize) { public static class PathScannerResult { private final List scoredPaths; + private long dirCount = -1; + private long fileCount = -1; + private boolean hasFilter = false; PathScannerResult(List scoredPaths, long dirCount, long fileCount, boolean hasFilter) { @@ -335,7 +341,8 @@ public static PathScannerResult of(List scoredPaths, boolean hasFilt return new PathScannerResult(scoredPaths, -1, -1, hasFilter); } - public static PathScannerResult of(List scoredPaths, long dirCount, long fileCount, boolean hasFilter) { + public static PathScannerResult of(List scoredPaths, long dirCount, long fileCount, + boolean hasFilter) { return new PathScannerResult(scoredPaths, dirCount, fileCount, hasFilter); } @@ -354,6 +361,7 @@ public long getFileCount() { public boolean hasFilter() { return hasFilter; } + } /** @@ -363,35 +371,30 @@ public interface PathSearchContext extends TextComponentContext getPathViewItems(); /** * Sets a path view items. - * * @param items the path view items */ void setPathViewItems(List items); /** * Get path search config. - * * @return a path search config */ PathSearchConfig getPathSearchConfig(); /** * Sets a path search config. - * * @param config a path search config */ void setPathSearchConfig(PathSearchConfig config); /** * Gets an empty {@link PathSearchContext}. - * * @return empty path search context */ public static PathSearchContext empty() { @@ -405,7 +408,9 @@ public static PathSearchContext empty() { public static class PathViewItem implements Nameable { private Path path; + private PartsText partsText; + private boolean selected; public PathViewItem(Path path, PartsText partsText, boolean selected) { @@ -430,12 +435,11 @@ public boolean isSelected() { public PartsText getPartsText() { return partsText; } - } + } /** * Split given text into {@link PartText}'s by given positions. - * * @param text the text to split * @param positions the positions array, expected to be ordered and no duplicates * @return parts text @@ -497,12 +501,14 @@ else if (position == text.length() - 1) { } return parts; } + } private static class DefaultPathSearchContext extends BaseTextComponentContext implements PathSearchContext { private List pathViewItems; + private PathSearchConfig pathSearchConfig; @Override @@ -533,6 +539,7 @@ public Map toTemplateModel() { model.put("model", attributes); return model; } + } private class DefaultRenderer implements Function> { @@ -541,6 +548,7 @@ private class DefaultRenderer implements Function apply(PathSearchContext context) { return renderTemplateResource(context.toTemplateModel()); } + } /** @@ -549,6 +557,7 @@ public List apply(PathSearchContext context) { public static class ScoredPath implements Comparable { private final Path path; + private final SearchMatchResult result; ScoredPath(Path path, SearchMatchResult result) { @@ -577,6 +586,7 @@ public int compareTo(ScoredPath other) { } return scoreCompare; } + } private static class DefaultPathScanner implements BiFunction { @@ -593,7 +603,8 @@ public PathScannerResult apply(String input, PathSearchContext context) { String match = split.length == 2 ? split[1] : null; // walk files to find candidates - PathSearchPathVisitor visitor = new PathSearchPathVisitor(context.getPathSearchConfig().getMaxPathsSearch()); + PathSearchPathVisitor visitor = new PathSearchPathVisitor( + context.getPathSearchConfig().getMaxPathsSearch()); try { String p = split[0]; if (".".equals(p)) { @@ -604,28 +615,28 @@ public PathScannerResult apply(String input, PathSearchContext context) { Files.walkFileTree(path, visitor); log.debug("walked files {} dirs {}", visitor.getPathCounters().getFileCounter().get(), visitor.getPathCounters().getDirectoryCounter().get()); - } catch (Exception e) { + } + catch (Exception e) { log.debug("PathSearchPathVisitor caused exception", e); } // match and score candidates - Set treeSet = new HashSet(); - Stream.concat(visitor.getFileList().stream(), visitor.getDirList().stream()) - .forEach(p -> { - SearchMatchResult result; - if (StringUtils.hasText(match)) { - SearchMatch searchMatch = SearchMatch.builder() - .caseSensitive(context.getPathSearchConfig().isSearchCaseSensitive()) - .normalize(context.getPathSearchConfig().isSearchNormalize()) - .forward(context.getPathSearchConfig().searchForward) - .build(); - result = searchMatch.match(p.toString(), match); - } - else { - result = SearchMatchResult.ofMinus(); - } - treeSet.add(ScoredPath.of(p, result)); - }); + Set treeSet = new HashSet(); + Stream.concat(visitor.getFileList().stream(), visitor.getDirList().stream()).forEach(p -> { + SearchMatchResult result; + if (StringUtils.hasText(match)) { + SearchMatch searchMatch = SearchMatch.builder() + .caseSensitive(context.getPathSearchConfig().isSearchCaseSensitive()) + .normalize(context.getPathSearchConfig().isSearchNormalize()) + .forward(context.getPathSearchConfig().searchForward) + .build(); + result = searchMatch.match(p.toString(), match); + } + else { + result = SearchMatchResult.ofMinus(); + } + treeSet.add(ScoredPath.of(p, result)); + }); // sort and limit return treeSet.stream() @@ -635,15 +646,17 @@ public PathScannerResult apply(String input, PathSearchContext context) { list -> PathScannerResult.of(list, visitor.getPathCounters().getDirectoryCounter().get(), visitor.getPathCounters().getFileCounter().get(), StringUtils.hasText(match)))); } + } /** - * Extension to AccumulatorPathVisitor which allows to break out from scanning - * when enough results are found. + * Extension to AccumulatorPathVisitor which allows to break out from scanning when + * enough results are found. */ private static class PathSearchPathVisitor extends AccumulatorPathVisitor { private final int limitFiles; + private final static IOFileFilter DNFILTER = new NotFileFilter(new WildcardFileFilter(".*")); PathSearchPathVisitor(int limitFiles) { @@ -659,5 +672,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) thro } return result; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/SingleItemSelector.java b/spring-shell-core/src/main/java/org/springframework/shell/component/SingleItemSelector.java index dff5f6e17..43c148b1b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/SingleItemSelector.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/SingleItemSelector.java @@ -89,21 +89,18 @@ public interface SingleItemSelectorContext getResultItem(); /** * Gets a value. - * * @return a value */ Optional getValue(); /** * Creates an empty {@link SingleItemSelectorContext}. - * * @return empty context */ static > SingleItemSelectorContext empty() { @@ -112,16 +109,18 @@ static > SingleItemSelectorConte /** * Creates a {@link SingleItemSelectorContext}. - * * @return context */ - static > SingleItemSelectorContext empty(Function itemMapper) { + static > SingleItemSelectorContext empty( + Function itemMapper) { return new DefaultSingleItemSelectorContext<>(itemMapper); } + } - private static class DefaultSingleItemSelectorContext> extends - BaseSelectorComponentContext> implements SingleItemSelectorContext { + private static class DefaultSingleItemSelectorContext> + extends BaseSelectorComponentContext> + implements SingleItemSelectorContext { private Function itemMapper = item -> item.toString(); @@ -151,14 +150,12 @@ public Map toTemplateModel() { getValue().ifPresent(value -> { attributes.put("value", value); }); - List> rows = getItemStateView().stream() - .map(is -> { - Map map = new HashMap<>(); - map.put("name", is.getName()); - map.put("selected", getCursorRow().intValue() == is.getIndex()); - return map; - }) - .collect(Collectors.toList()); + List> rows = getItemStateView().stream().map(is -> { + Map map = new HashMap<>(); + map.put("name", is.getName()); + map.put("selected", getCursorRow().intValue() == is.getIndex()); + return map; + }).collect(Collectors.toList()); attributes.put("rows", rows); // finally wrap it into 'model' as that's what // we expect in stg template. @@ -171,6 +168,7 @@ public Map toTemplateModel() { public String toString() { return "DefaultSingleItemSelectorContext [super=" + super.toString() + "]"; } + } private class DefaultRenderer implements Function, List> { @@ -179,5 +177,7 @@ private class DefaultRenderer implements Function apply(SingleItemSelectorContext context) { return renderTemplateResource(context.toTemplateModel()); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java index 5a972c1bb..00c5d1510 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/StringInput.java @@ -41,8 +41,11 @@ public class StringInput extends AbstractTextComponent { private final static Logger log = LoggerFactory.getLogger(StringInput.class); + private final String defaultValue; + private StringInputContext currentContext; + private Character maskCharacter; public StringInput(Terminal terminal) { @@ -63,7 +66,6 @@ public StringInput(Terminal terminal, String name, String defaultValue, /** * Sets a mask character for input and result value. - * * @param maskCharacter a mask character */ public void setMaskCharacter(Character maskCharacter) { @@ -131,56 +133,48 @@ public interface StringInputContext extends TextComponentContext implements StringInputContext { private String defaultValue; + private Character maskCharacter; public DefaultStringInputContext(String defaultValue, Character maskCharacter) { @@ -264,6 +259,7 @@ private String maybeMask(String str) { return str; } } + } private class DefaultRenderer implements Function> { @@ -272,5 +268,7 @@ private class DefaultRenderer implements Function apply(StringInputContext context) { return renderTemplateResource(context.toTemplateModel()); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponent.java index ce30d32b6..ae71eabbf 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponent.java @@ -36,16 +36,21 @@ public class ViewComponent { private final static Logger log = LoggerFactory.getLogger(ViewComponent.class); + private final Terminal terminal; + private final View view; + private EventLoop eventLoop; + private TerminalUI terminalUI; + private boolean useTerminalWidth = true; + private ViewComponentExecutor viewComponentExecutor; /** * Construct view component with a given {@link Terminal} and {@link View}. - * * @param terminal the terminal * @param view the main view */ @@ -63,9 +68,8 @@ public ViewComponent(TerminalUI terminalUI, Terminal terminal, ViewComponentExec } /** - * Run a component asyncronously. Returned state can be used to wait, cancel or - * see its completion status. - * + * Run a component asyncronously. Returned state can be used to wait, cancel or see + * its completion status. * @return run state */ public ViewComponentRun runAsync() { @@ -80,11 +84,9 @@ public ViewComponentRun runAsync() { */ public void runBlocking() { log.debug("Start run()"); - eventLoop.onDestroy(eventLoop.viewEvents(ViewDoneEvent.class, view) - .subscribe(event -> { - exit(); - } - )); + eventLoop.onDestroy(eventLoop.viewEvents(ViewDoneEvent.class, view).subscribe(event -> { + exit(); + })); view.setEventLoop(eventLoop); Size terminalSize = terminal.getSize(); Rectangle rect = view.getRect(); @@ -98,7 +100,6 @@ public void runBlocking() { /** * Sets if full terminal width should be used for a view. Defaults to {@code true}. - * * @param useTerminalWidth the use terminal width flag */ public void setUseTerminalWidth(boolean useTerminalWidth) { @@ -107,7 +108,6 @@ public void setUseTerminalWidth(boolean useTerminalWidth) { /** * Gets an {@link EventLoop} associated with this view component. - * * @return event loop with this view component */ public EventLoop getEventLoop() { @@ -137,9 +137,8 @@ public interface ViewComponentRun { void cancel(); /** - * Returns {@code true} if component run has completed. - * - * @return {@code true} if component run has completed + * Returns {@code true} if component run has completed. + * @return {@code true} if component run has completed */ boolean isDone(); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentBuilder.java b/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentBuilder.java index db5d94fff..4ffa2294f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentBuilder.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentBuilder.java @@ -28,7 +28,9 @@ public class ViewComponentBuilder { private final TerminalUIBuilder terminalUIBuilder; + private final ViewComponentExecutor viewComponentExecutor; + private final Terminal terminal; public ViewComponentBuilder(TerminalUIBuilder terminalUIBuilder, ViewComponentExecutor viewComponentExecutor, @@ -40,7 +42,6 @@ public ViewComponentBuilder(TerminalUIBuilder terminalUIBuilder, ViewComponentEx /** * Build a new {@link ViewComponent} instance and configure it using this builder. - * * @param view the view to use with view component * @return a configured {@link ViewComponent} instance. */ diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentExecutor.java b/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentExecutor.java index c42c98609..19870844a 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentExecutor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/ViewComponentExecutor.java @@ -25,15 +25,17 @@ import org.springframework.shell.component.ViewComponent.ViewComponentRun; /** - * Executor for {@code ViewComponent}. Purpose of this executor is to run - * component in a thread so that it doesn't need to block from a command. + * Executor for {@code ViewComponent}. Purpose of this executor is to run component in a + * thread so that it doesn't need to block from a command. * * @author Janne Valkealahti */ public class ViewComponentExecutor implements AutoCloseable { private final Logger log = LoggerFactory.getLogger(ViewComponentExecutor.class); + private final SimpleAsyncTaskExecutor executor; + private Future future; public ViewComponentExecutor() { @@ -57,8 +59,10 @@ private FutureViewComponentRun(Future future) { public void await() { try { this.future.get(); - } catch (InterruptedException e) { - } catch (ExecutionException e) { + } + catch (InterruptedException e) { + } + catch (ExecutionException e) { } } @@ -76,7 +80,6 @@ public boolean isDone() { /** * Execute runnable and return state which can be used for further operations. - * * @param runnable the runnable * @return run state */ @@ -93,8 +96,7 @@ public ViewComponentRun start(Runnable runnable) { } /** - * Stop a {@code ViewComponent} which has been previously started with this - * executor. + * Stop a {@code ViewComponent} which has been previously started with this executor. */ public void stop() { if (future != null) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/context/BaseComponentContext.java b/spring-shell-core/src/main/java/org/springframework/shell/component/context/BaseComponentContext.java index c8c04f37d..d8a1ab549 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/context/BaseComponentContext.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/context/BaseComponentContext.java @@ -45,8 +45,8 @@ public Object get(Object key) { public T get(Object key, Class type) { Object value = get(key); if (!type.isAssignableFrom(value.getClass())) { - throw new IllegalArgumentException("Incorrect type specified for key '" + - key + "'. Expected [" + type + "] but actual type is [" + value.getClass() + "]"); + throw new IllegalArgumentException("Incorrect type specified for key '" + key + "'. Expected [" + type + + "] but actual type is [" + value.getClass() + "]"); } return (T) value; } @@ -86,4 +86,5 @@ public Map toTemplateModel() { public String toString() { return "BaseComponentContext [terminalWidth=" + terminalWidth + "]"; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/context/ComponentContext.java b/spring-shell-core/src/main/java/org/springframework/shell/component/context/ComponentContext.java index 082e20e5e..35f42c508 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/context/ComponentContext.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/context/ComponentContext.java @@ -19,9 +19,9 @@ import java.util.stream.Stream; /** - * Contract for base component context having access to basic key/value pairs. - * This is a base context which components can extend to provide their own - * component spesific contexts. + * Contract for base component context having access to basic key/value pairs. This is a + * base context which components can extend to provide their own component spesific + * contexts. * * @author Janne Valkealahti */ @@ -29,7 +29,6 @@ public interface ComponentContext> { /** * Gets an empty context. - * * @param the type of context * @return empty context */ @@ -39,7 +38,6 @@ static > ComponentContext empty() { /** * Gets a value from a context. - * * @param the type of context * @param key the key * @return a value @@ -48,7 +46,6 @@ static > ComponentContext empty() { /** * Gets a value from a context with a given type to get cast to. - * * @param the type of context * @param key the key * @param type the class type @@ -58,7 +55,6 @@ static > ComponentContext empty() { /** * Check if a context contains a key. - * * @param key the key * @return true if context contains key */ @@ -66,7 +62,6 @@ static > ComponentContext empty() { /** * Put an entry into a context. - * * @param key the entry key * @param value the entry value * @return a context @@ -75,32 +70,28 @@ static > ComponentContext empty() { /** * Stream key/value pairs from this {@link ComponentContext} - * * @return a {@link Stream} of key/value pairs held by this context */ Stream> stream(); /** * Get terminal width. - * * @return a terminal width */ Integer getTerminalWidth(); /** * Set terminal width. - * * @param terminalWidth the width */ void setTerminalWidth(Integer terminalWidth); /** - * Gets context values as a map. Every context implementation can - * do their own model as essentially what matter is a one coming - * out from a last child which is one most likely to feed into - * a template engine. - * + * Gets context values as a map. Every context implementation can do their own model + * as essentially what matter is a one coming out from a last child which is one most + * likely to feed into a template engine. * @return map of context values */ Map toTemplateModel(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java index f92ec594d..4e207bda5 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseConfirmationInput.java @@ -34,14 +34,23 @@ public abstract class BaseConfirmationInput extends BaseInput implements ConfirmationInputSpec { private String name; + private Boolean defaultValue; + private Boolean resultValue; + private ResultMode resultMode; + private Function> renderer; + private List> preHandlers = new ArrayList<>(); + private List> postHandlers = new ArrayList<>(); + private boolean storeResult = true; + private String templateLocation; + private Function next; public BaseConfirmationInput(BaseBuilder builder, String id) { @@ -158,4 +167,5 @@ public boolean isStoreResult() { public Function getNext() { return next; } + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInput.java index 6b00f130f..310b22a19 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInput.java @@ -26,7 +26,9 @@ public abstract class BaseInput> implements Ordered, BaseInputSpec { private final BaseBuilder builder; + private final String id; + private int order; BaseInput(BaseBuilder builder, String id) { @@ -56,4 +58,5 @@ public BaseBuilder getBuilder() { public String getId() { return id; } + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInputSpec.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInputSpec.java index 5d01f5ba0..73000c9b1 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInputSpec.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseInputSpec.java @@ -24,7 +24,6 @@ public interface BaseInputSpec> { /** * Sets order of this component. - * * @param order the order * @return a builder */ @@ -32,8 +31,8 @@ public interface BaseInputSpec> { /** * Usual this trick to get typed child. - * * @return a builder */ T getThis(); + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseMultiItemSelector.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseMultiItemSelector.java index a9c4a050f..5fd164203 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseMultiItemSelector.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseMultiItemSelector.java @@ -36,16 +36,27 @@ public abstract class BaseMultiItemSelector extends BaseInput implements MultiItemSelectorSpec { private String name; + private List resultValues = new ArrayList<>(); + private ResultMode resultMode; + private List selectItems = new ArrayList<>(); + private Comparator> comparator; + private Function>, List> renderer; + private Integer maxItems; + private List>>> preHandlers = new ArrayList<>(); + private List>>> postHandlers = new ArrayList<>(); + private boolean storeResult = true; + private String templateLocation; + private Function>, String> next; public BaseMultiItemSelector(BaseBuilder builder, String id) { @@ -83,7 +94,8 @@ public MultiItemSelectorSpec sort(Comparator> comparator) { } @Override - public MultiItemSelectorSpec renderer(Function>, List> renderer) { + public MultiItemSelectorSpec renderer( + Function>, List> renderer) { this.renderer = renderer; return this; } @@ -119,8 +131,7 @@ public MultiItemSelectorSpec storeResult(boolean store) { } @Override - public MultiItemSelectorSpec next( - Function>, String> next) { + public MultiItemSelectorSpec next(Function>, String> next) { this.next = next; return this; } @@ -183,4 +194,5 @@ public boolean isStoreResult() { public Function>, String> getNext() { return next; } + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BasePathInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BasePathInput.java index 8af011408..774e4fd1b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BasePathInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BasePathInput.java @@ -34,14 +34,23 @@ public abstract class BasePathInput extends BaseInput implements PathInputSpec { private String name; + private String resultValue; + private ResultMode resultMode; + private String defaultValue; + private Function> renderer; + private List> preHandlers = new ArrayList<>(); + private List> postHandlers = new ArrayList<>(); + private boolean storeResult = true; + private String templateLocation; + private Function next; public BasePathInput(BaseBuilder builder, String id) { @@ -158,4 +167,5 @@ public boolean isStoreResult() { public Function getNext() { return next; } + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseSingleItemSelector.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseSingleItemSelector.java index 7866c5895..8cd0337d6 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseSingleItemSelector.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseSingleItemSelector.java @@ -36,20 +36,33 @@ * * @author Janne Valkealahti */ -public abstract class BaseSingleItemSelector extends BaseInput implements SingleItemSelectorSpec { +public abstract class BaseSingleItemSelector extends BaseInput + implements SingleItemSelectorSpec { private String name; + private String resultValue; + private ResultMode resultMode; + private List selectItems = new ArrayList<>(); + private String defaultSelect; + private Comparator> comparator; + private Function>, List> renderer; + private Integer maxItems; + private List>>> preHandlers = new ArrayList<>(); + private List>>> postHandlers = new ArrayList<>(); + private boolean storeResult = true; + private String templateLocation; + private Function>, String> next; public BaseSingleItemSelector(BaseBuilder builder, String id) { @@ -83,10 +96,11 @@ public SingleItemSelectorSpec selectItem(String name, String item) { @Override public SingleItemSelectorSpec selectItems(Map selectItems) { // TODO: we changed to keep items as SelectItem's, to try to keep old sorting - // behaviour we go via HashMap gh-946. Later we should remove this step. + // behaviour we go via HashMap gh-946. Later we should remove this step. Map selectItemsMap = new HashMap<>(); selectItemsMap.putAll(selectItems); - List items = selectItemsMap.entrySet().stream() + List items = selectItemsMap.entrySet() + .stream() .map(e -> SelectItem.of(e.getKey(), e.getValue())) .collect(Collectors.toList()); selectItems(items); @@ -112,7 +126,8 @@ public SingleItemSelectorSpec sort(Comparator> comparator) } @Override - public SingleItemSelectorSpec renderer(Function>, List> renderer) { + public SingleItemSelectorSpec renderer( + Function>, List> renderer) { this.renderer = renderer; return this; } @@ -130,13 +145,15 @@ public SingleItemSelectorSpec max(int max) { } @Override - public SingleItemSelectorSpec preHandler(Consumer>> handler) { + public SingleItemSelectorSpec preHandler( + Consumer>> handler) { this.preHandlers.add(handler); return this; } @Override - public SingleItemSelectorSpec postHandler(Consumer>> handler) { + public SingleItemSelectorSpec postHandler( + Consumer>> handler) { this.postHandlers.add(handler); return this; } @@ -148,8 +165,7 @@ public SingleItemSelectorSpec storeResult(boolean store) { } @Override - public SingleItemSelectorSpec next( - Function>, String> next) { + public SingleItemSelectorSpec next(Function>, String> next) { this.next = next; return this; } @@ -216,4 +232,5 @@ public boolean isStoreResult() { public Function>, String> getNext() { return next; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java index 14e165466..6924202ba 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/BaseStringInput.java @@ -34,15 +34,25 @@ public abstract class BaseStringInput extends BaseInput implements StringInputSpec { private String name; + private String resultValue; + private ResultMode resultMode; + private String defaultValue; + private Character maskCharacter; + private Function> renderer; + private List> preHandlers = new ArrayList<>(); + private List> postHandlers = new ArrayList<>(); + private boolean storeResult = true; + private String templateLocation; + private Function next; public BaseStringInput(BaseBuilder builder, String id) { @@ -169,4 +179,5 @@ public boolean isStoreResult() { public Function getNext() { return next; } + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java index b7a663e91..6497503c4 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ComponentFlow.java @@ -62,14 +62,12 @@ public interface ComponentFlow { /** * Run a wizard and returns a result from it. - * * @return the input wizard result */ ComponentFlowResult run(); /** * Gets a new instance of an input wizard builder. - * * @return the input wizard builder */ public static Builder builder() { @@ -83,10 +81,10 @@ interface ComponentFlowResult { /** * Gets a context. - * * @return a context */ ComponentContext getContext(); + } /** @@ -96,7 +94,6 @@ interface Builder { /** * Gets a builder for string input. - * * @param id the identifier * @return builder for string input */ @@ -104,7 +101,6 @@ interface Builder { /** * Gets a builder for path input. - * * @param id the identifier * @return builder for text input */ @@ -112,7 +108,6 @@ interface Builder { /** * Gets a builder for confirmation input. - * * @param id the identifier * @return builder for text input */ @@ -120,7 +115,6 @@ interface Builder { /** * Gets a builder for single item selector. - * * @param id the identifier * @return builder for single item selector */ @@ -128,7 +122,6 @@ interface Builder { /** * Gets a builder for multi item selector. - * * @param id the identifier * @return builder for multi item selector */ @@ -136,7 +129,6 @@ interface Builder { /** * Sets a {@link Terminal}. - * * @param terminal the terminal * @return a builder */ @@ -144,7 +136,6 @@ interface Builder { /** * Sets a {@link ResourceLoader}. - * * @param resourceLoader the resource loader * @return a builder */ @@ -152,7 +143,6 @@ interface Builder { /** * Sets a {@link TemplateExecutor}. - * * @param templateExecutor the template executor * @return a builder */ @@ -160,37 +150,44 @@ interface Builder { /** * Clones existing builder. - * * @return a builder */ Builder clone(); /** * Resets existing builder. - * * @return a builder */ Builder reset(); /** * Builds instance of input wizard. - * * @return instance of input wizard */ ComponentFlow build(); + } static abstract class BaseBuilder implements Builder { private final List stringInputs = new ArrayList<>(); + private final List pathInputs = new ArrayList<>(); + private final List confirmationInputs = new ArrayList<>(); + private final List singleItemSelectors = new ArrayList<>(); + private final List multiItemSelectors = new ArrayList<>(); + private final AtomicInteger order = new AtomicInteger(); + private final HashSet uniqueIds = new HashSet<>(); + private Terminal terminal; + private ResourceLoader resourceLoader; + private TemplateExecutor templateExecutor; BaseBuilder() { @@ -310,6 +307,7 @@ private void checkUniqueId(String id) { } uniqueIds.add(id); } + } static class DefaultBuilder extends BaseBuilder { @@ -323,6 +321,7 @@ static class DefaultBuilder extends BaseBuilder { resourceLoader(other.getResourceLoader()); templateExecutor(other.getTemplateExecutor()); } + } static class DefaultComponentFlowResult implements ComponentFlowResult { @@ -336,23 +335,33 @@ static class DefaultComponentFlowResult implements ComponentFlowResult { public ComponentContext getContext() { return context; } + } static class DefaultComponentFlow implements ComponentFlow { private static final Logger log = LoggerFactory.getLogger(DefaultComponentFlow.class); + private final Terminal terminal; + private final List stringInputs; + private final List pathInputs; + private final List confirmationInputs; + private final List singleInputs; + private final List multiInputs; + private final ResourceLoader resourceLoader; + private final TemplateExecutor templateExecutor; DefaultComponentFlow(Terminal terminal, ResourceLoader resourceLoader, TemplateExecutor templateExecutor, - List stringInputs, List pathInputs, List confirmationInputs, - List singleInputs, List multiInputs) { + List stringInputs, List pathInputs, + List confirmationInputs, List singleInputs, + List multiInputs) { this.terminal = terminal; this.resourceLoader = resourceLoader; this.templateExecutor = templateExecutor; @@ -371,6 +380,7 @@ public ComponentFlowResult run() { private static class OrderedInputOperationList { private final Map map = new HashMap<>(); + private Node first; OrderedInputOperationList(List values) { @@ -397,18 +407,23 @@ Node getFirst() { } static class Node { + OrderedInputOperation data; + Node next; + Node(OrderedInputOperation data) { this.data = data; } + } + } private DefaultComponentFlowResult runGetResults() { List oios = Stream - .of(stringInputsStream(), pathInputsStream(), confirmationInputsStream(), - singleItemSelectorsStream(), multiItemSelectorsStream()) + .of(stringInputsStream(), pathInputsStream(), confirmationInputsStream(), singleItemSelectorsStream(), + multiItemSelectorsStream()) .flatMap(oio -> oio) .sorted(OrderComparator.INSTANCE) .collect(Collectors.toList()); @@ -447,42 +462,41 @@ private Stream stringInputsStream() { return stringInputs.stream().map(input -> { StringInput selector = new StringInput(terminal, input.getName(), input.getDefaultValue()); Function, ComponentContext> operation = (context) -> { - if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() - && StringUtils.hasText(input.getResultValue())) { - context.put(input.getId(), input.getResultValue()); - return context; - } - selector.setResourceLoader(resourceLoader); - selector.setTemplateExecutor(templateExecutor); - selector.setMaskCharacter(input.getMaskCharacter()); - if (StringUtils.hasText(input.getTemplateLocation())) { - selector.setTemplateLocation(input.getTemplateLocation()); - } - if (input.getRenderer() != null) { - selector.setRenderer(input.getRenderer()); - } - if (input.isStoreResult()) { - if (input.getResultMode() == ResultMode.VERIFY && StringUtils.hasText(input.getResultValue())) { - selector.addPreRunHandler(c -> { - c.setDefaultValue(input.getResultValue()); - }); - } - selector.addPostRunHandler(c -> { - c.put(input.getId(), c.getResultValue()); + if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() + && StringUtils.hasText(input.getResultValue())) { + context.put(input.getId(), input.getResultValue()); + return context; + } + selector.setResourceLoader(resourceLoader); + selector.setTemplateExecutor(templateExecutor); + selector.setMaskCharacter(input.getMaskCharacter()); + if (StringUtils.hasText(input.getTemplateLocation())) { + selector.setTemplateLocation(input.getTemplateLocation()); + } + if (input.getRenderer() != null) { + selector.setRenderer(input.getRenderer()); + } + if (input.isStoreResult()) { + if (input.getResultMode() == ResultMode.VERIFY && StringUtils.hasText(input.getResultValue())) { + selector.addPreRunHandler(c -> { + c.setDefaultValue(input.getResultValue()); }); } - for (Consumer handler : input.getPreHandlers()) { - selector.addPreRunHandler(handler); - } - for (Consumer handler : input.getPostHandlers()) { - selector.addPostRunHandler(handler); - } - return selector.run(context); + selector.addPostRunHandler(c -> { + c.put(input.getId(), c.getResultValue()); + }); + } + for (Consumer handler : input.getPreHandlers()) { + selector.addPreRunHandler(handler); + } + for (Consumer handler : input.getPostHandlers()) { + selector.addPostRunHandler(handler); + } + return selector.run(context); }; Function f1 = input.getNext(); Function, Optional> f2 = context -> f1 != null - ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) - : null; + ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) : null; return OrderedInputOperation.of(input.getId(), input.getOrder(), operation, f2); }); } @@ -491,36 +505,35 @@ private Stream pathInputsStream() { return pathInputs.stream().map(input -> { PathInput selector = new PathInput(terminal, input.getName()); Function, ComponentContext> operation = (context) -> { - if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() - && StringUtils.hasText(input.getResultValue())) { - context.put(input.getId(), Paths.get(input.getResultValue())); - return context; - } - selector.setResourceLoader(resourceLoader); - selector.setTemplateExecutor(templateExecutor); - if (StringUtils.hasText(input.getTemplateLocation())) { - selector.setTemplateLocation(input.getTemplateLocation()); - } - if (input.getRenderer() != null) { - selector.setRenderer(input.getRenderer()); - } - if (input.isStoreResult()) { - selector.addPostRunHandler(c -> { - c.put(input.getId(), c.getResultValue()); - }); - } - for (Consumer handler : input.getPreHandlers()) { - selector.addPreRunHandler(handler); - } - for (Consumer handler : input.getPostHandlers()) { - selector.addPostRunHandler(handler); - } - return selector.run(context); + if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() + && StringUtils.hasText(input.getResultValue())) { + context.put(input.getId(), Paths.get(input.getResultValue())); + return context; + } + selector.setResourceLoader(resourceLoader); + selector.setTemplateExecutor(templateExecutor); + if (StringUtils.hasText(input.getTemplateLocation())) { + selector.setTemplateLocation(input.getTemplateLocation()); + } + if (input.getRenderer() != null) { + selector.setRenderer(input.getRenderer()); + } + if (input.isStoreResult()) { + selector.addPostRunHandler(c -> { + c.put(input.getId(), c.getResultValue()); + }); + } + for (Consumer handler : input.getPreHandlers()) { + selector.addPreRunHandler(handler); + } + for (Consumer handler : input.getPostHandlers()) { + selector.addPostRunHandler(handler); + } + return selector.run(context); }; Function f1 = input.getNext(); Function, Optional> f2 = context -> f1 != null - ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) - : null; + ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) : null; return OrderedInputOperation.of(input.getId(), input.getOrder(), operation, f2); }); } @@ -529,51 +542,50 @@ private Stream confirmationInputsStream() { return confirmationInputs.stream().map(input -> { ConfirmationInput selector = new ConfirmationInput(terminal, input.getName(), input.getDefaultValue()); Function, ComponentContext> operation = (context) -> { - if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() - && input.getResultValue() != null) { - context.put(input.getId(), input.getResultValue()); - return context; - } - selector.setResourceLoader(resourceLoader); - selector.setTemplateExecutor(templateExecutor); - if (StringUtils.hasText(input.getTemplateLocation())) { - selector.setTemplateLocation(input.getTemplateLocation()); - } - if (input.getRenderer() != null) { - selector.setRenderer(input.getRenderer()); - } - if (input.isStoreResult()) { - selector.addPostRunHandler(c -> { - c.put(input.getId(), c.getResultValue()); - }); - } - for (Consumer handler : input.getPreHandlers()) { - selector.addPreRunHandler(handler); - } - for (Consumer handler : input.getPostHandlers()) { - selector.addPostRunHandler(handler); - } - return selector.run(context); + if (input.getResultMode() == ResultMode.ACCEPT && input.isStoreResult() + && input.getResultValue() != null) { + context.put(input.getId(), input.getResultValue()); + return context; + } + selector.setResourceLoader(resourceLoader); + selector.setTemplateExecutor(templateExecutor); + if (StringUtils.hasText(input.getTemplateLocation())) { + selector.setTemplateLocation(input.getTemplateLocation()); + } + if (input.getRenderer() != null) { + selector.setRenderer(input.getRenderer()); + } + if (input.isStoreResult()) { + selector.addPostRunHandler(c -> { + c.put(input.getId(), c.getResultValue()); + }); + } + for (Consumer handler : input.getPreHandlers()) { + selector.addPreRunHandler(handler); + } + for (Consumer handler : input.getPostHandlers()) { + selector.addPostRunHandler(handler); + } + return selector.run(context); }; Function f1 = input.getNext(); Function, Optional> f2 = context -> f1 != null - ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) - : null; + ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) : null; return OrderedInputOperation.of(input.getId(), input.getOrder(), operation, f2); }); } private Stream singleItemSelectorsStream() { return singleInputs.stream().map(input -> { - List> selectorItems = input.getSelectItems().stream() - .map(si -> SelectorItem.of(si.name(), si.item())) - .collect(Collectors.toList()); + List> selectorItems = input.getSelectItems() + .stream() + .map(si -> SelectorItem.of(si.name(), si.item())) + .collect(Collectors.toList()); // setup possible item for initial expose String defaultSelect = input.getDefaultSelect(); Stream> defaultCheckStream = StringUtils.hasText(defaultSelect) - ? selectorItems.stream() - : Stream.empty(); + ? selectorItems.stream() : Stream.empty(); SelectorItem defaultExpose = defaultCheckStream .filter(si -> ObjectUtils.nullSafeEquals(defaultSelect, si.getName())) .findFirst() @@ -606,27 +618,29 @@ private Stream singleItemSelectorsStream() { }); }); } - for (Consumer>> handler : input.getPreHandlers()) { + for (Consumer>> handler : input + .getPreHandlers()) { selector.addPreRunHandler(handler); } - for (Consumer>> handler : input.getPostHandlers()) { + for (Consumer>> handler : input + .getPostHandlers()) { selector.addPostRunHandler(handler); } return selector.run(context); }; Function>, String> f1 = input.getNext(); Function, Optional> f2 = context -> f1 != null - ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) - : null; + ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) : null; return OrderedInputOperation.of(input.getId(), input.getOrder(), operation, f2); }); } private Stream multiItemSelectorsStream() { return multiInputs.stream().map(input -> { - List> selectorItems = input.getSelectItems().stream() - .map(si -> SelectorItem.of(si.name(), si.item(), si.enabled(), si.selected())) - .collect(Collectors.toList()); + List> selectorItems = input.getSelectItems() + .stream() + .map(si -> SelectorItem.of(si.name(), si.item(), si.enabled(), si.selected())) + .collect(Collectors.toList()); MultiItemSelector> selector = new MultiItemSelector<>(terminal, selectorItems, input.getName(), input.getComparator()); Function, ComponentContext> operation = (context) -> { @@ -651,28 +665,33 @@ private Stream multiItemSelectorsStream() { c.put(input.getId(), c.getValues()); }); } - for (Consumer>> handler : input.getPreHandlers()) { + for (Consumer>> handler : input + .getPreHandlers()) { selector.addPreRunHandler(handler); } - for (Consumer>> handler : input.getPostHandlers()) { + for (Consumer>> handler : input + .getPostHandlers()) { selector.addPostRunHandler(handler); } return selector.run(context); }; Function>, String> f1 = input.getNext(); Function, Optional> f2 = context -> f1 != null - ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) - : null; + ? Optional.ofNullable(f1.apply(selector.getThisContext(context))) : null; return OrderedInputOperation.of(input.getId(), input.getOrder(), operation, f2); }); } + } static class OrderedInputOperation implements Ordered { private String id; + private int order; + private Function, ComponentContext> operation; + private Function, Optional> next; @Override @@ -702,5 +721,7 @@ static OrderedInputOperation of(String id, int order, oio.next = next; return oio; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java index d7f449012..d8087eaf0 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ConfirmationInputSpec.java @@ -34,14 +34,13 @@ public interface ConfirmationInputSpec extends BaseInputSpec{ +public interface MultiItemSelectorSpec extends BaseInputSpec { /** * Sets a name. - * * @param name the name * @return a builder */ @@ -44,7 +43,6 @@ public interface MultiItemSelectorSpec extends BaseInputSpec>, List> renderer); + MultiItemSelectorSpec renderer( + Function>, List> renderer); /** * Sets a default renderer template location. - * * @param location the template location * @return a builder */ @@ -92,7 +86,6 @@ public interface MultiItemSelectorSpec extends BaseInputSpec { /** * Sets a name. - * * @param name the name * @return a builder */ @@ -43,7 +42,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Sets a result value. - * * @param resultValue the result value * @return a builder */ @@ -51,7 +49,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Sets a result mode. - * * @param resultMode the result mode * @return a builder */ @@ -59,7 +56,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Sets a default value. - * * @param defaultValue the defult value * @return a builder */ @@ -67,7 +63,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Sets a renderer function. - * * @param renderer the renderer * @return a builder */ @@ -75,7 +70,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Sets a default renderer template location. - * * @param location the template location * @return a builder */ @@ -83,7 +77,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Adds a pre-run context handler. - * * @param handler the context handler * @return a builder */ @@ -91,7 +84,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Adds a post-run context handler. - * * @param handler the context handler * @return a builder */ @@ -100,7 +92,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Automatically stores result from a {@link StringInputContext} into * {@link ComponentContext} with key given to builder. Defaults to {@code true}. - * * @param store the flag if storing result * @return a builder */ @@ -109,7 +100,6 @@ public interface PathInputSpec extends BaseInputSpec { /** * Define a function which may return id of a next component to go. Returning a * {@code null} or non existent id indicates that flow should stop. - * * @param next next component function * @return a builder */ @@ -117,8 +107,8 @@ public interface PathInputSpec extends BaseInputSpec { /** * Build and return parent builder. - * * @return the parent builder */ Builder and(); + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ResultMode.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ResultMode.java index 735b5178c..3a0d97964 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ResultMode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/ResultMode.java @@ -23,15 +23,16 @@ public enum ResultMode { /** - * Blindly accept a given {@code resultValue} resulting component run to be - * skipped and value set as a result automatically. + * Blindly accept a given {@code resultValue} resulting component run to be skipped + * and value set as a result automatically. */ ACCEPT, /** - * Verify a given {@code resultValue} with a component run. It is up to a - * component to define how it's done but usually result value is set as a - * default value which allows user to just continue. + * Verify a given {@code resultValue} with a component run. It is up to a component to + * define how it's done but usually result value is set as a default value which + * allows user to just continue. */ VERIFY + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SelectItem.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SelectItem.java index 436db2850..87b2a8906 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SelectItem.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SelectItem.java @@ -24,28 +24,24 @@ public interface SelectItem { /** * Gets a name. - * * @return a name */ String name(); /** * Gets an item - * * @return an item */ String item(); /** * Returns if item is enabled. - * * @return if item is enabled */ boolean enabled(); /** * Return if the item is selected. - * * @return if item is selected */ boolean selected(); @@ -57,4 +53,5 @@ public static SelectItem of(String name, String item) { public static SelectItem of(String name, String item, boolean enabled, boolean selected) { return new DefaultSelectItem(name, item, enabled, selected); } + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SingleItemSelectorSpec.java b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SingleItemSelectorSpec.java index c57b713d8..386e23c03 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SingleItemSelectorSpec.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/flow/SingleItemSelectorSpec.java @@ -37,7 +37,6 @@ public interface SingleItemSelectorSpec extends BaseInputSpec>, List> renderer); + SingleItemSelectorSpec renderer( + Function>, List> renderer); /** * Sets a default renderer template location. - * * @param location the template location * @return a builder */ @@ -120,7 +111,6 @@ public interface SingleItemSelectorSpec extends BaseInputSpec { /** * Sets a name. - * * @param name the name * @return a builder */ @@ -42,7 +41,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Sets a result value. - * * @param resultValue the result value * @return a builder */ @@ -50,7 +48,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Sets a result mode. - * * @param resultMode the result mode * @return a builder */ @@ -58,7 +55,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Sets a default value. - * * @param defaultValue the defult value * @return a builder */ @@ -66,7 +62,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Sets a mask character. - * * @param maskCharacter the mask character * @return a builder */ @@ -74,7 +69,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Sets a renderer function. - * * @param renderer the renderer * @return a builder */ @@ -82,7 +76,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Sets a default renderer template location. - * * @param location the template location * @return a builder */ @@ -90,7 +83,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Adds a pre-run context handler. - * * @param handler the context handler * @return a builder */ @@ -98,7 +90,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Adds a post-run context handler. - * * @param handler the context handler * @return a builder */ @@ -107,7 +98,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Automatically stores result from a {@link StringInputContext} into * {@link ComponentContext} with key given to builder. Defaults to {@code true}. - * * @param store the flag if storing result * @return a builder */ @@ -116,7 +106,6 @@ public interface StringInputSpec extends BaseInputSpec { /** * Define a function which may return id of a next component to go. Returning a * {@code null} or non existent id indicates that flow should stop. - * * @param next next component function * @return a builder */ @@ -124,8 +113,8 @@ public interface StringInputSpec extends BaseInputSpec { /** * Build and return parent builder. - * * @return the parent builder */ Builder and(); + } \ No newline at end of file diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageBuilder.java b/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageBuilder.java index 58b1c4811..20be07907 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageBuilder.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageBuilder.java @@ -28,30 +28,29 @@ * Shell spesific message builder. * * @param the payload type. - * * @author Janne Valkealahti */ public final class ShellMessageBuilder { private final T payload; + private final ShellMessageHeaderAccessor headerAccessor; + @Nullable private final Message originalMessage; - private ShellMessageBuilder(T payload, @Nullable Message originalMessage) { Assert.notNull(payload, "payload must not be null"); this.payload = payload; this.originalMessage = originalMessage; this.headerAccessor = new ShellMessageHeaderAccessor(originalMessage); // if (originalMessage != null) { - // this.modified = (!this.payload.equals(originalMessage.getPayload())); + // this.modified = (!this.payload.equals(originalMessage.getPayload())); // } } /** * Create a builder for a new {@link Message} instance with the provided payload. - * * @param The type of the payload. * @param payload the payload for the new message * @return A ShellMessageBuilder. @@ -62,76 +61,52 @@ public static ShellMessageBuilder withPayload(T payload) { /** * Create a {@code redraw} message. - * * @return a redraw message */ public static Message ofRedraw() { - return new ShellMessageBuilder<>("redraw", null) - .setEventType(EventLoop.Type.SYSTEM) - .setPriority(0) - .build(); + return new ShellMessageBuilder<>("redraw", null).setEventType(EventLoop.Type.SYSTEM).setPriority(0).build(); } /** * Create a {@code interrupt} message. - * * @return a interrupt message */ public static Message ofInterrupt() { - return new ShellMessageBuilder<>("int", null) - .setEventType(EventLoop.Type.SYSTEM) - .setPriority(0) - .build(); + return new ShellMessageBuilder<>("int", null).setEventType(EventLoop.Type.SYSTEM).setPriority(0).build(); } /** * Create a {@code signal} message. - * * @return a signal message */ public static Message ofSignal(String signal) { - return new ShellMessageBuilder<>(signal, null) - .setEventType(EventLoop.Type.SIGNAL) - .setPriority(0) - .build(); + return new ShellMessageBuilder<>(signal, null).setEventType(EventLoop.Type.SIGNAL).setPriority(0).build(); } /** * Create a message of a {@link KeyEvent}. - * * @param event the event type * @return a message with {@link KeyEvent} as a payload */ public static Message ofKeyEvent(KeyEvent event) { - return new ShellMessageBuilder<>(event, null) - .setEventType(EventLoop.Type.KEY) - .build(); + return new ShellMessageBuilder<>(event, null).setEventType(EventLoop.Type.KEY).build(); } /** * Create a message of a {@link MouseEvent}. - * * @param event the event type * @return a message with {@link MouseEvent} as a payload */ public static Message ofMouseEvent(MouseEvent event) { - return new ShellMessageBuilder<>(event, null) - .setEventType(EventLoop.Type.MOUSE) - .build(); + return new ShellMessageBuilder<>(event, null).setEventType(EventLoop.Type.MOUSE).build(); } public static Message ofView(View view, Object args) { - return new ShellMessageBuilder<>(args, null) - .setEventType(EventLoop.Type.VIEW) - .setView(view) - .build(); + return new ShellMessageBuilder<>(args, null).setEventType(EventLoop.Type.VIEW).setView(view).build(); } public static Message ofViewFocus(String action, View view) { - return new ShellMessageBuilder<>(action, null) - .setEventType(EventLoop.Type.SYSTEM) - .setView(view) - .build(); + return new ShellMessageBuilder<>(action, null).setEventType(EventLoop.Type.SYSTEM).setView(view).build(); } public ShellMessageBuilder setPriority(Integer priority) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageHeaderAccessor.java b/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageHeaderAccessor.java index 876ccdf7d..51c146816 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageHeaderAccessor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/message/ShellMessageHeaderAccessor.java @@ -52,8 +52,8 @@ public class ShellMessageHeaderAccessor extends MessageHeaderAccessor { */ public static final String EVENT_TYPE = "eventType"; - private static final BiFunction TYPE_VERIFY_MESSAGE_FUNCTION = - (name, trailer) -> "The '" + name + trailer; + private static final BiFunction TYPE_VERIFY_MESSAGE_FUNCTION = (name, trailer) -> "The '" + + name + trailer; private Set readOnlyHeaders = new HashSet<>(); @@ -64,7 +64,6 @@ public ShellMessageHeaderAccessor(@Nullable Message message) { /** * Specify a list of headers which should be considered as read only and prohibited * from being populated in the message. - * * @param readOnlyHeaders the list of headers for {@code readOnly} mode. Defaults to * {@link org.springframework.messaging.MessageHeaders#ID} and * {@link org.springframework.messaging.MessageHeaders#TIMESTAMP}. @@ -91,7 +90,6 @@ public View getView() { /** * Get a {@link ContextView} header if present. - * * @return the {@link ContextView} header if present. */ @Nullable @@ -101,7 +99,6 @@ public ContextView getReactorContext() { /** * Get a {@link EventLoop.Type} header if present. - * * @return the {@link EventLoop.Type} header if present. */ @Nullable @@ -152,4 +149,5 @@ public Map toMap() { return headers; } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/message/StaticShellMessageHeaderAccessor.java b/spring-shell-core/src/main/java/org/springframework/shell/component/message/StaticShellMessageHeaderAccessor.java index af7912142..97467d2f7 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/message/StaticShellMessageHeaderAccessor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/message/StaticShellMessageHeaderAccessor.java @@ -27,11 +27,9 @@ import org.springframework.shell.component.view.event.EventLoop; /** - * Lightweight type-safe header accessor avoiding object creation just to access - * a header. + * Lightweight type-safe header accessor avoiding object creation just to access a header. * * @author Janne Valkealahti - * * @see ShellMessageHeaderAccessor */ public final class StaticShellMessageHeaderAccessor { @@ -71,13 +69,12 @@ public static View getView(Message message) { /** * Get a {@link ContextView} header if present. - * * @param message the message to get a header from. * @return the {@link ContextView} header if present. */ public static ContextView getReactorContext(Message message) { ContextView reactorContext = message.getHeaders() - .get(ShellMessageHeaderAccessor.REACTOR_CONTEXT, ContextView.class); + .get(ShellMessageHeaderAccessor.REACTOR_CONTEXT, ContextView.class); if (reactorContext == null) { reactorContext = Context.empty(); } @@ -86,13 +83,13 @@ public static ContextView getReactorContext(Message message) { /** * Get a {@link EventLoop.Type} header if present. - * * @param message the message to get a header from. * @return the {@link EventLoop.Type} header if present. */ public static EventLoop.Type getEventType(Message message) { EventLoop.Type eventType = message.getHeaders() - .get(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.class); + .get(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.class); return eventType; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractComponent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractComponent.java index 058045882..3d77b74a9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractComponent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractComponent.java @@ -57,23 +57,39 @@ public abstract class AbstractComponent> implements ResourceLoaderAware { private final static Logger log = LoggerFactory.getLogger(AbstractComponent.class); + public final static String OPERATION_EXIT = "EXIT"; + public final static String OPERATION_BACKSPACE = "BACKSPACE"; + public final static String OPERATION_CHAR = "CHAR"; + public final static String OPERATION_UNICODE = "UNICODE"; + public final static String OPERATION_SELECT = "SELECT"; + public final static String OPERATION_DOWN = "DOWN"; + public final static String OPERATION_UP = "UP"; private final Terminal terminal; + private final BindingReader bindingReader; + private final KeyMap keyMap = new KeyMap<>(); + private final List> preRunHandlers = new ArrayList<>(); + private final List> postRunHandlers = new ArrayList<>(); + private Function> renderer; + private boolean printResults = true; + private String templateLocation; + private TemplateExecutor templateExecutor; + private ResourceLoader resourceLoader; public AbstractComponent(Terminal terminal) { @@ -89,7 +105,6 @@ public void setResourceLoader(ResourceLoader resourceLoader) { /** * Gets a {@link Terminal}. - * * @return a terminal */ public Terminal getTerminal() { @@ -98,7 +113,6 @@ public Terminal getTerminal() { /** * Sets a display renderer. - * * @param renderer the display renderer function */ public void setRenderer(Function> renderer) { @@ -106,9 +120,8 @@ public void setRenderer(Function> renderer) { } /** - * Render to be shows content of a display with set display renderer using a - * given context. - * + * Render to be shows content of a display with set display renderer using a given + * context. * @param context the context * @return list of attributed strings */ @@ -119,7 +132,6 @@ public List render(T context) { /** * Adds a pre-run handler. - * * @param handler the handler */ public void addPreRunHandler(Consumer handler) { @@ -128,7 +140,6 @@ public void addPreRunHandler(Consumer handler) { /** * Adds a post-run handler. - * * @param handler the handler */ public void addPostRunHandler(Consumer handler) { @@ -137,7 +148,6 @@ public void addPostRunHandler(Consumer handler) { /** * Sets if results should be printed into a console, Defaults to {@code true}. - * * @param printResults flag setting if results are printed */ public void setPrintResults(boolean printResults) { @@ -146,7 +156,6 @@ public void setPrintResults(boolean printResults) { /** * Runs a component logic with a given context and returns updated context. - * * @param context the context * @return a context */ @@ -164,7 +173,6 @@ public final T run(ComponentContext context) { /** * Gets a template executor. - * * @return a template executor */ public TemplateExecutor getTemplateExecutor() { @@ -173,7 +181,6 @@ public TemplateExecutor getTemplateExecutor() { /** * Sets a template executor. - * * @param templateExecutor the template executor */ public void setTemplateExecutor(TemplateExecutor templateExecutor) { @@ -182,7 +189,6 @@ public void setTemplateExecutor(TemplateExecutor templateExecutor) { /** * Sets a template location. - * * @param templateLocation the template location */ public void setTemplateLocation(String templateLocation) { @@ -191,7 +197,6 @@ public void setTemplateLocation(String templateLocation) { /** * Checks if this component has an existing {@code tty}. - * * @return true if component has tty */ protected boolean hasTty() { @@ -207,7 +212,6 @@ protected boolean hasTty() { /** * Render a given template with attributes. - * * @param attributes the attributes * @return rendered content as attributed strings */ @@ -234,7 +238,6 @@ protected List renderTemplateResource(Map attr /** * Gets a real component context using common this trick. - * * @param context the context * @return a component context */ @@ -242,7 +245,6 @@ protected List renderTemplateResource(Map attr /** * Read input. - * * @param bindingReader the binding reader * @param keyMap the key map * @param context the context @@ -252,7 +254,6 @@ protected List renderTemplateResource(Map attr /** * Run internal logic called from public run method. - * * @param context the context * @return a context */ @@ -260,14 +261,12 @@ protected List renderTemplateResource(Map attr /** * Bind key map. - * * @param keyMap */ protected abstract void bindKeyMap(KeyMap keyMap); /** * Enter into read loop. This should be called from a component. - * * @param context the context */ protected void loop(ComponentContext context) { @@ -302,7 +301,6 @@ protected void loop(ComponentContext context) { /** * Run pre-run handlers - * * @param context the context * @return a context */ @@ -313,7 +311,6 @@ protected T runPreRunHandlers(T context) { /** * Run post-run handlers - * * @param context the context * @return a context */ @@ -325,9 +322,7 @@ protected T runPostRunHandlers(T context) { private void printResults(ComponentContext context) { log.debug("About to write result with incoming context [{}] as class [{}] in [{}]", context, context.getClass(), this); - String out = render(getThisContext(context)).stream() - .map(as -> as.toAnsi()) - .collect(Collectors.joining("\n")); + String out = render(getThisContext(context)).stream().map(as -> as.toAnsi()).collect(Collectors.joining("\n")); log.debug("Writing result [{}] in [{}]", out, this); if (StringUtils.hasText(out)) { terminal.writer().println(out); @@ -338,8 +333,10 @@ private void printResults(ComponentContext context) { private static String resourceAsString(Resource resource) { try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) { return FileCopyUtils.copyToString(reader); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractSelectorComponent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractSelectorComponent.java index 07522058b..ef05cbabb 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractSelectorComponent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractSelectorComponent.java @@ -49,16 +49,27 @@ public abstract class AbstractSelectorComponent { private final static Logger log = LoggerFactory.getLogger(AbstractSelectorComponent.class); + protected final String name; + private final List items; + private Comparator comparator = (o1, o2) -> 0; + private boolean exitSelects; + private int maxItems = 5; + private Function itemMapper = item -> item.toString(); + private boolean stale = false; + private AtomicInteger start = new AtomicInteger(0); + private AtomicInteger pos = new AtomicInteger(0); + private I defaultExpose; + private boolean expose = false; public AbstractSelectorComponent(Terminal terminal, String name, List items, boolean exitSelects, @@ -74,7 +85,6 @@ public AbstractSelectorComponent(Terminal terminal, String name, List items, /** * Set max items to show. - * * @param maxItems max items */ public void setMaxItems(int maxItems) { @@ -84,7 +94,6 @@ public void setMaxItems(int maxItems) { /** * Sets an item mapper. - * * @param itemMapper the item mapper */ public void setItemMapper(Function itemMapper) { @@ -94,7 +103,6 @@ public void setItemMapper(Function itemMapper) { /** * Gets an item mapper. - * * @return */ public Function getItemMapper() { @@ -103,7 +111,6 @@ public Function getItemMapper() { /** * Sets default expose item when component start. - * * @param defaultExpose the default item */ public void setDefaultExpose(I defaultExpose) { @@ -115,7 +122,6 @@ public void setDefaultExpose(I defaultExpose) { /** * Gets items. - * * @return a list of items */ protected List getItems() { @@ -232,10 +238,11 @@ else if (start.get() + pos.get() <= 0) { } }); } - List values = thisContext.getItemStates().stream() - .filter(i -> i.selected) - .map(i -> i.item) - .collect(Collectors.toList()); + List values = thisContext.getItemStates() + .stream() + .filter(i -> i.selected) + .map(i -> i.item) + .collect(Collectors.toList()); thisContext.setResultItems(values); return true; default: @@ -255,10 +262,12 @@ private void initialExpose(C context) { List> itemStates = context.getItemStates(); if (itemStates == null) { AtomicInteger index = new AtomicInteger(0); - itemStates = context.getItems().stream() - .sorted(comparator) - .map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled(), item.isSelected())) - .collect(Collectors.toList()); + itemStates = context.getItems() + .stream() + .sorted(comparator) + .map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled(), + item.isSelected())) + .collect(Collectors.toList()); } for (int i = 0; i < itemStates.size(); i++) { if (ObjectUtils.nullSafeEquals(itemStates.get(i).getName(), defaultExpose.getName())) { @@ -278,36 +287,36 @@ private ItemStateViewProjection buildItemStateView(int skip, SelectorComponentCo List> itemStates = context.getItemStates(); if (itemStates == null) { AtomicInteger index = new AtomicInteger(0); - itemStates = context.getItems().stream() - .sorted(comparator) - .map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled(), item.isSelected())) - .collect(Collectors.toList()); + itemStates = context.getItems() + .stream() + .sorted(comparator) + .map(item -> ItemState.of(item, item.getName(), index.getAndIncrement(), item.isEnabled(), + item.isSelected())) + .collect(Collectors.toList()); context.setItemStates(itemStates); } AtomicInteger reindex = new AtomicInteger(0); - List> filtered = itemStates.stream() - .filter(i -> { - return i.matches(context.getInput()); - }) - .map(i -> { - i.index = reindex.getAndIncrement(); - return i; - }) - .collect(Collectors.toList()); - List> items = filtered.stream() - .skip(skip) - .limit(maxItems) - .collect(Collectors.toList()); + List> filtered = itemStates.stream().filter(i -> { + return i.matches(context.getInput()); + }).map(i -> { + i.index = reindex.getAndIncrement(); + return i; + }).collect(Collectors.toList()); + List> items = filtered.stream().skip(skip).limit(maxItems).collect(Collectors.toList()); return new ItemStateViewProjection(items, filtered.size()); } private class ItemStateViewProjection { + List> items; + int total; + ItemStateViewProjection(List> items, int total) { this.items = items; this.total = total; } + } /** @@ -318,117 +327,102 @@ public interface SelectorComponentContext> getItemStates(); /** * Sets an item states. - * * @param itemStateView the input state */ void setItemStates(List> itemStateView); /** * Gets an item state view. - * * @return an item state view */ List> getItemStateView(); /** * Sets an item state view - * * @param itemStateView the item state view */ void setItemStateView(List> itemStateView); /** * Return if there is a result. - * * @return true if context represents result */ boolean isResult(); /** * Gets a cursor row. - * * @return a cursor row. */ Integer getCursorRow(); /** * Sets a cursor row. - * * @param cursorRow the cursor row */ void setCursorRow(Integer cursorRow); /** * Gets an items. - * * @return an items */ List getItems(); /** * Sets an items. - * * @param items the items */ void setItems(List items); /** * Gets a result items. - * * @return a result items */ List getResultItems(); /** * Sets a result items. - * * @param items the result items */ void setResultItems(List items); /** * Creates an empty {@link SelectorComponentContext}. - * * @return empty context */ static , C extends SelectorComponentContext> SelectorComponentContext empty() { return new BaseSelectorComponentContext<>(); } + } /** @@ -438,11 +432,17 @@ protected static class BaseSelectorComponentContext implements SelectorComponentContext { private String name; + private String input; + private List> itemStates; + private List> itemStateView; + private Integer cursorRow; + private List items; + private List resultItems; @Override @@ -496,7 +496,7 @@ public Integer getCursorRow() { } @Override - public java.util.Map toTemplateModel() { + public java.util.Map toTemplateModel() { Map attributes = super.toTemplateModel(); attributes.put("name", getName()); attributes.put("input", getInput()); @@ -535,16 +535,22 @@ public void setResultItems(List resultItems) { public String toString() { return "DefaultSelectorComponentContext [cursorRow=" + cursorRow + "]"; } + } /** * Class keeping item state. */ public static class ItemState implements Matchable { + I item; + String name; + boolean selected; + boolean enabled; + int index; ItemState(I item, String name, int index, boolean enabled, boolean selected) { @@ -575,9 +581,11 @@ public boolean isEnabled() { return enabled; } - static ItemState of(I item, String name, int index, boolean enabled, boolean selected) { + static ItemState of(I item, String name, int index, boolean enabled, + boolean selected) { return new ItemState(item, name, index, enabled, selected); } + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractTextComponent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractTextComponent.java index 6dc26589c..530fe22cd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractTextComponent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/AbstractTextComponent.java @@ -76,7 +76,6 @@ protected C runInternal(C context) { /** * Gets a name. - * * @return a name */ protected String getName() { @@ -87,63 +86,54 @@ public interface TextComponentContext> e /** * Gets a name. - * * @return a name */ String getName(); /** * Sets a name. - * * @param name the name */ void setName(String name); /** * Gets an input. - * * @return an input */ String getInput(); /** * Sets an input. - * * @param input the input */ void setInput(String input); /** * Sets a result value. - * * @return a result value */ T getResultValue(); /** * Sets a result value. - * * @param resultValue the result value */ void setResultValue(T resultValue); /** * Sets a message. - * * @return a message */ String getMessage(); /** * Sets a message. - * * @param message the message */ void setMessage(String message); /** * Sets a message with level. - * * @param message the message * @param level the message level */ @@ -151,14 +141,12 @@ public interface TextComponentContext> e /** * Gets a {@link MessageLevel}. - * * @return a message level */ MessageLevel getMessageLevel(); /** * Sets a {@link MessageLevel}. - * * @param level the message level */ void setMessageLevel(MessageLevel level); @@ -167,19 +155,24 @@ public interface TextComponentContext> e * Message levels which can be used to alter how message is shown. */ public enum MessageLevel { - INFO, - WARN, - ERROR + + INFO, WARN, ERROR + } + } - public static class BaseTextComponentContext> extends BaseComponentContext - implements TextComponentContext { + public static class BaseTextComponentContext> + extends BaseComponentContext implements TextComponentContext { private String name; + private String input; + private T resultValue; + private String message; + private MessageLevel messageLevel = MessageLevel.INFO; @Override @@ -251,5 +244,7 @@ public Map toTemplateModel() { attributes.put("input", getInput()); return attributes; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Enableable.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Enableable.java index ae6afb02e..a27f3bbe2 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Enableable.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Enableable.java @@ -18,4 +18,5 @@ public interface Enableable { boolean isEnabled(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Itemable.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Itemable.java index aaa0c166c..057a36c8b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Itemable.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Itemable.java @@ -18,4 +18,5 @@ public interface Itemable { T getItem(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Matchable.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Matchable.java index 6c688cef6..a0df18d38 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Matchable.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Matchable.java @@ -18,4 +18,5 @@ public interface Matchable { boolean matches(String match); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Nameable.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Nameable.java index 39f1f8cf2..40a49e751 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Nameable.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Nameable.java @@ -17,5 +17,6 @@ public interface Nameable { - String getName(); + String getName(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Selectable.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Selectable.java index 17cadba60..a58c60aad 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/Selectable.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/Selectable.java @@ -18,4 +18,5 @@ public interface Selectable { boolean isSelected(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorItem.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorItem.java index 91febf842..33901b535 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorItem.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorItem.java @@ -28,9 +28,13 @@ static SelectorItem of(String name, T item, boolean enabled, boolean sele } public static class SelectorItemWrapper implements SelectorItem { + private String name; + private boolean enabled; + private T item; + private boolean selected; public SelectorItemWrapper(String name, T item) { @@ -71,5 +75,7 @@ public T getItem() { public boolean isSelected() { return selected; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorList.java b/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorList.java index 2a2ab9cc4..d565dafa9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorList.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/support/SelectorList.java @@ -21,9 +21,13 @@ public interface SelectorList { void reset(List items); + T getSelected(); + void scrollUp(); + void scrollDown(); + List> getProjection(); public static SelectorList of(int max) { @@ -31,14 +35,19 @@ public static SelectorList of(int max) { } public interface ProjectionItem extends Nameable, Selectable { + T getItem(); + } static class DefaultSelectorList implements SelectorList { private final List items = new ArrayList<>(); + private final int max; + private int start; + private int position; public DefaultSelectorList(int max) { @@ -92,12 +101,12 @@ public void scrollDown() { position++; } // at lowest position in page, can't go further, start over from top - else if(start + position + 1 >= items.size()) { + else if (start + position + 1 >= items.size()) { start = 0; position = 0; } // in middle of a page, nor highest or lowest - else if(position < max - 1) { + else if (position < max - 1) { position++; } // at lowest position in page, scroll down @@ -122,6 +131,7 @@ public List> getProjection() { static class BaseProjectionItem implements ProjectionItem { private final T item; + private final boolean selected; BaseProjectionItem(T item, boolean selected) { @@ -143,5 +153,7 @@ public String getName() { public boolean isSelected() { return this.selected; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java index 87e0107b7..f47979525 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUI.java @@ -52,34 +52,46 @@ import org.springframework.util.StringUtils; /** - * {@link TerminalUI} is a main component orchestrating terminal, eventloop, - * key/mouse events and view structure to work together. In many ways it can - * be think of being a "main application" when terminal ui is shown in - * a screen. + * {@link TerminalUI} is a main component orchestrating terminal, eventloop, key/mouse + * events and view structure to work together. In many ways it can be think of being a + * "main application" when terminal ui is shown in a screen. * * @author Janne Valkealahti */ public class TerminalUI implements ViewService { private final static Logger log = LoggerFactory.getLogger(TerminalUI.class); + private final Terminal terminal; + private final BindingReader bindingReader; + private final KeyMap keyMap = new KeyMap<>(); + private final DefaultScreen virtualDisplay = new DefaultScreen(); + private Display display; + private Size size; + private View rootView; + private View modalView; + private boolean fullScreen; + private final KeyBinder keyBinder; + private DefaultEventLoop eventLoop = new DefaultEventLoop(); + private View focus = null; + private ThemeResolver themeResolver; + private String themeName = "default"; /** * Constructs a handler with a given terminal. - * * @param terminal the terminal */ public TerminalUI(Terminal terminal) { @@ -101,7 +113,6 @@ public void setModal(View view) { /** * Sets a root view. - * * @param root the root view * @param fullScreen if root view should request full screen */ @@ -123,7 +134,6 @@ public void run() { /** * Gets an {@link EventLoop}. - * * @return an event loop */ public EventLoop getEventLoop() { @@ -131,8 +141,8 @@ public EventLoop getEventLoop() { } /** - * Redraw a whole screen. Essentially a message is dispatched to an event loop - * which is handled as soon as possible. + * Redraw a whole screen. Essentially a message is dispatched to an event loop which + * is handled as soon as possible. */ public void redraw() { getEventLoop().dispatch(ShellMessageBuilder.ofRedraw()); @@ -140,7 +150,6 @@ public void redraw() { /** * Sets a {@link ThemeResolver}. - * * @param themeResolver the theme resolver */ public void setThemeResolver(ThemeResolver themeResolver) { @@ -149,7 +158,6 @@ public void setThemeResolver(ThemeResolver themeResolver) { /** * Sets a {@link ThemeResolver}. - * * @return a theme resolver */ public ThemeResolver getThemeResolver() { @@ -158,7 +166,6 @@ public ThemeResolver getThemeResolver() { /** * Sets a {@code theme name}. - * * @param themeName the theme name */ public void setThemeName(String themeName) { @@ -167,7 +174,6 @@ public void setThemeName(String themeName) { /** * Gets a {@code theme name}. - * * @return a theme name */ public String getThemeName() { @@ -176,7 +182,6 @@ public String getThemeName() { /** * Gets a {@link ViewService}. - * * @return a view service */ public ViewService getViewService() { @@ -184,9 +189,8 @@ public ViewService getViewService() { } /** - * Configure view for {@link EventLoop}, {@link ThemeResolver}, - * {@code theme name} and {@link ViewService}. - * + * Configure view for {@link EventLoop}, {@link ThemeResolver}, {@code theme name} and + * {@link ViewService}. * @param view the view to configure */ public void configure(View view) { @@ -235,9 +239,8 @@ private void render(Rectangle rect) { }; /** - * Sets a view rect function for full screen mode. Default behaviour uses {@link Rectangle} - * area equal to terminal size. - * + * Sets a view rect function for full screen mode. Default behaviour uses + * {@link Rectangle} area equal to terminal size. * @param fullScreenViewRect the view rect function */ public void setFullScreenViewRect(BiFunction fullScreenViewRect) { @@ -246,10 +249,9 @@ public void setFullScreenViewRect(BiFunction fullScre } /** - * Sets a view rect function for full screen mode. Default behaviour uses {@link Rectangle} - * from {@code rootView} if it's not empty, otherwise uses zero based area with - * width matching terminal columns and height matching 5. - * + * Sets a view rect function for full screen mode. Default behaviour uses + * {@link Rectangle} from {@code rootView} if it's not empty, otherwise uses zero + * based area with width matching terminal columns and height matching 5. * @param nonfullScreenViewRect the view rect function */ public void setNonfullScreenViewRect(BiFunction nonfullScreenViewRect) { @@ -284,7 +286,8 @@ private synchronized void display() { int targetCursorPos = 0; if (virtualDisplay.isShowCursor()) { terminal.puts(Capability.cursor_normal); - targetCursorPos = size.cursorPos(virtualDisplay.getCursorPosition().y(), virtualDisplay.getCursorPosition().x()); + targetCursorPos = size.cursorPos(virtualDisplay.getCursorPosition().y(), + virtualDisplay.getCursorPosition().x()); log.debug("Display targetCursorPos {}", targetCursorPos); } else { @@ -299,32 +302,26 @@ private void dispatchWinch() { } private void registerEventHandling() { - eventLoop.onDestroy(eventLoop.signalEvents() - .subscribe(event -> { + eventLoop.onDestroy(eventLoop.signalEvents().subscribe(event -> { + display(); + })); + + eventLoop.onDestroy(eventLoop.systemEvents().subscribe(event -> { + if ("redraw".equals(event)) { display(); - })); + } + else if ("int".equals(event)) { + this.terminal.raise(Signal.INT); + } + })); - eventLoop.onDestroy(eventLoop.systemEvents() - .subscribe(event -> { - if ("redraw".equals(event)) { - display(); - } - else if ("int".equals(event)) { - this.terminal.raise(Signal.INT); - } - })); - - eventLoop.onDestroy(eventLoop.keyEvents() - .doOnNext(m -> { - handleKeyEvent(m); - }) - .subscribe()); - - eventLoop.onDestroy(eventLoop.mouseEvents() - .doOnNext(m -> { - handleMouseEvent(m); - }) - .subscribe()); + eventLoop.onDestroy(eventLoop.keyEvents().doOnNext(m -> { + handleKeyEvent(m); + }).subscribe()); + + eventLoop.onDestroy(eventLoop.mouseEvents().doOnNext(m -> { + handleMouseEvent(m); + }).subscribe()); } private void handleKeyEvent(KeyEvent event) { @@ -422,7 +419,7 @@ private void bindKeyMap(KeyMap keyMap) { } private boolean read(BindingReader bindingReader, KeyMap keyMap) { - Thread readThread = Thread.currentThread(); + Thread readThread = Thread.currentThread(); terminal.handle(Signal.INT, signal -> { log.debug("Handling signal {}", signal); readThread.interrupt(); @@ -432,8 +429,9 @@ private boolean read(BindingReader bindingReader, KeyMap keyMap) { try { operation = bindingReader.readBinding(keyMap); log.debug("Read got operation {}", operation); - } catch (IOError e) { - // Ignore Ctrl+C interrupts and just exit the loop + } + catch (IOError e) { + // Ignore Ctrl+C interrupts and just exit the loop log.trace("Read binding error {}", e); } if (operation == null) { @@ -472,7 +470,8 @@ private void dispatchMouse(MouseEvent event) { eventLoop.dispatch(ShellMessageBuilder.ofMouseEvent(event)); } - private void mouseEvent() { + private void mouseEvent() { dispatchMouse(MouseEvent.of(terminal.readMouseEvent())); - } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUIBuilder.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUIBuilder.java index 48360430d..55d0278b6 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUIBuilder.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUIBuilder.java @@ -36,17 +36,18 @@ public class TerminalUIBuilder { private final Terminal terminal; + private final Set 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 + * @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; @@ -57,11 +58,9 @@ public TerminalUIBuilder(Terminal terminal, TerminalUICustomizer... customizers) /** * 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 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 */ @@ -75,7 +74,6 @@ public TerminalUIBuilder(Terminal terminal, Set customizer /** * Sets a {@link ThemeResolver} for {@link TerminalUI} to build. - * * @param themeResolver the theme resolver * @return a new builder instance */ @@ -85,7 +83,6 @@ public TerminalUIBuilder themeResolver(ThemeResolver themeResolver) { /** * Sets a {@code theme name} for {@link TerminalUI} to build. - * * @param themeName the theme name * @return a new builder instance */ @@ -94,11 +91,10 @@ public TerminalUIBuilder themeName(String 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. - * + * 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 */ @@ -109,7 +105,6 @@ public TerminalUIBuilder customizers(Collection /** * Build a new {@link TerminalUI} instance and configure it using this builder. - * * @return a configured {@link TerminalUI} instance. */ public TerminalUI build() { @@ -118,7 +113,6 @@ public TerminalUI build() { /** * Configure the provided {@link TerminalUI} instance using this builder. - * * @param the type of terminal ui * @param terminalUI the {@link TerminalUI} to configure * @return the terminal ui instance diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUICustomizer.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUICustomizer.java index 2ae67e3bd..1f7e071cc 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUICustomizer.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/TerminalUICustomizer.java @@ -26,7 +26,6 @@ public interface TerminalUICustomizer { /** * Callback to customize a {@link TerminalUI} instance. - * * @param terminalUI the terminal ui to customize */ void customize(TerminalUI terminalUI); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractControl.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractControl.java index 3f36a7cfb..4f61025d2 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractControl.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractControl.java @@ -32,10 +32,15 @@ public abstract class AbstractControl implements Control { private int x = 0; + private int y = 0; + private int width = 0; + private int height = 0; + private ThemeResolver themeResolver; + private String themeName; @Override @@ -53,7 +58,6 @@ public Rectangle getRect() { /** * Sets a {@link ThemeResolver}. - * * @param themeResolver the theme resolver */ public void setThemeResolver(@Nullable ThemeResolver themeResolver) { @@ -62,7 +66,6 @@ public void setThemeResolver(@Nullable ThemeResolver themeResolver) { /** * Gets a {@link ThemeResolver}. - * * @return a theme resolver */ @Nullable @@ -72,7 +75,6 @@ protected ThemeResolver getThemeResolver() { /** * Sets a theme name to use. - * * @param themeName the theme name */ public void setThemeName(@Nullable String themeName) { @@ -81,7 +83,6 @@ public void setThemeName(@Nullable String themeName) { /** * Gets a theme name. - * * @return a theme name */ @Nullable @@ -100,9 +101,8 @@ private Optional getThemeResolvedValues(String tag) { } /** - * Resolve style using existing {@link ThemeResolver} and {@code theme name}. - * Use {@code defaultStyle} if resolving cannot happen. - * + * Resolve style using existing {@link ThemeResolver} and {@code theme name}. Use + * {@code defaultStyle} if resolving cannot happen. * @param tag the style tag to use * @param defaultStyle the default style to use * @return resolved style @@ -112,10 +112,9 @@ protected int resolveThemeStyle(String tag, int defaultStyle) { } /** - * Resolve foreground color using existing {@link ThemeResolver} and {@code theme name}. - * {@code defaultColor} is used if it's value is not negative. {@code fallbackColor} is - * used if theme resolver cannot be used. - * + * Resolve foreground color using existing {@link ThemeResolver} and + * {@code theme name}. {@code defaultColor} is used if it's value is not negative. + * {@code fallbackColor} is used if theme resolver cannot be used. * @param tag the style tag to use * @param defaultColor the default foreground color to use * @param fallbackColor the fallback foreground color to use @@ -129,10 +128,9 @@ protected int resolveThemeForeground(String tag, int defaultColor, int fallbackC } /** - * Resolve background color using existing {@link ThemeResolver} and {@code theme name}. - * {@code defaultColor} is used if it's value is not negative. {@code fallbackColor} is - * used if theme resolver cannot be used. - * + * Resolve background color using existing {@link ThemeResolver} and + * {@code theme name}. {@code defaultColor} is used if it's value is not negative. + * {@code fallbackColor} is used if theme resolver cannot be used. * @param tag the style tag to use * @param defaultColor the default background color to use * @param fallbackColor the fallback background color to use @@ -146,10 +144,9 @@ protected int resolveThemeBackground(String tag, int defaultColor, int fallbackC } /** - * Resolve {@link Spinner} using existing {@link ThemeResolver} and {@code theme name}. - * {@code defaultSpinner} is used if it's not {@code null}. {@code fallbackSpinner} is - * used if theme resolver cannot be used. - * + * Resolve {@link Spinner} using existing {@link ThemeResolver} and + * {@code theme name}. {@code defaultSpinner} is used if it's not {@code null}. + * {@code fallbackSpinner} is used if theme resolver cannot be used. * @param tag the spinner tag to use * @param defaultSpinner the default spinner to use * @param fallbackSpinner the fallback spinner to use diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java index f05a34827..ecfe7f80c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AbstractView.java @@ -42,29 +42,39 @@ import org.springframework.shell.geom.Rectangle; /** - * Base implementation of a {@link View} and its parent interface - * {@link Control} providing some common functionality for implementations. + * Base implementation of a {@link View} and its parent interface {@link Control} + * providing some common functionality for implementations. * * @author Janne Valkealahti */ public abstract class AbstractView extends AbstractControl implements View { private final static Logger log = LoggerFactory.getLogger(AbstractView.class); + private final Disposable.Composite disposables = Disposables.composite(); + private BiFunction drawFunction; + private boolean hasFocus; + private int layer; + private EventLoop eventLoop; + private ViewService viewService; + private final Map commands = new HashMap<>(); + private Map keyBindings = new HashMap<>(); + private Map hotKeyBindings = new HashMap<>(); + private Map mouseBindings = new HashMap<>(); + private boolean init = false; /** * Register {@link Disposable} to get disposed when view terminates. - * * @param disposable a disposable to dispose */ protected void onDestroy(Disposable disposable) { @@ -95,15 +105,17 @@ public final void init() { } private Integer shortcutKey; + private Runnable shortcutAction; + public void shortcut(Integer key, Runnable runnable) { this.shortcutKey = key; this.shortcutAction = runnable; } /** - * Internal init method called from {@link #init()}. Override to do something - * usefull. Typically key and mousebindings are registered from this method. + * Internal init method called from {@link #init()}. Override to do something usefull. + * Typically key and mousebindings are registered from this method. */ protected void initInternal() { if (shortcutKey != null && shortcutAction != null) { @@ -121,10 +133,10 @@ protected int getLayer() { } /** - * Calls drawing logic in two stages. First a background is drawn and then an - * actual content. This logic allows to separate how child implementation - * can use drawing logic from its parent as usually background should get - * overridden in child but actual content should get overridden in a parent. + * Calls drawing logic in two stages. First a background is drawn and then an actual + * content. This logic allows to separate how child implementation can use drawing + * logic from its parent as usually background should get overridden in child but + * actual content should get overridden in a parent. */ @Override public final void draw(Screen screen) { @@ -133,16 +145,14 @@ public final void draw(Screen screen) { } /** - * Component internal drawing method. Implementing classes needs to define this - * method to draw something into a {@link Screen}. - * + * Component internal drawing method. Implementing classes needs to define this method + * to draw something into a {@link Screen}. * @param screen the screen */ protected abstract void drawInternal(Screen screen); /** * Internal drawing method for background. - * * @param screen the screen */ protected void drawBackground(Screen screen) { @@ -238,9 +248,7 @@ public KeyHandler getHotKeyHandler() { } /** - * Sets a callback function which is invoked after a {@link View} has been - * drawn. - * + * Sets a callback function which is invoked after a {@link View} has been drawn. * @param drawFunction the draw function */ public void setDrawFunction(BiFunction drawFunction) { @@ -249,7 +257,6 @@ public void setDrawFunction(BiFunction drawFunctio /** * Gets a draw function. - * * @return null if function is not set * @see #setDrawFunction(BiFunction) */ @@ -259,7 +266,6 @@ public BiFunction getDrawFunction() { /** * Set an {@link EventLoop}. - * * @param eventLoop the event loop */ public void setEventLoop(@Nullable EventLoop eventLoop) { @@ -268,7 +274,6 @@ public void setEventLoop(@Nullable EventLoop eventLoop) { /** * Get an {@link EventLoop}. - * * @return event loop */ protected EventLoop getEventLoop() { @@ -277,7 +282,6 @@ protected EventLoop getEventLoop() { /** * Set a {@link ViewService} - * * @param viewService the view service */ @Override @@ -287,7 +291,6 @@ public void setViewService(ViewService viewService) { /** * Get a {@link ViewService} - * * @return view service */ protected ViewService getViewService() { @@ -315,7 +318,8 @@ protected void registerKeyBinding(Integer keyType, Runnable keyRunnable) { registerKeyBinding(keyType, null, null, keyRunnable); } - private void registerKeyBinding(Integer keyType, String keyCommand, KeyBindingConsumer keyConsumer, Runnable keyRunnable) { + private void registerKeyBinding(Integer keyType, String keyCommand, KeyBindingConsumer keyConsumer, + Runnable keyRunnable) { keyBindings.compute(keyType, (key, old) -> { return KeyBindingValue.of(old, keyCommand, keyConsumer, keyRunnable); }); @@ -333,7 +337,8 @@ protected void registerHotKeyBinding(Integer keyType, Runnable keyRunnable) { registerHotKeyBinding(keyType, null, null, keyRunnable); } - private void registerHotKeyBinding(Integer keyType, String keyCommand, KeyBindingConsumer keyConsumer, Runnable keyRunnable) { + private void registerHotKeyBinding(Integer keyType, String keyCommand, KeyBindingConsumer keyConsumer, + Runnable keyRunnable) { hotKeyBindings.compute(keyType, (key, old) -> { return KeyBindingValue.of(old, keyCommand, keyConsumer, keyRunnable); }); @@ -353,7 +358,6 @@ static KeyBindingValue of(KeyBindingValue old, String keyCommand, KeyBindingCons /** * Get key bindings. - * * @return key bindings */ protected Map getKeyBindings() { @@ -362,7 +366,6 @@ protected Map getKeyBindings() { /** * Get hotkey bindings. - * * @return hotkey bindings */ protected Map getHotKeyBindings() { @@ -385,7 +388,6 @@ static MouseBindingValue of(MouseBindingValue old, String mouseCommand, MouseBin /** * Get mouse bindings. - * * @return mouse bindings */ protected Map getMouseBindings() { @@ -404,7 +406,8 @@ protected void registerMouseBinding(Integer keyType, Runnable mouseRunnable) { registerMouseBinding(keyType, null, null, mouseRunnable); } - private void registerMouseBinding(Integer mouseType, String mouseCommand, MouseBindingConsumer mouseConsumer, Runnable mouseRunnable) { + private void registerMouseBinding(Integer mouseType, String mouseCommand, MouseBindingConsumer mouseConsumer, + Runnable mouseRunnable) { Predicate mousePredicate = event -> { int x = event.x(); int y = event.y(); @@ -417,7 +420,6 @@ private void registerMouseBinding(Integer mouseType, String mouseCommand, MouseB /** * Dispatch a {@link Message} into an event loop. - * * @param message the message to dispatch */ protected void dispatch(Message message) { @@ -433,10 +435,7 @@ protected boolean dispatchRunnable(Runnable runnable) { if (eventLoop == null) { return false; } - Message message = ShellMessageBuilder - .withPayload(runnable) - .setEventType(EventLoop.Type.TASK) - .build(); + Message message = ShellMessageBuilder.withPayload(runnable).setEventType(EventLoop.Type.TASK).build(); dispatch(message); return true; } @@ -449,8 +448,7 @@ public boolean runViewCommand(String command) { if (command != null) { Runnable runnable = commands.get(command); if (runnable != null) { - Message message = ShellMessageBuilder - .withPayload(runnable) + Message message = ShellMessageBuilder.withPayload(runnable) .setEventType(EventLoop.Type.TASK) .build(); dispatch(message); @@ -470,8 +468,7 @@ protected boolean dispatchKeyRunCommand(KeyEvent event, KeyBindingValue keyBindi } Runnable keyRunnable = keyBindingValue.keyRunnable(); if (keyRunnable != null) { - Message message = ShellMessageBuilder - .withPayload(keyRunnable) + Message message = ShellMessageBuilder.withPayload(keyRunnable) .setEventType(EventLoop.Type.TASK) .build(); dispatch(message); @@ -499,8 +496,7 @@ protected boolean dispatchMouseRunCommand(MouseEvent event, MouseBindingValue mo } Runnable mouseRunnable = mouseBindingValue.mouseRunnable(); if (mouseRunnable != null) { - Message message = ShellMessageBuilder - .withPayload(mouseRunnable) + Message message = ShellMessageBuilder.withPayload(mouseRunnable) .setEventType(EventLoop.Type.TASK) .build(); dispatch(message); @@ -517,4 +513,5 @@ protected boolean dispatchMouseRunCommand(MouseEvent event, MouseBindingValue mo } return false; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AppView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AppView.java index 26ee85335..b82daeccc 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AppView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/AppView.java @@ -26,18 +26,23 @@ import org.springframework.util.Assert; /** - * {@link AppView} provides an opinionated terminal UI application view - * controlling main viewing area, menubar, statusbar and modal window system. + * {@link AppView} provides an opinionated terminal UI application view controlling main + * viewing area, menubar, statusbar and modal window system. * * @author Janne Valkealahti */ public class AppView extends BoxView { private GridView grid; + private View main; + private View menu; + private View status; + private boolean menuVisible = true; + private boolean statusVisible = true; public AppView(View main, View menuBar, View statusBar) { @@ -151,7 +156,6 @@ public boolean hasFocus() { /** * Sets visibility for a {@code menubar}. - * * @param visible the menubar visibility */ public void setMenuBarVisible(boolean visible) { @@ -161,7 +165,6 @@ public void setMenuBarVisible(boolean visible) { /** * Sets visibility for a {@code statusbar}. - * * @param visible the statusbar visibility */ public void setStatusBarVisible(boolean visible) { @@ -194,8 +197,9 @@ public record AppViewEventArgs(Direction direction) implements ViewEventArgs { * Direction where next selection should go. */ public enum Direction { - PREVIOUS, - NEXT + + PREVIOUS, NEXT + } public static AppViewEventArgs of(Direction direction) { @@ -215,4 +219,5 @@ public static AppViewEvent of(View view, AppViewEventArgs.Direction direction) { return new AppViewEvent(view, AppViewEventArgs.of(direction)); } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/BoxView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/BoxView.java index 5a30d53ab..cc5c9b985 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/BoxView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/BoxView.java @@ -26,30 +26,46 @@ import org.springframework.util.StringUtils; /** - * {@code BoxView} is a {@link View} with an empty background and optional - * border and title. All "boxed" views can use this as their base - * implementation by either subclassing or wrapping. + * {@code BoxView} is a {@link View} with an empty background and optional border and + * title. All "boxed" views can use this as their base implementation by either + * subclassing or wrapping. * * @author Janne Valkealahti */ public class BoxView extends AbstractView { private final static Logger log = LoggerFactory.getLogger(BoxView.class); + private String title = null; + private boolean showBorder = false; + private int innerX = -1; + private int innerY; + private int innerWidth; + private int innerHeight; + private int paddingTop; + private int paddingBottom; + private int paddingLeft; + private int paddingRight; + private int backgroundColor = -1; + private int titleColor = -1; + private int titleStyle = -1; + private int focusedTitleColor = -1; + private int focusedTitleStyle = -1; + private HorizontalAlign titleAlign; @Override @@ -60,7 +76,6 @@ public void setRect(int x, int y, int width, int height) { /** * Sets a paddings for this view. - * * @param paddingTop the top padding * @param paddingBottom the bottom padding * @param paddingLeft the left padding @@ -77,7 +92,6 @@ public BoxView setBorderPadding(int paddingTop, int paddingBottom, int paddingLe /** * Defines if border is shown. - * * @param showBorder the flag showing border */ public void setShowBorder(boolean showBorder) { @@ -86,7 +100,6 @@ public void setShowBorder(boolean showBorder) { /** * Returns if border is shown. - * * @return true if border is shown */ public boolean isShowBorder() { @@ -94,9 +107,8 @@ public boolean isShowBorder() { } /** - * Sets a title. {@code title} is shown within a top-level border boundary and - * will not be visible if border itself is not visible. - * + * Sets a title. {@code title} is shown within a top-level border boundary and will + * not be visible if border itself is not visible. * @param title the border title */ public void setTitle(String title) { @@ -107,7 +119,6 @@ public void setTitle(String title) { * Sets a background color. If color is set to {@code null} it indicates that * background should be set to be {@code empty} causing possible layer to be * non-transparent. - * * @param backgroundColor the background color */ public void setBackgroundColor(int backgroundColor) { @@ -116,7 +127,6 @@ public void setBackgroundColor(int backgroundColor) { /** * Sets a title color. - * * @param titleColor the title color */ public void setTitleColor(int titleColor) { @@ -125,7 +135,6 @@ public void setTitleColor(int titleColor) { /** * Sets a title style. - * * @param titleStyle the title style */ public void setTitleStyle(int titleStyle) { @@ -133,9 +142,7 @@ public void setTitleStyle(int titleStyle) { } /** - * Sets a focused title color. Takes precedence set from - * {@link #setTitleColor(int)}. - * + * Sets a focused title color. Takes precedence set from {@link #setTitleColor(int)}. * @param focusedTitleColor the title color */ public void setFocusedTitleColor(int focusedTitleColor) { @@ -143,9 +150,7 @@ public void setFocusedTitleColor(int focusedTitleColor) { } /** - * Sets a focused title style. Takes precedence set from - * {@link #setTitleStyle(int)}. - * + * Sets a focused title style. Takes precedence set from {@link #setTitleStyle(int)}. * @param focusedTitleStyle the title style */ public void setFocusedTitleStyle(int focusedTitleStyle) { @@ -154,7 +159,6 @@ public void setFocusedTitleStyle(int focusedTitleStyle) { /** * Sets a title align. - * * @param titleAlign the title align */ public void setTitleAlign(HorizontalAlign titleAlign) { @@ -173,9 +177,8 @@ protected void drawBackground(Screen screen) { } /** - * Possibly draws a box around this view and title in a box top boundary. Also - * calls a {@code draw function} if defined. - * + * Possibly draws a box around this view and title in a box top boundary. Also calls a + * {@code draw function} if defined. * @param screen the screen */ protected void drawInternal(Screen screen) { @@ -202,8 +205,12 @@ protected void drawInternal(Screen screen) { style = titleStyle; } - screen.writerBuilder().layer(getLayer()).color(color).style(style).build().text(title, r, titleAlign, - VerticalAlign.TOP); + screen.writerBuilder() + .layer(getLayer()) + .color(color) + .style(style) + .build() + .text(title, r, titleAlign, VerticalAlign.TOP); } } if (getDrawFunction() != null) { @@ -224,7 +231,6 @@ protected void drawInternal(Screen screen) { /** * Gets an inner rectangle of this view. - * * @return an inner rectangle of this view */ protected Rectangle getInnerRect() { @@ -254,4 +260,5 @@ protected Rectangle getInnerRect() { } return new Rectangle(x, y, width, height); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ButtonView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ButtonView.java index 43e685e10..c000537c9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ButtonView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ButtonView.java @@ -36,6 +36,7 @@ public class ButtonView extends BoxView { private String text; + private Runnable action; public ButtonView() { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Control.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Control.java index 8a9ead4a2..27607cd04 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Control.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Control.java @@ -22,8 +22,8 @@ import org.springframework.shell.style.ThemeResolver; /** - * Base interface for all controls. {@link Control} is able to define a - * {@link Rectangle} it is bound to and draw into a {@link Screen}. + * Base interface for all controls. {@link Control} is able to define a {@link Rectangle} + * it is bound to and draw into a {@link Screen}. * * @author Janne Valkealahti * @see View @@ -33,21 +33,18 @@ public interface Control { /** * Draw {@link Control} into a {@link Screen}. - * * @param screen the screen */ void draw(Screen screen); /** * Gets rectanle of a bounded box for this {@link View}. - * * @return the rectanle of a bounded box */ Rectangle getRect(); /** * Sets bounds where this {@link Control} should operate. - * * @param x a x coord of a bounded box * @param y an y coord of a bounded box * @param width a width of a bounded box @@ -57,14 +54,12 @@ public interface Control { /** * Sets a {@link ThemeResolver}. - * * @param themeResolver the theme resolver */ void setThemeResolver(@Nullable ThemeResolver themeResolver); /** * Sets a theme name to use. - * * @param themeName the theme name */ void setThemeName(@Nullable String themeName); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/DialogView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/DialogView.java index 9ccd74f1e..ebdcf4885 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/DialogView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/DialogView.java @@ -30,14 +30,15 @@ import org.springframework.shell.style.StyleSettings; /** - * {@code DialogView} is a {@link View} with border, number of buttons and area - * for a generic content. + * {@code DialogView} is a {@link View} with border, number of buttons and area for a + * generic content. * * @author Janne Valkealahti */ public class DialogView extends WindowView { private View content; + private List buttons; public DialogView() { @@ -76,14 +77,13 @@ public void setLayer(int index) { private void hookButtonEvents() { buttons.forEach(b -> { - onDestroy(getEventLoop().viewEvents(ButtonViewSelectEvent.class, b) - .subscribe(event -> { - dispatch(); - ViewService viewService = getViewService(); - if (viewService != null) { - viewService.setModal(null); - } - })); + onDestroy(getEventLoop().viewEvents(ButtonViewSelectEvent.class, b).subscribe(event -> { + dispatch(); + ViewService viewService = getViewService(); + if (viewService != null) { + viewService.setModal(null); + } + })); }); } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/GridView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/GridView.java index 3d9f2b55a..9bdc17ea5 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/GridView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/GridView.java @@ -35,59 +35,70 @@ /** * {@code GridView} is a layout container with no initial {@link View views}. * - * Loosely based on ideas from other grid layouts having features like rows and - * columns, column and row spanning, dynamic layouts based on container size - * using "CSS media queries" type of structure. + * Loosely based on ideas from other grid layouts having features like rows and columns, + * column and row spanning, dynamic layouts based on container size using "CSS media + * queries" type of structure. * * @author Janne Valkealahti */ public class GridView extends BoxView { private final static Logger log = LoggerFactory.getLogger(GridView.class); + private List gridItems = new ArrayList<>(); + private int[] columnSize; + private int[] rowSize; + private int minWidth; + private int minHeight; + private int gapRows; + private int gapColumns; + private int rowOffset; + private int columnOffset; + private boolean showBorders; /** - * Defines how the columns of the grid are distributed. Each value defines the - * size of one column, starting with the leftmost column. Values greater 0 - * represent absolute column widths (gaps not included). Values less or equal 0 - * represent proportional column widths or fractions of the remaining free - * space, where 0 is treated the same as -1. That is, a column with a value - * of -3 will have three times the width of a column with a value of -1 (or 0). - * The minimum width set with {@link #setMinSize(int, int)} is always observed. + * Defines how the columns of the grid are distributed. Each value defines the size of + * one column, starting with the leftmost column. Values greater 0 represent absolute + * column widths (gaps not included). Values less or equal 0 represent proportional + * column widths or fractions of the remaining free space, where 0 is treated the same + * as -1. That is, a column with a value of -3 will have three times the width of a + * column with a value of -1 (or 0). The minimum width set with + * {@link #setMinSize(int, int)} is always observed. * - *

Views may extend beyond the columns defined explicitly with this function. A - * value of 0 is assumed for any undefined column. In fact, if you never call - * this function, all columns occupied by Views will have the same width. On the - * other hand, unoccupied columns defined with this function will always take - * their place. + *

+ * Views may extend beyond the columns defined explicitly with this function. A value + * of 0 is assumed for any undefined column. In fact, if you never call this function, + * all columns occupied by Views will have the same width. On the other hand, + * unoccupied columns defined with this function will always take their place. * - *

Assuming a total width of the grid of 100 cells and a minimum width of 0, the - * following call will result in columns with widths of 30, 10, 15, 15, and 30 - * cells: + *

+ * Assuming a total width of the grid of 100 cells and a minimum width of 0, the + * following call will result in columns with widths of 30, 10, 15, 15, and 30 cells: *

* * grid.setColumnSize(30, 10, -1, -1, -2) * - *

If a {@link View} were then placed in the 6th and 7th column, the resulting - * widths would be: 30, 10, 10, 10, 20, 10, and 10 cells. + *

+ * If a {@link View} were then placed in the 6th and 7th column, the resulting widths + * would be: 30, 10, 10, 10, 20, 10, and 10 cells. * * If you then called setMinSize() as follows: *

* * grid.setMinSize(15, 20) * - *

The resulting widths would be: 30, 15, 15, 15, 20, 15, and 15 cells, a total - * of 125 cells, 25 cells wider than the available grid width. - * + *

+ * The resulting widths would be: 30, 15, 15, 15, 20, 15, and 15 cells, a total of 125 + * cells, 25 cells wider than the available grid width. * @param columns the column sizes * @return a grid view for chaining * @see #setRowSize(int...) @@ -99,7 +110,6 @@ public GridView setColumnSize(int... columns) { /** * For documentation see {@link #setColumnSize(int...)} as it's equivalent for rows. - * * @param rows the row sizes * @return a grid view for chaining * @see #setColumnSize(int...) @@ -110,9 +120,8 @@ public GridView setRowSize(int... rows) { } /** - * Sets an absolute minimum width for rows and an absolute minimum height for - * columns. Negative values cannot be used. - * + * Sets an absolute minimum width for rows and an absolute minimum height for columns. + * Negative values cannot be used. * @param minWidth the rows minimum width * @param minHeight the columns minimum height * @return a grid view for chaining @@ -126,9 +135,9 @@ public GridView setMinSize(int minWidth, int minHeight) { /** * Adds a {@link View} and its position to the grid. The top-left corner of the - * {@link View} will be located in the top-left corner of the grid cell at - * the given row and column and will span "rowSpan" rows and "colSpan" columns. - * For example, for a primitive to occupy rows 2, 3, and 4 and columns 5 and 6: + * {@link View} will be located in the top-left corner of the grid cell at the given + * row and column and will span "rowSpan" rows and "colSpan" columns. For example, for + * a primitive to occupy rows 2, 3, and 4 and columns 5 and 6: * *

* grid.addItem(view, 2, 5, 3, 2, 0, 0) @@ -136,27 +145,26 @@ public GridView setMinSize(int minWidth, int minHeight) { * If {@code rowSpan} or colSpan is 0, the {@link View} will not be drawn. * *

- * You can add the same {@link View} multiple times with different grid - * positions. The {@code minGridWidth} and {@code minGridHeight} values will - * then determine which of those positions will be used. These minimum values - * refer to the overall size of the grid. If multiple items for the same - * primitive apply, the one that has at least one highest minimum value will - * be used, or the {@link View} added last if those values are the same. Example: + * You can add the same {@link View} multiple times with different grid positions. The + * {@code minGridWidth} and {@code minGridHeight} values will then determine which of + * those positions will be used. These minimum values refer to the overall size of the + * grid. If multiple items for the same primitive apply, the one that has at least one + * highest minimum value will be used, or the {@link View} added last if those values + * are the same. Example: * *

- * AddItem(view, 0, 0, 0, 0, 0, 0). // Hide in small grids. - * AddItem(view, 0, 0, 1, 2, 100, 0). // One-column layout for medium grids. - * AddItem(view, 1, 1, 3, 2, 300, 0) // Multi-column layout for large grids. + * AddItem(view, 0, 0, 0, 0, 0, 0). // Hide in small grids. AddItem(view, 0, 0, 1, 2, + * 100, 0). // One-column layout for medium grids. AddItem(view, 1, 1, 3, 2, 300, 0) + * // Multi-column layout for large grids. * *

- * To use the same grid layout for all sizes, simply set {@code minGridWidth} - * and {@code minGridHeight} to 0. + * To use the same grid layout for all sizes, simply set {@code minGridWidth} and + * {@code minGridHeight} to 0. * *

- * If the item's focus is set to true, it will receive focus when the grid - * receives focus. If there are multiple items with a true focus flag, the - * last visible one that was added will receive focus. - * + * If the item's focus is set to true, it will receive focus when the grid receives + * focus. If there are multiple items with a true focus flag, the last visible one + * that was added will receive focus. * @param view the view to add * @param row the row * @param column the column @@ -168,8 +176,7 @@ public GridView setMinSize(int minWidth, int minHeight) { */ public GridView addItem(View view, int row, int column, int rowSpan, int colSpan, int minGridHeight, int minGridWidth) { - GridItem gridItem = new GridItem(view, row, column, colSpan, rowSpan, minGridHeight, - minGridWidth, false); + GridItem gridItem = new GridItem(view, row, column, colSpan, rowSpan, minGridHeight, minGridWidth, false); gridItems.add(gridItem); return this; } @@ -183,7 +190,6 @@ public void clearItems() { /** * Defines if borders is shown. - * * @param showBorders the flag showing borders */ public void setShowBorders(boolean showBorders) { @@ -192,7 +198,6 @@ public void setShowBorders(boolean showBorders) { /** * Returns if borders is shown. - * * @return true if borders is shown */ public boolean isShowBorders() { @@ -274,8 +279,8 @@ public KeyHandler getHotKeyHandler() { } // handler = i.view.getHotKeyHandler(); // if (i.view.hasFocus()) { - // handler = i.view.getHotKeyHandler(); - // break; + // handler = i.view.getHotKeyHandler(); + // break; // } } if (handler != null) { @@ -346,7 +351,6 @@ protected void drawInternal(Screen screen) { int proportionalWidth = 0; int proportionalHeight = 0; - for (int index = 0; index < rowSize.length; index++) { int row = rowSize[index]; if (row > 0) { @@ -544,7 +548,7 @@ else if (column == 0) { // Adjust row/column offsets based on this value. int from = 0; int to = 0; - for (int index = 0; index < rowPos.length; index ++) { + for (int index = 0; index < rowPos.length; index++) { int pos = rowPos[index]; if (pos - offsetY < 0) { from = index + 1; @@ -562,7 +566,7 @@ else if (column == 0) { from = 0; to = 0; - for (int index = 0; index < columnPos.length; index ++) { + for (int index = 0; index < columnPos.length; index++) { int pos = columnPos[index]; if (pos - offsetX < 0) { from = index + 1; @@ -628,14 +632,23 @@ else if (column == 0) { } private static class GridItem { + View view; + int row; + int column; + int width; + int height; + int minGridHeight; + int minGridWidth; + boolean visible; + // The last position of the item relative to the top-left // corner of the grid. Undefined if visible is false. int x, y, w, h; @@ -651,5 +664,7 @@ private static class GridItem { this.minGridWidth = minGridWidth; this.visible = visible; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java index f64e00d1c..a9c6de28e 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/InputView.java @@ -37,7 +37,9 @@ public class InputView extends BoxView { private final Logger log = LoggerFactory.getLogger(InputView.class); + private final ArrayList text = new ArrayList<>(); + private int cursorIndex = 0; @Override @@ -64,7 +66,7 @@ public KeyHandler getKeyHandler() { if (event.isKey()) { consumed = true; int plainKey = event.getPlainKey(); - add(new String(new char[]{(char)plainKey})); + add(new String(new char[] { (char) plainKey })); } else if (event.isKey(KeyEvent.Key.Unicode)) { add(event.data()); @@ -89,7 +91,6 @@ protected void drawInternal(Screen screen) { /** * Get a current known input text. - * * @return current input text */ public String getInputText() { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java index 8b239e4f0..200ce418b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ListView.java @@ -38,7 +38,8 @@ /** * {@code ListView} is a {@link View} showing items in a vertical list. * - *

Supported view commands: + *

+ * Supported view commands: *

    *
  • {@link ViewCommand#LINE_UP} - Move active line upwards. *
  • {@link ViewCommand#LINE_DOWN} - Move active line downwards. @@ -49,11 +50,17 @@ public class ListView extends BoxView { private final List items = new ArrayList<>(); + private final List> cells = new ArrayList<>(); + private final ItemStyle itemStyle; + private int start = 0; + private int pos = 0; + private final Set selected = new HashSet<>(); + private BiFunction, T, ListCell> factory = (listView, item) -> ListCell.of(item, listView.getItemStyle()); @@ -76,6 +83,7 @@ public enum ItemStyle { * The item is part of a radio group and will indicate selected state. */ RADIO + } public ListView() { @@ -94,7 +102,7 @@ public ListView(T[] items, ItemStyle itemStyle) { public ListView(@Nullable List items, ItemStyle itemStyle) { Assert.notNull(itemStyle, "item style must be set"); - this.itemStyle = itemStyle; + this.itemStyle = itemStyle; setItems(items); } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuBarView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuBarView.java index b87550ae6..462de497b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuBarView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuBarView.java @@ -40,8 +40,8 @@ import org.springframework.shell.style.ThemeResolver; /** - * {@link MenuBarView} shows {@link MenuBarItem items} horizontally and is - * typically used in layouts which builds complete terminal UI's. + * {@link MenuBarView} shows {@link MenuBarItem items} horizontally and is typically used + * in layouts which builds complete terminal UI's. * * Internally {@link MenuView} is used to show the menus. * @@ -50,8 +50,11 @@ public class MenuBarView extends BoxView { private final Logger log = LoggerFactory.getLogger(MenuBarView.class); + private final List items = new ArrayList<>(); + private MenuView currentMenuView; + private int activeItemIndex = -1; // Need to keep menuviews alive not to lose their states @@ -59,7 +62,6 @@ public class MenuBarView extends BoxView { /** * Construct menubar view with menubar items. - * * @param items the menubar items */ public MenuBarView(MenuBarItem[] items) { @@ -68,7 +70,6 @@ public MenuBarView(MenuBarItem[] items) { /** * Construct menubar view with menubar items. - * * @param items the menubar items */ public static MenuBarView of(MenuBarItem... items) { @@ -127,7 +128,6 @@ public MouseHandler getMouseHandler() { /** * Gets a menubar items. - * * @return menubar items */ public List getItems() { @@ -137,7 +137,6 @@ public List getItems() { /** * Sets a selected index. If given index is not within bounds of size of items, * selection is set to {@code -1} effectively un-selecting active item. - * * @param index the new index */ public void setSelected(int index) { @@ -258,17 +257,15 @@ private MenuView buildMenuView(MenuBarItem item) { int x = positionAtIndex(activeItemIndex); Dimension dim = menuView.getPreferredDimension(); menuView.setRect(rect.x() + x, rect.y() + 1, dim.width(), dim.height()); - menuView.onDestroy(getEventLoop().viewEvents(MenuViewOpenSelectedItemEvent.class, menuView) - .subscribe(event -> { - closeCurrentMenuView(); - })); + menuView.onDestroy(getEventLoop().viewEvents(MenuViewOpenSelectedItemEvent.class, menuView).subscribe(event -> { + closeCurrentMenuView(); + })); return menuView; } /** * Sets items. - * * @param items status items */ public void setItems(List items) { @@ -286,11 +283,9 @@ private void selectItem(MenuBarItem item) { } private void registerHotKeys() { - getItems().stream() - .filter(item -> item.getHotKey() != null) - .forEach(item -> { - registerHotKeyBinding(item.getHotKey(), () -> selectItem(item)); - }); + getItems().stream().filter(item -> item.getHotKey() != null).forEach(item -> { + registerHotKeyBinding(item.getHotKey(), () -> selectItem(item)); + }); } /** @@ -299,7 +294,9 @@ private void registerHotKeys() { public static class MenuBarItem { private String title; + private List items; + private Integer hotKey; public MenuBarItem(String title) { @@ -331,6 +328,7 @@ public MenuBarItem setHotKey(Integer hotKey) { this.hotKey = hotKey; return this; } + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java index b41fc09e5..717a51d1e 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/MenuView.java @@ -39,15 +39,17 @@ import org.springframework.util.StringUtils; /** - * {@link MenuView} shows {@link MenuView} items vertically and is - * typically used in layouts which builds complete terminal UI's. + * {@link MenuView} shows {@link MenuView} items vertically and is typically used in + * layouts which builds complete terminal UI's. * * @author Janne Valkealahti */ public class MenuView extends BoxView { private final Logger log = LoggerFactory.getLogger(MenuView.class); + private final List items = new ArrayList<>(); + private int activeItemIndex = -1; // we support only one radio group @@ -65,7 +67,6 @@ public MenuView() { /** * Construct menu view with menu items. - * * @param items the menu items */ public MenuView(MenuItem[] items) { @@ -74,7 +75,6 @@ public MenuView(MenuItem[] items) { /** * Construct menu view with menu items. - * * @param items the menu items */ public MenuView(@Nullable List items) { @@ -82,9 +82,8 @@ public MenuView(@Nullable List items) { } /** - * Sets a new menu items. Will always clear existing items and if {@code null} - * is passed this effectively keeps items empty. - * + * Sets a new menu items. Will always clear existing items and if {@code null} is + * passed this effectively keeps items empty. * @param items the menu items */ public void setItems(@Nullable List items) { @@ -108,7 +107,6 @@ else if (i.initialCheckState && i.getCheckStyle() == MenuItemCheckStyle.RADIO) { /** * Gets a menu items. - * * @return the menu items */ public List getItems() { @@ -117,7 +115,6 @@ public List getItems() { /** * Gets a preferred dimension menu needs to show it's content. - * * @return preferred dimension */ public Dimension getPreferredDimension() { @@ -146,12 +143,12 @@ protected void drawInternal(Screen screen) { int selectedStyle = resolveThemeStyle(StyleSettings.TAG_HIGHLIGHT, ScreenItem.STYLE_BOLD); int selectedForegroundColor = resolveThemeForeground(StyleSettings.TAG_HIGHLIGHT, -1, -1); int selectedBackgroundColor = resolveThemeBackground(StyleSettings.TAG_HIGHLIGHT, -1, -1); - Writer writer = screen.writerBuilder() - .layer(getLayer()).build(); + Writer writer = screen.writerBuilder().layer(getLayer()).build(); Writer selectedWriter = screen.writerBuilder() .layer(getLayer()) .color(selectedForegroundColor) - .style(selectedStyle).build(); + .style(selectedStyle) + .build(); int i = 0; boolean hasCheck = false; for (MenuItem item : items) { @@ -224,7 +221,6 @@ private void mouseSelect(MouseEvent event) { /** * Toggle {@link MenuItem} checked state. - * * @param item the menu item to toggle */ public void toggle(MenuItem item) { @@ -274,7 +270,7 @@ private void setSelected(int index) { if (index >= items.size()) { activeItemIndex = 0; } - else if(index < 0) { + else if (index < 0) { activeItemIndex = items.size() - 1; } else { @@ -289,7 +285,6 @@ else if(index < 0) { /** * Gets an index of a item at given position. Returns negative index if position * doesn't map to existing item. - * * @param x the x coordinate * @param y the y coordinate * @return an index or negative if not found @@ -328,6 +323,7 @@ public enum MenuItemCheckStyle { * The menu item is part of a menu radio group and will indicate selected state. */ RADIO + } /** @@ -335,17 +331,20 @@ public enum MenuItemCheckStyle { * * @see Menu */ - public static class MenuItem { + public static class MenuItem { private final String title; + private final MenuItemCheckStyle checkStyle; + private final List items; + private Runnable action; + private boolean initialCheckState = false; /** * Construct menu item with a title. - * * @param title the title */ public MenuItem(String title) { @@ -354,7 +353,6 @@ public MenuItem(String title) { /** * Construct menu item with a title and a check style. - * * @param title the title * @param checkStyle the check style */ @@ -364,7 +362,6 @@ public MenuItem(String title, MenuItemCheckStyle checkStyle) { /** * Construct menu item with a title, a check style and a runnable. - * * @param title the title * @param checkStyle the check style * @param action the action to run when item is chosen @@ -374,9 +371,8 @@ public MenuItem(String title, MenuItemCheckStyle checkStyle, Runnable action) { } /** - * Construct menu item with a title, a check style, a runnable and initial - * checked state. - * + * Construct menu item with a title, a check style, a runnable and initial checked + * state. * @param title the title * @param checkStyle the check style * @param action the action to run when item is chosen @@ -406,7 +402,6 @@ protected MenuItem(String title, List items) { /** * Return a {@link MenuItem} with a given {@code title}. - * * @param title the title * @return a menu item */ @@ -415,9 +410,7 @@ public static MenuItem of(String title) { } /** - * Return a {@link MenuItem} with a given {@code title} and a - * {@code check style}. - * + * Return a {@link MenuItem} with a given {@code title} and a {@code check style}. * @param title the title * @param checkStyle the check style * @return a menu item @@ -430,7 +423,8 @@ public static MenuItem of(String title, MenuItemCheckStyle checkStyle, Runnable return new MenuItem(title, checkStyle, action); } - public static MenuItem of(String title, MenuItemCheckStyle checkStyle, Runnable action, boolean initialCheckState) { + public static MenuItem of(String title, MenuItemCheckStyle checkStyle, Runnable action, + boolean initialCheckState) { return new MenuItem(title, checkStyle, action, initialCheckState); } @@ -444,7 +438,6 @@ public void setAction(Runnable action) { /** * Gets initial check state. - * * @return initial check state */ public boolean isInitialCheckState() { @@ -453,7 +446,6 @@ public boolean isInitialCheckState() { /** * Get a {@code title}. Never null, empty or just having white spaces. - * * @return a title */ public String getTitle() { @@ -461,9 +453,8 @@ public String getTitle() { } /** - * Gets a check style. This will be {@code null} if constructed via - * {@link Menu} as style doesn't apply items being a sub-menu. - * + * Gets a check style. This will be {@code null} if constructed via {@link Menu} + * as style doesn't apply items being a sub-menu. * @return a check style */ @Nullable @@ -474,18 +465,18 @@ public MenuItemCheckStyle getCheckStyle() { /** * Gets sub menu items. This will be {@code null} if not constructed via * {@link Menu} as plain {@link MenuItem} can't have other items. - * * @return a menu items */ @Nullable public List getItems() { return items; } + } /** - * {@link Menu} represents an item in a {@link MenuView} being a specialisation - * of {@link MenuItem} indicating it having a sub-menu. + * {@link Menu} represents an item in a {@link MenuView} being a specialisation of + * {@link MenuItem} indicating it having a sub-menu. * * @see MenuItem */ @@ -493,7 +484,6 @@ public static class Menu extends MenuItem { /** * Construct menu with a title. - * * @param title the title */ public Menu(String title) { @@ -502,7 +492,6 @@ public Menu(String title) { /** * Construct menu with a title and a menu items. - * * @param title the title * @param items the menu items */ @@ -512,7 +501,6 @@ public Menu(String title, MenuItem[] items) { /** * Construct menu with a title and a menu items. - * * @param title the title * @param items the menu items */ @@ -522,7 +510,6 @@ public Menu(String title, List items) { /** * Return a {@link Menu} with a given {@code title} and {@link MenuItem}s. - * * @param title the title * @param items the menu items * @return a menu @@ -530,6 +517,7 @@ public Menu(String title, List items) { public static Menu of(String title, MenuItem... items) { return new Menu(title, items); } + } /** diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ProgressView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ProgressView.java index 45679c268..15a9ecc82 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ProgressView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ProgressView.java @@ -53,62 +53,71 @@ public class ProgressView extends BoxView { private final static Logger log = LoggerFactory.getLogger(ProgressView.class); + private final int tickStart; + private final int tickEnd; + private int tickValue; + private boolean running = false; + private String description; + private Spinner spinner; + private List items; + private GridView grid; + private long startTime; + private long updateTime; + private List> cells = new ArrayList<>(); - private final static Function> DEFAULT_DESCRIPTION_FACTORY = - (item) -> TextCell.of(item, ctx -> { + private final static Function> DEFAULT_DESCRIPTION_FACTORY = ( + item) -> TextCell.of(item, ctx -> { return ctx.getDescription(); }); - private final static Function> DEFAULT_PERCENT_FACTORY = - (item) -> { - TextCell cell = TextCell.of(item, ctx -> { - ProgressState state = ctx.getState(); - int percentAbs = state.tickEnd() - state.tickStart(); - int relativeValue = state.tickValue() - state.tickStart(); - int percent = (relativeValue * 100) / percentAbs; - return String.format("%s%%", percent); - }); - return cell; - }; - - private final static Function> DEFAULT_SPINNER_FACTORY = - item -> { - TextCell cell = TextCell.of(item, ctx -> { - int frame = 0; - - // via view setting, then via theming, then fallback default - Spinner spin = ctx.resolveThemeSpinner(SpinnerSettings.TAG_DOT, ctx.getSpinner(), - Spinner.of(Spinner.LINE1, 130)); - - if (ctx.getState().running()) { - // we know start time and current update time, - // calculate elapsed time "frame" to pick rolling - // spinner frame. - int interval = spin.getInterval(); - long startTime = ctx.getState().startTime(); - long updateTime = ctx.getState().updateTime(); - long elapsedTime = updateTime - startTime; - long elapsedFrame = elapsedTime / interval; - frame = (int) elapsedFrame % spin.getFrames().length; - log.debug("Calculate frame {} {} {}", interval, elapsedTime, elapsedFrame); - } - log.debug("Drawing frame {}", frame); - - return String.format("%s", spin.getFrames()[frame]); - }); - return cell; - }; + private final static Function> DEFAULT_PERCENT_FACTORY = (item) -> { + TextCell cell = TextCell.of(item, ctx -> { + ProgressState state = ctx.getState(); + int percentAbs = state.tickEnd() - state.tickStart(); + int relativeValue = state.tickValue() - state.tickStart(); + int percent = (relativeValue * 100) / percentAbs; + return String.format("%s%%", percent); + }); + return cell; + }; + + private final static Function> DEFAULT_SPINNER_FACTORY = item -> { + TextCell cell = TextCell.of(item, ctx -> { + int frame = 0; + + // via view setting, then via theming, then fallback default + Spinner spin = ctx.resolveThemeSpinner(SpinnerSettings.TAG_DOT, ctx.getSpinner(), + Spinner.of(Spinner.LINE1, 130)); + + if (ctx.getState().running()) { + // we know start time and current update time, + // calculate elapsed time "frame" to pick rolling + // spinner frame. + int interval = spin.getInterval(); + long startTime = ctx.getState().startTime(); + long updateTime = ctx.getState().updateTime(); + long elapsedTime = updateTime - startTime; + long elapsedFrame = elapsedTime / interval; + frame = (int) elapsedFrame % spin.getFrames().length; + log.debug("Calculate frame {} {} {}", interval, elapsedTime, elapsedFrame); + } + log.debug("Drawing frame {}", frame); + + return String.format("%s", spin.getFrames()[frame]); + }); + return cell; + }; /** * Construct view with {@code tickStart 0} and {@code tickEnd 100}. Uses default @@ -121,9 +130,8 @@ public ProgressView() { /** * Construct view with {@code tickStart 0} and {@code tickEnd 100}. Uses default * {@link ProgressViewItem}s. - * * @param tickStart the tick start - * @param tickEnd the tick end + * @param tickEnd the tick end */ public ProgressView(int tickStart, int tickEnd) { this(tickStart, tickEnd, new ProgressViewItem[] { ProgressViewItem.ofText(), ProgressViewItem.ofSpinner(), @@ -131,9 +139,8 @@ public ProgressView(int tickStart, int tickEnd) { } /** - * Construct view with given {@link ProgressViewItem}s using {@code tickStart 0} - * and {@code tickEnd 100}. - * + * Construct view with given {@link ProgressViewItem}s using {@code tickStart 0} and + * {@code tickEnd 100}. * @param items the progress view items */ public ProgressView(ProgressViewItem... items) { @@ -142,9 +149,8 @@ public ProgressView(ProgressViewItem... items) { /** * Construct view with given bounds for {@code tickStart} and {@code tickEnd}. - * {@code tickStart} needs to be equal or more than zero. {@code tickEnd} needs - * to be higher than {@code tickStart}. Uses defined progress view items. - * + * {@code tickStart} needs to be equal or more than zero. {@code tickEnd} needs to be + * higher than {@code tickStart}. Uses defined progress view items. * @param tickStart the tick start * @param tickEnd the tick end * @param items the progress view items @@ -161,16 +167,19 @@ public ProgressView(int tickStart, int tickEnd, ProgressViewItem... items) { } /** - * Defines an item within a progress view. Allows to set item's factory, size - * and horizontal alignment. + * Defines an item within a progress view. Allows to set item's factory, size and + * horizontal alignment. */ public static class ProgressViewItem { private final Function> factory; + private final int size; + private final HorizontalAlign align; - public ProgressViewItem(Function> factory, int size, HorizontalAlign align) { + public ProgressViewItem(Function> factory, int size, + HorizontalAlign align) { this.factory = factory; this.size = size; this.align = align; @@ -199,11 +208,11 @@ public static ProgressViewItem ofPercent() { public static ProgressViewItem ofPercent(int size, HorizontalAlign hAligh) { return new ProgressViewItem(DEFAULT_PERCENT_FACTORY, size, hAligh); } + } /** * Gets a progress description. - * * @return a progress description */ public String getDescription() { @@ -212,7 +221,6 @@ public String getDescription() { /** * Sets a progress description. Used in items as a text item. - * * @param description the progress description */ public void setDescription(String description) { @@ -221,7 +229,6 @@ public void setDescription(String description) { /** * Sets an explicit spinner to use. - * * @param spinner the spinner to use */ public void setSpinner(Spinner spinner) { @@ -243,7 +250,9 @@ public void start() { } private Disposable.Composite disposables; + private final String TAG_KEY = "ProgressView"; + private final String TAG_VALUE = UUID.randomUUID().toString(); private void scheduleTicks() { @@ -255,8 +264,7 @@ private void scheduleTicks() { return; } Flux> ticks = Flux.interval(Duration.ofMillis(50)).map(l -> { - Message message = MessageBuilder - .withPayload(l) + Message message = MessageBuilder.withPayload(l) .setHeader(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.USER) .setHeader(TAG_KEY, TAG_VALUE) .build(); @@ -300,10 +308,13 @@ public void stop() { } private static class BoxWrapper extends BoxView { + TextCell delegate; + BoxWrapper(TextCell delegate) { this.delegate = delegate; } + @Override protected void drawInternal(Screen screen) { Rectangle rect = getRect(); @@ -311,6 +322,7 @@ protected void drawInternal(Screen screen) { delegate.draw(screen); super.drawInternal(screen); } + } private void initLayout() { @@ -348,9 +360,8 @@ protected void drawInternal(Screen screen) { } /** - * Advance {@code tickValue} by a given count. Note that negative count - * will advance backwards. - * + * Advance {@code tickValue} by a given count. Note that negative count will advance + * backwards. * @param count the count to advance tick value */ public void tickAdvance(int count) { @@ -359,9 +370,8 @@ public void tickAdvance(int count) { /** * Sets a tick value. If value is lower or higher than {@code tickStart} or - * {@code tickEnd} respectively {@code tickValue} will be set to low/high - * bounds. This means {@code tickValue} is always kept within range inclusively. - * + * {@code tickEnd} respectively {@code tickValue} will be set to low/high bounds. This + * means {@code tickValue} is always kept within range inclusively. * @param value the new tick value to set */ public void setTickValue(int value) { @@ -387,7 +397,6 @@ else if (value < tickStart) { /** * Gets a state of this {@code ProgressView}. - * * @return a view progress state */ public ProgressState getState() { @@ -436,36 +445,31 @@ public interface ProgressContext { /** * Get a {@link ProgressView} description. - * * @return a progress description */ String getDescription(); /** * Get a state of a {@link ProgressView}. - * * @return progress view state */ ProgressState getState(); /** * Gets an encapsulating owner view. - * * @return an owner view */ ProgressView getView(); /** * Gets a {@link Spinner} frames. - * * @return spinner frames */ Spinner getSpinner(); /** - * Resolve style using existing {@link ThemeResolver} and {@code theme name}. - * Use {@code defaultStyle} if resolving cannot happen. - * + * Resolve style using existing {@link ThemeResolver} and {@code theme name}. Use + * {@code defaultStyle} if resolving cannot happen. * @param tag the style tag to use * @param defaultStyle the default style to use * @return resolved style diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Spinner.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Spinner.java index 9c2dbab8c..8c593dce2 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Spinner.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/Spinner.java @@ -16,9 +16,9 @@ package org.springframework.shell.component.view.control; /** - * {@code Spinner} represents how user is notified that something is happening - * using a traditional spinner concept. Represented in a console with an array - * of characters which are looped. + * {@code Spinner} represents how user is notified that something is happening using a + * traditional spinner concept. Represented in a console with an array of characters which + * are looped. * * @author Janne Valkealahti */ @@ -26,23 +26,20 @@ public interface Spinner { /** * Gets a frame characters. Type is {@link String} to support unicode. - * * @return a frame characters */ String[] getFrames(); /** - * Gets an interval which should be used to estimate how often frame - * should get changed. This is always an estimate as actual change - * depends how ofter console gets redrawn. - * + * Gets an interval which should be used to estimate how often frame should get + * changed. This is always an estimate as actual change depends how ofter console gets + * redrawn. * @return an interval in milliseconds */ int getInterval(); /** * Construct {@link Spinner} from given frames and interval. - * * @param frames the spinner frames * @param interval the spinner interval * @return a Spinner implementation @@ -63,280 +60,41 @@ public int getInterval() { }; } - final static String[] LINE1 = new String[] { - "-", - "\\", - "|", - "/" - }; + final static String[] LINE1 = new String[] { "-", "\\", "|", "/" }; - final static String[] DOTS1 = new String[] { - "⠋", - "⠙", - "⠹", - "⠸", - "⠼", - "⠴", - "⠦", - "⠧", - "⠇", - "⠏" - }; + final static String[] DOTS1 = new String[] { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" }; - final static String[] DOTS2 = new String[] { - "⣾", - "⣽", - "⣻", - "⢿", - "⡿", - "⣟", - "⣯", - "⣷" - }; + final static String[] DOTS2 = new String[] { "⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷" }; - final static String[] DOTS3 = new String[] { - "⠋", - "⠙", - "⠚", - "⠞", - "⠖", - "⠦", - "⠴", - "⠲", - "⠳", - "⠓" - }; + final static String[] DOTS3 = new String[] { "⠋", "⠙", "⠚", "⠞", "⠖", "⠦", "⠴", "⠲", "⠳", "⠓" }; - final static String[] DOTS4 = new String[] { - "⠄", - "⠆", - "⠇", - "⠋", - "⠙", - "⠸", - "⠰", - "⠠", - "⠰", - "⠸", - "⠙", - "⠋", - "⠇", - "⠆" - }; + final static String[] DOTS4 = new String[] { "⠄", "⠆", "⠇", "⠋", "⠙", "⠸", "⠰", "⠠", "⠰", "⠸", "⠙", "⠋", "⠇", "⠆" }; - final static String[] DOTS5 = new String[] { - "⠋", - "⠙", - "⠚", - "⠒", - "⠂", - "⠂", - "⠒", - "⠲", - "⠴", - "⠦", - "⠖", - "⠒", - "⠐", - "⠐", - "⠒", - "⠓", - "⠋" - }; + final static String[] DOTS5 = new String[] { "⠋", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠦", "⠖", "⠒", "⠐", "⠐", + "⠒", "⠓", "⠋" }; - final static String[] DOTS6 = new String[] { - "⠁", - "⠉", - "⠙", - "⠚", - "⠒", - "⠂", - "⠂", - "⠒", - "⠲", - "⠴", - "⠤", - "⠄", - "⠄", - "⠤", - "⠴", - "⠲", - "⠒", - "⠂", - "⠂", - "⠒", - "⠚", - "⠙", - "⠉", - "⠁" - }; + final static String[] DOTS6 = new String[] { "⠁", "⠉", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠤", "⠄", "⠄", "⠤", + "⠴", "⠲", "⠒", "⠂", "⠂", "⠒", "⠚", "⠙", "⠉", "⠁" }; - final static String[] DOTS7 = new String[] { - "⠈", - "⠉", - "⠋", - "⠓", - "⠒", - "⠐", - "⠐", - "⠒", - "⠖", - "⠦", - "⠤", - "⠠", - "⠠", - "⠤", - "⠦", - "⠖", - "⠒", - "⠐", - "⠐", - "⠒", - "⠓", - "⠋", - "⠉", - "⠈" - }; + final static String[] DOTS7 = new String[] { "⠈", "⠉", "⠋", "⠓", "⠒", "⠐", "⠐", "⠒", "⠖", "⠦", "⠤", "⠠", "⠠", "⠤", + "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋", "⠉", "⠈" }; - final static String[] DOTS8 = new String[] { - "⠁", - "⠁", - "⠉", - "⠙", - "⠚", - "⠒", - "⠂", - "⠂", - "⠒", - "⠲", - "⠴", - "⠤", - "⠄", - "⠄", - "⠤", - "⠠", - "⠠", - "⠤", - "⠦", - "⠖", - "⠒", - "⠐", - "⠐", - "⠒", - "⠓", - "⠋", - "⠉", - "⠈", - "⠈" - }; + final static String[] DOTS8 = new String[] { "⠁", "⠁", "⠉", "⠙", "⠚", "⠒", "⠂", "⠂", "⠒", "⠲", "⠴", "⠤", "⠄", "⠄", + "⠤", "⠠", "⠠", "⠤", "⠦", "⠖", "⠒", "⠐", "⠐", "⠒", "⠓", "⠋", "⠉", "⠈", "⠈" }; - final static String[] DOTS9 = new String[] { - "⢹", - "⢺", - "⢼", - "⣸", - "⣇", - "⡧", - "⡗", - "⡏" - }; + final static String[] DOTS9 = new String[] { "⢹", "⢺", "⢼", "⣸", "⣇", "⡧", "⡗", "⡏" }; - final static String[] DOTS10 = new String[] { - "⢄", - "⢂", - "⢁", - "⡁", - "⡈", - "⡐", - "⡠" - }; + final static String[] DOTS10 = new String[] { "⢄", "⢂", "⢁", "⡁", "⡈", "⡐", "⡠" }; - final static String[] DOTS11 = new String[] { - "⠁", - "⠂", - "⠄", - "⡀", - "⢀", - "⠠", - "⠐", - "⠈" - }; + final static String[] DOTS11 = new String[] { "⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈" }; - final static String[] DOTS12 = new String[] { - "⢀⠀", - "⡀⠀", - "⠄⠀", - "⢂⠀", - "⡂⠀", - "⠅⠀", - "⢃⠀", - "⡃⠀", - "⠍⠀", - "⢋⠀", - "⡋⠀", - "⠍⠁", - "⢋⠁", - "⡋⠁", - "⠍⠉", - "⠋⠉", - "⠋⠉", - "⠉⠙", - "⠉⠙", - "⠉⠩", - "⠈⢙", - "⠈⡙", - "⢈⠩", - "⡀⢙", - "⠄⡙", - "⢂⠩", - "⡂⢘", - "⠅⡘", - "⢃⠨", - "⡃⢐", - "⠍⡐", - "⢋⠠", - "⡋⢀", - "⠍⡁", - "⢋⠁", - "⡋⠁", - "⠍⠉", - "⠋⠉", - "⠋⠉", - "⠉⠙", - "⠉⠙", - "⠉⠩", - "⠈⢙", - "⠈⡙", - "⠈⠩", - "⠀⢙", - "⠀⡙", - "⠀⠩", - "⠀⢘", - "⠀⡘", - "⠀⠨", - "⠀⢐", - "⠀⡐", - "⠀⠠", - "⠀⢀", - "⠀⡀" - }; + final static String[] DOTS12 = new String[] { "⢀⠀", "⡀⠀", "⠄⠀", "⢂⠀", "⡂⠀", "⠅⠀", "⢃⠀", "⡃⠀", "⠍⠀", "⢋⠀", "⡋⠀", + "⠍⠁", "⢋⠁", "⡋⠁", "⠍⠉", "⠋⠉", "⠋⠉", "⠉⠙", "⠉⠙", "⠉⠩", "⠈⢙", "⠈⡙", "⢈⠩", "⡀⢙", "⠄⡙", "⢂⠩", "⡂⢘", "⠅⡘", "⢃⠨", + "⡃⢐", "⠍⡐", "⢋⠠", "⡋⢀", "⠍⡁", "⢋⠁", "⡋⠁", "⠍⠉", "⠋⠉", "⠋⠉", "⠉⠙", "⠉⠙", "⠉⠩", "⠈⢙", "⠈⡙", "⠈⠩", "⠀⢙", "⠀⡙", + "⠀⠩", "⠀⢘", "⠀⡘", "⠀⠨", "⠀⢐", "⠀⡐", "⠀⠠", "⠀⢀", "⠀⡀" }; - final static String[] DOTS13 = new String[] { - "⣼", - "⣹", - "⢻", - "⠿", - "⡟", - "⣏", - "⣧", - "⣶" - }; + final static String[] DOTS13 = new String[] { "⣼", "⣹", "⢻", "⠿", "⡟", "⣏", "⣧", "⣶" }; - final static String[] DOTS14 = new String[] { - ". ", - " . ", - " . ", - " ." - }; + final static String[] DOTS14 = new String[] { ". ", " . ", " . ", " ." }; } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/StatusBarView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/StatusBarView.java index a47be39cc..6794c82e8 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/StatusBarView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/StatusBarView.java @@ -35,20 +35,21 @@ import org.springframework.util.StringUtils; /** - * {@link StatusBarView} shows {@link StatusItem items} horizontally and is - * typically used in layouts which builds complete terminal UI's. + * {@link StatusBarView} shows {@link StatusItem items} horizontally and is typically used + * in layouts which builds complete terminal UI's. * - * {@link StatusItem item} {@code primary} denotes if item is drawn to left - * or right, {@code priority} on which order items are drawn until bar runs - * out of space. Default {@code primary} is {@code true} and {@code priority} - * is {@code 0}. + * {@link StatusItem item} {@code primary} denotes if item is drawn to left or right, + * {@code priority} on which order items are drawn until bar runs out of space. Default + * {@code primary} is {@code true} and {@code priority} is {@code 0}. * * @author Janne Valkealahti */ public class StatusBarView extends BoxView { private final Logger log = LoggerFactory.getLogger(StatusBarView.class); + private final List items = new ArrayList<>(); + private String itemSeparator = " | "; public StatusBarView() { @@ -70,7 +71,6 @@ protected String getBackgroundStyle() { /** * Gets the item separator. - * * @return a separator */ @Nullable @@ -79,9 +79,8 @@ public String getItemSeparator() { } /** - * Sets the item separator. Separator can be {@code null} or empty which - * essentially disables it. - * + * Sets the item separator. Separator can be {@code null} or empty which essentially + * disables it. * @param itemSeparator the item separator */ public void setItemSeparator(@Nullable String itemSeparator) { @@ -170,7 +169,6 @@ private StatusItem itemAt(int x, int y) { /** * Sets items. - * * @param items status items */ public void setItems(List items) { @@ -194,7 +192,6 @@ else if (!o1.primary && o2.primary) { /** * Gets a status items. - * * @return the status items */ public List getItems() { @@ -202,14 +199,12 @@ public List getItems() { } private void registerHotKeys() { - getItems().stream() - .filter(item -> item.getHotKey() != null) - .forEach(item -> { - Runnable action = item.getAction(); - if (action != null) { - registerHotKeyBinding(item.getHotKey(), action); - } - }); + getItems().stream().filter(item -> item.getHotKey() != null).forEach(item -> { + Runnable action = item.getAction(); + if (action != null) { + registerHotKeyBinding(item.getHotKey(), action); + } + }); } /** @@ -218,9 +213,13 @@ private void registerHotKeys() { public static class StatusItem { private String title; + private Runnable action; + private Integer hotKey; + private boolean primary = true; + private int priority = 0; public StatusItem(String title) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/View.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/View.java index dce078e62..f751a6a08 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/View.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/View.java @@ -23,8 +23,8 @@ import org.springframework.shell.component.view.event.MouseHandler; /** - * Base interface for all views. Represents a visible element that can render - * itself and contains zero or more nested {@code Views}. + * Base interface for all views. Represents a visible element that can render itself and + * contains zero or more nested {@code Views}. * * @author Janne Valkealahti */ @@ -34,14 +34,12 @@ public interface View extends Control { /** * Sets a layer index this {@code View} operates on. - * * @param index the layer index */ void setLayer(int index); /** * Called when {@code View} gets or loses a focus. - * * @param view the view receiving focus * @param focus flag if focus is received */ @@ -49,15 +47,13 @@ public interface View extends Control { /** * Gets if this {@code View} has a focus. - * * @return true if view has a focus */ boolean hasFocus(); /** - * Gets a {@link View} mouse {@link MouseHandler}. Can be {@code null} which - * indicates view will not handle any mouse events. - * + * Gets a {@link View} mouse {@link MouseHandler}. Can be {@code null} which indicates + * view will not handle any mouse events. * @return a view mouse handler * @see MouseHandler */ @@ -65,9 +61,8 @@ public interface View extends Control { MouseHandler getMouseHandler(); /** - * Gets a {@link View} key {@link KeyHandler}. Can be {@code null} which - * indicates view will not handle any key events. - * + * Gets a {@link View} key {@link KeyHandler}. Can be {@code null} which indicates + * view will not handle any key events. * @return a view key handler * @see KeyHandler */ @@ -75,9 +70,8 @@ public interface View extends Control { KeyHandler getKeyHandler(); /** - * Gets a {@link View} hotkey {@link KeyHandler}. Can be {@code null} which - * indicates view will not handle any key events. - * + * Gets a {@link View} hotkey {@link KeyHandler}. Can be {@code null} which indicates + * view will not handle any key events. * @return a view hotkey handler * @see KeyHandler */ @@ -86,21 +80,18 @@ public interface View extends Control { /** * Sets an {@link EventLoop}. - * * @param eventLoop the event loop */ void setEventLoop(@Nullable EventLoop eventLoop); /** * Sets a {@link ViewService}. - * * @param viewService the view service */ void setViewService(ViewService viewService); /** * Get supported commands. - * * @return supported commands * @see ViewCommand */ @@ -108,10 +99,10 @@ public interface View extends Control { /** * Run command. - * * @param command the command to run * @return true if command was succesfully dispatched * @see ViewCommand */ boolean runViewCommand(String command); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewCommand.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewCommand.java index 83ee8547f..57b3e1b51 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewCommand.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewCommand.java @@ -16,10 +16,10 @@ package org.springframework.shell.component.view.control; /** - * Commands which can be performed by the application or bound to keys in a - * {@link View}. This class is a placeholder for constants of types usually - * needed in a views. We've chosen this not to be enumerable so that there - * would not be restrictions in an api's to use these types. + * Commands which can be performed by the application or bound to keys in a {@link View}. + * This class is a placeholder for constants of types usually needed in a views. We've + * chosen this not to be enumerable so that there would not be restrictions in an api's to + * use these types. * * @author Janne Valkealahti */ diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewDoneEvent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewDoneEvent.java index 834339a7c..20883acc9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewDoneEvent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewDoneEvent.java @@ -24,7 +24,6 @@ public interface ViewDoneEvent extends ViewEvent { /** * Create a generic event with empty view args. - * * @param view the view * @return a generic view done event */ diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEvent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEvent.java index d612c74f7..341781380 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEvent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEvent.java @@ -27,4 +27,5 @@ public interface ViewEvent { default ViewEventArgs args() { return ViewEventArgs.EMPTY; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEventArgs.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEventArgs.java index 13d8191b7..4479af55c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEventArgs.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewEventArgs.java @@ -24,4 +24,5 @@ public interface ViewEventArgs { public static final ViewEventArgs EMPTY = new ViewEventArgs() { }; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewService.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewService.java index 0a639d358..5380ee2dd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewService.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/ViewService.java @@ -26,7 +26,6 @@ public interface ViewService { /** * Gets a current modal view. - * * @return current modal view */ @Nullable @@ -34,15 +33,14 @@ public interface ViewService { /** * Sets a new modal view. Setting modal to {@code null} clears existing modal. - * * @param view a view to use as modal */ void setModal(@Nullable View view); /** * Sets a view to be focused. Setting focus to {@code null} clears focused view. - * * @param view a view to be focused */ void setFocus(@Nullable View view); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/WindowView.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/WindowView.java index 4fd589a88..94ff381e1 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/WindowView.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/WindowView.java @@ -19,7 +19,6 @@ import org.springframework.shell.geom.Rectangle; import org.springframework.shell.style.StyleSettings; - /** * {@code WindowView} is a {@link View} defining area within view itself. * @@ -28,16 +27,19 @@ public class WindowView extends AbstractView { private int backgroundColor = -1; + private int minWidth = 30; + private int maxWidth = 60; + private int minHeight = 8; + private int maxHeight = 12; /** * Sets a background color. If color is set to {@code null} it indicates that * background should be set to be {@code empty} causing possible layer to be * non-transparent. - * * @param backgroundColor the background color */ public void setBackgroundColor(int backgroundColor) { @@ -57,7 +59,6 @@ protected void drawInternal(Screen screen) { /** * Gets an inner rectangle of this view. - * * @return an inner rectangle of this view */ protected Rectangle getInnerRect() { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractCell.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractCell.java index d19c0115d..fc02594f4 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractCell.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractCell.java @@ -26,8 +26,11 @@ public abstract class AbstractCell extends AbstractControl implements Cell { private T item; + private int style = -1; + private int foregroundColor = -1; + private int backgroundColor = -1; public AbstractCell(T item) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractListCell.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractListCell.java index b48d2cb80..e76ff3d08 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractListCell.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractListCell.java @@ -30,6 +30,7 @@ public abstract class AbstractListCell extends AbstractCell implements ListCell { private ItemStyle itemStyle; + private boolean selected; public AbstractListCell(T item) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractTextCell.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractTextCell.java index bbcc207b1..4273917f0 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractTextCell.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/AbstractTextCell.java @@ -32,7 +32,9 @@ public abstract class AbstractTextCell extends AbstractCell implements TextCell { private Function itemFunction; + private HorizontalAlign hAlign = HorizontalAlign.CENTER; + private VerticalAlign vAlign = VerticalAlign.CENTER; public AbstractTextCell(T item, Function itemFunction) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/Cell.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/Cell.java index 107dab78b..d6b918d15 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/Cell.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/Cell.java @@ -20,10 +20,10 @@ import org.springframework.shell.component.view.screen.Screen; /** - * Base interface for all cells. Typically a {@link Cell} is a building block in - * a {@link View} not needing to be aware of how it is drawn into a {@link Screen} - * but needs to aware of its "item", bounds via {@link Control} and other - * properties like {@code background}. + * Base interface for all cells. Typically a {@link Cell} is a building block in a + * {@link View} not needing to be aware of how it is drawn into a {@link Screen} but needs + * to aware of its "item", bounds via {@link Control} and other properties like + * {@code background}. * * @author Janne Valkealahti */ @@ -31,35 +31,30 @@ public interface Cell extends Control { /** * Get item bound to a cell. - * * @return item bound to a cell */ T getItem(); /** * Sets an item to bound into a cell. - * * @param item item to bound into a cell */ void setItem(T item); /** * Sets a style. - * * @param style the style */ void setStyle(int style); /** * Sets a foreground color. - * * @param foregroundColor the background color */ void setForegroundColor(int foregroundColor); /** * Sets a background color. - * * @param backgroundColor the background color */ void setBackgroundColor(int backgroundColor); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/ListCell.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/ListCell.java index 48a142f82..e020af443 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/ListCell.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/ListCell.java @@ -26,21 +26,18 @@ public interface ListCell extends Cell { /** * Set {@link ItemStyle}. - * * @param itemStyle the item style */ void setItemStyle(ItemStyle itemStyle); /** * Set selection state. - * * @param selected the selection state */ void setSelected(boolean selected); /** * Helper method to build a {@code ListCell}. - * * @param item the item * @param itemStyle the item style * @return a default list cell @@ -56,4 +53,5 @@ static class DefaultListCell extends AbstractListCell { } } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/TextCell.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/TextCell.java index 3b7b151db..4d7d1acfd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/TextCell.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/control/cell/TextCell.java @@ -30,22 +30,18 @@ public interface TextCell extends Cell { /** * Sets horizontal align for a text to draw. Defaults to * {@link HorizontalAlign#CENTER}. - * * @param hAlign the horizontal align */ void setHorizontalAlign(HorizontalAlign hAlign); /** - * Sets vertical align for a text to draw. Defaults to - * {@link VerticalAlign#CENTER}. - * + * Sets vertical align for a text to draw. Defaults to {@link VerticalAlign#CENTER}. * @param vAlign the vertical align */ void setVerticalAlign(VerticalAlign vAlign); /** * Helper method to build a {@code TextCell}. - * * @param type of an item * @param item the item * @param itemFunction the item function @@ -57,7 +53,6 @@ static TextCell of(T item, Function itemFunction) { /** * Helper method to build a {@code TextCell}. - * * @param type of an item * @param item the item * @param itemFunction the item function diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/DefaultEventLoop.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/DefaultEventLoop.java index 0d5459a1c..c3d888e39 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/DefaultEventLoop.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/DefaultEventLoop.java @@ -54,13 +54,21 @@ public class DefaultEventLoop implements EventLoop { private final static Logger log = LoggerFactory.getLogger(DefaultEventLoop.class); + private final Queue> messageQueue = new PriorityQueue<>(MessageComparator.comparingPriority()); + private final Many> many = Sinks.many().unicast().onBackpressureBuffer(messageQueue); + private Flux> sink; - // private final Sinks.Many subscribedSignal = Sinks.many().replay().limit(1); + + // private final Sinks.Many subscribedSignal = + // Sinks.many().replay().limit(1); private final Disposable.Composite disposables = Disposables.composite(); + private final Scheduler scheduler = Schedulers.boundedElastic(); + private volatile boolean active = true; + private final List processors; public DefaultEventLoop() { @@ -78,21 +86,19 @@ public DefaultEventLoop(List processors) { } private void init() { - sink = many.asFlux() - .flatMap(m -> { - Flux> pm = null; - for (EventLoopProcessor processor : processors) { - if (processor.canProcess(m)) { - pm = processor.process(m); - break; - } + sink = many.asFlux().flatMap(m -> { + Flux> pm = null; + for (EventLoopProcessor processor : processors) { + if (processor.canProcess(m)) { + pm = processor.process(m); + break; } - if (pm != null) { - return pm; - } - return Mono.just(m); - }) - .share(); + } + if (pm != null) { + return pm; + } + return Mono.just(m); + }).share(); } @Override @@ -111,14 +117,14 @@ public void dispatch(Publisher> messages) { @Override public Flux> events() { return sink - // .doFinally((s) -> subscribedSignal.tryEmitNext(sink.currentSubscriberCount() > 0)) + // .doFinally((s) -> subscribedSignal.tryEmitNext(sink.currentSubscriberCount() > + // 0)) ; } @Override public Flux events(EventLoop.Type type, Class clazz) { - return events() - .filter(m -> type.equals(StaticShellMessageHeaderAccessor.getEventType(m))) + return events().filter(m -> type.equals(StaticShellMessageHeaderAccessor.getEventType(m))) .map(m -> m.getPayload()) .ofType(clazz); } @@ -127,40 +133,35 @@ public Flux events(EventLoop.Type type, Class clazz) { @SuppressWarnings("unchecked") public Flux events(Type type, ParameterizedTypeReference typeRef) { ResolvableType resolvableType = ResolvableType.forType(typeRef); - return (Flux) events() - .filter(m -> type.equals(StaticShellMessageHeaderAccessor.getEventType(m))) + return (Flux) events().filter(m -> type.equals(StaticShellMessageHeaderAccessor.getEventType(m))) .map(m -> m.getPayload()) .ofType(resolvableType.getRawClass()); } @Override public Flux keyEvents() { - return events() - .filter(m -> EventLoop.Type.KEY.equals(StaticShellMessageHeaderAccessor.getEventType(m))) + return events().filter(m -> EventLoop.Type.KEY.equals(StaticShellMessageHeaderAccessor.getEventType(m))) .map(m -> m.getPayload()) .ofType(KeyEvent.class); } @Override public Flux mouseEvents() { - return events() - .filter(m -> EventLoop.Type.MOUSE.equals(StaticShellMessageHeaderAccessor.getEventType(m))) + return events().filter(m -> EventLoop.Type.MOUSE.equals(StaticShellMessageHeaderAccessor.getEventType(m))) .map(m -> m.getPayload()) .ofType(MouseEvent.class); } @Override public Flux systemEvents() { - return events() - .filter(m -> EventLoop.Type.SYSTEM.equals(StaticShellMessageHeaderAccessor.getEventType(m))) + return events().filter(m -> EventLoop.Type.SYSTEM.equals(StaticShellMessageHeaderAccessor.getEventType(m))) .map(m -> m.getPayload()) .ofType(String.class); } @Override public Flux signalEvents() { - return events() - .filter(m -> EventLoop.Type.SIGNAL.equals(StaticShellMessageHeaderAccessor.getEventType(m))) + return events().filter(m -> EventLoop.Type.SIGNAL.equals(StaticShellMessageHeaderAccessor.getEventType(m))) .map(m -> m.getPayload()) .ofType(String.class); } @@ -190,14 +191,14 @@ public void onDestroy(Disposable disposable) { disposables.add(disposable); } - // @Override // public void subcribe(Flux> messages) { - // upstreamSubscriptions.add( - // messages - // // .delaySubscription(subscribedSignal.asFlux().filter(Boolean::booleanValue).next()) - // .subscribe() - // ); + // upstreamSubscriptions.add( + // messages + // // + // .delaySubscription(subscribedSignal.asFlux().filter(Boolean::booleanValue).next()) + // .subscribe() + // ); // } private boolean doSend(Message message, long timeout) { @@ -205,7 +206,7 @@ private boolean doSend(Message message, long timeout) { return false; } // Assert.state(this.active && this.many.currentSubscriberCount() > 0, - // () -> "The [" + this + "] doesn't have subscribers to accept messages"); + // () -> "The [" + this + "] doesn't have subscribers to accept messages"); long remainingTime = 0; if (timeout > 0) { remainingTime = timeout; @@ -227,54 +228,50 @@ private boolean tryEmitMessage(Message message) { case OK -> true; case FAIL_NON_SERIALIZED, FAIL_OVERFLOW -> false; case FAIL_ZERO_SUBSCRIBER -> - throw new IllegalStateException("The [" + this + "] doesn't have subscribers to accept messages"); + throw new IllegalStateException("The [" + this + "] doesn't have subscribers to accept messages"); case FAIL_TERMINATED, FAIL_CANCELLED -> - throw new IllegalStateException("Cannot emit messages into the cancelled or terminated sink: " + many); + throw new IllegalStateException("Cannot emit messages into the cancelled or terminated sink: " + many); }; } // public void subscribe(Subscriber> subscriber) { - // sink.asFlux() - // .doFinally((s) -> subscribedSignal.tryEmitNext(sink.currentSubscriberCount() > 0)) - // .share() - // .subscribe(subscriber); - - // upstreamSubscriptions.add( - // Mono.fromCallable(() -> sink.currentSubscriberCount() > 0) - // .filter(Boolean::booleanValue) - // .doOnNext(subscribedSignal::tryEmitNext) - // .repeatWhenEmpty((repeat) -> - // active ? repeat.delayElements(Duration.ofMillis(100)) : repeat) - // .subscribe()); + // sink.asFlux() + // .doFinally((s) -> subscribedSignal.tryEmitNext(sink.currentSubscriberCount() > 0)) + // .share() + // .subscribe(subscriber); + + // upstreamSubscriptions.add( + // Mono.fromCallable(() -> sink.currentSubscriberCount() > 0) + // .filter(Boolean::booleanValue) + // .doOnNext(subscribedSignal::tryEmitNext) + // .repeatWhenEmpty((repeat) -> + // active ? repeat.delayElements(Duration.ofMillis(100)) : repeat) + // .subscribe()); // } public void subscribeTo(Publisher> publisher) { - disposables.add( - Flux.from(publisher) - // .delaySubscription(subscribedSignal.asFlux().filter(Boolean::booleanValue).next()) - .publishOn(scheduler) - .flatMap((message) -> - Mono.just(message) - .handle((messageToHandle, syncSink) -> sendReactiveMessage(messageToHandle)) - .contextWrite(StaticShellMessageHeaderAccessor.getReactorContext(message)) - ) - .contextCapture() - .subscribe()); + disposables.add(Flux.from(publisher) + // .delaySubscription(subscribedSignal.asFlux().filter(Boolean::booleanValue).next()) + .publishOn(scheduler) + .flatMap((message) -> Mono.just(message) + .handle((messageToHandle, syncSink) -> sendReactiveMessage(messageToHandle)) + .contextWrite(StaticShellMessageHeaderAccessor.getReactorContext(message))) + .contextCapture() + .subscribe()); } private void sendReactiveMessage(Message message) { Message messageToSend = message; // We have just restored Reactor context, so no need in a header anymore. if (messageToSend.getHeaders().containsKey(ShellMessageHeaderAccessor.REACTOR_CONTEXT)) { - messageToSend = - MessageBuilder.fromMessage(message) - .removeHeader(ShellMessageHeaderAccessor.REACTOR_CONTEXT) - .build(); + messageToSend = MessageBuilder.fromMessage(message) + .removeHeader(ShellMessageHeaderAccessor.REACTOR_CONTEXT) + .build(); } try { dispatch(messageToSend); // if (!doSend(messageToSend, 1000)) { - // log.warn("Failed to send message: {}", messageToSend); + // log.warn("Failed to send message: {}", messageToSend); // } } catch (Exception ex) { @@ -305,5 +302,7 @@ public int compare(Message left, Message right) { static Comparator> comparingPriority() { return new MessageComparator(); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/EventLoop.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/EventLoop.java index 9a4cd53fd..03908bc0d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/EventLoop.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/EventLoop.java @@ -26,9 +26,9 @@ import org.springframework.shell.component.view.control.ViewEvent; /** - * {@code EventLoop} is a central place where all eventing will be orchestrated - * for a lifecycle of a component. Orchestration is usually needed around timings - * of redraws and and component state updates. + * {@code EventLoop} is a central place where all eventing will be orchestrated for a + * lifecycle of a component. Orchestration is usually needed around timings of redraws and + * and component state updates. * * Generic message type is a Spring {@link Message} and it's up to an {@code EventLoop} * implementation how those are processed. @@ -38,48 +38,38 @@ public interface EventLoop { /** - * Return a {@link Flux} of {@link Message} events. When subscribed events will - * be received until disposed or {@code EventLoop} terminates. - * + * Return a {@link Flux} of {@link Message} events. When subscribed events will be + * received until disposed or {@code EventLoop} terminates. * @return the events from an event loop */ Flux> events(); /** - * Specialisation of {@link #events()} which returns type safe - * {@link KeyEvent}s. - * + * Specialisation of {@link #events()} which returns type safe {@link KeyEvent}s. * @return the key events from an event loop */ Flux keyEvents(); /** - * Specialisation of {@link #events()} which returns type safe - * {@link MouseEvent}s. - * + * Specialisation of {@link #events()} which returns type safe {@link MouseEvent}s. * @return the mouse events from an event loop */ Flux mouseEvents(); /** - * Specialisation of {@link #events()} which returns type safe - * {code system} events. - * + * Specialisation of {@link #events()} which returns type safe {code system} events. * @return the system events from an event loop */ Flux systemEvents(); /** - * Specialisation of {@link #events()} which returns type safe - * {code signal} events. - * + * Specialisation of {@link #events()} which returns type safe {code signal} events. * @return the signal events from an event loop */ Flux signalEvents(); /** * Specialisation of {@link #events()} which returns type safe {@link ViewEvent}s. - * * @param the type to expect * @param clazz the type class to filter * @return the filtered events from an event loop @@ -88,7 +78,6 @@ public interface EventLoop { /** * Specialisation of {@link #events()} which returns type safe {@link ViewEvent}s. - * * @param the type to expect * @param typeRef the parameterized type to filter * @return the filtered events from an event loop @@ -97,7 +86,6 @@ public interface EventLoop { /** * Specialisation of {@link #events()} which returns type safe {@link ViewEvent}s. - * * @param the type to expect * @param clazz the type class to filter * @param filterBy the view to filter @@ -107,7 +95,6 @@ public interface EventLoop { /** * Specialisation of {@link #events()} which returns type safe {@link ViewEvent}s. - * * @param the type to expect * @param typeRef the parameterized type to filter * @param filterBy the view to filter @@ -116,10 +103,8 @@ public interface EventLoop { Flux viewEvents(ParameterizedTypeReference typeRef, View filterBy); /** - * Specialisation of {@link #events()} which returns type safe - * stream filtered by given eventloop message type and message - * payload class type. - * + * Specialisation of {@link #events()} which returns type safe stream filtered by + * given eventloop message type and message payload class type. * @param the type to expect * @param type the eventloop message type to filter * @param clazz the type class to filter @@ -128,10 +113,8 @@ public interface EventLoop { Flux events(EventLoop.Type type, Class clazz); /** - * Specialisation of {@link #events()} which returns type safe - * stream filtered by given eventloop message type and message - * payload class type. - * + * Specialisation of {@link #events()} which returns type safe stream filtered by + * given eventloop message type and message payload class type. * @param the type to expect * @param type the eventloop message type to filter * @param typeRef the parameterized type to filter @@ -142,21 +125,18 @@ public interface EventLoop { /** * Dispatch {@link Message}s into an {@code EventLoop} from a {@link Publisher}. * Usually type is either {@link Mono} or {@link Flux}. - * * @param messages the messages to dispatch */ void dispatch(Publisher> messages); /** * Dispatch a {@link Message} into an {@code EventLoop}. - * * @param message the message to dispatch */ void dispatch(Message message); /** * Register {@link Disposable} to get disposed when event loop terminates. - * * @param disposable a disposable to dispose */ void onDestroy(Disposable disposable); @@ -197,19 +177,19 @@ enum Type { USER, TASK + } /** - * Contract to process event loop messages, possibly translating an event into - * some other type of event or events. + * Contract to process event loop messages, possibly translating an event into some + * other type of event or events. */ interface EventLoopProcessor { /** - * Checks if this processor can process an event. If this method returns {@code true} - * it's quaranteed that {@link #process(Message)} is called to resolve translation - * of a message. - * + * Checks if this processor can process an event. If this method returns + * {@code true} it's quaranteed that {@link #process(Message)} is called to + * resolve translation of a message. * @param message the message * @return true if processor can process an event */ @@ -218,10 +198,11 @@ interface EventLoopProcessor { /** * Process a message and transform it into a new {@link Flux} of {@link Message} * instances. - * * @param message the message to process * @return a flux of messages */ Flux> process(Message message); + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBinder.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBinder.java index 7aef6368d..672250509 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBinder.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBinder.java @@ -60,7 +60,6 @@ public void bindAll(KeyMap keyMap) { keyMap.bind(KeyEvent.Key.Tab, "\t"); keyMap.bind(KeyEvent.Key.Backtab, key(terminal, Capability.key_btab)); - keyMap.bind(KeyEvent.Key.CursorLeft, key(terminal, Capability.key_left)); keyMap.bind(KeyEvent.Key.CursorRight, key(terminal, Capability.key_right)); keyMap.bind(KeyEvent.Key.CursorUp, key(terminal, Capability.key_up)); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBindingConsumer.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBindingConsumer.java index 558eda254..f7c10de3f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBindingConsumer.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyBindingConsumer.java @@ -19,4 +19,5 @@ @FunctionalInterface public interface KeyBindingConsumer extends Consumer { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyEvent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyEvent.java index 054f77e1a..797e1d7c7 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyEvent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyEvent.java @@ -17,9 +17,8 @@ /** * - * mask special keys unicode keys ascii keys - * [ ] [ ] [ ] [ ] - * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * mask special keys unicode keys ascii keys [ ] [ ] [ ] [ ] 31 30 29 28 27 26 25 24 23 22 + * 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 * * */ @@ -52,135 +51,245 @@ public boolean isKey() { public static class Key { public static final int Space = 32; + public static final int ExclamationMark = 33; + public static final int DoubleQuote = 34; + public static final int NumberSign = 35; + public static final int Dollar = 36; + public static final int Percent = 37; + public static final int Ampersand = 38; + public static final int SingleQuote = 39; + public static final int LeftParenthesis = 40; + public static final int RightParenthesis = 41; + public static final int Asterisk = 42; + public static final int Plus = 43; + public static final int Comma = 44; + public static final int Hyphen = 45; + public static final int Dot = 46; + public static final int Slash = 47; public static final int Zero = 48; + public static final int One = 49; + public static final int Two = 50; + public static final int Three = 51; + public static final int Four = 52; + public static final int Five = 53; + public static final int Six = 54; + public static final int Seven = 55; + public static final int Eight = 56; + public static final int Nine = 57; public static final int Colon = 58; + public static final int SemiColon = 59; + public static final int OpenBracket = 60; + public static final int Equals = 61; + public static final int CloseBracket = 62; + public static final int QuestionMark = 63; + public static final int EuroSign = 64; public static final int A = 65; + public static final int B = 66; + public static final int C = 67; + public static final int D = 68; + public static final int E = 69; + public static final int F = 70; + public static final int G = 71; + public static final int H = 72; + public static final int I = 73; + public static final int J = 74; + public static final int K = 75; + public static final int L = 76; + public static final int M = 77; + public static final int N = 78; + public static final int O = 79; + public static final int P = 80; + public static final int Q = 81; + public static final int R = 82; + public static final int S = 83; + public static final int T = 84; + public static final int U = 85; + public static final int V = 86; + public static final int W = 87; + public static final int X = 88; + public static final int Y = 89; + public static final int Z = 90; public static final int a = 97; + public static final int b = 98; + public static final int c = 99; + public static final int d = 100; + public static final int e = 101; + public static final int f = 102; + public static final int g = 103; + public static final int h = 104; + public static final int i = 105; + public static final int j = 106; + public static final int k = 107; + public static final int l = 108; + public static final int m = 109; + public static final int n = 110; + public static final int o = 111; + public static final int p = 112; + public static final int q = 113; + public static final int r = 114; + public static final int s = 115; + public static final int t = 116; + public static final int u = 117; + public static final int v = 118; + public static final int w = 119; + public static final int x = 120; + public static final int y = 121; + public static final int z = 122; public static final int BraceLeft = 123; + public static final int Pipe = 124; + public static final int BraceRight = 125; + public static final int Tilde = 126; public static final int CursorUp = 0x100000; + public static final int CursorDown = 0x100001; + public static final int CursorLeft = 0x100002; + public static final int CursorRight = 0x100003; + public static final int Enter = 0x100004; + public static final int Backspace = 0x100005; + public static final int Delete = 0x100006; + public static final int Tab = 0x100007; + public static final int Backtab = 0x100008; public static final int f1 = 0x100009; + public static final int f2 = 0x10000a; + public static final int f3 = 0x10000b; + public static final int f4 = 0x10000c; + public static final int f5 = 0x10000d; + public static final int f6 = 0x10000e; + public static final int f7 = 0x10000f; + public static final int f8 = 0x100010; + public static final int f9 = 0x100011; + public static final int f10 = 0x100012; + public static final int f11 = 0x100013; + public static final int f12 = 0x100014; public static final int Char = 0x1000000; + public static final int Mouse = 0x1000001; + public static final int Unicode = 0x1000002; } public static class KeyMask { + public static final int CharMask = 0x000fffff; + public static final int SpecialMask = 0xfff00000; + public static final int ShiftMask = 0x10000000; + public static final int CtrlMask = 0x40000000; + public static final int AltMask = 0x80000000; + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyHandler.java index 316674d16..9428a3cbd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/KeyHandler.java @@ -31,18 +31,16 @@ public interface KeyHandler { /** * Handle Key event wrapped in a {@link KeyHandlerArgs}. - * * @param args the Key handler arguments * @return a handler result */ KeyHandlerResult handle(KeyHandlerArgs args); /** - * Returns a composed handler that first handles {@code this} handler and then - * handles {@code other} handler if {@code predicate} against result from - * {@code this} matches. - * - * @param other the handler to handle after this handler + * Returns a composed handler that first handles {@code this} handler and then handles + * {@code other} handler if {@code predicate} against result from {@code this} + * matches. + * @param other the handler to handle after this handler * @param predicate the predicate test against results from this * @return a composed handler */ @@ -54,33 +52,30 @@ default KeyHandler thenConditionally(KeyHandler other, Predicate result.consumed()); - } + } /** - * Returns a composed handler that first handles {@code this} handler and then - * handles {@code other} if {@code this} did not consume an event. - * + * Returns a composed handler that first handles {@code this} handler and then handles + * {@code other} if {@code this} did not consume an event. * @param other the handler to handle after this handler * @return a composed handler */ - default KeyHandler thenIfNotConsumed(KeyHandler other) { + default KeyHandler thenIfNotConsumed(KeyHandler other) { return thenConditionally(other, result -> !result.consumed()); - } + } /** - * Returns a handler that always returns a non-consumed result. - * + * Returns a handler that always returns a non-consumed result. * @return a handler that always returns a non-consumed result */ static KeyHandler neverConsume() { @@ -89,7 +84,6 @@ static KeyHandler neverConsume() { /** * Construct {@link KeyHandlerArgs} from a {@link KeyEvent}. - * * @param event the Key event * @return a Key handler args */ @@ -98,11 +92,9 @@ static KeyHandlerArgs argsOf(KeyEvent event) { } /** - * Construct {@link KeyHandlerResult} from a {@link KeyEvent} and a - * {@link View}. - * + * Construct {@link KeyHandlerResult} from a {@link KeyEvent} and a {@link View}. * @param event the Key event - * @param focus the view + * @param focus the view * @return a Key handler result */ static KeyHandlerResult resultOf(KeyEvent event, boolean consumed, View focus) { @@ -125,7 +117,7 @@ record KeyHandlerArgs(KeyEvent event) { * @param focus the view which consumed an event * @param capture the view which captured an event */ - record KeyHandlerResult(@Nullable KeyEvent event, boolean consumed, @Nullable View focus, - @Nullable View capture) { + record KeyHandlerResult(@Nullable KeyEvent event, boolean consumed, @Nullable View focus, @Nullable View capture) { } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseBindingConsumer.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseBindingConsumer.java index 950a86feb..0f7b77534 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseBindingConsumer.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseBindingConsumer.java @@ -19,4 +19,5 @@ @FunctionalInterface public interface MouseBindingConsumer extends Consumer { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseEvent.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseEvent.java index 658b0d0f6..8c8909a11 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseEvent.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseEvent.java @@ -17,9 +17,8 @@ /** * - * unused modifier button type - * [ ] [ ] [ ] [ ] - * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * unused modifier button type [ ] [ ] [ ] [ ] 31 30 29 28 27 26 25 24 23 22 21 20 19 18 + * 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 * * */ @@ -79,35 +78,56 @@ public boolean has(int mask) { } public static class Type { + public static final int Released = 0x00000001; + public static final int Pressed = 0x00000002; + public static final int Wheel = 0x00000004; + public static final int Moved = 0x00000008; + public static final int Dragged = 0x00000010; + } public static class Button { + public static final int NoButton = 0x00000020; + public static final int Button1 = 0x00000040; + public static final int Button2 = 0x00000080; + public static final int Button3 = 0x00000100; + public static final int WheelUp = 0x00000200; + public static final int WheelDown = 0x00000400; + } public static class Modifier { + public static final int Shift = 0x00000800; + public static final int Alt = 0x00001000; + public static final int Control = 0x00002000; + } public static class MouseMask { + // bits 0-4 public static final int TypeMask = 0x0000001f; + // bits 5-10 public static final int ButtonMask = 0x000007e0; + // bits 11-13 public static final int ModifierMask = 0x00003800; + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseHandler.java index 20cc60316..b0c37a4c0 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/MouseHandler.java @@ -33,18 +33,16 @@ public interface MouseHandler { /** * Handle mouse event wrapped in a {@link MouseHandlerArgs}. - * * @param args the mouse handler arguments * @return a handler result */ MouseHandlerResult handle(MouseHandlerArgs args); /** - * Returns a composed handler that first handles {@code this} handler and then - * handles {@code other} handler if {@code predicate} against result from - * {@code this} matches. - * - * @param other the handler to handle after this handler + * Returns a composed handler that first handles {@code this} handler and then handles + * {@code other} handler if {@code predicate} against result from {@code this} + * matches. + * @param other the handler to handle after this handler * @param predicate the predicate test against results from this * @return a composed handler */ @@ -56,33 +54,30 @@ default MouseHandler thenConditionally(MouseHandler other, Predicate result.consumed()); - } + } /** - * Returns a composed handler that first handles {@code this} handler and then - * handles {@code other} if {@code this} did not consume an event. - * + * Returns a composed handler that first handles {@code this} handler and then handles + * {@code other} if {@code this} did not consume an event. * @param other the handler to handle after this handler * @return a composed handler */ - default MouseHandler thenIfNotConsumed(MouseHandler other) { + default MouseHandler thenIfNotConsumed(MouseHandler other) { return thenConditionally(other, result -> !result.consumed()); - } + } /** - * Returns a handler that always returns a non-consumed result. - * + * Returns a handler that always returns a non-consumed result. * @return a handler that always returns a non-consumed result */ static MouseHandler neverConsume() { @@ -91,7 +86,6 @@ static MouseHandler neverConsume() { /** * Construct {@link MouseHandlerArgs} from a {@link MouseEvent}. - * * @param event the mouse event * @return a mouse handler args */ @@ -108,9 +102,7 @@ record MouseHandlerArgs(MouseEvent event) { } /** - * Construct {@link MouseHandlerResult} from a {@link MouseEvent} and a - * {@link View}. - * + * Construct {@link MouseHandlerResult} from a {@link MouseEvent} and a {@link View}. * @param event the mouse event * @param consumed flag telling if event was consumed * @param focus the view which is requesting focus @@ -132,4 +124,5 @@ static MouseHandlerResult resultOf(MouseEvent event, boolean consumed, View focu record MouseHandlerResult(@Nullable MouseEvent event, boolean consumed, @Nullable View focus, @Nullable View capture) { } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/AnimationEventLoopProcessor.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/AnimationEventLoopProcessor.java index da0a56598..c288bf555 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/AnimationEventLoopProcessor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/AnimationEventLoopProcessor.java @@ -27,8 +27,7 @@ import org.springframework.shell.component.view.event.EventLoop.EventLoopProcessor; /** - * {@link EventLoopProcessor} converting incoming message into animation tick - * messages. + * {@link EventLoopProcessor} converting incoming message into animation tick messages. * * @author Janne Valkealahti */ @@ -46,16 +45,14 @@ public boolean canProcess(Message message) { @Override public Flux> process(Message message) { - return Flux.range(0, 40) - .delayElements(Duration.ofMillis(100)) - .map(i -> { - return MessageBuilder - .withPayload(i) - .setHeader(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.SYSTEM) - .setHeader("animationtick", true) - .setHeader("animationfrom", 0) - .setHeader("animationto", 9) - .build(); - }); + return Flux.range(0, 40).delayElements(Duration.ofMillis(100)).map(i -> { + return MessageBuilder.withPayload(i) + .setHeader(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.SYSTEM) + .setHeader("animationtick", true) + .setHeader("animationfrom", 0) + .setHeader("animationto", 9) + .build(); + }); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/TaskEventLoopProcessor.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/TaskEventLoopProcessor.java index 55aa622be..f12270e4b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/TaskEventLoopProcessor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/event/processor/TaskEventLoopProcessor.java @@ -35,10 +35,10 @@ public boolean canProcess(Message message) { if (payload instanceof Runnable) { return true; } - else if(payload instanceof KeyBindingConsumerArgs) { + else if (payload instanceof KeyBindingConsumerArgs) { return true; } - else if(payload instanceof MouseBindingConsumerArgs) { + else if (payload instanceof MouseBindingConsumerArgs) { return true; } } @@ -51,10 +51,10 @@ public Flux> process(Message message) { if (payload instanceof Runnable) { return processRunnable(message); } - else if(payload instanceof KeyBindingConsumerArgs) { + else if (payload instanceof KeyBindingConsumerArgs) { return processKeyConsumer(message); } - else if(payload instanceof MouseBindingConsumerArgs) { + else if (payload instanceof MouseBindingConsumerArgs) { return processMouseConsumer(message); } // should not happen @@ -88,4 +88,5 @@ private Flux> processKeyConsumer(Message message) { .then(Mono.just(MessageBuilder.withPayload(new Object()).build())) .flux(); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Color.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Color.java index 240a2cf19..aae3d11f7 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Color.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Color.java @@ -19,425 +19,841 @@ public class Color { // https://en.wikipedia.org/wiki/X11_color_names#Numbered_variants public static final int ANTIQUEWHITE = 0xFAEBD7; + public static final int AQUAMARINE = 0x7FFFD4; + public static final int AZURE = 0xF0FFFF; + public static final int BISQUE = 0xFFE4C4; + public static final int BLUE = 0x0000FF; + public static final int BROWN = 0xA52A2A; + public static final int BURLYWOOD = 0xDEB887; + public static final int CADETBLUE = 0x5F9EA0; + public static final int CHARTREUSE = 0x7FFF00; + public static final int CHOCOLATE = 0xD2691E; + public static final int CORAL = 0xFF7F50; + public static final int CORNSILK = 0xFFF8DC; + public static final int CYAN = 0x00FFFF; + public static final int DARKGOLDENROD = 0xB8860B; + public static final int DARKOLIVE = 0x556B2F; + public static final int DARKORANGE = 0xFF8C00; + public static final int DARKORCHID = 0x9932CC; + public static final int DARKSEAGREEN = 0x8FBC8F; + public static final int DARKSLATEGRAY = 0x2F4F4F; + public static final int DEEPPINK = 0xFF1493; + public static final int DEEPSKYBLUE = 0x00BFFF; + public static final int DODGERBLUE = 0x1E90FF; + public static final int FIREBRICK = 0xB22222; + public static final int GOLD = 0xFFD700; + public static final int GOLDENROD = 0xDAA520; + public static final int GREEN = 0x00FF00; + public static final int HONEYDEW = 0xF0FFF0; + public static final int HOTPINK = 0xFF69B4; + public static final int INDIANRED = 0xCD5C5C; + public static final int IVORY = 0xFFFFF0; + public static final int KHAKI = 0xF0E68C; + public static final int LAVENDERBLUSH = 0xFFF0F5; + public static final int LEMONCHIFFON = 0xFFFACD; + public static final int LIGHTBLUE = 0xADD8E6; + public static final int LIGHTCYAN = 0xE0FFFF; + public static final int LIGHTGOLDENROD = 0xEEDD82; + public static final int LIGHTPINK = 0xFFB6C1; + public static final int LIGHTSALMON = 0xFFA07A; + public static final int LIGHTSKYBLUE = 0x87CEFA; + public static final int LIGHTSTEELBLUE = 0xB0C4DE; + public static final int LIGHTYELLOW = 0xFFFFE0; + public static final int MAGENTA = 0xFF00FF; + public static final int MAROON = 0xB03060; + public static final int MEDIUMORCHID = 0xBA55D3; + public static final int MEDIUMPURPLE = 0x9370DB; + public static final int MISTYROSE = 0xFFE4E1; + public static final int NAVAJOWHITE = 0xFFDEAD; + public static final int OLIVEDRAB = 0x6B8E23; + public static final int ORANGE = 0xFFA500; + public static final int ORCHID = 0xDA70D6; + public static final int PALEGREEN = 0x98FB98; + public static final int PALETURQUOISE = 0xAFEEEE; + public static final int PALEVIOLETRED = 0xDB7093; + public static final int PEACHPUFF = 0xFFDAB9; + public static final int PINK = 0xFFC0CB; + public static final int PLUM = 0xDDA0DD; + public static final int PURPLE = 0xA020F0; + public static final int RED = 0xFF0000; + public static final int ROSYBROWN = 0xBC8F8F; + public static final int ROYALBLUE = 0x4169E1; + public static final int SALMON = 0xFA8072; + public static final int SEAGREEN = 0x2E8B57; + public static final int SEASHELL = 0xFFF5EE; + public static final int SIENNA = 0xA0522D; + public static final int SKYBLUE = 0x87CEEB; + public static final int SLATEBLUE = 0x6A5ACD; + public static final int SLATEGRAY = 0x708090; + public static final int SNOW = 0xFFFAFA; + public static final int SPRINGGREEN = 0x00FF7F; + public static final int STEELBLUE = 0x4682B4; + public static final int TAN = 0xD2B48C; + public static final int THISTLE = 0xD8BFD8; + public static final int TOMATO = 0xFF6347; + public static final int TURQUOISE = 0x40E0D0; + public static final int VIOLETRED = 0xD02090; + public static final int WHEAT = 0xF5DEB3; + public static final int YELLOW = 0xFFFF00; + public static final int ANTIQUEWHITE1 = 0xFFEFDB; + public static final int AQUAMARINE1 = 0x7FFFD4; + public static final int AZURE1 = 0xF0FFFF; + public static final int BISQUE1 = 0xFFE4C4; + public static final int BLUE1 = 0x0000FF; + public static final int BROWN1 = 0xFF4040; + public static final int BURLYWOOD1 = 0xFFD39B; + public static final int CADETBLUE1 = 0x98F5FF; + public static final int CHARTREUSE1 = 0x7FFF00; + public static final int CHOCOLATE1 = 0xFF7F24; + public static final int CORAL1 = 0xFF7256; + public static final int CORNSILK1 = 0xFFF8DC; + public static final int CYAN1 = 0x00FFFF; + public static final int DARKGOLDENROD1 = 0xFFB90F; + public static final int DARKOLIVE1 = 0xCAFF70; + public static final int DARKORANGE1 = 0xFF7F00; + public static final int DARKORCHID1 = 0xBF3EFF; + public static final int DARKSEAGREEN1 = 0xC1FFC1; + public static final int DARKSLATEGRAY1 = 0x97FFFF; + public static final int DEEPPINK1 = 0xFF1493; + public static final int DEEPSKYBLUE1 = 0x00BFFF; + public static final int DODGERBLUE1 = 0x1E90FF; + public static final int FIREBRICK1 = 0xFF3030; + public static final int GOLD1 = 0xFFD700; + public static final int GOLDENROD1 = 0xFFC125; + public static final int GREEN1 = 0x00FF00; + public static final int HONEYDEW1 = 0xF0FFF0; + public static final int HOTPINK1 = 0xFF6EB4; + public static final int INDIANRED1 = 0xFF6A6A; + public static final int IVORY1 = 0xFFFFF0; + public static final int KHAKI1 = 0xFFF68F; + public static final int LAVENDERBLUSH1 = 0xFFF0F5; + public static final int LEMONCHIFFON1 = 0xFFFACD; + public static final int LIGHTBLUE1 = 0xBFEFFF; + public static final int LIGHTCYAN1 = 0xE0FFFF; + public static final int LIGHTGOLDENROD1 = 0xFFEC8B; + public static final int LIGHTPINK1 = 0xFFAEB9; + public static final int LIGHTSALMON1 = 0xFFA07A; + public static final int LIGHTSKYBLUE1 = 0xB0E2FF; + public static final int LIGHTSTEELBLUE1 = 0xCAE1FF; + public static final int LIGHTYELLOW1 = 0xFFFFE0; + public static final int MAGENTA1 = 0xFF00FF; + public static final int MAROON1 = 0xFF34B3; + public static final int MEDIUMORCHID1 = 0xE066FF; + public static final int MEDIUMPURPLE1 = 0xAB82FF; + public static final int MISTYROSE1 = 0xFFE4E1; + public static final int NAVAJOWHITE1 = 0xFFDEAD; + public static final int OLIVEDRAB1 = 0xC0FF3E; + public static final int ORANGE1 = 0xFFA500; + public static final int ORCHID1 = 0xFF83FA; + public static final int PALEGREEN1 = 0x9AFF9A; + public static final int PALETURQUOISE1 = 0xBBFFFF; + public static final int PALEVIOLETRED1 = 0xFF82AB; + public static final int PEACHPUFF1 = 0xFFDAB9; + public static final int PINK1 = 0xFFB5C5; + public static final int PLUM1 = 0xFFBBFF; + public static final int PURPLE1 = 0x9B30FF; + public static final int RED1 = 0xFF0000; + public static final int ROSYBROWN1 = 0xFFC1C1; + public static final int ROYALBLUE1 = 0x4876FF; + public static final int SALMON1 = 0xFF8C69; + public static final int SEAGREEN1 = 0x54FF9F; + public static final int SEASHELL1 = 0xFFF5EE; + public static final int SIENNA1 = 0xFF8247; + public static final int SKYBLUE1 = 0x87CEFF; + public static final int SLATEBLUE1 = 0x836FFF; + public static final int SLATEGRAY1 = 0xC6E2FF; + public static final int SNOW1 = 0xFFFAFA; + public static final int SPRINGGREEN1 = 0x00FF7F; + public static final int STEELBLUE1 = 0x63B8FF; + public static final int TAN1 = 0xFFA54F; + public static final int THISTLE1 = 0xFFE1FF; + public static final int TOMATO1 = 0xFF6347; + public static final int TURQUOISE1 = 0x00F5FF; + public static final int VIOLETRED1 = 0xFF3E96; + public static final int WHEAT1 = 0xFFE7BA; + public static final int YELLOW1 = 0xFFFF00; + public static final int ANTIQUEWHITE2 = 0xEEDFCC; + public static final int AQUAMARINE2 = 0x76EEC6; + public static final int AZURE2 = 0xE0EEEE; + public static final int BISQUE2 = 0xEED5B7; + public static final int BLUE2 = 0x0000EE; + public static final int BROWN2 = 0xEE3B3B; + public static final int BURLYWOOD2 = 0xEEC591; + public static final int CADETBLUE2 = 0x8EE5EE; + public static final int CHARTREUSE2 = 0x76EE00; + public static final int CHOCOLATE2 = 0xEE7621; + public static final int CORAL2 = 0xEE6A50; + public static final int CORNSILK2 = 0xEEE8CD; + public static final int CYAN2 = 0x00EEEE; + public static final int DARKGOLDENROD2 = 0xEEAD0E; + public static final int DARKOLIVE2 = 0xBCEE68; + public static final int DARKORANGE2 = 0xEE7600; + public static final int DARKORCHID2 = 0xB23AEE; + public static final int DARKSEAGREEN2 = 0xB4EEB4; + public static final int DARKSLATEGRAY2 = 0x8DEEEE; + public static final int DEEPPINK2 = 0xEE1289; + public static final int DEEPSKYBLUE2 = 0x00B2EE; + public static final int DODGERBLUE2 = 0x1C86EE; + public static final int FIREBRICK2 = 0xEE2C2C; + public static final int GOLD2 = 0xEEC900; + public static final int GOLDENROD2 = 0xEEB422; + public static final int GREEN2 = 0x00EE00; + public static final int HONEYDEW2 = 0xE0EEE0; + public static final int HOTPINK2 = 0xEE6AA7; + public static final int INDIANRED2 = 0xEE6363; + public static final int IVORY2 = 0xEEEEE0; + public static final int KHAKI2 = 0xEEE685; + public static final int LAVENDERBLUSH2 = 0xEEE0E5; + public static final int LEMONCHIFFON2 = 0xEEE9BF; + public static final int LIGHTBLUE2 = 0xB2DFEE; + public static final int LIGHTCYAN2 = 0xD1EEEE; + public static final int LIGHTGOLDENROD2 = 0xEEDC82; + public static final int LIGHTPINK2 = 0xEEA2AD; + public static final int LIGHTSALMON2 = 0xEE9572; + public static final int LIGHTSKYBLUE2 = 0xA4D3EE; + public static final int LIGHTSTEELBLUE2 = 0xBCD2EE; + public static final int LIGHTYELLOW2 = 0xEEEED1; + public static final int MAGENTA2 = 0xEE00EE; + public static final int MAROON2 = 0xEE30A7; + public static final int MEDIUMORCHID2 = 0xD15FEE; + public static final int MEDIUMPURPLE2 = 0x9F79EE; + public static final int MISTYROSE2 = 0xEED5D2; + public static final int NAVAJOWHITE2 = 0xEECFA1; + public static final int OLIVEDRAB2 = 0xB3EE3A; + public static final int ORANGE2 = 0xEE9A00; + public static final int ORCHID2 = 0xEE7AE9; + public static final int PALEGREEN2 = 0x90EE90; + public static final int PALETURQUOISE2 = 0xAEEEEE; + public static final int PALEVIOLETRED2 = 0xEE799F; + public static final int PEACHPUFF2 = 0xEECBAD; + public static final int PINK2 = 0xEEA9B8; + public static final int PLUM2 = 0xEEAEEE; + public static final int PURPLE2 = 0x912CEE; + public static final int RED2 = 0xEE0000; + public static final int ROSYBROWN2 = 0xEEB4B4; + public static final int ROYALBLUE2 = 0x436EEE; + public static final int SALMON2 = 0xEE8262; + public static final int SEAGREEN2 = 0x4EEE94; + public static final int SEASHELL2 = 0xEEE5DE; + public static final int SIENNA2 = 0xEE7942; + public static final int SKYBLUE2 = 0x7EC0EE; + public static final int SLATEBLUE2 = 0x7A67EE; + public static final int SLATEGRAY2 = 0xB9D3EE; + public static final int SNOW2 = 0xEEE9E9; + public static final int SPRINGGREEN2 = 0x00EE76; + public static final int STEELBLUE2 = 0x5CACEE; + public static final int TAN2 = 0xEE9A49; + public static final int THISTLE2 = 0xEED2EE; + public static final int TOMATO2 = 0xEE5C42; + public static final int TURQUOISE2 = 0x00E5EE; + public static final int VIOLETRED2 = 0xEE3A8C; + public static final int WHEAT2 = 0xEED8AE; + public static final int YELLOW2 = 0xEEEE00; + public static final int ANTIQUEWHITE3 = 0xCDC0B0; + public static final int AQUAMARINE3 = 0x66CDAA; + public static final int AZURE3 = 0xC1CDCD; + public static final int BISQUE3 = 0xCDB79E; + public static final int BLUE3 = 0x0000CD; + public static final int BROWN3 = 0xCD3333; + public static final int BURLYWOOD3 = 0xCDAA7D; + public static final int CADETBLUE3 = 0x7AC5CD; + public static final int CHARTREUSE3 = 0x66CD00; + public static final int CHOCOLATE3 = 0xCD661D; + public static final int CORAL3 = 0xCD5B45; + public static final int CORNSILK3 = 0xCDC8B1; + public static final int CYAN3 = 0x00CDCD; + public static final int DARKGOLDENROD3 = 0xCD950C; + public static final int DARKOLIVE3 = 0xA2CD5A; + public static final int DARKORANGE3 = 0xCD6600; + public static final int DARKORCHID3 = 0x9A32CD; + public static final int DARKSEAGREEN3 = 0x9BCD9B; + public static final int DARKSLATEGRAY3 = 0x79CDCD; + public static final int DEEPPINK3 = 0xCD1076; + public static final int DEEPSKYBLUE3 = 0x009ACD; + public static final int DODGERBLUE3 = 0x1874CD; + public static final int FIREBRICK3 = 0xCD2626; + public static final int GOLD3 = 0xCDAD00; + public static final int GOLDENROD3 = 0xCD9B1D; + public static final int GREEN3 = 0x00CD00; + public static final int HONEYDEW3 = 0xC1CDC1; + public static final int HOTPINK3 = 0xCD6090; + public static final int INDIANRED3 = 0xCD5555; + public static final int IVORY3 = 0xCDCDC1; + public static final int KHAKI3 = 0xCDC673; + public static final int LAVENDERBLUSH3 = 0xCDC1C5; + public static final int LEMONCHIFFON3 = 0xCDC9A5; + public static final int LIGHTBLUE3 = 0x9AC0CD; + public static final int LIGHTCYAN3 = 0xB4CDCD; + public static final int LIGHTGOLDENROD3 = 0xCDBE70; + public static final int LIGHTPINK3 = 0xCD8C95; + public static final int LIGHTSALMON3 = 0xCD8162; + public static final int LIGHTSKYBLUE3 = 0x8DB6CD; + public static final int LIGHTSTEELBLUE3 = 0xA2B5CD; + public static final int LIGHTYELLOW3 = 0xCDCDB4; + public static final int MAGENTA3 = 0xCD00CD; + public static final int MAROON3 = 0xCD2990; + public static final int MEDIUMORCHID3 = 0xB452CD; + public static final int MEDIUMPURPLE3 = 0x8968CD; + public static final int MISTYROSE3 = 0xCDB7B5; + public static final int NAVAJOWHITE3 = 0xCDB38B; + public static final int OLIVEDRAB3 = 0x9ACD32; + public static final int ORANGE3 = 0xCD8500; + public static final int ORCHID3 = 0xCD69C9; + public static final int PALEGREEN3 = 0x7CCD7C; + public static final int PALETURQUOISE3 = 0x96CDCD; + public static final int PALEVIOLETRED3 = 0xCD6889; + public static final int PEACHPUFF3 = 0xCDAF95; + public static final int PINK3 = 0xCD919E; + public static final int PLUM3 = 0xCD96CD; + public static final int PURPLE3 = 0x7D26CD; + public static final int RED3 = 0xCD0000; + public static final int ROSYBROWN3 = 0xCD9B9B; + public static final int ROYALBLUE3 = 0x3A5FCD; + public static final int SALMON3 = 0xCD7054; + public static final int SEAGREEN3 = 0x43CD80; + public static final int SEASHELL3 = 0xCDC5BF; + public static final int SIENNA3 = 0xCD6839; + public static final int SKYBLUE3 = 0x6CA6CD; + public static final int SLATEBLUE3 = 0x6959CD; + public static final int SLATEGRAY3 = 0x9FB6CD; + public static final int SNOW3 = 0xCDC9C9; + public static final int SPRINGGREEN3 = 0x00CD66; + public static final int STEELBLUE3 = 0x4F94CD; + public static final int TAN3 = 0xCD853F; + public static final int THISTLE3 = 0xCDB5CD; + public static final int TOMATO3 = 0xCD4F39; + public static final int TURQUOISE3 = 0x00C5CD; + public static final int VIOLETRED3 = 0xCD3278; + public static final int WHEAT3 = 0xCDBA96; + public static final int YELLOW3 = 0xCDCD00; + public static final int ANTIQUEWHITE4 = 0x8B8378; + public static final int AQUAMARINE4 = 0x458B74; + public static final int AZURE4 = 0x838B8B; + public static final int BISQUE4 = 0x8B7D6B; + public static final int BLUE4 = 0x00008B; + public static final int BROWN4 = 0x8B2323; + public static final int BURLYWOOD4 = 0x8B7355; + public static final int CADETBLUE4 = 0x53868B; + public static final int CHARTREUSE4 = 0x458B00; + public static final int CHOCOLATE4 = 0x8B4513; + public static final int CORAL4 = 0x8B3E2F; + public static final int CORNSILK4 = 0x8B8878; + public static final int CYAN4 = 0x008B8B; + public static final int DARKGOLDENROD4 = 0x8B6508; + public static final int DARKOLIVE4 = 0x6E8B3D; + public static final int DARKORANGE4 = 0x8B4500; + public static final int DARKORCHID4 = 0x68228B; + public static final int DARKSEAGREEN4 = 0x698B69; + public static final int DARKSLATEGRAY4 = 0x528B8B; + public static final int DEEPPINK4 = 0x8B0A50; + public static final int DEEPSKYBLUE4 = 0x00688B; + public static final int DODGERBLUE4 = 0x104E8B; + public static final int FIREBRICK4 = 0x8B1A1A; + public static final int GOLD4 = 0x8B7500; + public static final int GOLDENROD4 = 0x8B6914; + public static final int GREEN4 = 0x008B00; + public static final int HONEYDEW4 = 0x838B83; + public static final int HOTPINK4 = 0x8B3A62; + public static final int INDIANRED4 = 0x8B3A3A; + public static final int IVORY4 = 0x8B8B83; + public static final int KHAKI4 = 0x8B864E; + public static final int LAVENDERBLUSH4 = 0x8B8386; + public static final int LEMONCHIFFON4 = 0x8B8970; + public static final int LIGHTBLUE4 = 0x68838B; + public static final int LIGHTCYAN4 = 0x7A8B8B; + public static final int LIGHTGOLDENROD4 = 0x8B814C; + public static final int LIGHTPINK4 = 0x8B5F65; + public static final int LIGHTSALMON4 = 0x8B5742; + public static final int LIGHTSKYBLUE4 = 0x607B8B; + public static final int LIGHTSTEELBLUE4 = 0x6E7B8B; + public static final int LIGHTYELLOW4 = 0x8B8B7A; + public static final int MAGENTA4 = 0x8B008B; + public static final int MAROON4 = 0x8B1C62; + public static final int MEDIUMORCHID4 = 0x7A378B; + public static final int MEDIUMPURPLE4 = 0x5D478B; + public static final int MISTYROSE4 = 0x8B7D7B; + public static final int NAVAJOWHITE4 = 0x8B795E; + public static final int OLIVEDRAB4 = 0x698B22; + public static final int ORANGE4 = 0x8B5A00; + public static final int ORCHID4 = 0x8B4789; + public static final int PALEGREEN4 = 0x548B54; + public static final int PALETURQUOISE4 = 0x668B8B; + public static final int PALEVIOLETRED4 = 0x8B475D; + public static final int PEACHPUFF4 = 0x8B7765; + public static final int PINK4 = 0x8B636C; + public static final int PLUM4 = 0x8B668B; + public static final int PURPLE4 = 0x551A8B; + public static final int RED4 = 0x8B0000; + public static final int ROSYBROWN4 = 0x8B6969; + public static final int ROYALBLUE4 = 0x27408B; + public static final int SALMON4 = 0x8B4C39; + public static final int SEAGREEN4 = 0x2E8B57; + public static final int SEASHELL4 = 0x8B8682; + public static final int SIENNA4 = 0x8B4726; + public static final int SKYBLUE4 = 0x4A708B; + public static final int SLATEBLUE4 = 0x473C8B; + public static final int SLATEGRAY4 = 0x6C7B8B; + public static final int SNOW4 = 0x8B8989; + public static final int SPRINGGREEN4 = 0x008B45; + public static final int STEELBLUE4 = 0x36648B; + public static final int TAN4 = 0x8B5A2B; + public static final int THISTLE4 = 0x8B7B8B; + public static final int TOMATO4 = 0x8B3626; + public static final int TURQUOISE4 = 0x00868B; + public static final int VIOLETRED4 = 0x8B2252; + public static final int WHEAT4 = 0x8B7E66; + public static final int YELLOW4 = 0x8B8B00; // basic color types public final static int WHITE = 0xffffff; + public final static int BLACK = 0x000000; // grays public final static int GREY0 = 0x000000; + public final static int GREY3 = 0x080808; + public final static int GREY7 = 0x121212; + public final static int GREY11 = 0x1c1c1c; + public final static int GREY15 = 0x262626; + public final static int GREY19 = 0x303030; + public final static int GREY23 = 0x3a3a3a; + public final static int GREY27 = 0x444444; + public final static int GREY30 = 0x4e4e4e; + public final static int GREY35 = 0x585858; + public final static int GREY37 = 0x5f5f5f; + public final static int GREY39 = 0x626262; + public final static int GREY42 = 0x6c6c6c; + public final static int GREY46 = 0x767676; + public final static int GREY50 = 0x808080; + public final static int GREY53 = 0x878787; + public final static int GREY54 = 0x8a8a8a; + public final static int GREY58 = 0x949494; + public final static int GREY62 = 0x9e9e9e; + public final static int GREY63 = 0xaf87af; + public final static int GREY66 = 0xa8a8a8; + public final static int GREY69 = 0xafafaf; + public final static int GREY70 = 0xb2b2b2; + public final static int GREY74 = 0xbcbcbc; + public final static int GREY78 = 0xc6c6c6; + public final static int GREY82 = 0xd0d0d0; + public final static int GREY84 = 0xd7d7d7; + public final static int GREY85 = 0xdadada; + public final static int GREY89 = 0xe4e4e4; + public final static int GREY93 = 0xeeeeee; + public final static int GREY100 = 0xffffff; + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DefaultScreen.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DefaultScreen.java index 4c5402783..fc7c3ef10 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DefaultScreen.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DefaultScreen.java @@ -42,9 +42,13 @@ public class DefaultScreen implements Screen, DisplayLines { private final static Logger log = LoggerFactory.getLogger(DefaultScreen.class); + private boolean showCursor; + private Position cursorPosition = new Position(0, 0); + private int rows = 0; + private int columns = 0; public DefaultScreen() { @@ -145,7 +149,7 @@ public List getScreenLines() { s = s.crossedOut(); } } - if (item.getContent() != null){ + if (item.getContent() != null) { builder.append(item.getContent(), s); } else if (item.getBorder() > 0) { @@ -170,9 +174,13 @@ else if (item.getBorder() > 0) { private static class DefaultScreenItem implements ScreenItem { CharSequence content; + int foreground = -1; + int background = -1; + int style = -1; + int border; @Override @@ -208,7 +216,9 @@ public int getStyle() { private class DefaultWriterBuilder implements WriterBuilder { int layer; + int color = -1; + int style = -1; @Override @@ -233,6 +243,7 @@ public WriterBuilder style(int style) { this.style = style; return this; } + } private void reset() { @@ -240,6 +251,7 @@ private void reset() { } private class Layer { + DefaultScreenItem[][] items = new DefaultScreenItem[rows][columns]; DefaultScreenItem getScreenItem(int x, int y) { @@ -253,6 +265,7 @@ DefaultScreenItem getScreenItem(int x, int y) { return null; } } + } private Map layers = new TreeMap<>(); @@ -287,7 +300,9 @@ public ScreenItem[][] getScreenItems() { private class DefaultWriter implements Writer { int index; + int color = -1; + int style = -1; DefaultWriter(int index, int color, int style) { @@ -419,6 +434,6 @@ private void printBorderVertical(int x, int y, int height) { } } - } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DisplayLines.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DisplayLines.java index 8a6701e9e..27eddc851 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DisplayLines.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/DisplayLines.java @@ -30,8 +30,8 @@ public interface DisplayLines { /** * Gets a list of screen lines. - * * @return list of screen lines */ List getScreenLines(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Screen.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Screen.java index 8f0703a59..0f76bf25f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Screen.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/Screen.java @@ -24,9 +24,8 @@ import org.springframework.shell.geom.VerticalAlign; /** - * {@code Screen} is representing a virtual area which is sitting between a user - * and lower level {@code jline} terminal providing convenient methods working - * with visible content. + * {@code Screen} is representing a virtual area which is sitting between a user and lower + * level {@code jline} terminal providing convenient methods working with visible content. * * @author Janne Valkealahti */ @@ -34,42 +33,36 @@ public interface Screen { /** * Sets if cursor should be visible. - * * @param show true if cursor should be visible */ void setShowCursor(boolean show); /** * Gets if cursor is visible. - * * @return true if cursor is visible */ boolean isShowCursor(); /** * Sets a cursor position. - * * @param position new cursor position */ void setCursorPosition(Position position); /** * Gets a cursor position. - * * @return cursor position */ Position getCursorPosition(); /** * Gets a new instance of a {@link WriterBuilder}. - * * @return a new writer builder */ WriterBuilder writerBuilder(); /** * Resize a screen. - * * @param rows the new row count * @param columns the new column count */ @@ -77,14 +70,12 @@ public interface Screen { /** * Gets a screen items. - * * @return a screen items */ ScreenItem[][] getItems(); /** * Clip a screen with a given bounds. - * * @param x the x coordinate * @param y the y coordinate * @param width the width @@ -94,15 +85,14 @@ public interface Screen { Screen clip(int x, int y, int width, int height); /** - * Interface to write into a {@link Screen}. Contains convenient methods user is - * most likely to need to operate on a {@link Screen}. + * Interface to write into a {@link Screen}. Contains convenient methods user is most + * likely to need to operate on a {@link Screen}. */ interface Writer { /** * Write a text horizontally starting from a position defined by {@code x} and * {@code y} within a bounds of a {@link Screen}. - * * @param text the text to write * @param x the x position * @param y the y position @@ -112,7 +102,6 @@ interface Writer { /** * Write an attributed text horizontally starting from a position defined by * {@code x} and {@code y} within a bounds of a {@link Screen}. - * * @param text the text to write * @param x the x position * @param y the y position @@ -121,7 +110,6 @@ interface Writer { /** * Write a border with a given rectangle coordinates. - * * @param x the x position * @param y the y position * @param width the rectangle width @@ -131,7 +119,6 @@ interface Writer { /** * Fill background with a given color. - * * @param rect the rectange to fill * @param color the color to use */ @@ -139,34 +126,32 @@ interface Writer { /** * Write aligned text within a bounds. - * * @param text the text to write * @param rect the rectangle bounds * @param hAlign the horizontal aligment * @param vAlign the vertical aligment */ void text(String text, Rectangle rect, @Nullable HorizontalAlign hAlign, @Nullable VerticalAlign vAlign); + } /** - * Builder interface for a {@link Writer}. Allows to defined settings a builder - * will operare on. + * Builder interface for a {@link Writer}. Allows to defined settings a builder will + * operare on. */ interface WriterBuilder { /** - * Define a {@code z-index} this {@link Writer} operates on. - * {@code WriterBuilder} defaults on a layer index {@code 0}. - * + * Define a {@code z-index} this {@link Writer} operates on. {@code WriterBuilder} + * defaults on a layer index {@code 0}. * @param index the z-index * @return a writer builder for chaining */ WriterBuilder layer(int index); /** - * Define a color this {@link Writer} operates on. - * {@code WriterBuilder} defaults to no defined color. - * + * Define a color this {@link Writer} operates on. {@code WriterBuilder} defaults + * to no defined color. * @param color the color * @return a writer builder for chaining * @see Color @@ -174,9 +159,8 @@ interface WriterBuilder { WriterBuilder color(int color); /** - * Define a style this {@link Writer} operates on. - * {@code WriterBuilder} defaults to no defined style. - * + * Define a style this {@link Writer} operates on. {@code WriterBuilder} defaults + * to no defined style. * @param style the style * @return a writer builder for chaining * @see ScreenItem @@ -185,9 +169,10 @@ interface WriterBuilder { /** * Build a {@link Writer}. - * * @return a build writer */ Writer build(); + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/ScreenItem.java b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/ScreenItem.java index 1ebd1542d..e889cbe2b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/ScreenItem.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/component/view/screen/ScreenItem.java @@ -16,20 +16,18 @@ package org.springframework.shell.component.view.screen; /** - * - * * @author Janne Valkealahti */ public interface ScreenItem { - static final int STYLE_BOLD = 1; - static final int STYLE_FAINT = STYLE_BOLD << 1; - static final int STYLE_ITALIC = STYLE_BOLD << 2; - static final int STYLE_UNDERLINE = STYLE_BOLD << 3; - static final int STYLE_BLINK = STYLE_BOLD << 4; - static final int STYLE_INVERSE = STYLE_BOLD << 5; - static final int STYLE_CONCEAL = STYLE_BOLD << 6; - static final int STYLE_CROSSEDOUT = STYLE_BOLD << 7; + static final int STYLE_BOLD = 1; + static final int STYLE_FAINT = STYLE_BOLD << 1; + static final int STYLE_ITALIC = STYLE_BOLD << 2; + static final int STYLE_UNDERLINE = STYLE_BOLD << 3; + static final int STYLE_BLINK = STYLE_BOLD << 4; + static final int STYLE_INVERSE = STYLE_BOLD << 5; + static final int STYLE_CONCEAL = STYLE_BOLD << 6; + static final int STYLE_CROSSEDOUT = STYLE_BOLD << 7; static final int BORDER_LEFT = 1; static final int BORDER_TOP = BORDER_LEFT << 1; diff --git a/spring-shell-core/src/main/java/org/springframework/shell/config/ShellConversionServiceSupplier.java b/spring-shell-core/src/main/java/org/springframework/shell/config/ShellConversionServiceSupplier.java index 2031d2fcc..353f0dd3d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/config/ShellConversionServiceSupplier.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/config/ShellConversionServiceSupplier.java @@ -25,4 +25,5 @@ * @author Janne Valkealahti */ public interface ShellConversionServiceSupplier extends Supplier { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/config/UserConfigPathProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/config/UserConfigPathProvider.java index 5edfa0cd9..b17f6f369 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/config/UserConfigPathProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/config/UserConfigPathProvider.java @@ -18,8 +18,8 @@ import java.nio.file.Path; /** - * Interface providing a {@link Path} to a location where - * user level runtime configuration files are strored. + * Interface providing a {@link Path} to a location where user level runtime configuration + * files are strored. * * @author Janne Valkealahti */ @@ -28,8 +28,8 @@ public interface UserConfigPathProvider { /** * Provides a path to a user config location. - * * @return a path to user config location */ Path provide(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/context/DefaultShellContext.java b/spring-shell-core/src/main/java/org/springframework/shell/context/DefaultShellContext.java index d92e6abcb..942bf7756 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/context/DefaultShellContext.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/context/DefaultShellContext.java @@ -25,6 +25,7 @@ public class DefaultShellContext implements ShellContext { private InteractionMode interactionMode = InteractionMode.ALL; + private final boolean pty; public DefaultShellContext() { @@ -50,4 +51,5 @@ public void setInteractionMode(InteractionMode interactionMode) { public boolean hasPty() { return this.pty; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/context/InteractionMode.java b/spring-shell-core/src/main/java/org/springframework/shell/context/InteractionMode.java index ffb5f019e..3e56bc312 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/context/InteractionMode.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/context/InteractionMode.java @@ -28,14 +28,15 @@ public enum InteractionMode { ALL, /** - * Non-interactive mode which is expected to exit and doesn't have any kind of - * running mode to keep shell alive. + * Non-interactive mode which is expected to exit and doesn't have any kind of running + * mode to keep shell alive. */ NONINTERACTIVE, /** - * Interactive mode which is expected to not exit and do have a running mode to - * keep shell alive. + * Interactive mode which is expected to not exit and do have a running mode to keep + * shell alive. */ INTERACTIVE + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/context/ShellContext.java b/spring-shell-core/src/main/java/org/springframework/shell/context/ShellContext.java index 6ea25ad47..0d25fddbd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/context/ShellContext.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/context/ShellContext.java @@ -16,8 +16,8 @@ package org.springframework.shell.context; /** - * Interface defining a contract for a context which allows to loosely connect - * different components together and keep things alive between commands. + * Interface defining a contract for a context which allows to loosely connect different + * components together and keep things alive between commands. * * @author Janne Valkealahti */ @@ -25,24 +25,22 @@ public interface ShellContext { /** * Gets an interaction mode. - * * @return a current interaction mode */ InteractionMode getInteractionMode(); /** * Sets an interaction mode. - * * @param interactionMode the interaction mode */ void setInteractionMode(InteractionMode interactionMode); /** - * Gets if shell has a proper {@code pty} terminal. Terminal don't have - * {@code pty} in cases where output is piped into a file or terminal is run in - * an ci system where there is no real user interaction. - * + * Gets if shell has a proper {@code pty} terminal. Terminal don't have {@code pty} in + * cases where output is piped into a file or terminal is run in an ci system where + * there is no real user interaction. * @return {@code true} if terminal has pty features */ boolean hasPty(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeExceptionProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeExceptionProvider.java index a198e89bb..be42208bc 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeExceptionProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeExceptionProvider.java @@ -18,10 +18,11 @@ import java.util.function.BiFunction; /** - * Interface to provide exception for an exit code. Typically providing - * exception implementing boot's {@code ExitCodeGenerator}. + * Interface to provide exception for an exit code. Typically providing exception + * implementing boot's {@code ExitCodeGenerator}. * * @author Janne Valkealahti */ public interface ExitCodeExceptionProvider extends BiFunction { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeMappings.java b/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeMappings.java index 01c81a0e1..a940264fd 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeMappings.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/exit/ExitCodeMappings.java @@ -19,10 +19,10 @@ import java.util.function.Function; /** - * Interface used with implementation of a boot's ExitCodeExceptionMapper - * in a context of spring-shell spesific one. Mostly needed not to have a - * direct dependencies to boot classes as currently only one implementation - * instance can exist which we need to reset between command executions. + * Interface used with implementation of a boot's ExitCodeExceptionMapper in a context of + * spring-shell spesific one. Mostly needed not to have a direct dependencies to boot + * classes as currently only one implementation instance can exist which we need to reset + * between command executions. * * @author Janne Valkealahti */ @@ -30,8 +30,8 @@ public interface ExitCodeMappings { /** * Reset mappings into a given functions. - * * @param functions the mapping functions */ void reset(List> functions); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/geom/HorizontalAlign.java b/spring-shell-core/src/main/java/org/springframework/shell/geom/HorizontalAlign.java index 41532249b..1c052c11b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/geom/HorizontalAlign.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/geom/HorizontalAlign.java @@ -16,5 +16,7 @@ package org.springframework.shell.geom; public enum HorizontalAlign { + LEFT, CENTER, RIGHT, + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/geom/Rectangle.java b/spring-shell-core/src/main/java/org/springframework/shell/geom/Rectangle.java index 7a8bfd7e3..7477fee0f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/geom/Rectangle.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/geom/Rectangle.java @@ -16,8 +16,8 @@ package org.springframework.shell.geom; /** - * Record representing coordinates {@code x}, {@code y} and its {@code width} - * and {@code height}. + * Record representing coordinates {@code x}, {@code y} and its {@code width} and + * {@code height}. */ public record Rectangle(int x, int y, int width, int height) { @@ -38,11 +38,9 @@ public boolean contains(int X, int Y) { } /** - * Determines whether the {@code Rectangle} is empty. When the {@code Rectangle} - * is empty, it encloses no area. - * - * @return {@code true} if the {@code Rectangle} is empty; {@code false} - * otherwise. + * Determines whether the {@code Rectangle} is empty. When the {@code Rectangle} is + * empty, it encloses no area. + * @return {@code true} if the {@code Rectangle} is empty; {@code false} otherwise. */ public boolean isEmpty() { return width <= 0 || height <= 0; diff --git a/spring-shell-core/src/main/java/org/springframework/shell/geom/VerticalAlign.java b/spring-shell-core/src/main/java/org/springframework/shell/geom/VerticalAlign.java index e3e9d5215..216343ec8 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/geom/VerticalAlign.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/geom/VerticalAlign.java @@ -16,5 +16,7 @@ package org.springframework.shell.geom; public enum VerticalAlign { + TOP, CENTER, BOTTOM + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/ExtendedDefaultParser.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/ExtendedDefaultParser.java index cf4f1b726..b76636b3a 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/ExtendedDefaultParser.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/ExtendedDefaultParser.java @@ -151,7 +151,6 @@ else if (!isEscapeChar(line, i)) { * that the character is not escaped by any of {@link #getQuoteChars}, and is not * escaped by ant of the {@link #getEscapeChars}, and returns true from * {@link #isDelimiterChar}. - * * @param buffer The complete command buffer * @param pos The index of the character in the buffer * @return True if the character should be a delimiter @@ -197,7 +196,6 @@ public boolean isEscapeChar(final CharSequence buffer, final int pos) { /** * Check if a character is escaped (i.e. if the previous character is an escape) - * * @param buffer the buffer to check in * @param pos the position of the character to check * @return true if the character at the specified position in the given buffer is an @@ -228,6 +226,7 @@ public boolean isDelimiterChar(CharSequence buffer, int pos) { * @author Marc Prud'hommeaux */ public class ExtendedArgumentList implements ParsedLine, CompletingParsedLine { + private final String line; private final List words; @@ -283,14 +282,18 @@ public CharSequence emit(CharSequence candidate) { StringBuilder sb = new StringBuilder(candidate); Predicate needToBeEscaped; // Completion is protected by an opening quote: - // Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does. + // Delimiters (spaces) don't need to be escaped, nor do other quotes, but + // everything else does. // Also, close the quote at the end if (openingQuote != null) { - needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote); - } // No quote protection, need to escape everything: delimiter chars (spaces), quote chars - // and escapes themselves + needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) + || String.valueOf(sb.charAt(i)).equals(openingQuote); + } // No quote protection, need to escape everything: delimiter chars (spaces), + // quote chars + // and escapes themselves else { - needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i)); + needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) + || isRawQuoteChar(sb.charAt(i)); } for (int i = 0; i < sb.length(); i++) { if (needToBeEscaped.test(i)) { @@ -302,6 +305,7 @@ public CharSequence emit(CharSequence candidate) { } return sb; } + } private boolean isRawEscapeChar(char key) { @@ -325,7 +329,8 @@ private boolean isRawQuoteChar(char key) { /** * Another copy from JLine's {@link org.jline.reader.impl.LineReaderImpl} * - * Used to wrap {@link org.jline.reader.ParsedLine} into {@link org.jline.reader.CompletingParsedLine} + * Used to wrap {@link org.jline.reader.ParsedLine} into + * {@link org.jline.reader.CompletingParsedLine} */ private static org.jline.reader.CompletingParsedLine wrap(ParsedLine line) { if (line instanceof org.jline.reader.CompletingParsedLine) { @@ -336,27 +341,35 @@ private static org.jline.reader.CompletingParsedLine wrap(ParsedLine line) { public String word() { return line.word(); } + public int wordCursor() { return line.wordCursor(); } + public int wordIndex() { return line.wordIndex(); } + public List words() { return line.words(); } + public String line() { return line.line(); } + public int cursor() { return line.cursor(); } + public CharSequence escape(CharSequence candidate, boolean complete) { return candidate; } + public int rawWordCursor() { return wordCursor(); } + public int rawWordLength() { return word().length(); } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/FileInputProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/FileInputProvider.java index 2b421eceb..a90af39eb 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/FileInputProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/FileInputProvider.java @@ -28,54 +28,61 @@ /** * An {@link InputProvider} that reads input from file-like sources. - *

    Still uses a {@link org.jline.reader.Parser} to interpret word boundaries. Supports backslashes at end - * of line to signal line continuation.

    + *

    + * Still uses a {@link org.jline.reader.Parser} to interpret word boundaries. Supports + * backslashes at end of line to signal line continuation. + *

    * * @author Eric Bottard */ public class FileInputProvider implements InputProvider, Closeable { - private static final String BACKSLASH_AT_EOL_REGEX = "(.*)\\\\\\s*$"; - private final BufferedReader reader; + private static final String BACKSLASH_AT_EOL_REGEX = "(.*)\\\\\\s*$"; - private final Parser parser; + private final BufferedReader reader; - public FileInputProvider(Reader reader, Parser parser) { - this.reader = new BufferedReader(reader); - this.parser = parser; - } + private final Parser parser; - @Override - public Input readInput() { - StringBuilder sb = new StringBuilder(); - boolean continued = false; - String line; - try { - do { - line = reader.readLine(); - if (line == null) { - break; - } - continued = line.matches(BACKSLASH_AT_EOL_REGEX); - sb.append(line.replaceFirst(BACKSLASH_AT_EOL_REGEX, "$1 ")); - } while (continued); - } catch (IOException e) { - throw new RuntimeException(e); - } - if (line == null || isComment(line)) { - return null; - } else { + public FileInputProvider(Reader reader, Parser parser) { + this.reader = new BufferedReader(reader); + this.parser = parser; + } + + @Override + public Input readInput() { + StringBuilder sb = new StringBuilder(); + boolean continued = false; + String line; + try { + do { + line = reader.readLine(); + if (line == null) { + break; + } + continued = line.matches(BACKSLASH_AT_EOL_REGEX); + sb.append(line.replaceFirst(BACKSLASH_AT_EOL_REGEX, "$1 ")); + } + while (continued); + } + catch (IOException e) { + throw new RuntimeException(e); + } + if (line == null || isComment(line)) { + return null; + } + else { ParsedLine parsedLine = parser.parse(sb.toString(), sb.toString().length()); return new ParsedLineInput(parsedLine); - } - } + } + } - @Override - public void close() throws IOException { - reader.close(); - } + @Override + public void close() throws IOException { + reader.close(); + } private boolean isComment(String line) { return line.matches("\\s*//.*"); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/InteractiveShellRunner.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/InteractiveShellRunner.java index c29c8f98d..f0622d8c0 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/InteractiveShellRunner.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/InteractiveShellRunner.java @@ -33,8 +33,10 @@ /** * A {@link ShellRunner} that bootstraps the shell in interactive mode. * - *

    Has lower precedence than {@link ScriptShellRunner} and {@link NonInteractiveShellRunner} which makes it the - * default shell runner when the other runners opt-out of handling the shell. + *

    + * Has lower precedence than {@link ScriptShellRunner} and + * {@link NonInteractiveShellRunner} which makes it the default shell runner when the + * other runners opt-out of handling the shell. * * @author Eric Bottard * @author Janne Valkealahti @@ -44,8 +46,9 @@ public class InteractiveShellRunner implements ShellRunner { /** - * The precedence at which this runner is ordered by the DefaultApplicationRunner - which also controls - * the order it is consulted on the ability to handle the current shell. + * The precedence at which this runner is ordered by the DefaultApplicationRunner - + * which also controls the order it is consulted on the ability to handle the current + * shell. */ public static final int PRECEDENCE = 0; @@ -93,7 +96,8 @@ public Input readInput() { catch (UserInterruptException e) { if (e.getPartialLine().isEmpty()) { throw new ExitRequest(1); - } else { + } + else { return Input.EMPTY; } } @@ -102,5 +106,7 @@ public Input readInput() { } return new ParsedLineInput(lineReader.getParsedLine()); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/NonInteractiveShellRunner.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/NonInteractiveShellRunner.java index 13399c7a2..bf0085393 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/NonInteractiveShellRunner.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/NonInteractiveShellRunner.java @@ -39,8 +39,9 @@ /** * A {@link ShellRunner} that executes commands without entering interactive shell mode. * - *

    Has higher precedence than {@link InteractiveShellRunner} which gives it an opportunity to handle the shell - * in non-interactive fashion. + *

    + * Has higher precedence than {@link InteractiveShellRunner} which gives it an opportunity + * to handle the shell in non-interactive fashion. * * @author Janne Valkealahti * @author Chris Bono @@ -49,8 +50,9 @@ public class NonInteractiveShellRunner implements ShellRunner { /** - * The precedence at which this runner is ordered by the DefaultApplicationRunner - which also controls - * the order it is consulted on the ability to handle the current shell. + * The precedence at which this runner is ordered by the DefaultApplicationRunner - + * which also controls the order it is consulted on the ability to handle the current + * shell. */ public static final int PRECEDENCE = InteractiveShellRunner.PRECEDENCE - 50; @@ -62,8 +64,9 @@ public class NonInteractiveShellRunner implements ShellRunner { private String primaryCommand; - private static final String SINGLE_QUOTE = "\'"; - private static final String DOUBLE_QUOTE = "\""; + private static final String SINGLE_QUOTE = "\'"; + + private static final String DOUBLE_QUOTE = "\""; private Function> commandsFromArgs = args -> { if (ObjectUtils.isEmpty(args)) { @@ -75,14 +78,12 @@ public class NonInteractiveShellRunner implements ShellRunner { } } // re-quote if needed having whitespace - String raw = Arrays.stream(args) - .map(a -> { - if (!isQuoted(a) && StringUtils.containsWhitespace(a)) { - return "\"" + a + "\""; - } - return a; - }) - .collect(Collectors.joining(" ")); + String raw = Arrays.stream(args).map(a -> { + if (!isQuoted(a) && StringUtils.containsWhitespace(a)) { + return "\"" + a + "\""; + } + return a; + }).collect(Collectors.joining(" ")); if (StringUtils.hasText(primaryCommand)) { return Collections.singletonList(primaryCommand + " " + raw); } @@ -111,11 +112,11 @@ public NonInteractiveShellRunner(Shell shell, ShellContext shellContext, String } /** - * Sets the function that creates the command() to run from the input application arguments. - * - * @param commandsFromArgs function that takes input application arguments and creates zero or more commands - * where each command is a string that specifies the command and options - * (eg. 'history --file myHistory.txt') + * Sets the function that creates the command() to run from the input application + * arguments. + * @param commandsFromArgs function that takes input application arguments and creates + * zero or more commands where each command is a string that specifies the command and + * options (eg. 'history --file myHistory.txt') */ public void setCommandsFromArgs(Function> commandsFromArgs) { this.commandsFromArgs = commandsFromArgs; @@ -123,7 +124,6 @@ public void setCommandsFromArgs(Function> commandsFromArg /** * Sets the line parser used to parse commands. - * * @param lineParser the line parser used to parse commands */ public void setLineParser(Parser lineParser) { @@ -137,8 +137,8 @@ public boolean run(String[] args) throws Exception { return false; } List parsedLines = commands.stream() - .map(rawCommandLine -> lineParser.parse(rawCommandLine, rawCommandLine.length() + 1)) - .collect(Collectors.toList()); + .map(rawCommandLine -> lineParser.parse(rawCommandLine, rawCommandLine.length() + 1)) + .collect(Collectors.toList()); MultiParsedLineInputProvider inputProvider = new MultiParsedLineInputProvider(parsedLines); shellContext.setInteractionMode(InteractionMode.NONINTERACTIVE); shell.run(inputProvider); @@ -146,17 +146,17 @@ public boolean run(String[] args) throws Exception { } /** - * An {@link InputProvider} that returns an input for each entry in a list of {@link ParsedLine parsed lines}. + * An {@link InputProvider} that returns an input for each entry in a list of + * {@link ParsedLine parsed lines}. */ static class MultiParsedLineInputProvider implements InputProvider { private final List parsedLineInputs; + private int inputIdx; MultiParsedLineInputProvider(List parsedLines) { - this.parsedLineInputs = parsedLines.stream() - .map(ParsedLineInput::new) - .collect(Collectors.toList()); + this.parsedLineInputs = parsedLines.stream().map(ParsedLineInput::new).collect(Collectors.toList()); } @Override @@ -184,6 +184,9 @@ public String rawText() { public List words() { return Utils.sanitizeInput(parsedLine.words()); } + } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/ParsedLineInput.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/ParsedLineInput.java index 82c6eae22..1c883d981 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/ParsedLineInput.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/ParsedLineInput.java @@ -24,25 +24,27 @@ import org.springframework.shell.Utils; /** - * An implementation of {@link Input} backed by the result of a {@link org.jline.reader.Parser#parse(String, int)}. + * An implementation of {@link Input} backed by the result of a + * {@link org.jline.reader.Parser#parse(String, int)}. * * @author Eric Bottard */ class ParsedLineInput implements Input { - private final ParsedLine parsedLine; + private final ParsedLine parsedLine; - ParsedLineInput(ParsedLine parsedLine) { - this.parsedLine = parsedLine; - } + ParsedLineInput(ParsedLine parsedLine) { + this.parsedLine = parsedLine; + } - @Override - public String rawText() { - return parsedLine.line(); - } + @Override + public String rawText() { + return parsedLine.line(); + } + + @Override + public List words() { + return Utils.sanitizeInput(parsedLine.words()); + } - @Override - public List words() { - return Utils.sanitizeInput(parsedLine.words()); - } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/PromptProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/PromptProvider.java index f1d8ecfa4..788c03f57 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/PromptProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/PromptProvider.java @@ -10,4 +10,5 @@ public interface PromptProvider { AttributedString getPrompt(); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/ScriptShellRunner.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/ScriptShellRunner.java index 30fa1aa03..e8483bf81 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/ScriptShellRunner.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/ScriptShellRunner.java @@ -31,22 +31,26 @@ import org.springframework.util.ObjectUtils; /** - * A {@link ShellRunner} that looks for process arguments that start with {@literal @}, which are then interpreted as - * references to script files to run and exit. + * A {@link ShellRunner} that looks for process arguments that start with {@literal @}, + * which are then interpreted as references to script files to run and exit. * - *

    Has higher precedence than {@link NonInteractiveShellRunner} and {@link InteractiveShellRunner} which gives it - * top priority to run the shell if scripts are found. + *

    + * Has higher precedence than {@link NonInteractiveShellRunner} and + * {@link InteractiveShellRunner} which gives it top priority to run the shell if scripts + * are found. * * @author Eric Bottard */ -//tag::documentation[] +// tag::documentation[] @Order(ScriptShellRunner.PRECEDENCE) public class ScriptShellRunner implements ShellRunner { -//end::documentation[] + + // end::documentation[] /** - * The precedence at which this runner is ordered by the DefaultApplicationRunner - which also controls - * the order it is consulted on the ability to handle the current shell. + * The precedence at which this runner is ordered by the DefaultApplicationRunner - + * which also controls the order it is consulted on the ability to handle the current + * shell. */ public static final int PRECEDENCE = InteractiveShellRunner.PRECEDENCE - 100; @@ -69,10 +73,11 @@ public boolean run(String[] args) throws Exception { return false; } - List scriptsToRun = Arrays.asList(args).stream() - .filter(s -> s.startsWith("@")) - .map(s -> new File(s.substring(1))) - .collect(Collectors.toList()); + List scriptsToRun = Arrays.asList(args) + .stream() + .filter(s -> s.startsWith("@")) + .map(s -> new File(s.substring(1))) + .collect(Collectors.toList()); for (File file : scriptsToRun) { try (Reader reader = new FileReader(file); diff --git a/spring-shell-core/src/main/java/org/springframework/shell/package-info.java b/spring-shell-core/src/main/java/org/springframework/shell/package-info.java index 66ef91fc4..21967a80c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/package-info.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/package-info.java @@ -15,7 +15,8 @@ */ /** - * Contains core classes for Spring Shell, irrespective of the way commands are actually implemented. + * Contains core classes for Spring Shell, irrespective of the way commands are actually + * implemented. * * @author Eric Bottard */ diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/AttributedCharSequenceResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/AttributedCharSequenceResultHandler.java index 1372d65c5..c76beaccf 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/AttributedCharSequenceResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/AttributedCharSequenceResultHandler.java @@ -22,7 +22,8 @@ import org.springframework.shell.ResultHandler; /** - * A {@link ResultHandler} that knows how to render JLine's {@link AttributedCharSequence}. + * A {@link ResultHandler} that knows how to render JLine's + * {@link AttributedCharSequence}. * * @author Eric Bottard */ @@ -37,4 +38,5 @@ protected void doHandleResult(AttributedCharSequence result) { terminal.writer().println(result.toAnsi(terminal)); terminal.writer().flush(); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundMessageProvider.java b/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundMessageProvider.java index 66c9e1efa..b5f3527bc 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundMessageProvider.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundMessageProvider.java @@ -30,7 +30,8 @@ @FunctionalInterface public interface CommandNotFoundMessageProvider extends Function { - static ProviderContext contextOf(Throwable error, List commands, Map registrations, String text) { + static ProviderContext contextOf(Throwable error, List commands, + Map registrations, String text) { return new ProviderContext() { @Override @@ -62,31 +63,28 @@ interface ProviderContext { /** * Gets an actual error. - * * @return actual error */ Throwable error(); /** * Gets a list of commands parsed. - * * @return list of commands parsed */ List commands(); /** * Gets a command registrations. - * * @return a command registrations */ Map registrations(); /** * Gets a raw input text. - * * @return a raw input text */ String text(); + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundResultHandler.java index bdf6a0bd8..ed8399ccf 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/CommandNotFoundResultHandler.java @@ -13,10 +13,10 @@ /** * {@link ResultHandler} for {@link CommandNotFound} using - * {@link CommandNotFoundMessageProvider} to provide an error message. - * Default internal provider simply provides message from a {@link CommandNotFound} - * with a red color. Provider can be defined by providing a custom - * {@link CommandNotFoundMessageProvider} bean. + * {@link CommandNotFoundMessageProvider} to provide an error message. Default internal + * provider simply provides message from a {@link CommandNotFound} with a red color. + * Provider can be defined by providing a custom {@link CommandNotFoundMessageProvider} + * bean. * * @author Janne Valkealahti */ @@ -45,8 +45,11 @@ private static class DefaultProvider implements CommandNotFoundMessageProvider { @Override public String apply(ProviderContext context) { String message = new AttributedString(context.error().getMessage(), - AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi(); + AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) + .toAnsi(); return message; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/DefaultResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/DefaultResultHandler.java index c58a985d9..8e43b8103 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/DefaultResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/DefaultResultHandler.java @@ -36,4 +36,5 @@ public DefaultResultHandler(Terminal terminal) { protected void doHandleResult(Object result) { terminal.writer().println(String.valueOf(result)); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandler.java index c679f4b43..fda620307 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandler.java @@ -6,9 +6,10 @@ public interface GenericResultHandler { - Set> getHandlerTypes(); + Set> getHandlerTypes(); - void handle(Object result, TypeDescriptor resultType); + void handle(Object result, TypeDescriptor resultType); + + boolean matches(TypeDescriptor resultType); - boolean matches(TypeDescriptor resultType); } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandlerService.java b/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandlerService.java index e6c1c096e..21ea6db68 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandlerService.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/GenericResultHandlerService.java @@ -36,8 +36,7 @@ import org.springframework.util.StringUtils; /** - * Base {@link ResultHandlerService} implementation suitable for use in most - * environments. + * Base {@link ResultHandlerService} implementation suitable for use in most environments. * * @author Janne Valkealahti */ @@ -65,21 +64,19 @@ public void handle(Object result, TypeDescriptor resultType) { /** * Add a plain result handler to this registry. - * * @param resultHandler the result handler */ public void addResultHandler(ResultHandler resultHandler) { ResolvableType[] typeInfo = getRequiredTypeInfo(resultHandler.getClass(), ResultHandler.class); if (typeInfo == null) { - throw new IllegalArgumentException("Unable to determine result type for your " + - "ResultHandler [" + resultHandler.getClass().getName() + "]; does the class parameterize those types?"); + throw new IllegalArgumentException("Unable to determine result type for your " + "ResultHandler [" + + resultHandler.getClass().getName() + "]; does the class parameterize those types?"); } addResultHandler(new ResultHandlerAdapter(resultHandler, typeInfo[0])); } /** * Add a plain result handler to this registry. - * * @param the type of result handler * @param resultType the class of a result type * @param resultHandler the result handler @@ -90,7 +87,6 @@ public void addResultHandler(Class resultType, ResultHandler r /** * Add a generic result handler this this registry. - * * @param handler the generic result handler */ public void addResultHandler(GenericResultHandler handler) { @@ -102,8 +98,7 @@ private GenericResultHandler getResultHandler(TypeDescriptor resultType) { } @Nullable - private Object handleResultHandlerNotFound( - @Nullable Object source, @Nullable TypeDescriptor sourceType) { + private Object handleResultHandlerNotFound(@Nullable Object source, @Nullable TypeDescriptor sourceType) { if (source == null) { return null; } @@ -131,6 +126,7 @@ private ResolvableType[] getRequiredTypeInfo(Class handlerClass, Class gen private final static class ResultHandlerAdapter implements GenericResultHandler { ResultHandler handler; + Class result; public ResultHandlerAdapter(ResultHandler handler, ResolvableType resultType) { @@ -153,6 +149,7 @@ public boolean matches(TypeDescriptor resultType) { // always true until we create conditional handlers return true; } + } /** @@ -180,11 +177,13 @@ public GenericResultHandler getHandler(TypeDescriptor resultType) { public String toString() { return StringUtils.collectionToCommaDelimitedString(this.handlers); } + } private static class ResultHandlers { private final Set globalHandlers = new CopyOnWriteArraySet<>(); + private final Map, ResultHandlersForType> handlers = new ConcurrentHashMap<>(16); public void add(GenericResultHandler handler) { @@ -260,15 +259,15 @@ private List> getClassHierarchy(Class type) { return hierarchy; } - private void addInterfacesToClassHierarchy(Class type, boolean asArray, - List> hierarchy, Set> visited) { + private void addInterfacesToClassHierarchy(Class type, boolean asArray, List> hierarchy, + Set> visited) { for (Class implementedInterface : type.getInterfaces()) { addToClassHierarchy(hierarchy.size(), implementedInterface, asArray, hierarchy, visited); } } - private void addToClassHierarchy(int index, Class type, boolean asArray, - List> hierarchy, Set> visited) { + private void addToClassHierarchy(int index, Class type, boolean asArray, List> hierarchy, + Set> visited) { if (asArray) { type = Array.newInstance(type, 0).getClass(); } @@ -276,9 +275,12 @@ private void addToClassHierarchy(int index, Class type, boolean asArray, hierarchy.add(index, type); } } + } private static void invokeHandler(GenericResultHandler handler, Object result, TypeDescriptor resultType) { - handler.handle(result, resultType);; + handler.handle(result, resultType); + ; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/ParameterValidationExceptionResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/ParameterValidationExceptionResultHandler.java index 7954e6dc3..3bc115460 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/ParameterValidationExceptionResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/ParameterValidationExceptionResultHandler.java @@ -39,16 +39,18 @@ public ParameterValidationExceptionResultHandler(Terminal terminal) { @Override protected void doHandleResult(ParameterValidationException result) { - terminal.writer().println(new AttributedString("The following constraints were not met:", - AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi()); - result.getConstraintViolations().stream() - .forEach(violation -> { - Path propertyPath = violation.getPropertyPath(); - String violationMessage = violation.getMessage(); - String errorMessage = String.format("\t--%s: %s", extractPropertyName(propertyPath), violationMessage); - terminal.writer().println(new AttributedString(errorMessage, - AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi(terminal)); - }); + terminal.writer() + .println(new AttributedString("The following constraints were not met:", + AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) + .toAnsi()); + result.getConstraintViolations().stream().forEach(violation -> { + Path propertyPath = violation.getPropertyPath(); + String violationMessage = violation.getMessage(); + String errorMessage = String.format("\t--%s: %s", extractPropertyName(propertyPath), violationMessage); + terminal.writer() + .println(new AttributedString(errorMessage, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) + .toAnsi(terminal)); + }); } private String extractPropertyName(Path propertyPath) { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerConfig.java b/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerConfig.java index 24fde7e45..4a53fdfb4 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerConfig.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerConfig.java @@ -73,7 +73,8 @@ public ThrowableResultHandler throwableResultHandler(Terminal terminal, CommandC @Bean public CommandNotFoundResultHandler commandNotFoundResultHandler(Terminal terminal, - ObjectProvider provider) { + ObjectProvider provider) { return new CommandNotFoundResultHandler(terminal, provider); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerNotFoundException.java b/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerNotFoundException.java index c4df57baf..8c4bc1512 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerNotFoundException.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlerNotFoundException.java @@ -25,15 +25,13 @@ public class ResultHandlerNotFoundException extends ResultHandlingException { /** * Create a new handling executor not found exception. - * * @param resultType the result type requested to handle from */ public ResultHandlerNotFoundException(@Nullable TypeDescriptor resultType) { super("No handler found capable of handling from type [" + resultType + "]"); - this.resultType = resultType; + this.resultType = resultType; } - /** * Return the source type that was requested to convert from. */ @@ -41,4 +39,5 @@ public ResultHandlerNotFoundException(@Nullable TypeDescriptor resultType) { public TypeDescriptor getResultType() { return this.resultType; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlingException.java b/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlingException.java index 98b16ba3d..c35912e0f 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlingException.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/ResultHandlingException.java @@ -21,7 +21,6 @@ public class ResultHandlingException extends NestedRuntimeException { /** * Construct a new result handling exception. - * * @param message the exception message */ public ResultHandlingException(String message) { @@ -30,11 +29,11 @@ public ResultHandlingException(String message) { /** * Construct a new result handling exception. - * * @param message the exception message * @param cause the cause */ public ResultHandlingException(String message, Throwable cause) { super(message, cause); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalAwareResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalAwareResultHandler.java index 66553afb0..2bf4064b7 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalAwareResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalAwareResultHandler.java @@ -40,4 +40,5 @@ public final void handleResult(T result) { } protected abstract void doHandleResult(T result); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalSizeAwareResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalSizeAwareResultHandler.java index dc3bde81a..945bca22a 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalSizeAwareResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/TerminalSizeAwareResultHandler.java @@ -21,7 +21,8 @@ import org.springframework.shell.TerminalSizeAware; /** - * A ResultHandler that prints {@link TerminalSizeAware} according to the {@link org.jline.terminal.Terminal} size. + * A ResultHandler that prints {@link TerminalSizeAware} according to the + * {@link org.jline.terminal.Terminal} size. * * @author Eric Bottard */ @@ -36,4 +37,5 @@ protected void doHandleResult(TerminalSizeAware result) { CharSequence toPrint = result.render(terminal.getWidth()); terminal.writer().println(toPrint); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/result/ThrowableResultHandler.java b/spring-shell-core/src/main/java/org/springframework/shell/result/ThrowableResultHandler.java index daa2486ab..f91b86d0b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/result/ThrowableResultHandler.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/result/ThrowableResultHandler.java @@ -34,9 +34,9 @@ /** * A {@link ResultHandler} that prints thrown exceptions messages in red. * - * Stores the last exception reported, so that details can be printed using a - * dedicated command if in interactive mode. Prints stacktrace if in - * non-interactive mode as dedicated command could not be used. + * Stores the last exception reported, so that details can be printed using a dedicated + * command if in interactive mode. Prints stacktrace if in non-interactive mode as + * dedicated command could not be used. * * @author Eric Bottard * @author Janne Valkealahti @@ -71,15 +71,18 @@ protected void doHandleResult(Throwable result) { if (shouldHandle) { String errorMsg = StringUtils.hasLength(result.getMessage()) ? result.getMessage() : result.toString(); - terminal.writer().println(new AttributedString(errorMsg, - AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi()); + terminal.writer() + .println(new AttributedString(errorMsg, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) + .toAnsi()); String noteMsg; if (showShortError()) { noteMsg = new AttributedStringBuilder() - .append("Details of the error have been omitted. You can use the ", AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) + .append("Details of the error have been omitted. You can use the ", + AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) .append(DETAILS_COMMAND_NAME, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED).bold()) - .append(" command to print the full stacktrace.", AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) + .append(" command to print the full stacktrace.", + AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) .toAnsi(); } else { @@ -87,8 +90,8 @@ protected void doHandleResult(Throwable result) { PrintWriter pw = new PrintWriter(sw); result.printStackTrace(pw); String stacktraceStr = sw.toString(); - noteMsg = new AttributedString(stacktraceStr, - AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi(); + noteMsg = new AttributedString(stacktraceStr, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)) + .toAnsi(); } terminal.writer().println(noteMsg); terminal.writer().flush(); @@ -121,4 +124,5 @@ private boolean showShortError() { return commandCatalog.getRegistrations().keySet().contains(DETAILS_COMMAND_NAME) && this.shellContext.getInteractionMode() == InteractionMode.INTERACTIVE; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/FigureSettings.java b/spring-shell-core/src/main/java/org/springframework/shell/style/FigureSettings.java index 441c218c9..ed032faa4 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/FigureSettings.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/FigureSettings.java @@ -180,24 +180,13 @@ public static FigureSettings dump() { } public static String[] tags() { - return new String[] { - TAG_TICK, - TAG_INFO, - TAG_WARNING, - TAG_ERROR, - TAG_CHECKBOX_OFF, - TAG_CHECKBOX_ON, - TAG_LEFTWARDS_ARROR, - TAG_UPWARDS_ARROR, - TAG_RIGHTWARDS_ARROR, - TAG_DOWNWARDS_ARROR, - TAG_LEFT_POINTING_QUOTATION, - TAG_RIGHT_POINTING_QUOTATION, - TAG_QUESTION_MARK - }; + return new String[] { TAG_TICK, TAG_INFO, TAG_WARNING, TAG_ERROR, TAG_CHECKBOX_OFF, TAG_CHECKBOX_ON, + TAG_LEFTWARDS_ARROR, TAG_UPWARDS_ARROR, TAG_RIGHTWARDS_ARROR, TAG_DOWNWARDS_ARROR, + TAG_LEFT_POINTING_QUOTATION, TAG_RIGHT_POINTING_QUOTATION, TAG_QUESTION_MARK }; } private static class DefaultFigureSettings extends FigureSettings { + } private static class DumpFigureSettings extends FigureSettings { @@ -253,5 +242,7 @@ public String leftPointingQuotation() { public String rightPointingQuotation() { return ">"; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/PartsText.java b/spring-shell-core/src/main/java/org/springframework/shell/style/PartsText.java index f1c3b6a4f..1b647db88 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/PartsText.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/PartsText.java @@ -41,6 +41,7 @@ public List getParts() { public static class PartText { private String text; + private boolean match; public PartText(String text, boolean match) { @@ -59,5 +60,7 @@ public String getText() { public boolean isMatch() { return match; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/PartsTextRenderer.java b/spring-shell-core/src/main/java/org/springframework/shell/style/PartsTextRenderer.java index 54aa19e14..73d5fece1 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/PartsTextRenderer.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/PartsTextRenderer.java @@ -61,10 +61,10 @@ public String toString(PartsText value, String formatString, Locale locale) { text = text.substring(0, text.length() - 1) + ".."; } else if (diff == 0) { - text = String.format(locale, "%1." + (text.length() - 2) + "s.." , text); + text = String.format(locale, "%1." + (text.length() - 2) + "s..", text); } else { - text = String.format(locale, "%1." + (l - dots) + "s.." , text); + text = String.format(locale, "%1." + (l - dots) + "s..", text); } doBreak = true; } @@ -78,7 +78,7 @@ else if (currentLen > max) { text = ".."; } else { - text = String.format(locale, "%1." + l + "s.." , text); + text = String.format(locale, "%1." + l + "s..", text); } doBreak = true; } @@ -95,46 +95,53 @@ else if (currentLen > max) { } private static class Values { + Integer width; + Integer prefix; + String textStyle; + String matchStyle; public void setWidth(Integer width) { this.width = width; } + public void setPrefix(Integer prefix) { this.prefix = prefix; } + public void setTextStyle(String textStyle) { this.textStyle = textStyle; } + public void setMatchStyle(String matchStyle) { this.matchStyle = matchStyle; } + } private static Values mapValues(String expression) { Values values = new Values(); - Stream.of(expression.split(",")) - .map(String::trim) - .forEach(v -> { - String[] split = v.split(":", 2); - if (split.length == 2) { - if ("width".equals(split[0])) { - values.setWidth(Integer.parseInt(split[1])); - } - else if ("prefix".equals(split[0])) { - values.setPrefix(Integer.parseInt(split[1])); - } - else if ("textStyle".equals(split[0])) { - values.setTextStyle(split[1]); - } - else if ("matchStyle".equals(split[0])) { - values.setMatchStyle(split[1]); - } + Stream.of(expression.split(",")).map(String::trim).forEach(v -> { + String[] split = v.split(":", 2); + if (split.length == 2) { + if ("width".equals(split[0])) { + values.setWidth(Integer.parseInt(split[1])); + } + else if ("prefix".equals(split[0])) { + values.setPrefix(Integer.parseInt(split[1])); + } + else if ("textStyle".equals(split[0])) { + values.setTextStyle(split[1]); } - }); + else if ("matchStyle".equals(split[0])) { + values.setMatchStyle(split[1]); + } + } + }); return values; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/SpinnerSettings.java b/spring-shell-core/src/main/java/org/springframework/shell/style/SpinnerSettings.java index ba6475b70..a9ef74c32 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/SpinnerSettings.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/SpinnerSettings.java @@ -53,10 +53,7 @@ public Spinner resolveTag(String tag) { } public static String[] tags() { - return new String[] { - TAG_LINE, - TAG_DOT, - }; + return new String[] { TAG_LINE, TAG_DOT, }; } public static SpinnerSettings defaults() { @@ -68,6 +65,7 @@ public static SpinnerSettings dump() { } private static class DefaultSpinnerSettings extends SpinnerSettings { + } private static class DumpSpinnerSettings extends SpinnerSettings { @@ -76,6 +74,7 @@ private static class DumpSpinnerSettings extends SpinnerSettings { public Spinner dot() { return Spinner.of(Spinner.DOTS14, 200); } + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/StringToStyleExpressionRenderer.java b/spring-shell-core/src/main/java/org/springframework/shell/style/StringToStyleExpressionRenderer.java index 50e71bc91..3d562171c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/StringToStyleExpressionRenderer.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/StringToStyleExpressionRenderer.java @@ -25,15 +25,15 @@ import org.springframework.util.StringUtils; /** - * {@code ST} {@link AttributeRenderer} which knows to use format string to - * render strings into {@code jline} {@link StyleExpression} based on theming - * settings. + * {@code ST} {@link AttributeRenderer} which knows to use format string to render strings + * into {@code jline} {@link StyleExpression} based on theming settings. * * @author Janne Valkealahti */ public class StringToStyleExpressionRenderer implements AttributeRenderer { private final ThemeResolver themeResolver; + private final static String TRUNCATE = "truncate-"; public StringToStyleExpressionRenderer(ThemeResolver themeResolver) { @@ -53,7 +53,7 @@ else if (formatString.startsWith(TRUNCATE)) { String f = formatString.substring(TRUNCATE.length()); TruncateValues config = mapValues(f); if (value.length() + config.prefix > config.width) { - return String.format(locale, "%1." + (config.width - config.prefix - 2) + "s.." , value); + return String.format(locale, "%1." + (config.width - config.prefix - 2) + "s..", value); } else { return value; @@ -65,32 +65,35 @@ else if (formatString.startsWith(TRUNCATE)) { } private static class TruncateValues { + Integer width; + Integer prefix; public void setWidth(Integer width) { this.width = width; } + public void setPrefix(Integer prefix) { this.prefix = prefix; } + } private static TruncateValues mapValues(String expression) { TruncateValues values = new TruncateValues(); - Stream.of(expression.split("-")) - .map(String::trim) - .forEach(v -> { - String[] split = v.split(":", 2); - if (split.length == 2) { - if ("width".equals(split[0])) { - values.setWidth(Integer.parseInt(split[1])); - } - else if ("prefix".equals(split[0])) { - values.setPrefix(Integer.parseInt(split[1])); - } + Stream.of(expression.split("-")).map(String::trim).forEach(v -> { + String[] split = v.split(":", 2); + if (split.length == 2) { + if ("width".equals(split[0])) { + values.setWidth(Integer.parseInt(split[1])); + } + else if ("prefix".equals(split[0])) { + values.setPrefix(Integer.parseInt(split[1])); } - }); + } + }); return values; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/StyleSettings.java b/spring-shell-core/src/main/java/org/springframework/shell/style/StyleSettings.java index 25760313e..1c532a31d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/StyleSettings.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/StyleSettings.java @@ -194,7 +194,6 @@ public String statusbarBackground() { /** * Resolve a theme setting from a given tag. - * * @param tag the tag * @return a theme setting */ @@ -242,7 +241,6 @@ public String resolveTag(String tag) { /** * Creates an instance of a default settings. - * * @return a default theme settings */ public static StyleSettings defaults() { @@ -255,33 +253,17 @@ public static StyleSettings dump() { /** * Gets all tags. - * * @return array of all tags */ public static String[] tags() { - return new String[] { - TAG_TITLE, - TAG_VALUE, - TAG_LIST_KEY, - TAG_LIST_VALUE, - TAG_LEVEL_INFO, - TAG_LEVEL_WARN, - TAG_LEVEL_ERROR, - TAG_ITEM_ENABLED, - TAG_ITEM_DISABLED, - TAG_ITEM_SELECTED, - TAG_ITEM_UNSELECTED, - TAG_ITEM_SELECTOR, - TAG_HIGHLIGHT, - TAG_BACKGROUND, - TAG_DIALOG_BACKGROUND, - TAG_BUTTON_BACKGROUND, - TAG_MENUBAR_BACKGROUND, - TAG_STATUSBAR_BACKGROUND - }; + return new String[] { TAG_TITLE, TAG_VALUE, TAG_LIST_KEY, TAG_LIST_VALUE, TAG_LEVEL_INFO, TAG_LEVEL_WARN, + TAG_LEVEL_ERROR, TAG_ITEM_ENABLED, TAG_ITEM_DISABLED, TAG_ITEM_SELECTED, TAG_ITEM_UNSELECTED, + TAG_ITEM_SELECTOR, TAG_HIGHLIGHT, TAG_BACKGROUND, TAG_DIALOG_BACKGROUND, TAG_BUTTON_BACKGROUND, + TAG_MENUBAR_BACKGROUND, TAG_STATUSBAR_BACKGROUND }; } private static class DefaultStyleSettings extends StyleSettings { + } private static class DumpStyleSettings extends StyleSettings { @@ -350,5 +332,7 @@ public String itemSelector() { public String highlight() { return "default"; } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/TemplateExecutor.java b/spring-shell-core/src/main/java/org/springframework/shell/style/TemplateExecutor.java index 14cfe5f0a..e66d50e72 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/TemplateExecutor.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/TemplateExecutor.java @@ -36,9 +36,13 @@ public class TemplateExecutor { private final static Logger log = LoggerFactory.getLogger(TemplateExecutor.class); + private final static STErrorListener ERROR_LISTENER = new LoggingSTErrorListener(); + private final ThemeResolver themeResolver; + private StringToStyleExpressionRenderer renderer1; + private PartsTextRenderer renderer2; public TemplateExecutor(ThemeResolver themeResolver) { @@ -49,7 +53,6 @@ public TemplateExecutor(ThemeResolver themeResolver) { /** * Render template with a given attributes. - * * @param template the ST template * @param attributes the ST template attributes * @return a rendered template @@ -69,10 +72,9 @@ public AttributedString render(String template, Map attributes) } /** - * Render template group with a given attributes expecting to find instance - * named {@code main}. - * - * @param template the ST template + * Render template group with a given attributes expecting to find instance named + * {@code main}. + * @param template the ST template * @param attributes the ST template attributes * @return a rendered template */ @@ -122,5 +124,7 @@ public void IOError(STMessage msg) { public void internalError(STMessage msg) { log.debug("internalError [{}]", msg); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/Theme.java b/spring-shell-core/src/main/java/org/springframework/shell/style/Theme.java index 0aaa44120..7cfcf0bf4 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/Theme.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/Theme.java @@ -18,9 +18,9 @@ /** * Contract representing a theme with its name and settings. * - * {@link Theme} is a concept where you can request a {@code style} by using a theme {@code tag}. - * At this point an actual style is not known as it's going to get resolved from an - * enable {@code theme}. + * {@link Theme} is a concept where you can request a {@code style} by using a theme + * {@code tag}. At this point an actual style is not known as it's going to get resolved + * from an enable {@code theme}. * * @author Janne Valkealahti */ @@ -28,21 +28,18 @@ public interface Theme { /** * Gets a theme name. - * * @return a theme name. */ String getName(); /** * Gets a theme settings. - * * @return a theme settings */ ThemeSettings getSettings(); /** * Create a {@link Theme}. - * * @param name the theme name * @param themeSettings the theme settings * @return a theme @@ -61,4 +58,5 @@ public ThemeSettings getSettings() { } }; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeActive.java b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeActive.java index a45a3a2ab..a1c7c40c9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeActive.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeActive.java @@ -18,4 +18,5 @@ import java.util.function.Supplier; public interface ThemeActive extends Supplier { + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeRegistry.java b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeRegistry.java index 64f8ca18e..c65ddb6a5 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeRegistry.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeRegistry.java @@ -32,7 +32,6 @@ public class ThemeRegistry { /** * Gets a theme from a registry. - * * @param name the theme name * @return a theme */ @@ -42,7 +41,6 @@ public Theme get(String name) { /** * Register a theme. - * * @param theme the theme */ public void register(Theme theme) { @@ -52,10 +50,10 @@ public void register(Theme theme) { /** * Gets all theme names registered. - * * @return theme names */ public Set getThemeNames() { return themes.keySet(); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeResolver.java index b0591e73a..ad8f5bf22 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeResolver.java @@ -36,9 +36,13 @@ public class ThemeResolver { private StyleSource styleSource = new MemoryStyleSource(); + private StyleResolver styleResolver = new StyleResolver(styleSource, "default"); + private StyleExpression styleExpression = new StyleExpression(styleResolver); + private ThemeRegistry themeRegistry; + private final Theme theme; public ThemeResolver(ThemeRegistry themeRegistry, String themeName) { @@ -48,25 +52,34 @@ public ThemeResolver(ThemeRegistry themeRegistry, String themeName) { // copied from jline as no public access private static final long F_FOREGROUND_IND = 0x00000100; + private static final long F_FOREGROUND_RGB = 0x00000200; + private static final long F_FOREGROUND = F_FOREGROUND_IND | F_FOREGROUND_RGB; + private static final long F_BACKGROUND_IND = 0x00000400; + private static final long F_BACKGROUND_RGB = 0x00000800; + private static final long F_BACKGROUND = F_BACKGROUND_IND | F_BACKGROUND_RGB; + private static final int FG_COLOR_EXP = 15; + private static final int BG_COLOR_EXP = 39; + private static final long FG_COLOR = 0xFFFFFFL << FG_COLOR_EXP; + private static final long BG_COLOR = 0xFFFFFFL << BG_COLOR_EXP; /** * Stores resolved values for {@link ThemeResolver#resolveValues(AttributedStyle)}. */ - public record ResolvedValues(int style, int foreground, int background){} + public record ResolvedValues(int style, int foreground, int background) { + } /** - * Resolve {@code style}, {@code foreground color} and {@code background color} - * from an {@link AttributedStyle}. - * + * Resolve {@code style}, {@code foreground color} and {@code background color} from + * an {@link AttributedStyle}. * @param attributedStyle the attibuted style * @return resolved values */ @@ -87,12 +100,11 @@ public static ResolvedValues resolveValues(AttributedStyle attributedStyle) { bg = Colors.DEFAULT_COLORS_256[bg & 0xFF]; } - return new ResolvedValues((int)s, hasFb ? fg : -1, hasBg ? bg : -1); + return new ResolvedValues((int) s, hasFb ? fg : -1, hasBg ? bg : -1); } /** * Return all known theme names. - * * @return all theme names */ public Set themeNames() { @@ -101,7 +113,6 @@ public Set themeNames() { /** * Evaluate expression. - * * @param expression the expression * @return evaluated attributed string */ @@ -109,10 +120,8 @@ public AttributedString evaluateExpression(String expression) { return styleExpression.evaluate(expression); } - /** * Resolve style from a tag with activated theme. - * * @param tag the tag * @return a style */ @@ -122,7 +131,6 @@ public String resolveStyleTag(String tag) { /** * Resolve style from a tag with given theme. - * * @param tag the tag * @param themeName the theme name * @return a style @@ -134,7 +142,6 @@ public String resolveStyleTag(String tag, String themeName) { /** * Resolve figure from a tag with activated theme. - * * @param tag the tag * @return a style */ @@ -144,7 +151,6 @@ public String resolveFigureTag(String tag) { /** * Resolve spinner from a tag with activated theme. - * * @param tag the tag * @return a spinner */ @@ -154,11 +160,11 @@ public Spinner resolveSpinnerTag(String tag) { /** * Resolve {@link AttributedStyle} from a {@code spec}. - * * @param spec the spec * @return resolved attributed style */ public AttributedStyle resolveStyle(String spec) { return styleResolver.resolve(spec); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeSettings.java b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeSettings.java index 40ea94adf..756d8f264 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeSettings.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/style/ThemeSettings.java @@ -23,7 +23,9 @@ public abstract class ThemeSettings { private StyleSettings styleSettings; + private FigureSettings figureSettings; + private SpinnerSettings spinnerSettings; /** @@ -35,7 +37,6 @@ public ThemeSettings() { /** * Creates theme settings with styles. - * * @param styleSettings style settings */ public ThemeSettings(StyleSettings styleSettings) { @@ -44,7 +45,6 @@ public ThemeSettings(StyleSettings styleSettings) { /** * Creates theme settings with styles and figures. - * * @param styleSettings style settings * @param figureSettings figure settings */ @@ -54,7 +54,6 @@ public ThemeSettings(StyleSettings styleSettings, FigureSettings figureSettings) /** * Creates theme settings with styles, figures and spinners. - * * @param styleSettings style settings * @param figureSettings figure settings * @param spinnerSettings spinner settings @@ -67,7 +66,6 @@ public ThemeSettings(StyleSettings styleSettings, FigureSettings figureSettings, /** * Gets a {@link StyleSettings}. - * * @return style settings */ public StyleSettings styles() { @@ -76,7 +74,6 @@ public StyleSettings styles() { /** * Gets a {@link FigureSettings}. - * * @return figure settings */ public FigureSettings figures() { @@ -85,7 +82,6 @@ public FigureSettings figures() { /** * Gets a {@link SpinnerSettings}. - * * @return spinner settings */ public SpinnerSettings spinners() { @@ -94,16 +90,15 @@ public SpinnerSettings spinners() { /** * Gets a default theme settings. - * * @return default theme settings */ public static ThemeSettings defaults() { - return new DefaultThemeSettings(StyleSettings.defaults(), FigureSettings.defaults(), SpinnerSettings.defaults()); + return new DefaultThemeSettings(StyleSettings.defaults(), FigureSettings.defaults(), + SpinnerSettings.defaults()); } /** * Gets a dump theme settings. - * * @return dump theme settings */ public static ThemeSettings dump() { @@ -116,8 +111,11 @@ private static class DefaultThemeSettings extends ThemeSettings { super(); } - DefaultThemeSettings(StyleSettings styleSettings, FigureSettings figureSettings, SpinnerSettings spinnerSettings) { + DefaultThemeSettings(StyleSettings styleSettings, FigureSettings figureSettings, + SpinnerSettings spinnerSettings) { super(styleSettings, figureSettings, spinnerSettings); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/AbstractArgumentMethodArgumentResolver.java b/spring-shell-core/src/main/java/org/springframework/shell/support/AbstractArgumentMethodArgumentResolver.java index fa0d1c991..fbf83a9b4 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/AbstractArgumentMethodArgumentResolver.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/AbstractArgumentMethodArgumentResolver.java @@ -34,20 +34,23 @@ import org.springframework.util.ClassUtils; /** - * Abstract base class to resolve method arguments from a named value, e.g. - * message headers or destination variables. Named values could have one or more - * of a name, a required flag, and a default value. + * Abstract base class to resolve method arguments from a named value, e.g. message + * headers or destination variables. Named values could have one or more of a name, a + * required flag, and a default value. * - *

    Subclasses only need to define specific steps such as how to obtain named - * value details from a method parameter, how to resolve to argument values, or - * how to handle missing values. + *

    + * Subclasses only need to define specific steps such as how to obtain named value details + * from a method parameter, how to resolve to argument values, or how to handle missing + * values. * - *

    A default value string can contain ${...} placeholders and Spring - * Expression Language {@code #{...}} expressions which will be resolved if a - * {@link ConfigurableBeanFactory} is supplied to the class constructor. + *

    + * A default value string can contain ${...} placeholders and Spring Expression Language + * {@code #{...}} expressions which will be resolved if a {@link ConfigurableBeanFactory} + * is supplied to the class constructor. * - *

    A {@link ConversionService} is used to convert a resolved String argument - * value to the expected target method parameter type. + *

    + * A {@link ConversionService} is used to convert a resolved String argument value to the + * expected target method parameter type. * * @author Janne Valkealahti */ @@ -67,10 +70,10 @@ public abstract class AbstractArgumentMethodArgumentResolver implements HandlerM /** * Constructor with a {@link ConversionService} and a {@link BeanFactory}. - * @param conversionService conversion service for converting String values - * to the target method parameter type - * @param beanFactory a bean factory for resolving {@code ${...}} - * placeholders and {@code #{...}} SpEL expressions in default values + * @param conversionService conversion service for converting String values to the + * target method parameter type + * @param beanFactory a bean factory for resolving {@code ${...}} placeholders and + * {@code #{...}} SpEL expressions in default values */ protected AbstractArgumentMethodArgumentResolver(ConversionService conversionService, @Nullable ConfigurableBeanFactory beanFactory) { @@ -78,9 +81,9 @@ protected AbstractArgumentMethodArgumentResolver(ConversionService conversionSer // Fallback on shared ConversionService for now for historic reasons. // Possibly remove after discussion in gh-23882. - //noinspection ConstantConditions - this.conversionService = (conversionService != null ? - conversionService : DefaultConversionService.getSharedInstance()); + // noinspection ConstantConditions + this.conversionService = (conversionService != null ? conversionService + : DefaultConversionService.getSharedInstance()); this.configurableBeanFactory = beanFactory; this.expressionContext = (beanFactory != null ? new BeanExpressionContext(beanFactory, null) : null); @@ -108,8 +111,8 @@ else if ("".equals(arg) && namedValueInfo.defaultValue != null) { if (parameter != nestedParameter || !ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) { arg = this.conversionService.convert(arg, TypeDescriptor.forObject(arg), new TypeDescriptor(parameter)); // Check for null value after conversion of incoming argument value - if (arg == null && namedValueInfo.defaultValue == null && - namedValueInfo.required && !nestedParameter.isOptional()) { + if (arg == null && namedValueInfo.defaultValue == null && namedValueInfo.required + && !nestedParameter.isOptional()) { handleMissingValue(namedValueInfo.names, nestedParameter, message); } } @@ -142,8 +145,8 @@ private NamedValueInfo getNamedValueInfo(MethodParameter parameter) { protected abstract NamedValueInfo createNamedValueInfo(MethodParameter parameter); /** - * Fall back on the parameter name from the class file if necessary and - * replace {@link ValueConstants#DEFAULT_NONE} with null. + * Fall back on the parameter name from the class file if necessary and replace + * {@link ValueConstants#DEFAULT_NONE} with null. */ private NamedValueInfo updateNamedValueInfo(MethodParameter parameter, NamedValueInfo info) { List names = info.names; @@ -151,8 +154,8 @@ private NamedValueInfo updateNamedValueInfo(MethodParameter parameter, NamedValu String name = parameter.getParameterName(); if (name == null) { throw new IllegalArgumentException( - "Name for argument of type [" + parameter.getNestedParameterType().getName() + - "] not specified, and parameter name information not found in class file either."); + "Name for argument of type [" + parameter.getNestedParameterType().getName() + + "] not specified, and parameter name information not found in class file either."); } names.add(name); } @@ -161,8 +164,8 @@ private NamedValueInfo updateNamedValueInfo(MethodParameter parameter, NamedValu } /** - * Resolve the given annotation-specified value, - * potentially containing placeholders and expressions. + * Resolve the given annotation-specified value, potentially containing placeholders + * and expressions. */ @Nullable private Object resolveEmbeddedValuesAndExpressions(String value) { @@ -179,7 +182,6 @@ private Object resolveEmbeddedValuesAndExpressions(String value) { /** * Resolves the given parameter type and value name into an argument value. - * * @param parameter the method parameter to resolve to an argument value * @param message the current request * @param names the name of the values being resolved @@ -191,10 +193,9 @@ protected abstract Object resolveArgumentInternal(MethodParameter parameter, Mes throws Exception; /** - * Invoked when a value is required, but {@link #resolveArgumentInternal} - * returned {@code null} and there is no default value. Sub-classes can - * throw an appropriate exception for this case. - * + * Invoked when a value is required, but {@link #resolveArgumentInternal} returned + * {@code null} and there is no default value. Sub-classes can throw an appropriate + * exception for this case. * @param names the name for the value * @param parameter the target method parameter * @param message the message being processed @@ -202,9 +203,8 @@ protected abstract Object resolveArgumentInternal(MethodParameter parameter, Mes protected abstract void handleMissingValue(List names, MethodParameter parameter, Message message); /** - * One last chance to handle a possible null value. - * Specifically for booleans method parameters, use {@link Boolean#FALSE}. - * Also raise an ISE for primitive types. + * One last chance to handle a possible null value. Specifically for booleans method + * parameters, use {@link Boolean#FALSE}. Also raise an ISE for primitive types. */ @Nullable private Object handleNullValue(List name, @Nullable Object value, Class paramType) { @@ -213,10 +213,10 @@ private Object handleNullValue(List name, @Nullable Object value, Class< return Boolean.FALSE; } else if (paramType.isPrimitive()) { - throw new IllegalStateException("Optional " + paramType + " parameter '" + name + - "' is present but cannot be translated into a null value due to being " + - "declared as a primitive type. Consider declaring it as object wrapper " + - "for the corresponding primitive type."); + throw new IllegalStateException("Optional " + paramType + " parameter '" + name + + "' is present but cannot be translated into a null value due to being " + + "declared as a primitive type. Consider declaring it as object wrapper " + + "for the corresponding primitive type."); } } return value; @@ -229,8 +229,8 @@ else if (paramType.isPrimitive()) { * @param parameter the argument parameter type * @param message the message */ - protected void handleResolvedValue( - @Nullable Object arg, List name, MethodParameter parameter, Message message) { + protected void handleResolvedValue(@Nullable Object arg, List name, MethodParameter parameter, + Message message) { } /** @@ -250,6 +250,7 @@ protected NamedValueInfo(List names, boolean required, @Nullable String this.required = required; this.defaultValue = defaultValue; } + } } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/AbstractSearchMatchAlgorithm.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/AbstractSearchMatchAlgorithm.java index 61f9e24d4..c6b824a2d 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/AbstractSearchMatchAlgorithm.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/AbstractSearchMatchAlgorithm.java @@ -22,8 +22,7 @@ import org.springframework.util.StringUtils; /** - * Base class for common search algorithms mostly based on {@code fzf} - * algorithms. + * Base class for common search algorithms mostly based on {@code fzf} algorithms. * * @author Janne Valkealahti */ @@ -31,37 +30,46 @@ abstract class AbstractSearchMatchAlgorithm implements SearchMatchAlgorithm { // points given to matches public static final int SCORE_MATCH = 16; + public static final int SCORE_GAP_START = -3; + public static final int SCORE_GAP_EXTENSION = -1; + public static final int BONUS_BOUNDARY = SCORE_MATCH / 2; + public static final int BONUS_NON_WORD = SCORE_MATCH / 2; + public static final int BONUS_CAMEL123 = BONUS_BOUNDARY + SCORE_GAP_EXTENSION; + public static final int BONUS_CONSECUTIVE = -(SCORE_GAP_START + SCORE_GAP_EXTENSION); + public static final int BONUS_FIRST_CHAR_MULTIPLIER = 2; + public static final int BONUS_BOUNDARY_WHITE = BONUS_BOUNDARY + 2; // default +2 - public static final int BONUS_BOUNDARY_DELIMITER = BONUS_BOUNDARY + 1 + 1; // default +1 + + public static final int BONUS_BOUNDARY_DELIMITER = BONUS_BOUNDARY + 1 + 1; // default + // +1 /** * Enumeration of matched characters. */ static enum CharClass { - WHITE, - NONWORD, - DELIMITER, - LOWER, - UPPER, - LETTER, - NUMBER + + WHITE, NONWORD, DELIMITER, LOWER, UPPER, LETTER, NUMBER + } static class CalculateScore { + int score; + int pos[]; CalculateScore(int score, int[] pos) { this.score = score; this.pos = pos; } + } static int indexAt(int index, int max, boolean forward) { @@ -126,8 +134,8 @@ else if (prevClass == CharClass.NONWORD) { return BONUS_BOUNDARY; } } - if (prevClass == CharClass.LOWER && clazz == CharClass.UPPER || - prevClass != CharClass.NUMBER && clazz == CharClass.NUMBER) { + if (prevClass == CharClass.LOWER && clazz == CharClass.UPPER + || prevClass != CharClass.NUMBER && clazz == CharClass.NUMBER) { return BONUS_CAMEL123; } else if (clazz == CharClass.NONWORD) { @@ -275,4 +283,5 @@ static char normalizeRune(char r) { } return r; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithm.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithm.java index 8f9daace1..166dc1716 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithm.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithm.java @@ -101,4 +101,5 @@ public SearchMatchResult match(boolean caseSensitive, boolean normalize, boolean } return SearchMatchResult.ofMinus(); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithm.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithm.java index 7a1b61c42..a2716f845 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithm.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithm.java @@ -23,7 +23,8 @@ class FuzzyMatchV1SearchMatchAlgorithm extends AbstractSearchMatchAlgorithm { @Override - public SearchMatchResult match(boolean caseSensitive, boolean normalize, boolean forward, String text, String pattern) { + public SearchMatchResult match(boolean caseSensitive, boolean normalize, boolean forward, String text, + String pattern) { int pidx = 0; int sidx = -1; int eidx = -1; @@ -88,4 +89,5 @@ public SearchMatchResult match(boolean caseSensitive, boolean normalize, boolean } return SearchMatchResult.of(-1, -1, 0, new int[0], this); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithm.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithm.java index 0467b138f..301102f4a 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithm.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithm.java @@ -86,8 +86,10 @@ public SearchMatchResult match(boolean caseSensitive, boolean normalize, boolean } } - // TODO: potential speed increase as go can directly modify underlying array/slice - // by access via for loop variables and so on. we create a lot of garbage here. + // TODO: potential speed increase as go can directly modify underlying + // array/slice + // by access via for loop variables and so on. we create a lot of garbage + // here. Tsub = Tsub.substring(0, off) + c + Tsub.substring(off + 1); int bonus = bonusFor(prevClass, clazz); Bsub.set(off, bonus); @@ -218,7 +220,7 @@ public SearchMatchResult match(boolean caseSensitive, boolean normalize, boolean j = maxScorePos; boolean preferMatch = true; int posidx = pos.length - 1; - for(;;) { + for (;;) { int I = i * width; int j0 = j - f0; int s = H.get(I + j0); @@ -262,4 +264,5 @@ private static List create(int size) { } return list; } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/Normalize.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/Normalize.java index 9430c554d..d2b34e06b 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/Normalize.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/Normalize.java @@ -23,407 +23,407 @@ public class Normalize { public static Map normalized = new HashMap<>(); static { - normalized.put((char)0x00E1, 'a'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0103, 'a'); // WITH BREVE, LATIN SMALL LETTER - normalized.put((char)0x01CE, 'a'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x00E2, 'a'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x00E4, 'a'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x0227, 'a'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1EA1, 'a'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0201, 'a'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER - normalized.put((char)0x00E0, 'a'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x1EA3, 'a'); // WITH HOOK ABOVE, LATIN SMALL LETTER - normalized.put((char)0x0203, 'a'); // WITH INVERTED BREVE, LATIN SMALL LETTER - normalized.put((char)0x0101, 'a'); // WITH MACRON, LATIN SMALL LETTER - normalized.put((char)0x0105, 'a'); // WITH OGONEK, LATIN SMALL LETTER - normalized.put((char)0x1E9A, 'a'); // WITH RIGHT HALF RING, LATIN SMALL LETTER - normalized.put((char)0x00E5, 'a'); // WITH RING ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E01, 'a'); // WITH RING BELOW, LATIN SMALL LETTER - normalized.put((char)0x00E3, 'a'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x0363, 'a'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x0250, 'a'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x1E03, 'b'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E05, 'b'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0253, 'b'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E07, 'b'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x0180, 'b'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x0183, 'b'); // WITH TOPBAR, LATIN SMALL LETTER - normalized.put((char)0x0107, 'c'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x010D, 'c'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x00E7, 'c'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x0109, 'c'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x0255, 'c'); // WITH CURL, LATIN SMALL LETTER - normalized.put((char)0x010B, 'c'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x0188, 'c'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x023C, 'c'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x0368, 'c'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x0297, 'c'); // , LATIN LETTER STRETCHED - normalized.put((char)0x2184, 'c'); // , LATIN SMALL LETTER REVERSED - normalized.put((char)0x010F, 'd'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x1E11, 'd'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x1E13, 'd'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER - normalized.put((char)0x0221, 'd'); // WITH CURL, LATIN SMALL LETTER - normalized.put((char)0x1E0B, 'd'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E0D, 'd'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0257, 'd'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E0F, 'd'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x0111, 'd'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x0256, 'd'); // WITH TAIL, LATIN SMALL LETTER - normalized.put((char)0x018C, 'd'); // WITH TOPBAR, LATIN SMALL LETTER - normalized.put((char)0x0369, 'd'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x00E9, 'e'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0115, 'e'); // WITH BREVE, LATIN SMALL LETTER - normalized.put((char)0x011B, 'e'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x0229, 'e'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x1E19, 'e'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER - normalized.put((char)0x00EA, 'e'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x00EB, 'e'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x0117, 'e'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1EB9, 'e'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0205, 'e'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER - normalized.put((char)0x00E8, 'e'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x1EBB, 'e'); // WITH HOOK ABOVE, LATIN SMALL LETTER - normalized.put((char)0x025D, 'e'); // WITH HOOK, LATIN SMALL LETTER REVERSED OPEN - normalized.put((char)0x0207, 'e'); // WITH INVERTED BREVE, LATIN SMALL LETTER - normalized.put((char)0x0113, 'e'); // WITH MACRON, LATIN SMALL LETTER - normalized.put((char)0x0119, 'e'); // WITH OGONEK, LATIN SMALL LETTER - normalized.put((char)0x0247, 'e'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x1E1B, 'e'); // WITH TILDE BELOW, LATIN SMALL LETTER - normalized.put((char)0x1EBD, 'e'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x0364, 'e'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x029A, 'e'); // , LATIN SMALL LETTER CLOSED OPEN - normalized.put((char)0x025E, 'e'); // , LATIN SMALL LETTER CLOSED REVERSED OPEN - normalized.put((char)0x025B, 'e'); // , LATIN SMALL LETTER OPEN - normalized.put((char)0x0258, 'e'); // , LATIN SMALL LETTER REVERSED - normalized.put((char)0x025C, 'e'); // , LATIN SMALL LETTER REVERSED OPEN - normalized.put((char)0x01DD, 'e'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x1D08, 'e'); // , LATIN SMALL LETTER TURNED OPEN - normalized.put((char)0x1E1F, 'f'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x0192, 'f'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x01F5, 'g'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x011F, 'g'); // WITH BREVE, LATIN SMALL LETTER - normalized.put((char)0x01E7, 'g'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x0123, 'g'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x011D, 'g'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x0121, 'g'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x0260, 'g'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E21, 'g'); // WITH MACRON, LATIN SMALL LETTER - normalized.put((char)0x01E5, 'g'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x0261, 'g'); // , LATIN SMALL LETTER SCRIPT - normalized.put((char)0x1E2B, 'h'); // WITH BREVE BELOW, LATIN SMALL LETTER - normalized.put((char)0x021F, 'h'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x1E29, 'h'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x0125, 'h'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x1E27, 'h'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x1E23, 'h'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E25, 'h'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x02AE, 'h'); // WITH FISHHOOK, LATIN SMALL LETTER TURNED - normalized.put((char)0x0266, 'h'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E96, 'h'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x0127, 'h'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x036A, 'h'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x0265, 'h'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x2095, 'h'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x00ED, 'i'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x012D, 'i'); // WITH BREVE, LATIN SMALL LETTER - normalized.put((char)0x01D0, 'i'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x00EE, 'i'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x00EF, 'i'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x1ECB, 'i'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0209, 'i'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER - normalized.put((char)0x00EC, 'i'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x1EC9, 'i'); // WITH HOOK ABOVE, LATIN SMALL LETTER - normalized.put((char)0x020B, 'i'); // WITH INVERTED BREVE, LATIN SMALL LETTER - normalized.put((char)0x012B, 'i'); // WITH MACRON, LATIN SMALL LETTER - normalized.put((char)0x012F, 'i'); // WITH OGONEK, LATIN SMALL LETTER - normalized.put((char)0x0268, 'i'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x1E2D, 'i'); // WITH TILDE BELOW, LATIN SMALL LETTER - normalized.put((char)0x0129, 'i'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x0365, 'i'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x0131, 'i'); // , LATIN SMALL LETTER DOTLESS - normalized.put((char)0x1D09, 'i'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x1D62, 'i'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x2071, 'i'); // , SUPERSCRIPT LATIN SMALL LETTER - normalized.put((char)0x01F0, 'j'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x0135, 'j'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x029D, 'j'); // WITH CROSSED-TAIL, LATIN SMALL LETTER - normalized.put((char)0x0249, 'j'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x025F, 'j'); // WITH STROKE, LATIN SMALL LETTER DOTLESS - normalized.put((char)0x0237, 'j'); // , LATIN SMALL LETTER DOTLESS - normalized.put((char)0x1E31, 'k'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x01E9, 'k'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x0137, 'k'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x1E33, 'k'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0199, 'k'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E35, 'k'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x029E, 'k'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x2096, 'k'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x013A, 'l'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x019A, 'l'); // WITH BAR, LATIN SMALL LETTER - normalized.put((char)0x026C, 'l'); // WITH BELT, LATIN SMALL LETTER - normalized.put((char)0x013E, 'l'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x013C, 'l'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x1E3D, 'l'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER - normalized.put((char)0x0234, 'l'); // WITH CURL, LATIN SMALL LETTER - normalized.put((char)0x1E37, 'l'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x1E3B, 'l'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x0140, 'l'); // WITH MIDDLE DOT, LATIN SMALL LETTER - normalized.put((char)0x026B, 'l'); // WITH MIDDLE TILDE, LATIN SMALL LETTER - normalized.put((char)0x026D, 'l'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER - normalized.put((char)0x0142, 'l'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x2097, 'l'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x1E3F, 'm'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x1E41, 'm'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E43, 'm'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0271, 'm'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x0270, 'm'); // WITH LONG LEG, LATIN SMALL LETTER TURNED - normalized.put((char)0x036B, 'm'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x1D1F, 'm'); // , LATIN SMALL LETTER SIDEWAYS TURNED - normalized.put((char)0x026F, 'm'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x2098, 'm'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x0144, 'n'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0148, 'n'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x0146, 'n'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x1E4B, 'n'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER - normalized.put((char)0x0235, 'n'); // WITH CURL, LATIN SMALL LETTER - normalized.put((char)0x1E45, 'n'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E47, 'n'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x01F9, 'n'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x0272, 'n'); // WITH LEFT HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E49, 'n'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x019E, 'n'); // WITH LONG RIGHT LEG, LATIN SMALL LETTER - normalized.put((char)0x0273, 'n'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER - normalized.put((char)0x00F1, 'n'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x2099, 'n'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x00F3, 'o'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x014F, 'o'); // WITH BREVE, LATIN SMALL LETTER - normalized.put((char)0x01D2, 'o'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x00F4, 'o'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x00F6, 'o'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x022F, 'o'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1ECD, 'o'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0151, 'o'); // WITH DOUBLE ACUTE, LATIN SMALL LETTER - normalized.put((char)0x020D, 'o'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER - normalized.put((char)0x00F2, 'o'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x1ECF, 'o'); // WITH HOOK ABOVE, LATIN SMALL LETTER - normalized.put((char)0x01A1, 'o'); // WITH HORN, LATIN SMALL LETTER - normalized.put((char)0x020F, 'o'); // WITH INVERTED BREVE, LATIN SMALL LETTER - normalized.put((char)0x014D, 'o'); // WITH MACRON, LATIN SMALL LETTER - normalized.put((char)0x01EB, 'o'); // WITH OGONEK, LATIN SMALL LETTER - normalized.put((char)0x00F8, 'o'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x1D13, 'o'); // WITH STROKE, LATIN SMALL LETTER SIDEWAYS - normalized.put((char)0x00F5, 'o'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x0366, 'o'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x0275, 'o'); // , LATIN SMALL LETTER BARRED - normalized.put((char)0x1D17, 'o'); // , LATIN SMALL LETTER BOTTOM HALF - normalized.put((char)0x0254, 'o'); // , LATIN SMALL LETTER OPEN - normalized.put((char)0x1D11, 'o'); // , LATIN SMALL LETTER SIDEWAYS - normalized.put((char)0x1D12, 'o'); // , LATIN SMALL LETTER SIDEWAYS OPEN - normalized.put((char)0x1D16, 'o'); // , LATIN SMALL LETTER TOP HALF - normalized.put((char)0x1E55, 'p'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x1E57, 'p'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x01A5, 'p'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x209A, 'p'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x024B, 'q'); // WITH HOOK TAIL, LATIN SMALL LETTER - normalized.put((char)0x02A0, 'q'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x0155, 'r'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0159, 'r'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x0157, 'r'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x1E59, 'r'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E5B, 'r'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0211, 'r'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER - normalized.put((char)0x027E, 'r'); // WITH FISHHOOK, LATIN SMALL LETTER - normalized.put((char)0x027F, 'r'); // WITH FISHHOOK, LATIN SMALL LETTER REVERSED - normalized.put((char)0x027B, 'r'); // WITH HOOK, LATIN SMALL LETTER TURNED - normalized.put((char)0x0213, 'r'); // WITH INVERTED BREVE, LATIN SMALL LETTER - normalized.put((char)0x1E5F, 'r'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x027C, 'r'); // WITH LONG LEG, LATIN SMALL LETTER - normalized.put((char)0x027A, 'r'); // WITH LONG LEG, LATIN SMALL LETTER TURNED - normalized.put((char)0x024D, 'r'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x027D, 'r'); // WITH TAIL, LATIN SMALL LETTER - normalized.put((char)0x036C, 'r'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x0279, 'r'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x1D63, 'r'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x015B, 's'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0161, 's'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x015F, 's'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x015D, 's'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x0219, 's'); // WITH COMMA BELOW, LATIN SMALL LETTER - normalized.put((char)0x1E61, 's'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E9B, 's'); // WITH DOT ABOVE, LATIN SMALL LETTER LONG - normalized.put((char)0x1E63, 's'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0282, 's'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x023F, 's'); // WITH SWASH TAIL, LATIN SMALL LETTER - normalized.put((char)0x017F, 's'); // , LATIN SMALL LETTER LONG - normalized.put((char)0x00DF, 's'); // , LATIN SMALL LETTER SHARP - normalized.put((char)0x209B, 's'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x0165, 't'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x0163, 't'); // WITH CEDILLA, LATIN SMALL LETTER - normalized.put((char)0x1E71, 't'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER - normalized.put((char)0x021B, 't'); // WITH COMMA BELOW, LATIN SMALL LETTER - normalized.put((char)0x0236, 't'); // WITH CURL, LATIN SMALL LETTER - normalized.put((char)0x1E97, 't'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x1E6B, 't'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E6D, 't'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x01AD, 't'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E6F, 't'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x01AB, 't'); // WITH PALATAL HOOK, LATIN SMALL LETTER - normalized.put((char)0x0288, 't'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER - normalized.put((char)0x0167, 't'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x036D, 't'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x0287, 't'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x209C, 't'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x0289, 'u'); // BAR, LATIN SMALL LETTER - normalized.put((char)0x00FA, 'u'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x016D, 'u'); // WITH BREVE, LATIN SMALL LETTER - normalized.put((char)0x01D4, 'u'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x1E77, 'u'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER - normalized.put((char)0x00FB, 'u'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x1E73, 'u'); // WITH DIAERESIS BELOW, LATIN SMALL LETTER - normalized.put((char)0x00FC, 'u'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x1EE5, 'u'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0171, 'u'); // WITH DOUBLE ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0215, 'u'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER - normalized.put((char)0x00F9, 'u'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x1EE7, 'u'); // WITH HOOK ABOVE, LATIN SMALL LETTER - normalized.put((char)0x01B0, 'u'); // WITH HORN, LATIN SMALL LETTER - normalized.put((char)0x0217, 'u'); // WITH INVERTED BREVE, LATIN SMALL LETTER - normalized.put((char)0x016B, 'u'); // WITH MACRON, LATIN SMALL LETTER - normalized.put((char)0x0173, 'u'); // WITH OGONEK, LATIN SMALL LETTER - normalized.put((char)0x016F, 'u'); // WITH RING ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E75, 'u'); // WITH TILDE BELOW, LATIN SMALL LETTER - normalized.put((char)0x0169, 'u'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x0367, 'u'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x1D1D, 'u'); // , LATIN SMALL LETTER SIDEWAYS - normalized.put((char)0x1D1E, 'u'); // , LATIN SMALL LETTER SIDEWAYS DIAERESIZED - normalized.put((char)0x1D64, 'u'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x1E7F, 'v'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x028B, 'v'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E7D, 'v'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x036E, 'v'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x028C, 'v'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x1D65, 'v'); // , LATIN SUBSCRIPT SMALL LETTER - normalized.put((char)0x1E83, 'w'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0175, 'w'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x1E85, 'w'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x1E87, 'w'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E89, 'w'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x1E81, 'w'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x1E98, 'w'); // WITH RING ABOVE, LATIN SMALL LETTER - normalized.put((char)0x028D, 'w'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x1E8D, 'x'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x1E8B, 'x'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x036F, 'x'); // , COMBINING LATIN SMALL LETTER - normalized.put((char)0x00FD, 'y'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x0177, 'y'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x00FF, 'y'); // WITH DIAERESIS, LATIN SMALL LETTER - normalized.put((char)0x1E8F, 'y'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1EF5, 'y'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x1EF3, 'y'); // WITH GRAVE, LATIN SMALL LETTER - normalized.put((char)0x1EF7, 'y'); // WITH HOOK ABOVE, LATIN SMALL LETTER - normalized.put((char)0x01B4, 'y'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x0233, 'y'); // WITH MACRON, LATIN SMALL LETTER - normalized.put((char)0x1E99, 'y'); // WITH RING ABOVE, LATIN SMALL LETTER - normalized.put((char)0x024F, 'y'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x1EF9, 'y'); // WITH TILDE, LATIN SMALL LETTER - normalized.put((char)0x028E, 'y'); // , LATIN SMALL LETTER TURNED - normalized.put((char)0x017A, 'z'); // WITH ACUTE, LATIN SMALL LETTER - normalized.put((char)0x017E, 'z'); // WITH CARON, LATIN SMALL LETTER - normalized.put((char)0x1E91, 'z'); // WITH CIRCUMFLEX, LATIN SMALL LETTER - normalized.put((char)0x0291, 'z'); // WITH CURL, LATIN SMALL LETTER - normalized.put((char)0x017C, 'z'); // WITH DOT ABOVE, LATIN SMALL LETTER - normalized.put((char)0x1E93, 'z'); // WITH DOT BELOW, LATIN SMALL LETTER - normalized.put((char)0x0225, 'z'); // WITH HOOK, LATIN SMALL LETTER - normalized.put((char)0x1E95, 'z'); // WITH LINE BELOW, LATIN SMALL LETTER - normalized.put((char)0x0290, 'z'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER - normalized.put((char)0x01B6, 'z'); // WITH STROKE, LATIN SMALL LETTER - normalized.put((char)0x0240, 'z'); // WITH SWASH TAIL, LATIN SMALL LETTER - normalized.put((char)0x0251, 'a'); // , latin small letter script - normalized.put((char)0x00C1, 'A'); // WITH ACUTE, LATIN CAPITAL LETTER - normalized.put((char)0x00C2, 'A'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER - normalized.put((char)0x00C4, 'A'); // WITH DIAERESIS, LATIN CAPITAL LETTER - normalized.put((char)0x00C0, 'A'); // WITH GRAVE, LATIN CAPITAL LETTER - normalized.put((char)0x00C5, 'A'); // WITH RING ABOVE, LATIN CAPITAL LETTER - normalized.put((char)0x023A, 'A'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x00C3, 'A'); // WITH TILDE, LATIN CAPITAL LETTER - normalized.put((char)0x1D00, 'A'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x0181, 'B'); // WITH HOOK, LATIN CAPITAL LETTER - normalized.put((char)0x0243, 'B'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x0299, 'B'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x1D03, 'B'); // , LATIN LETTER SMALL CAPITAL BARRED - normalized.put((char)0x00C7, 'C'); // WITH CEDILLA, LATIN CAPITAL LETTER - normalized.put((char)0x023B, 'C'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x1D04, 'C'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x018A, 'D'); // WITH HOOK, LATIN CAPITAL LETTER - normalized.put((char)0x0189, 'D'); // , LATIN CAPITAL LETTER AFRICAN - normalized.put((char)0x1D05, 'D'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x00C9, 'E'); // WITH ACUTE, LATIN CAPITAL LETTER - normalized.put((char)0x00CA, 'E'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER - normalized.put((char)0x00CB, 'E'); // WITH DIAERESIS, LATIN CAPITAL LETTER - normalized.put((char)0x00C8, 'E'); // WITH GRAVE, LATIN CAPITAL LETTER - normalized.put((char)0x0246, 'E'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x0190, 'E'); // , LATIN CAPITAL LETTER OPEN - normalized.put((char)0x018E, 'E'); // , LATIN CAPITAL LETTER REVERSED - normalized.put((char)0x1D07, 'E'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x0193, 'G'); // WITH HOOK, LATIN CAPITAL LETTER - normalized.put((char)0x029B, 'G'); // WITH HOOK, LATIN LETTER SMALL CAPITAL - normalized.put((char)0x0262, 'G'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x029C, 'H'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x00CD, 'I'); // WITH ACUTE, LATIN CAPITAL LETTER - normalized.put((char)0x00CE, 'I'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER - normalized.put((char)0x00CF, 'I'); // WITH DIAERESIS, LATIN CAPITAL LETTER - normalized.put((char)0x0130, 'I'); // WITH DOT ABOVE, LATIN CAPITAL LETTER - normalized.put((char)0x00CC, 'I'); // WITH GRAVE, LATIN CAPITAL LETTER - normalized.put((char)0x0197, 'I'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x026A, 'I'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x0248, 'J'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x1D0A, 'J'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x1D0B, 'K'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x023D, 'L'); // WITH BAR, LATIN CAPITAL LETTER - normalized.put((char)0x1D0C, 'L'); // WITH STROKE, LATIN LETTER SMALL CAPITAL - normalized.put((char)0x029F, 'L'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x019C, 'M'); // , LATIN CAPITAL LETTER TURNED - normalized.put((char)0x1D0D, 'M'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x019D, 'N'); // WITH LEFT HOOK, LATIN CAPITAL LETTER - normalized.put((char)0x0220, 'N'); // WITH LONG RIGHT LEG, LATIN CAPITAL LETTER - normalized.put((char)0x00D1, 'N'); // WITH TILDE, LATIN CAPITAL LETTER - normalized.put((char)0x0274, 'N'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x1D0E, 'N'); // , LATIN LETTER SMALL CAPITAL REVERSED - normalized.put((char)0x00D3, 'O'); // WITH ACUTE, LATIN CAPITAL LETTER - normalized.put((char)0x00D4, 'O'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER - normalized.put((char)0x00D6, 'O'); // WITH DIAERESIS, LATIN CAPITAL LETTER - normalized.put((char)0x00D2, 'O'); // WITH GRAVE, LATIN CAPITAL LETTER - normalized.put((char)0x019F, 'O'); // WITH MIDDLE TILDE, LATIN CAPITAL LETTER - normalized.put((char)0x00D8, 'O'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x00D5, 'O'); // WITH TILDE, LATIN CAPITAL LETTER - normalized.put((char)0x0186, 'O'); // , LATIN CAPITAL LETTER OPEN - normalized.put((char)0x1D0F, 'O'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x1D10, 'O'); // , LATIN LETTER SMALL CAPITAL OPEN - normalized.put((char)0x1D18, 'P'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x024A, 'Q'); // WITH HOOK TAIL, LATIN CAPITAL LETTER SMALL - normalized.put((char)0x024C, 'R'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x0280, 'R'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x0281, 'R'); // , LATIN LETTER SMALL CAPITAL INVERTED - normalized.put((char)0x1D19, 'R'); // , LATIN LETTER SMALL CAPITAL REVERSED - normalized.put((char)0x1D1A, 'R'); // , LATIN LETTER SMALL CAPITAL TURNED - normalized.put((char)0x023E, 'T'); // WITH DIAGONAL STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x01AE, 'T'); // WITH RETROFLEX HOOK, LATIN CAPITAL LETTER - normalized.put((char)0x1D1B, 'T'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x0244, 'U'); // BAR, LATIN CAPITAL LETTER - normalized.put((char)0x00DA, 'U'); // WITH ACUTE, LATIN CAPITAL LETTER - normalized.put((char)0x00DB, 'U'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER - normalized.put((char)0x00DC, 'U'); // WITH DIAERESIS, LATIN CAPITAL LETTER - normalized.put((char)0x00D9, 'U'); // WITH GRAVE, LATIN CAPITAL LETTER - normalized.put((char)0x1D1C, 'U'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x01B2, 'V'); // WITH HOOK, LATIN CAPITAL LETTER - normalized.put((char)0x0245, 'V'); // , LATIN CAPITAL LETTER TURNED - normalized.put((char)0x1D20, 'V'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x1D21, 'W'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x00DD, 'Y'); // WITH ACUTE, LATIN CAPITAL LETTER - normalized.put((char)0x0178, 'Y'); // WITH DIAERESIS, LATIN CAPITAL LETTER - normalized.put((char)0x024E, 'Y'); // WITH STROKE, LATIN CAPITAL LETTER - normalized.put((char)0x028F, 'Y'); // , LATIN LETTER SMALL CAPITAL - normalized.put((char)0x1D22, 'Z'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x00E1, 'a'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0103, 'a'); // WITH BREVE, LATIN SMALL LETTER + normalized.put((char) 0x01CE, 'a'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x00E2, 'a'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x00E4, 'a'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x0227, 'a'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1EA1, 'a'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0201, 'a'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x00E0, 'a'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x1EA3, 'a'); // WITH HOOK ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x0203, 'a'); // WITH INVERTED BREVE, LATIN SMALL LETTER + normalized.put((char) 0x0101, 'a'); // WITH MACRON, LATIN SMALL LETTER + normalized.put((char) 0x0105, 'a'); // WITH OGONEK, LATIN SMALL LETTER + normalized.put((char) 0x1E9A, 'a'); // WITH RIGHT HALF RING, LATIN SMALL LETTER + normalized.put((char) 0x00E5, 'a'); // WITH RING ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E01, 'a'); // WITH RING BELOW, LATIN SMALL LETTER + normalized.put((char) 0x00E3, 'a'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x0363, 'a'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x0250, 'a'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x1E03, 'b'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E05, 'b'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0253, 'b'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E07, 'b'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0180, 'b'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x0183, 'b'); // WITH TOPBAR, LATIN SMALL LETTER + normalized.put((char) 0x0107, 'c'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x010D, 'c'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x00E7, 'c'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x0109, 'c'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x0255, 'c'); // WITH CURL, LATIN SMALL LETTER + normalized.put((char) 0x010B, 'c'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x0188, 'c'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x023C, 'c'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x0368, 'c'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x0297, 'c'); // , LATIN LETTER STRETCHED + normalized.put((char) 0x2184, 'c'); // , LATIN SMALL LETTER REVERSED + normalized.put((char) 0x010F, 'd'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x1E11, 'd'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x1E13, 'd'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0221, 'd'); // WITH CURL, LATIN SMALL LETTER + normalized.put((char) 0x1E0B, 'd'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E0D, 'd'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0257, 'd'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E0F, 'd'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0111, 'd'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x0256, 'd'); // WITH TAIL, LATIN SMALL LETTER + normalized.put((char) 0x018C, 'd'); // WITH TOPBAR, LATIN SMALL LETTER + normalized.put((char) 0x0369, 'd'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x00E9, 'e'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0115, 'e'); // WITH BREVE, LATIN SMALL LETTER + normalized.put((char) 0x011B, 'e'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x0229, 'e'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x1E19, 'e'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER + normalized.put((char) 0x00EA, 'e'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x00EB, 'e'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x0117, 'e'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1EB9, 'e'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0205, 'e'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x00E8, 'e'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x1EBB, 'e'); // WITH HOOK ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x025D, 'e'); // WITH HOOK, LATIN SMALL LETTER REVERSED OPEN + normalized.put((char) 0x0207, 'e'); // WITH INVERTED BREVE, LATIN SMALL LETTER + normalized.put((char) 0x0113, 'e'); // WITH MACRON, LATIN SMALL LETTER + normalized.put((char) 0x0119, 'e'); // WITH OGONEK, LATIN SMALL LETTER + normalized.put((char) 0x0247, 'e'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x1E1B, 'e'); // WITH TILDE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x1EBD, 'e'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x0364, 'e'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x029A, 'e'); // , LATIN SMALL LETTER CLOSED OPEN + normalized.put((char) 0x025E, 'e'); // , LATIN SMALL LETTER CLOSED REVERSED OPEN + normalized.put((char) 0x025B, 'e'); // , LATIN SMALL LETTER OPEN + normalized.put((char) 0x0258, 'e'); // , LATIN SMALL LETTER REVERSED + normalized.put((char) 0x025C, 'e'); // , LATIN SMALL LETTER REVERSED OPEN + normalized.put((char) 0x01DD, 'e'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x1D08, 'e'); // , LATIN SMALL LETTER TURNED OPEN + normalized.put((char) 0x1E1F, 'f'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x0192, 'f'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x01F5, 'g'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x011F, 'g'); // WITH BREVE, LATIN SMALL LETTER + normalized.put((char) 0x01E7, 'g'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x0123, 'g'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x011D, 'g'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x0121, 'g'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x0260, 'g'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E21, 'g'); // WITH MACRON, LATIN SMALL LETTER + normalized.put((char) 0x01E5, 'g'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x0261, 'g'); // , LATIN SMALL LETTER SCRIPT + normalized.put((char) 0x1E2B, 'h'); // WITH BREVE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x021F, 'h'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x1E29, 'h'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x0125, 'h'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x1E27, 'h'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x1E23, 'h'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E25, 'h'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x02AE, 'h'); // WITH FISHHOOK, LATIN SMALL LETTER TURNED + normalized.put((char) 0x0266, 'h'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E96, 'h'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0127, 'h'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x036A, 'h'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x0265, 'h'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x2095, 'h'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x00ED, 'i'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x012D, 'i'); // WITH BREVE, LATIN SMALL LETTER + normalized.put((char) 0x01D0, 'i'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x00EE, 'i'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x00EF, 'i'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x1ECB, 'i'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0209, 'i'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x00EC, 'i'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x1EC9, 'i'); // WITH HOOK ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x020B, 'i'); // WITH INVERTED BREVE, LATIN SMALL LETTER + normalized.put((char) 0x012B, 'i'); // WITH MACRON, LATIN SMALL LETTER + normalized.put((char) 0x012F, 'i'); // WITH OGONEK, LATIN SMALL LETTER + normalized.put((char) 0x0268, 'i'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x1E2D, 'i'); // WITH TILDE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0129, 'i'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x0365, 'i'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x0131, 'i'); // , LATIN SMALL LETTER DOTLESS + normalized.put((char) 0x1D09, 'i'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x1D62, 'i'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x2071, 'i'); // , SUPERSCRIPT LATIN SMALL LETTER + normalized.put((char) 0x01F0, 'j'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x0135, 'j'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x029D, 'j'); // WITH CROSSED-TAIL, LATIN SMALL LETTER + normalized.put((char) 0x0249, 'j'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x025F, 'j'); // WITH STROKE, LATIN SMALL LETTER DOTLESS + normalized.put((char) 0x0237, 'j'); // , LATIN SMALL LETTER DOTLESS + normalized.put((char) 0x1E31, 'k'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x01E9, 'k'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x0137, 'k'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x1E33, 'k'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0199, 'k'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E35, 'k'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x029E, 'k'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x2096, 'k'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x013A, 'l'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x019A, 'l'); // WITH BAR, LATIN SMALL LETTER + normalized.put((char) 0x026C, 'l'); // WITH BELT, LATIN SMALL LETTER + normalized.put((char) 0x013E, 'l'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x013C, 'l'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x1E3D, 'l'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0234, 'l'); // WITH CURL, LATIN SMALL LETTER + normalized.put((char) 0x1E37, 'l'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x1E3B, 'l'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0140, 'l'); // WITH MIDDLE DOT, LATIN SMALL LETTER + normalized.put((char) 0x026B, 'l'); // WITH MIDDLE TILDE, LATIN SMALL LETTER + normalized.put((char) 0x026D, 'l'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER + normalized.put((char) 0x0142, 'l'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x2097, 'l'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x1E3F, 'm'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x1E41, 'm'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E43, 'm'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0271, 'm'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x0270, 'm'); // WITH LONG LEG, LATIN SMALL LETTER TURNED + normalized.put((char) 0x036B, 'm'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x1D1F, 'm'); // , LATIN SMALL LETTER SIDEWAYS TURNED + normalized.put((char) 0x026F, 'm'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x2098, 'm'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x0144, 'n'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0148, 'n'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x0146, 'n'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x1E4B, 'n'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0235, 'n'); // WITH CURL, LATIN SMALL LETTER + normalized.put((char) 0x1E45, 'n'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E47, 'n'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x01F9, 'n'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x0272, 'n'); // WITH LEFT HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E49, 'n'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x019E, 'n'); // WITH LONG RIGHT LEG, LATIN SMALL LETTER + normalized.put((char) 0x0273, 'n'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER + normalized.put((char) 0x00F1, 'n'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x2099, 'n'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x00F3, 'o'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x014F, 'o'); // WITH BREVE, LATIN SMALL LETTER + normalized.put((char) 0x01D2, 'o'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x00F4, 'o'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x00F6, 'o'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x022F, 'o'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1ECD, 'o'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0151, 'o'); // WITH DOUBLE ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x020D, 'o'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x00F2, 'o'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x1ECF, 'o'); // WITH HOOK ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x01A1, 'o'); // WITH HORN, LATIN SMALL LETTER + normalized.put((char) 0x020F, 'o'); // WITH INVERTED BREVE, LATIN SMALL LETTER + normalized.put((char) 0x014D, 'o'); // WITH MACRON, LATIN SMALL LETTER + normalized.put((char) 0x01EB, 'o'); // WITH OGONEK, LATIN SMALL LETTER + normalized.put((char) 0x00F8, 'o'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x1D13, 'o'); // WITH STROKE, LATIN SMALL LETTER SIDEWAYS + normalized.put((char) 0x00F5, 'o'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x0366, 'o'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x0275, 'o'); // , LATIN SMALL LETTER BARRED + normalized.put((char) 0x1D17, 'o'); // , LATIN SMALL LETTER BOTTOM HALF + normalized.put((char) 0x0254, 'o'); // , LATIN SMALL LETTER OPEN + normalized.put((char) 0x1D11, 'o'); // , LATIN SMALL LETTER SIDEWAYS + normalized.put((char) 0x1D12, 'o'); // , LATIN SMALL LETTER SIDEWAYS OPEN + normalized.put((char) 0x1D16, 'o'); // , LATIN SMALL LETTER TOP HALF + normalized.put((char) 0x1E55, 'p'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x1E57, 'p'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x01A5, 'p'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x209A, 'p'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x024B, 'q'); // WITH HOOK TAIL, LATIN SMALL LETTER + normalized.put((char) 0x02A0, 'q'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x0155, 'r'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0159, 'r'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x0157, 'r'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x1E59, 'r'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E5B, 'r'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0211, 'r'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x027E, 'r'); // WITH FISHHOOK, LATIN SMALL LETTER + normalized.put((char) 0x027F, 'r'); // WITH FISHHOOK, LATIN SMALL LETTER REVERSED + normalized.put((char) 0x027B, 'r'); // WITH HOOK, LATIN SMALL LETTER TURNED + normalized.put((char) 0x0213, 'r'); // WITH INVERTED BREVE, LATIN SMALL LETTER + normalized.put((char) 0x1E5F, 'r'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x027C, 'r'); // WITH LONG LEG, LATIN SMALL LETTER + normalized.put((char) 0x027A, 'r'); // WITH LONG LEG, LATIN SMALL LETTER TURNED + normalized.put((char) 0x024D, 'r'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x027D, 'r'); // WITH TAIL, LATIN SMALL LETTER + normalized.put((char) 0x036C, 'r'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x0279, 'r'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x1D63, 'r'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x015B, 's'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0161, 's'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x015F, 's'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x015D, 's'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x0219, 's'); // WITH COMMA BELOW, LATIN SMALL LETTER + normalized.put((char) 0x1E61, 's'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E9B, 's'); // WITH DOT ABOVE, LATIN SMALL LETTER LONG + normalized.put((char) 0x1E63, 's'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0282, 's'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x023F, 's'); // WITH SWASH TAIL, LATIN SMALL LETTER + normalized.put((char) 0x017F, 's'); // , LATIN SMALL LETTER LONG + normalized.put((char) 0x00DF, 's'); // , LATIN SMALL LETTER SHARP + normalized.put((char) 0x209B, 's'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x0165, 't'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x0163, 't'); // WITH CEDILLA, LATIN SMALL LETTER + normalized.put((char) 0x1E71, 't'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER + normalized.put((char) 0x021B, 't'); // WITH COMMA BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0236, 't'); // WITH CURL, LATIN SMALL LETTER + normalized.put((char) 0x1E97, 't'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x1E6B, 't'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E6D, 't'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x01AD, 't'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E6F, 't'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x01AB, 't'); // WITH PALATAL HOOK, LATIN SMALL LETTER + normalized.put((char) 0x0288, 't'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER + normalized.put((char) 0x0167, 't'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x036D, 't'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x0287, 't'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x209C, 't'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x0289, 'u'); // BAR, LATIN SMALL LETTER + normalized.put((char) 0x00FA, 'u'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x016D, 'u'); // WITH BREVE, LATIN SMALL LETTER + normalized.put((char) 0x01D4, 'u'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x1E77, 'u'); // WITH CIRCUMFLEX BELOW, LATIN SMALL LETTER + normalized.put((char) 0x00FB, 'u'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x1E73, 'u'); // WITH DIAERESIS BELOW, LATIN SMALL LETTER + normalized.put((char) 0x00FC, 'u'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x1EE5, 'u'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0171, 'u'); // WITH DOUBLE ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0215, 'u'); // WITH DOUBLE GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x00F9, 'u'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x1EE7, 'u'); // WITH HOOK ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x01B0, 'u'); // WITH HORN, LATIN SMALL LETTER + normalized.put((char) 0x0217, 'u'); // WITH INVERTED BREVE, LATIN SMALL LETTER + normalized.put((char) 0x016B, 'u'); // WITH MACRON, LATIN SMALL LETTER + normalized.put((char) 0x0173, 'u'); // WITH OGONEK, LATIN SMALL LETTER + normalized.put((char) 0x016F, 'u'); // WITH RING ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E75, 'u'); // WITH TILDE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0169, 'u'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x0367, 'u'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x1D1D, 'u'); // , LATIN SMALL LETTER SIDEWAYS + normalized.put((char) 0x1D1E, 'u'); // , LATIN SMALL LETTER SIDEWAYS DIAERESIZED + normalized.put((char) 0x1D64, 'u'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x1E7F, 'v'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x028B, 'v'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E7D, 'v'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x036E, 'v'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x028C, 'v'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x1D65, 'v'); // , LATIN SUBSCRIPT SMALL LETTER + normalized.put((char) 0x1E83, 'w'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0175, 'w'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x1E85, 'w'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x1E87, 'w'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E89, 'w'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x1E81, 'w'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x1E98, 'w'); // WITH RING ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x028D, 'w'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x1E8D, 'x'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x1E8B, 'x'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x036F, 'x'); // , COMBINING LATIN SMALL LETTER + normalized.put((char) 0x00FD, 'y'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x0177, 'y'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x00FF, 'y'); // WITH DIAERESIS, LATIN SMALL LETTER + normalized.put((char) 0x1E8F, 'y'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1EF5, 'y'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x1EF3, 'y'); // WITH GRAVE, LATIN SMALL LETTER + normalized.put((char) 0x1EF7, 'y'); // WITH HOOK ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x01B4, 'y'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x0233, 'y'); // WITH MACRON, LATIN SMALL LETTER + normalized.put((char) 0x1E99, 'y'); // WITH RING ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x024F, 'y'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x1EF9, 'y'); // WITH TILDE, LATIN SMALL LETTER + normalized.put((char) 0x028E, 'y'); // , LATIN SMALL LETTER TURNED + normalized.put((char) 0x017A, 'z'); // WITH ACUTE, LATIN SMALL LETTER + normalized.put((char) 0x017E, 'z'); // WITH CARON, LATIN SMALL LETTER + normalized.put((char) 0x1E91, 'z'); // WITH CIRCUMFLEX, LATIN SMALL LETTER + normalized.put((char) 0x0291, 'z'); // WITH CURL, LATIN SMALL LETTER + normalized.put((char) 0x017C, 'z'); // WITH DOT ABOVE, LATIN SMALL LETTER + normalized.put((char) 0x1E93, 'z'); // WITH DOT BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0225, 'z'); // WITH HOOK, LATIN SMALL LETTER + normalized.put((char) 0x1E95, 'z'); // WITH LINE BELOW, LATIN SMALL LETTER + normalized.put((char) 0x0290, 'z'); // WITH RETROFLEX HOOK, LATIN SMALL LETTER + normalized.put((char) 0x01B6, 'z'); // WITH STROKE, LATIN SMALL LETTER + normalized.put((char) 0x0240, 'z'); // WITH SWASH TAIL, LATIN SMALL LETTER + normalized.put((char) 0x0251, 'a'); // , latin small letter script + normalized.put((char) 0x00C1, 'A'); // WITH ACUTE, LATIN CAPITAL LETTER + normalized.put((char) 0x00C2, 'A'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER + normalized.put((char) 0x00C4, 'A'); // WITH DIAERESIS, LATIN CAPITAL LETTER + normalized.put((char) 0x00C0, 'A'); // WITH GRAVE, LATIN CAPITAL LETTER + normalized.put((char) 0x00C5, 'A'); // WITH RING ABOVE, LATIN CAPITAL LETTER + normalized.put((char) 0x023A, 'A'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x00C3, 'A'); // WITH TILDE, LATIN CAPITAL LETTER + normalized.put((char) 0x1D00, 'A'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x0181, 'B'); // WITH HOOK, LATIN CAPITAL LETTER + normalized.put((char) 0x0243, 'B'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x0299, 'B'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x1D03, 'B'); // , LATIN LETTER SMALL CAPITAL BARRED + normalized.put((char) 0x00C7, 'C'); // WITH CEDILLA, LATIN CAPITAL LETTER + normalized.put((char) 0x023B, 'C'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x1D04, 'C'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x018A, 'D'); // WITH HOOK, LATIN CAPITAL LETTER + normalized.put((char) 0x0189, 'D'); // , LATIN CAPITAL LETTER AFRICAN + normalized.put((char) 0x1D05, 'D'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x00C9, 'E'); // WITH ACUTE, LATIN CAPITAL LETTER + normalized.put((char) 0x00CA, 'E'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER + normalized.put((char) 0x00CB, 'E'); // WITH DIAERESIS, LATIN CAPITAL LETTER + normalized.put((char) 0x00C8, 'E'); // WITH GRAVE, LATIN CAPITAL LETTER + normalized.put((char) 0x0246, 'E'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x0190, 'E'); // , LATIN CAPITAL LETTER OPEN + normalized.put((char) 0x018E, 'E'); // , LATIN CAPITAL LETTER REVERSED + normalized.put((char) 0x1D07, 'E'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x0193, 'G'); // WITH HOOK, LATIN CAPITAL LETTER + normalized.put((char) 0x029B, 'G'); // WITH HOOK, LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x0262, 'G'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x029C, 'H'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x00CD, 'I'); // WITH ACUTE, LATIN CAPITAL LETTER + normalized.put((char) 0x00CE, 'I'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER + normalized.put((char) 0x00CF, 'I'); // WITH DIAERESIS, LATIN CAPITAL LETTER + normalized.put((char) 0x0130, 'I'); // WITH DOT ABOVE, LATIN CAPITAL LETTER + normalized.put((char) 0x00CC, 'I'); // WITH GRAVE, LATIN CAPITAL LETTER + normalized.put((char) 0x0197, 'I'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x026A, 'I'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x0248, 'J'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x1D0A, 'J'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x1D0B, 'K'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x023D, 'L'); // WITH BAR, LATIN CAPITAL LETTER + normalized.put((char) 0x1D0C, 'L'); // WITH STROKE, LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x029F, 'L'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x019C, 'M'); // , LATIN CAPITAL LETTER TURNED + normalized.put((char) 0x1D0D, 'M'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x019D, 'N'); // WITH LEFT HOOK, LATIN CAPITAL LETTER + normalized.put((char) 0x0220, 'N'); // WITH LONG RIGHT LEG, LATIN CAPITAL LETTER + normalized.put((char) 0x00D1, 'N'); // WITH TILDE, LATIN CAPITAL LETTER + normalized.put((char) 0x0274, 'N'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x1D0E, 'N'); // , LATIN LETTER SMALL CAPITAL REVERSED + normalized.put((char) 0x00D3, 'O'); // WITH ACUTE, LATIN CAPITAL LETTER + normalized.put((char) 0x00D4, 'O'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER + normalized.put((char) 0x00D6, 'O'); // WITH DIAERESIS, LATIN CAPITAL LETTER + normalized.put((char) 0x00D2, 'O'); // WITH GRAVE, LATIN CAPITAL LETTER + normalized.put((char) 0x019F, 'O'); // WITH MIDDLE TILDE, LATIN CAPITAL LETTER + normalized.put((char) 0x00D8, 'O'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x00D5, 'O'); // WITH TILDE, LATIN CAPITAL LETTER + normalized.put((char) 0x0186, 'O'); // , LATIN CAPITAL LETTER OPEN + normalized.put((char) 0x1D0F, 'O'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x1D10, 'O'); // , LATIN LETTER SMALL CAPITAL OPEN + normalized.put((char) 0x1D18, 'P'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x024A, 'Q'); // WITH HOOK TAIL, LATIN CAPITAL LETTER SMALL + normalized.put((char) 0x024C, 'R'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x0280, 'R'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x0281, 'R'); // , LATIN LETTER SMALL CAPITAL INVERTED + normalized.put((char) 0x1D19, 'R'); // , LATIN LETTER SMALL CAPITAL REVERSED + normalized.put((char) 0x1D1A, 'R'); // , LATIN LETTER SMALL CAPITAL TURNED + normalized.put((char) 0x023E, 'T'); // WITH DIAGONAL STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x01AE, 'T'); // WITH RETROFLEX HOOK, LATIN CAPITAL LETTER + normalized.put((char) 0x1D1B, 'T'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x0244, 'U'); // BAR, LATIN CAPITAL LETTER + normalized.put((char) 0x00DA, 'U'); // WITH ACUTE, LATIN CAPITAL LETTER + normalized.put((char) 0x00DB, 'U'); // WITH CIRCUMFLEX, LATIN CAPITAL LETTER + normalized.put((char) 0x00DC, 'U'); // WITH DIAERESIS, LATIN CAPITAL LETTER + normalized.put((char) 0x00D9, 'U'); // WITH GRAVE, LATIN CAPITAL LETTER + normalized.put((char) 0x1D1C, 'U'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x01B2, 'V'); // WITH HOOK, LATIN CAPITAL LETTER + normalized.put((char) 0x0245, 'V'); // , LATIN CAPITAL LETTER TURNED + normalized.put((char) 0x1D20, 'V'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x1D21, 'W'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x00DD, 'Y'); // WITH ACUTE, LATIN CAPITAL LETTER + normalized.put((char) 0x0178, 'Y'); // WITH DIAERESIS, LATIN CAPITAL LETTER + normalized.put((char) 0x024E, 'Y'); // WITH STROKE, LATIN CAPITAL LETTER + normalized.put((char) 0x028F, 'Y'); // , LATIN LETTER SMALL CAPITAL + normalized.put((char) 0x1D22, 'Z'); // , LATIN LETTER SMALL CAPITAL normalized.put('Ắ', 'A'); normalized.put('Ấ', 'A'); normalized.put('Ằ', 'A'); @@ -500,4 +500,5 @@ public static String normalizeRunes(String text) { } return new String(chars); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatch.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatch.java index 155ce7d5f..a1493baea 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatch.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatch.java @@ -16,10 +16,9 @@ package org.springframework.shell.support.search; /** - * Interface defining a search match for {@code text} agains {@code pattern}. - * Resulting match result gives information in a context of {@code text} how and - * where matches happens and provides a {@code score} number which can be to - * sort results. + * Interface defining a search match for {@code text} agains {@code pattern}. Resulting + * match result gives information in a context of {@code text} how and where matches + * happens and provides a {@code score} number which can be to sort results. * * @author Janne Valkealahti */ @@ -28,7 +27,6 @@ public interface SearchMatch { /** * Match a pattern into a given text. - * * @param text the text to search * @param pattern the search pattern * @return a result @@ -37,7 +35,6 @@ public interface SearchMatch { /** * Gets an instance of a builder for a {@link SearchMatch}. - * * @return builder for search match */ public static Builder builder() { @@ -51,7 +48,6 @@ interface Builder { /** * Set a flag for {@code caseSensitive}. - * * @param caseSensitive the caseSensitive * @return builder for chaining */ @@ -59,7 +55,6 @@ interface Builder { /** * Set a flag for {@code normalize}. - * * @param normalize the normalize * @return builder for chaining */ @@ -67,7 +62,6 @@ interface Builder { /** * Set a flag for {@code forward}. - * * @param forward the forward * @return builder for chaining */ @@ -75,16 +69,18 @@ interface Builder { /** * Build instance of a {@link SearchMatch}. - * * @return a build instance of {@link SearchMatch} */ SearchMatch build(); + } static class DefaultBuilder implements Builder { private boolean caseSensitive; + private boolean normalize; + private boolean forward; @Override @@ -109,12 +105,15 @@ public Builder forward(boolean forward) { public SearchMatch build() { return new DefaultSearchMatch(this.caseSensitive, this.normalize, this.forward); } + } static class DefaultSearchMatch implements SearchMatch { private boolean caseSensitive; + private boolean normalize; + private boolean forward; DefaultSearchMatch(boolean caseSensitive, boolean normalize, boolean forward) { @@ -154,5 +153,7 @@ public SearchMatchResult match(String text, String pattern) { return algo.match(caseSensitive, normalize, forward, text, pattern); } + } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchAlgorithm.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchAlgorithm.java index c1bf14eb4..d1c9d7d50 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchAlgorithm.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchAlgorithm.java @@ -25,7 +25,6 @@ public interface SearchMatchAlgorithm { /** * Match given text with pattern as a result. - * * @param caseSensitive the caseSensitive * @param normalize the normalize * @param forward the forward @@ -34,4 +33,5 @@ public interface SearchMatchAlgorithm { * @return a search match result */ SearchMatchResult match(boolean caseSensitive, boolean normalize, boolean forward, String text, String pattern); + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchResult.java b/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchResult.java index 0688cc64e..e918e515c 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchResult.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/support/search/SearchMatchResult.java @@ -24,42 +24,36 @@ public interface SearchMatchResult { /** * Get start of a match. - * * @return a start of a match */ int getStart(); /** * Get end of a match. - * * @return a end of a matchh */ int getEnd(); /** * Get score of a match. - * * @return a score of a match */ int getScore(); /** * Get positions of a match. - * * @return a positions of a match */ int[] getPositions(); /** * Get {@link SearchMatchAlgorithm} handling a search. - * * @return {@link SearchMatchAlgorithm} handling a search */ SearchMatchAlgorithm getAlgorithm(); /** * Construct {@link SearchMatchResult} with given parameters. - * * @param start the start * @param end the end * @param score the score @@ -81,9 +75,13 @@ public static SearchMatchResult ofMinus() { static class DefaultResult implements SearchMatchResult { int start; + int end; + int score; + int[] positions; + SearchMatchAlgorithm algo; DefaultResult(int start, int end, int score, int[] positions, SearchMatchAlgorithm algo) { @@ -118,5 +116,7 @@ public int[] getPositions() { public SearchMatchAlgorithm getAlgorithm() { return algo; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/AvailabilityReflectiveProcessorTests.java b/spring-shell-core/src/test/java/org/springframework/shell/AvailabilityReflectiveProcessorTests.java index 529af7715..2c5bc7eb4 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/AvailabilityReflectiveProcessorTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/AvailabilityReflectiveProcessorTests.java @@ -32,17 +32,17 @@ class AvailabilityReflectiveProcessorTests { @Test void registerReflectiveHintsForMethod() throws NoSuchMethodException { - processor.registerReflectionHints(hints, SampleBean.class); - assertThat(hints.typeHints()).singleElement().satisfies(typeHint -> { - assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleBean.class)); - assertThat(typeHint.getMemberCategories()).isEmpty(); - assertThat(typeHint.constructors()).isEmpty(); - assertThat(typeHint.fields()).isEmpty(); - assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> { - assertThat(methodHint.getName()).isEqualTo("test"); - assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE); - }); + processor.registerReflectionHints(hints, SampleBean.class); + assertThat(hints.typeHints()).singleElement().satisfies(typeHint -> { + assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleBean.class)); + assertThat(typeHint.getMemberCategories()).isEmpty(); + assertThat(typeHint.constructors()).isEmpty(); + assertThat(typeHint.fields()).isEmpty(); + assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> { + assertThat(methodHint.getName()).isEqualTo("test"); + assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE); }); + }); } @Reflective(AvailabilityReflectiveProcessor.class) @@ -51,5 +51,7 @@ static class SampleBean { public Availability test() { return null; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/JnaRuntimeHintsTests.java b/spring-shell-core/src/test/java/org/springframework/shell/JnaRuntimeHintsTests.java index 48c63f08f..834461760 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/JnaRuntimeHintsTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/JnaRuntimeHintsTests.java @@ -18,10 +18,12 @@ public class JnaRuntimeHintsTests { @Test void test() { - String[] classNames = Arrays.asList("com.sun.jna.CallbackReference", "com.sun.jna.Native", - "com.sun.jna.NativeLong", "com.sun.jna.Pointer", "com.sun.jna.Structure", - "com.sun.jna.ptr.IntByReference", "com.sun.jna.ptr.PointerByReference", "com.sun.jna.Klass", - "com.sun.jna.Structure$FFIType", "com.sun.jna.Structure$FFIType$size_t").toArray(new String[0]); + String[] classNames = Arrays + .asList("com.sun.jna.CallbackReference", "com.sun.jna.Native", "com.sun.jna.NativeLong", + "com.sun.jna.Pointer", "com.sun.jna.Structure", "com.sun.jna.ptr.IntByReference", + "com.sun.jna.ptr.PointerByReference", "com.sun.jna.Klass", "com.sun.jna.Structure$FFIType", + "com.sun.jna.Structure$FFIType$size_t") + .toArray(new String[0]); ReflectionHints hints = registerHints(); typeReferences(classNames).forEach(typeReference -> { TypeHint typeHint = hints.getTypeHint(typeReference); @@ -42,4 +44,5 @@ private ReflectionHints registerHints() { private Stream typeReferences(String... classNames) { return Stream.of(classNames).map(TypeReference::of); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/ShellTests.java b/spring-shell-core/src/test/java/org/springframework/shell/ShellTests.java index f91742921..958538095 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/ShellTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/ShellTests.java @@ -74,8 +74,8 @@ public void commandMatch() throws Exception { CommandRegistration registration = CommandRegistration.builder() .command("hello world") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration); @@ -100,8 +100,8 @@ public void commandNotFound() throws Exception { CommandRegistration registration = CommandRegistration.builder() .command("bonjour") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration); @@ -125,8 +125,8 @@ public void commandNotFoundPrefix() throws Exception { CommandRegistration registration = CommandRegistration.builder() .command("hello world") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration); @@ -149,8 +149,8 @@ public void noCommand() throws Exception { CommandRegistration registration = CommandRegistration.builder() .command("hello world") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration); @@ -175,14 +175,13 @@ public void commandThrowingAnException() throws Exception { CommandRegistration registration = CommandRegistration.builder() .command("fail") .withTarget() - .method(this, "failing") - .and() + .method(this, "failing") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("fail", registration); when(commandRegistry.getRegistrations()).thenReturn(registrations); - try { shell.run(inputProvider); fail("Exit expected"); @@ -206,14 +205,14 @@ public void commandNameCompletion() throws Exception { CommandRegistration registration1 = CommandRegistration.builder() .command("hello world") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .build(); CommandRegistration registration2 = CommandRegistration.builder() .command("another command") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration1); @@ -222,37 +221,53 @@ public void commandNameCompletion() throws Exception { // Invoke at very start List proposals = shell.complete(new CompletionContext(Arrays.asList(""), 0, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactlyInAnyOrder("another command", "hello world"); // Invoke in middle of first word proposals = shell.complete(new CompletionContext(Arrays.asList("hel"), 0, "hel".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactly("hello world"); // Invoke at end of first word (no space after yet) proposals = shell.complete(new CompletionContext(Arrays.asList("hello"), 0, "hello".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactly("hello world"); // Invoke after first word / start of second word proposals = shell.complete(new CompletionContext(Arrays.asList("hello", ""), 1, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactly("world"); // Invoke in middle of second word proposals = shell.complete(new CompletionContext(Arrays.asList("hello", "wo"), 1, "wo".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactly("world"); // Invoke at end of whole command (no space after yet) - proposals = shell.complete(new CompletionContext(Arrays.asList("hello", "world"), 1, "world".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + proposals = shell + .complete(new CompletionContext(Arrays.asList("hello", "world"), 1, "world".length(), null, null)) + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactly("world"); // Invoke in middle of second word - proposals = shell.complete(new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + proposals = shell + .complete(new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), null, null)) + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).isEmpty(); } @@ -272,19 +287,22 @@ public void completionArgWithMethod() throws Exception { CommandRegistration registration1 = CommandRegistration.builder() .command("hello world") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .withOption() - .longNames("arg1") - .description("arg1 desc") - .and() + .longNames("arg1") + .description("arg1 desc") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration1); when(commandRegistry.getRegistrations()).thenReturn(registrations); - List proposals = shell.complete(new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + List proposals = shell + .complete(new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), null, null)) + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactlyInAnyOrder("--arg1"); } @@ -293,21 +311,24 @@ public void completionArgWithFunction() throws Exception { CommandRegistration registration1 = CommandRegistration.builder() .command("hello world") .withTarget() - .function(ctx -> { - return null; - }) - .and() + .function(ctx -> { + return null; + }) + .and() .withOption() - .longNames("arg1") - .description("arg1 desc") - .and() + .longNames("arg1") + .description("arg1 desc") + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration1); when(commandRegistry.getRegistrations()).thenReturn(registrations); - List proposals = shell.complete(new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + List proposals = shell + .complete(new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), null, null)) + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals).containsExactlyInAnyOrder("--arg1"); } @@ -316,38 +337,57 @@ public void shouldCompleteWithCorrectArgument() throws Exception { CommandRegistration registration1 = CommandRegistration.builder() .command("hello world") .withTarget() - .method(this, "helloWorld") - .and() + .method(this, "helloWorld") + .and() .withOption() - .longNames("arg1") - .completion(ctx -> Arrays.asList("arg1Comp1").stream().map(CompletionProposal::new).collect(Collectors.toList())) - .and() + .longNames("arg1") + .completion(ctx -> Arrays.asList("arg1Comp1") + .stream() + .map(CompletionProposal::new) + .collect(Collectors.toList())) + .and() .withOption() - .longNames("arg2") - .completion(ctx -> Arrays.asList("arg2Comp1").stream().map(CompletionProposal::new).collect(Collectors.toList())) - .and() + .longNames("arg2") + .completion(ctx -> Arrays.asList("arg2Comp1") + .stream() + .map(CompletionProposal::new) + .collect(Collectors.toList())) + .and() .build(); Map registrations = new HashMap<>(); registrations.put("hello world", registration1); when(commandRegistry.getRegistrations()).thenReturn(registrations); - List proposals1 = shell.complete(new CompletionContext(Arrays.asList("hello", "world", "--arg1", ""), 3, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + List proposals1 = shell + .complete(new CompletionContext(Arrays.asList("hello", "world", "--arg1", ""), 3, "".length(), null, null)) + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals1).containsExactlyInAnyOrder("--arg2", "arg1Comp1"); - List proposals2 = shell.complete(new CompletionContext(Arrays.asList("hello", "world", "--arg1", "xxx", "--arg2", ""), 5, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + List proposals2 = shell + .complete(new CompletionContext(Arrays.asList("hello", "world", "--arg1", "xxx", "--arg2", ""), 5, + "".length(), null, null)) + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals2).containsExactlyInAnyOrder("arg2Comp1"); - List proposals3 = shell.complete(new CompletionContext(Arrays.asList("hello", "world", "--arg2", "xxx", "--arg1", ""), 5, "".length(), null, null)) - .stream().map(CompletionProposal::value).collect(Collectors.toList()); + List proposals3 = shell + .complete(new CompletionContext(Arrays.asList("hello", "world", "--arg2", "xxx", "--arg1", ""), 5, + "".length(), null, null)) + .stream() + .map(CompletionProposal::value) + .collect(Collectors.toList()); assertThat(proposals3).containsExactlyInAnyOrder("arg1Comp1"); } private static class Exit extends RuntimeException { + } private static class SomeException extends RuntimeException { } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/UtilsTests.java b/spring-shell-core/src/test/java/org/springframework/shell/UtilsTests.java index e63d1b841..8bc628bed 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/UtilsTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/UtilsTests.java @@ -61,4 +61,5 @@ public void testSplit() { split = Utils.split(new String[] { "-a1", "a1", "a2" }, predicate); assertThat(split).containsExactly(Arrays.asList("-a1", "a1", "a2")); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/ValueResultAsserts.java b/spring-shell-core/src/test/java/org/springframework/shell/ValueResultAsserts.java index 51da9c935..5bf1233f4 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/ValueResultAsserts.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/ValueResultAsserts.java @@ -20,7 +20,7 @@ /** * Assertions for {@link ValueResult}. - * + * * @author Camilo Gonzalez */ public class ValueResultAsserts extends AbstractAssert { @@ -66,4 +66,5 @@ public ValueResultAsserts notUsesWordsForValue() { public static ValueResultAsserts assertThat(ValueResult valueResult) { return new ValueResultAsserts(valueResult); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/AbstractCommandTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/AbstractCommandTests.java index 5dc15e304..da5ba3f8e 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/AbstractCommandTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/AbstractCommandTests.java @@ -42,29 +42,53 @@ public void setupAbstractCommandTests() { protected static class Pojo1 { public int method1Count; + public CommandContext method1Ctx; + public int method1Mixed1Count; + public String method1Mixed1Arg1; + public CommandContext method1Mixed1Ctx; + public String method1Mixed1Arg2; + public int method2Count; + public int method3Count; + public int method4Count; + public String method4Arg1; + public Boolean method5ArgA; + public Boolean method5ArgB; + public Boolean method5ArgC; + public int method6Count; + public String method6Arg1; + public String method6Arg2; + public String method6Arg3; + public int method7Count; + public int method7Arg1; + public int method7Arg2; + public int method7Arg3; + public int method8Count; + public float[] method8Arg1; + public int method9Count; + public String[] method9Arg1; public void method1(CommandContext ctx) { @@ -125,5 +149,7 @@ public void method9(String[] arg1) { method9Arg1 = arg1; method9Count++; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandCatalogTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandCatalogTests.java index b0664c33b..4ac30751e 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandCatalogTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandCatalogTests.java @@ -26,12 +26,12 @@ public class CommandCatalogTests extends AbstractCommandTests { @Test - public void testCommandCatalog () { + public void testCommandCatalog() { CommandRegistration r1 = CommandRegistration.builder() .command("group1 sub1") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); CommandCatalog catalog = CommandCatalog.of(); catalog.register(r1); @@ -41,15 +41,15 @@ public void testCommandCatalog () { } @Test - public void testCommandAliases () { + public void testCommandAliases() { CommandRegistration r1 = CommandRegistration.builder() .command("group1 sub1") .withAlias() - .command("group1 sub2") - .and() + .command("group1 sub2") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); CommandCatalog catalog = CommandCatalog.of(); catalog.register(r1); @@ -68,12 +68,14 @@ public void testResolver() { } class DynamicCommandResolver implements CommandResolver { + CommandRegistration r1 = CommandRegistration.builder() .command("group1 sub1") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); + boolean enabled = true; @Override @@ -84,5 +86,7 @@ public List resolve() { } return regs; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionCustomConversionTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionCustomConversionTests.java index 64a2edd2f..d031b8c20 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionCustomConversionTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionCustomConversionTests.java @@ -33,6 +33,7 @@ public class CommandExecutionCustomConversionTests { private CommandExecution execution; + private CommandCatalog commandCatalog; @BeforeEach @@ -54,11 +55,11 @@ public void testCustomPojo() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .method(pojo1, "method1") - .and() + .method(pojo1, "method1") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" }); @@ -73,11 +74,11 @@ public void testCustomPojoArray() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .method(pojo1, "method2") - .and() + .method(pojo1, "method2") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "a,b" }); @@ -95,13 +96,13 @@ public void testCustomPojoArrayPositional() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .arity(OptionArity.ONE_OR_MORE) - .position(0) - .and() + .longNames("arg1") + .arity(OptionArity.ONE_OR_MORE) + .position(0) + .and() .withTarget() - .method(pojo1, "method2") - .and() + .method(pojo1, "method2") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "a,b" }); @@ -121,12 +122,12 @@ public void testCustomPojoList() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .type(type) - .and() + .longNames("arg1") + .type(type) + .and() .withTarget() - .method(pojo1, "method3") - .and() + .method(pojo1, "method3") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "a,b" }); @@ -147,14 +148,14 @@ public void testCustomPojoListPositional() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .arity(OptionArity.ONE_OR_MORE) - .position(0) - .type(type) - .and() + .longNames("arg1") + .arity(OptionArity.ONE_OR_MORE) + .position(0) + .type(type) + .and() .withTarget() - .method(pojo1, "method3") - .and() + .method(pojo1, "method3") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "a,b" }); @@ -173,11 +174,11 @@ public void testCustomPojoSet() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "a,b" }); @@ -195,13 +196,13 @@ public void testCustomPojoSetPositional() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .arity(OptionArity.ONE_OR_MORE) - .position(0) - .and() + .longNames("arg1") + .arity(OptionArity.ONE_OR_MORE) + .position(0) + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "a,b" }); @@ -217,13 +218,17 @@ static class StringToMyPojo2Converter implements Converter { public Pojo2 convert(String from) { return new Pojo2(from); } + } static class Pojo1 { public Pojo2 method1Pojo2; + public Pojo2[] method2Pojo2; + public List method3Pojo2; + public Set method4Pojo2; public void method1(Pojo2 arg1) { @@ -241,6 +246,7 @@ public void method3(List arg1) { public void method4(Set arg1) { method4Pojo2 = arg1; } + } static class Pojo2 { @@ -253,5 +259,7 @@ public Pojo2() { public Pojo2(String arg) { this.arg = arg; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java index 76951b66a..570f8f8e7 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandExecutionTests.java @@ -38,6 +38,7 @@ public class CommandExecutionTests extends AbstractCommandTests { private CommandExecution execution; + private CommandCatalog commandCatalog; @BeforeEach @@ -56,12 +57,12 @@ public void testFunctionExecution() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); commandCatalog.register(r1); Object result = execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" }); @@ -74,12 +75,12 @@ public void testMethodExecution1() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withTarget() - .method(pojo1, "method3", String.class) - .and() + .method(pojo1, "method3", String.class) + .and() .build(); commandCatalog.register(r1); Object result = execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" }); @@ -93,12 +94,12 @@ public void testMethodExecution2() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withTarget() - .method(pojo1, "method1") - .and() + .method(pojo1, "method1") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" }); @@ -112,16 +113,16 @@ public void testMixedWithCtx1() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withOption() - .longNames("arg2") - .description("some arg1") - .and() + .longNames("arg2") + .description("some arg1") + .and() .withTarget() - .method(pojo1, "method1Mixed1") - .and() + .method(pojo1, "method1Mixed1") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1" }); @@ -137,16 +138,16 @@ public void testMixedWithCtx2() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withOption() - .longNames("arg2") - .description("some arg1") - .and() + .longNames("arg2") + .description("some arg1") + .and() .withTarget() - .method(pojo1, "method1Mixed1") - .and() + .method(pojo1, "method1Mixed1") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" }); @@ -162,16 +163,16 @@ public void testMixedWithCtx3() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withOption() - .longNames("arg2") - .description("some arg1") - .and() + .longNames("arg2") + .description("some arg1") + .and() .withTarget() - .method(pojo1, "method1Mixed1") - .and() + .method(pojo1, "method1Mixed1") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "myarg1value", "--arg2", "myarg2value" }); @@ -187,13 +188,13 @@ public void testMethodArgWithoutValue() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1" }); @@ -207,14 +208,14 @@ public void testMethodSinglePositionalArgs() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .arity(OptionArity.EXACTLY_ONE) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .arity(OptionArity.EXACTLY_ONE) + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "myarg1value" }); @@ -228,11 +229,11 @@ public void testMethodSingleWithNamedArgs() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); Object result = execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" }); @@ -247,14 +248,14 @@ public void testMethodMultiPositionalArgs() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .arity(OptionArity.EXACTLY_ONE) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .arity(OptionArity.EXACTLY_ONE) + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "myarg1value1", "myarg1value2" }); @@ -268,14 +269,14 @@ public void testMethodMultiPositionalArgsAll() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .arity(OptionArity.ONE_OR_MORE) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .arity(OptionArity.ONE_OR_MORE) + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "myarg1value1", "myarg1value2" }); @@ -289,14 +290,14 @@ public void testMethodMultiPositionalArgsAllToArray1() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .arity(OptionArity.ONE_OR_MORE) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .arity(OptionArity.ONE_OR_MORE) + .and() .withTarget() - .method(pojo1, "method9") - .and() + .method(pojo1, "method9") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "myarg1value1", "myarg1value2" }); @@ -310,14 +311,14 @@ public void testMethodMultiPositionalArgsAllToArray2() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .arity(OptionArity.ONE_OR_MORE) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .arity(OptionArity.ONE_OR_MORE) + .and() .withTarget() - .method(pojo1, "method8") - .and() + .method(pojo1, "method8") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "1", "2" }); @@ -331,20 +332,20 @@ public void testMethodMultipleArgs() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withOption() - .longNames("arg2") - .description("some arg2") - .and() + .longNames("arg2") + .description("some arg2") + .and() .withOption() - .longNames("arg3") - .description("some arg3") - .and() + .longNames("arg3") + .description("some arg3") + .and() .withTarget() - .method(pojo1, "method6") - .and() + .method(pojo1, "method6") + .and() .build(); commandCatalog.register(r1); @@ -356,27 +357,26 @@ public void testMethodMultipleArgs() { assertThat(pojo1.method6Arg3).isEqualTo("myarg3value"); } - @Test public void testMethodMultipleIntArgs() { CommandRegistration r1 = CommandRegistration.builder() .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withOption() - .longNames("arg2") - .description("some arg2") - .and() + .longNames("arg2") + .description("some arg2") + .and() .withOption() - .longNames("arg3") - .description("some arg3") - .and() + .longNames("arg3") + .description("some arg3") + .and() .withTarget() - .method(pojo1, "method7") - .and() + .method(pojo1, "method7") + .and() .build(); commandCatalog.register(r1); @@ -393,26 +393,26 @@ public void testMethodMultiplePositionalStringArgs() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .arity(OptionArity.EXACTLY_ONE) - .and() - .withOption() - .longNames("arg2") - .description("some arg2") - .position(1) - .arity(OptionArity.EXACTLY_ONE) - .and() - .withOption() - .longNames("arg3") - .description("some arg3") - .position(2) - .arity(OptionArity.EXACTLY_ONE) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .arity(OptionArity.EXACTLY_ONE) + .and() + .withOption() + .longNames("arg2") + .description("some arg2") + .position(1) + .arity(OptionArity.EXACTLY_ONE) + .and() + .withOption() + .longNames("arg3") + .description("some arg3") + .position(2) + .arity(OptionArity.EXACTLY_ONE) + .and() .withTarget() - .method(pojo1, "method6") - .and() + .method(pojo1, "method6") + .and() .build(); commandCatalog.register(r1); @@ -425,36 +425,34 @@ public void testMethodMultiplePositionalStringArgs() { @ParameterizedTest @Disabled("concepts change") - @ValueSource(strings = { - "command1 myarg1value --arg2 myarg2value --arg3 myarg3value", - "command1 --arg1 myarg1value myarg2value --arg3 myarg3value", - "command1 --arg1 myarg1value --arg2 myarg2value myarg3value" - }) + @ValueSource(strings = { "command1 myarg1value --arg2 myarg2value --arg3 myarg3value", + "command1 --arg1 myarg1value myarg2value --arg3 myarg3value", + "command1 --arg1 myarg1value --arg2 myarg2value myarg3value" }) public void testMethodMultiplePositionalStringArgsMixed(String arg) { CommandRegistration r1 = CommandRegistration.builder() .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .position(0) - .arity(OptionArity.EXACTLY_ONE) - .and() - .withOption() - .longNames("arg2") - .description("some arg2") - .position(1) - .arity(OptionArity.EXACTLY_ONE) - .and() - .withOption() - .longNames("arg3") - .description("some arg3") - .position(2) - .arity(OptionArity.EXACTLY_ONE) - .and() + .longNames("arg1") + .description("some arg1") + .position(0) + .arity(OptionArity.EXACTLY_ONE) + .and() + .withOption() + .longNames("arg2") + .description("some arg2") + .position(1) + .arity(OptionArity.EXACTLY_ONE) + .and() + .withOption() + .longNames("arg3") + .description("some arg3") + .position(2) + .arity(OptionArity.EXACTLY_ONE) + .and() .withTarget() - .method(pojo1, "method6") - .and() + .method(pojo1, "method6") + .and() .build(); String[] args = arg.split(" "); commandCatalog.register(r1); @@ -471,23 +469,23 @@ public void testShortCombinedWithoutValue() { .command("command1") .description("help") .withOption() - .shortNames('a') - .description("short arg a") - .type(boolean.class) - .and() + .shortNames('a') + .description("short arg a") + .type(boolean.class) + .and() .withOption() - .shortNames('b') - .description("short arg b") - .type(boolean.class) - .and() + .shortNames('b') + .description("short arg b") + .type(boolean.class) + .and() .withOption() - .shortNames('c') - .description("short arg c") - .type(boolean.class) - .and() + .shortNames('c') + .description("short arg c") + .type(boolean.class) + .and() .withTarget() - .method(pojo1, "method5") - .and() + .method(pojo1, "method5") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "-abc" }); @@ -502,23 +500,23 @@ public void testShortCombinedSomeHavingValue() { .command("command1") .description("help") .withOption() - .shortNames('a') - .description("short arg a") - .type(boolean.class) - .and() + .shortNames('a') + .description("short arg a") + .type(boolean.class) + .and() .withOption() - .shortNames('b') - .description("short arg b") - .type(boolean.class) - .and() + .shortNames('b') + .description("short arg b") + .type(boolean.class) + .and() .withOption() - .shortNames('c') - .description("short arg c") - .type(boolean.class) - .and() + .shortNames('c') + .description("short arg c") + .type(boolean.class) + .and() .withTarget() - .method(pojo1, "method5") - .and() + .method(pojo1, "method5") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "-ac", "-b", "false" }); @@ -533,17 +531,17 @@ public void testFloatArrayOne() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .type(float[].class) - .and() + .longNames("arg1") + .type(float[].class) + .and() .withTarget() - .method(pojo1, "method8") - .and() + .method(pojo1, "method8") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "0.1" }); assertThat(pojo1.method8Count).isEqualTo(1); - assertThat(pojo1.method8Arg1).isEqualTo(new float[]{0.1f}); + assertThat(pojo1.method8Arg1).isEqualTo(new float[] { 0.1f }); } @Test @@ -552,17 +550,17 @@ public void testFloatArrayTwo() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .type(float[].class) - .and() + .longNames("arg1") + .type(float[].class) + .and() .withTarget() - .method(pojo1, "method8") - .and() + .method(pojo1, "method8") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1", "--arg1", "0.1", "0.2" }); assertThat(pojo1.method8Count).isEqualTo(1); - assertThat(pojo1.method8Arg1).isEqualTo(new float[]{0.1f, 0.2f}); + assertThat(pojo1.method8Arg1).isEqualTo(new float[] { 0.1f, 0.2f }); } @Test @@ -570,11 +568,11 @@ public void testDefaultValueAsNull() { CommandRegistration r1 = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1" }); @@ -587,14 +585,14 @@ public void testDefaultValue() { CommandRegistration r1 = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .defaultValue("defaultValue1") - // .position(0) - // .arity(OptionArity.EXACTLY_ONE) - .and() + .longNames("arg1") + .defaultValue("defaultValue1") + // .position(0) + // .arity(OptionArity.EXACTLY_ONE) + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); execution.evaluate(new String[] { "command1" }); @@ -607,12 +605,12 @@ public void testRequiredArg() { CommandRegistration r1 = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .required() - .and() + .longNames("arg1") + .required() + .and() .withTarget() - .method(pojo1, "method4") - .and() + .method(pojo1, "method4") + .and() .build(); commandCatalog.register(r1); @@ -627,13 +625,13 @@ public void testCommandNotAvailable() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .availability(() -> Availability.unavailable("fake reason")) .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); commandCatalog.register(r1); Object result = execution.evaluate(new String[] { "command1", "--arg1", "myarg1value" }); @@ -645,12 +643,12 @@ public void testExecutionWithModifiedLongOption() { CommandRegistration r1 = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .nameModifier(orig -> "x" + orig) - .and() + .longNames("arg1") + .nameModifier(orig -> "x" + orig) + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); commandCatalog.register(r1); Object result = execution.evaluate(new String[] { "command1", "--xarg1", "myarg1value" }); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandHandlingResultTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandHandlingResultTests.java index 55fcc48e6..343d2ae7c 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandHandlingResultTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandHandlingResultTests.java @@ -76,4 +76,5 @@ void isPresentJustWithCode() { assertThat(result.isPresent()).isTrue(); assertThat(result.isEmpty()).isFalse(); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserExceptionResolverTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserExceptionResolverTests.java index 92419ac32..d7d229c38 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserExceptionResolverTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserExceptionResolverTests.java @@ -41,4 +41,5 @@ static CommandParserExceptionsException genericParserException() { List parserExceptions = Arrays.asList(e); return new CommandParserExceptionsException("msg", parserExceptions); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java index db9a80fea..036fd0ee4 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java @@ -35,12 +35,12 @@ public void testMethodExecution1() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withTarget() - .method(pojo1, "method3", String.class) - .and() + .method(pojo1, "method3", String.class) + .and() .build(); ConversionService conversionService = new DefaultConversionService(); @@ -51,4 +51,5 @@ public void testMethodExecution1() { assertThat(results.results()).hasSize(1); assertThat(results.results().get(0).value()).isEqualTo("myarg1value"); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandRegistrationTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandRegistrationTests.java index 0df451396..0202d086c 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandRegistrationTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandRegistrationTests.java @@ -43,8 +43,8 @@ public void testBasics() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getGroup()).isNull(); @@ -55,8 +55,8 @@ public void testBasics() { .interactionMode(InteractionMode.NONINTERACTIVE) .group("fakegroup") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getInteractionMode()).isEqualTo(InteractionMode.NONINTERACTIVE); assertThat(registration.getGroup()).isEqualTo("fakegroup"); @@ -67,32 +67,32 @@ public void testCommandStructures() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); registration = CommandRegistration.builder() .command("command1", "command2") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1 command2"); registration = CommandRegistration.builder() .command("command1 command2") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1 command2"); registration = CommandRegistration.builder() .command(" command1 command2 ") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1 command2"); } @@ -102,8 +102,8 @@ public void testFunctionRegistration() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getTarget().getTargetType()).isEqualTo(TargetType.FUNCTION); assertThat(registration.getTarget().getFunction()).isNotNull(); @@ -116,8 +116,9 @@ public void testConsumerRegistration() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); assertThat(registration.getTarget().getTargetType()).isEqualTo(TargetType.CONSUMER); assertThat(registration.getTarget().getFunction()).isNull(); @@ -131,8 +132,8 @@ public void testMethodRegistration() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withTarget() - .method(pojo1, "method3", String.class) - .and() + .method(pojo1, "method3", String.class) + .and() .build(); assertThat(registration.getTarget().getTargetType()).isEqualTo(TargetType.METHOD); assertThat(registration.getTarget().getFunction()).isNull(); @@ -146,9 +147,9 @@ public void testCanUseOnlyOneTarget() { CommandRegistration.builder() .command("command1") .withTarget() - .method(pojo1, "method3", String.class) - .function(function1) - .and() + .method(pojo1, "method3", String.class) + .function(function1) + .and() .build(); }).isInstanceOf(IllegalStateException.class).hasMessageContaining("only one target can exist"); } @@ -159,12 +160,12 @@ public void testSimpleFullRegistrationWithFunction() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getDescription()).isEqualTo("help"); @@ -178,12 +179,12 @@ public void testSimpleFullRegistrationWithMethod() { .command("command1") .description("help") .withOption() - .longNames("arg1") - .description("some arg1") - .and() + .longNames("arg1") + .description("some arg1") + .and() .withTarget() - .method(pojo1, "method3", String.class) - .and() + .method(pojo1, "method3", String.class) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getDescription()).isEqualTo("help"); @@ -196,14 +197,14 @@ public void testOptionWithType() { .command("command1") .description("help") .withOption() - .shortNames('v') - .type(boolean.class) - .description("some arg1") - .label("mylabel") - .and() + .shortNames('v') + .type(boolean.class) + .description("some arg1") + .label("mylabel") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getDescription()).isEqualTo("help"); @@ -219,12 +220,13 @@ public void testOptionWithResolvableType() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg") - .type(rtype) - .and() + .longNames("arg") + .type(rtype) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getOptions()).hasSize(1); @@ -239,14 +241,14 @@ public void testOptionWithRequired() { .command("command1") .description("help") .withOption() - .shortNames('v') - .type(boolean.class) - .description("some arg1") - .required(true) - .and() + .shortNames('v') + .type(boolean.class) + .description("some arg1") + .required(true) + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getDescription()).isEqualTo("help"); @@ -258,14 +260,14 @@ public void testOptionWithRequired() { .command("command1") .description("help") .withOption() - .shortNames('v') - .type(boolean.class) - .description("some arg1") - .required(false) - .and() + .shortNames('v') + .type(boolean.class) + .description("some arg1") + .required(false) + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getOptions()).hasSize(1); @@ -275,13 +277,13 @@ public void testOptionWithRequired() { .command("command1") .description("help") .withOption() - .shortNames('v') - .type(boolean.class) - .description("some arg1") - .and() + .shortNames('v') + .type(boolean.class) + .description("some arg1") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getOptions()).hasSize(1); @@ -291,14 +293,14 @@ public void testOptionWithRequired() { .command("command1") .description("help") .withOption() - .shortNames('v') - .type(boolean.class) - .description("some arg1") - .required() - .and() + .shortNames('v') + .type(boolean.class) + .description("some arg1") + .required() + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getOptions()).hasSize(1); @@ -311,14 +313,14 @@ public void testOptionWithDefaultValue() { .command("command1") .description("help") .withOption() - .shortNames('v') - .type(boolean.class) - .description("some arg1") - .defaultValue("defaultValue") - .and() + .shortNames('v') + .type(boolean.class) + .description("some arg1") + .defaultValue("defaultValue") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getDescription()).isEqualTo("help"); @@ -331,15 +333,15 @@ public void testOptionWithPositionValue() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .position(1) - .and() + .longNames("arg1") + .position(1) + .and() .withOption() - .longNames("arg2") - .and() + .longNames("arg2") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getOptions()).hasSize(2); @@ -352,16 +354,17 @@ public void testArityViaInts() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .arity(0, 0) - .and() + .longNames("arg1") + .arity(0, 0) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); - assertThat(registration.getOptions()).hasSize(1); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(0); + assertThat(registration.getOptions()).hasSize(1); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(0); } @Test @@ -369,16 +372,17 @@ public void testArityViaEnum() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .arity(OptionArity.ZERO) - .and() + .longNames("arg1") + .arity(OptionArity.ZERO) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); - assertThat(registration.getOptions()).hasSize(1); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(0); + assertThat(registration.getOptions()).hasSize(1); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(0); } @Test @@ -386,16 +390,17 @@ public void testArityViaEnumSetNone() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .arity(OptionArity.NONE) - .and() + .longNames("arg1") + .arity(OptionArity.NONE) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); - assertThat(registration.getOptions()).hasSize(1); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(-1); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(-1); + assertThat(registration.getOptions()).hasSize(1); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(-1); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(-1); } @Test @@ -404,16 +409,16 @@ public void testAliases() { .command("command1") .group("Test Group") .withAlias() - .command("alias1") - .group("Alias Group") - .and() + .command("alias1") + .group("Alias Group") + .and() .withAlias() - .command("alias2") - .group("Alias Group") - .and() + .command("alias2") + .group("Alias Group") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getCommand()).isEqualTo("command1"); assertThat(registration.getGroup()).isEqualTo("Test Group"); @@ -427,26 +432,21 @@ public void testAliases() { @Test public void testExitCodes() { CommandRegistration registration; - registration = CommandRegistration.builder() - .command("command1") - .withTarget() - .function(function1) - .and() - .build(); + registration = CommandRegistration.builder().command("command1").withTarget().function(function1).and().build(); assertThat(registration.getExitCode()).isNotNull(); assertThat(registration.getExitCode().getMappingFunctions()).hasSize(0); registration = CommandRegistration.builder() .command("command1") .withExitCode() - .map(RuntimeException.class, 1) - .map(IllegalArgumentException.class, 2) - .map(e -> 1) - .map(e -> 2) - .and() + .map(RuntimeException.class, 1) + .map(IllegalArgumentException.class, 2) + .map(e -> 1) + .map(e -> 2) + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getExitCode()).isNotNull(); assertThat(registration.getExitCode().getMappingFunctions()).hasSize(4); @@ -455,12 +455,7 @@ public void testExitCodes() { @Test public void testAvailability() { CommandRegistration registration; - registration = CommandRegistration.builder() - .command("command1") - .withTarget() - .function(function1) - .and() - .build(); + registration = CommandRegistration.builder().command("command1").withTarget().function(function1).and().build(); assertThat(registration.getAvailability()).isNotNull(); assertThat(registration.getAvailability().isAvailable()).isTrue(); @@ -468,8 +463,8 @@ public void testAvailability() { .command("command1") .availability(() -> Availability.unavailable("fake")) .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getAvailability()).isNotNull(); assertThat(registration.getAvailability().isAvailable()).isFalse(); @@ -481,14 +476,14 @@ public void testOptionWithCompletion() { registration = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .completion(ctx -> { - return new ArrayList<>(); - }) - .and() + .longNames("arg1") + .completion(ctx -> { + return new ArrayList<>(); + }) + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getOptions()).hasSize(1); assertThat(registration.getOptions().get(0).getCompletion()).isNotNull(); @@ -506,21 +501,16 @@ public CommandHandlingResult resolve(Exception e) { registration = CommandRegistration.builder() .command("command1") .withErrorHandling() - .resolver(er1) - .and() + .resolver(er1) + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getExceptionResolvers()).hasSize(1); assertThat(registration.getExceptionResolvers().get(0)).isSameAs(er1); - registration = CommandRegistration.builder() - .command("command1") - .withTarget() - .function(function1) - .and() - .build(); + registration = CommandRegistration.builder().command("command1").withTarget().function(function1).and().build(); assertThat(registration.getExceptionResolvers()).hasSize(0); } @@ -529,8 +519,8 @@ public void testHidden() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.isHidden()).isFalse(); @@ -538,8 +528,8 @@ public void testHidden() { .command("command1") .hidden() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.isHidden()).isTrue(); @@ -547,8 +537,8 @@ public void testHidden() { .command("command1") .hidden(false) .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.isHidden()).isFalse(); @@ -556,8 +546,8 @@ public void testHidden() { .command("command1") .hidden(true) .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.isHidden()).isTrue(); } @@ -567,14 +557,14 @@ public void testHelpOption() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withHelpOptions() - .enabled(true) - .longNames(new String[] { "help" }) - .shortNames(new Character[] { 'h' }) - .command("help") - .and() + .enabled(true) + .longNames(new String[] { "help" }) + .shortNames(new Character[] { 'h' }) + .command("help") + .and() .withTarget() - .function(function1) - .and() + .function(function1) + .and() .build(); assertThat(registration.getOptions()).hasSize(1); @@ -587,12 +577,13 @@ void testOptionNameModifierInOption() { CommandRegistration registration = CommandRegistration.builder() .command("command1") .withOption() - .longNames("arg1") - .nameModifier(name -> "x" + name) - .and() + .longNames("arg1") + .nameModifier(name -> "x" + name) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); assertThat(registration.getOptions()).hasSize(1); @@ -608,11 +599,12 @@ void testOptionNameModifierFromDefault() { .defaultOptionNameModifier(name -> "x" + name) .command("command1") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); assertThat(registration.getOptions()).hasSize(1); @@ -628,14 +620,16 @@ void optionShouldBeSameInstance() { .defaultOptionNameModifier(name -> "x" + name) .command("command1") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); List options1 = registration.getOptions(); List options2 = registration.getOptions(); assertThat(options1).isEqualTo(options2); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolverTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolverTests.java index 1c8e3398d..a0c3d4ec0 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolverTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/ExceptionResolverMethodResolverTests.java @@ -30,9 +30,9 @@ void resolvesFromAnnotation() { ExceptionResolverMethodResolver resolver = new ExceptionResolverMethodResolver(InAnnotation.class); assertThat(resolver.hasExceptionMappings()).isTrue(); assertThat(resolver.resolveMethod(new RuntimeException())) - .isSameAs(ReflectionUtils.findMethod(InAnnotation.class, "errorHandler")); + .isSameAs(ReflectionUtils.findMethod(InAnnotation.class, "errorHandler")); assertThat(resolver.resolveMethod(new IOException())) - .isSameAs(ReflectionUtils.findMethod(InAnnotation.class, "errorHandler")); + .isSameAs(ReflectionUtils.findMethod(InAnnotation.class, "errorHandler")); } private static class InAnnotation { @@ -40,6 +40,7 @@ private static class InAnnotation { @ExceptionResolver({ RuntimeException.class, IOException.class }) void errorHandler() { } + } @Test @@ -47,9 +48,9 @@ void resolvesFromMethodParameters() { ExceptionResolverMethodResolver resolver = new ExceptionResolverMethodResolver(InMethodParameter.class); assertThat(resolver.hasExceptionMappings()).isTrue(); assertThat(resolver.resolveMethod(new RuntimeException())).isSameAs(ReflectionUtils - .findMethod(InMethodParameter.class, "errorHandler", RuntimeException.class, IOException.class)); + .findMethod(InMethodParameter.class, "errorHandler", RuntimeException.class, IOException.class)); assertThat(resolver.resolveMethod(new IOException())).isSameAs(ReflectionUtils - .findMethod(InMethodParameter.class, "errorHandler", RuntimeException.class, IOException.class)); + .findMethod(InMethodParameter.class, "errorHandler", RuntimeException.class, IOException.class)); } private static class InMethodParameter { @@ -57,6 +58,7 @@ private static class InMethodParameter { @ExceptionResolver void errorHandler(RuntimeException e1, IOException e2) { } + } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolverTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolverTests.java index b5db4d766..f7e98fd54 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolverTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/MethodCommandExceptionResolverTests.java @@ -44,6 +44,7 @@ CommandHandlingResult errorHandler(Exception e) { called = e; return CommandHandlingResult.of("Hi, handled exception\n", 42); } + } @Test @@ -65,6 +66,7 @@ CommandHandlingResult errorHandler() { called = true; return CommandHandlingResult.of("Hi, handled exception\n", 42); } + } @Test @@ -86,6 +88,7 @@ CommandHandlingResult errorHandler(CustomException1 e) { called = e; return CommandHandlingResult.of("Hi, handled exception\n", 42); } + } @Test @@ -101,6 +104,7 @@ private static class NoMappedExceptions { CommandHandlingResult errorHandler() { return RESULT; } + } @Test @@ -119,10 +123,13 @@ private static class ShouldErrorWhenResolving { CommandHandlingResult errorHandler(RuntimeException e1, IOException e2) { return RESULT; } + } private static CommandHandlingResult RESULT = CommandHandlingResult.of("Hi, handled exception\n", 42); private static class CustomException1 extends RuntimeException { + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java index c754d6e6e..2aa9b69a1 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandAnnotationUtilsTests.java @@ -27,20 +27,25 @@ class CommandAnnotationUtilsTests { private static MergedAnnotation hiddenTrue = MergedAnnotations.from(HiddenTrue.class).get(Command.class); + private static MergedAnnotation hiddenFalse = MergedAnnotations.from(HiddenFalse.class).get(Command.class); + private static MergedAnnotation hiddenDefault = MergedAnnotations.from(HiddenDefault.class) - .get(Command.class); + .get(Command.class); @Command(hidden = true) private static class HiddenTrue { + } @Command(hidden = false) private static class HiddenFalse { + } @Command() private static class HiddenDefault { + } @Test @@ -55,124 +60,151 @@ void testHidden() { } private static MergedAnnotation commandDefault = MergedAnnotations.from(CommandDefault.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation commandValues1 = MergedAnnotations.from(CommandValues1.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation commandValues2 = MergedAnnotations.from(CommandValues2.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation commandValues3 = MergedAnnotations.from(CommandValues3.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation commandValues4 = MergedAnnotations.from(CommandValues4.class) - .get(Command.class); + .get(Command.class); @Command private static class CommandDefault { + } @Command(command = { "one", "two" }) private static class CommandValues1 { + } @Command(command = { "three", "four" }) private static class CommandValues2 { + } @Command(command = { " five", "six ", " seven " }) private static class CommandValues3 { + } @Command(command = { " eight nine " }) private static class CommandValues4 { + } @Test void testCommand() { assertThat(CommandAnnotationUtils.deduceCommand(commandDefault, commandDefault)).isEmpty(); assertThat(CommandAnnotationUtils.deduceCommand(commandDefault, commandValues1)) - .isEqualTo(new String[] { "one", "two" }); + .isEqualTo(new String[] { "one", "two" }); assertThat(CommandAnnotationUtils.deduceCommand(commandValues1, commandValues2)) - .isEqualTo(new String[] { "one", "two", "three", "four" }); + .isEqualTo(new String[] { "one", "two", "three", "four" }); assertThat(CommandAnnotationUtils.deduceCommand(commandDefault, commandValues3)) - .isEqualTo(new String[] { "five", "six", "seven" }); + .isEqualTo(new String[] { "five", "six", "seven" }); assertThat(CommandAnnotationUtils.deduceCommand(commandDefault, commandValues4)) - .isEqualTo(new String[] { "eight", "nine" }); + .isEqualTo(new String[] { "eight", "nine" }); } private static MergedAnnotation aliasDefault = MergedAnnotations.from(AliasDefault.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation aliasValues1 = MergedAnnotations.from(AliasValues1.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation aliasValues2 = MergedAnnotations.from(AliasValues2.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation aliasValues3 = MergedAnnotations.from(AliasValues3.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation aliasValues4 = MergedAnnotations.from(AliasValues4.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation aliasValues5 = MergedAnnotations.from(AliasValues5.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation aliasValues6 = MergedAnnotations.from(AliasValues6.class) - .get(Command.class); + .get(Command.class); @Command private static class AliasDefault { + } @Command(alias = { "one", "two" }) private static class AliasValues1 { + } @Command(alias = { "three", "four" }) private static class AliasValues2 { + } @Command(alias = { " five", "six ", " seven " }) private static class AliasValues3 { + } @Command(alias = { " eight nine " }) private static class AliasValues4 { + } @Command(alias = { "one" }) private static class AliasValues5 { + } @Command(alias = { "" }) private static class AliasValues6 { + } @Test void testAlias() { assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasDefault)).isEmpty(); assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues1)) - .isEqualTo(new String[][] { { "one" }, { "two" } }); + .isEqualTo(new String[][] { { "one" }, { "two" } }); assertThat(CommandAnnotationUtils.deduceAlias(aliasValues1, aliasValues2)) - .isEqualTo(new String[][] { { "one", "two", "three" }, { "one", "two", "four" } }); + .isEqualTo(new String[][] { { "one", "two", "three" }, { "one", "two", "four" } }); assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues3)) - .isEqualTo(new String[][] { { "five" }, { "six" }, { "seven" } }); + .isEqualTo(new String[][] { { "five" }, { "six" }, { "seven" } }); assertThat(CommandAnnotationUtils.deduceAlias(aliasDefault, aliasValues4)) - .isEqualTo(new String[][] { { "eight nine" } }); + .isEqualTo(new String[][] { { "eight nine" } }); assertThat(CommandAnnotationUtils.deduceAlias(aliasValues5, aliasValues6)) - .isEqualTo(new String[][] { { "one" } }); + .isEqualTo(new String[][] { { "one" } }); } private static MergedAnnotation groupValue1 = MergedAnnotations.from(GroupValues1.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation groupValue2 = MergedAnnotations.from(GroupValues2.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation groupDefault = MergedAnnotations.from(GroupDefault.class) - .get(Command.class); + .get(Command.class); @Command(group = "group1") private static class GroupValues1 { + } @Command(group = "group2") private static class GroupValues2 { + } @Command() private static class GroupDefault { + } @Test @@ -184,88 +216,104 @@ void testGroup() { } private static MergedAnnotation descriptionValue1 = MergedAnnotations.from(DescriptionValues1.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation descriptionValue2 = MergedAnnotations.from(DescriptionValues2.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation descriptionDefault = MergedAnnotations.from(DescriptionDefault.class) - .get(Command.class); + .get(Command.class); @Command(description = "description1") private static class DescriptionValues1 { + } @Command(description = "description2") private static class DescriptionValues2 { + } @Command() private static class DescriptionDefault { + } @Test void testDescription() { assertThat(CommandAnnotationUtils.deduceDescription(descriptionDefault, descriptionDefault)).isEqualTo(""); assertThat(CommandAnnotationUtils.deduceDescription(descriptionDefault, descriptionValue1)) - .isEqualTo("description1"); + .isEqualTo("description1"); assertThat(CommandAnnotationUtils.deduceDescription(descriptionValue1, descriptionDefault)) - .isEqualTo("description1"); + .isEqualTo("description1"); assertThat(CommandAnnotationUtils.deduceDescription(descriptionValue1, descriptionValue2)) - .isEqualTo("description2"); + .isEqualTo("description2"); } private static MergedAnnotation interactionModeDefault = MergedAnnotations - .from(InteractionModeDefault.class).get(Command.class); + .from(InteractionModeDefault.class) + .get(Command.class); + private static MergedAnnotation interactionModeAll = MergedAnnotations.from(InteractionModeAll.class) - .get(Command.class); + .get(Command.class); + private static MergedAnnotation interactionModeInteractive = MergedAnnotations - .from(InteractionModeInteractive.class).get(Command.class); + .from(InteractionModeInteractive.class) + .get(Command.class); + private static MergedAnnotation interactionModeNoninteractive = MergedAnnotations - .from(InteractionModeNoninteractive.class).get(Command.class); + .from(InteractionModeNoninteractive.class) + .get(Command.class); @Command() private static class InteractionModeDefault { + } @Command(interactionMode = InteractionMode.ALL) private static class InteractionModeAll { + } @Command(interactionMode = InteractionMode.INTERACTIVE) private static class InteractionModeInteractive { + } @Command(interactionMode = InteractionMode.NONINTERACTIVE) private static class InteractionModeNoninteractive { + } @Test void testInteractionMode() { assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeDefault, interactionModeDefault)) - .isNull(); + .isNull(); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeAll, interactionModeDefault)) - .isEqualTo(InteractionMode.ALL); + .isEqualTo(InteractionMode.ALL); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeInteractive, interactionModeDefault)) - .isEqualTo(InteractionMode.INTERACTIVE); + .isEqualTo(InteractionMode.INTERACTIVE); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeNoninteractive, interactionModeDefault)) - .isEqualTo(InteractionMode.NONINTERACTIVE); + .isEqualTo(InteractionMode.NONINTERACTIVE); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeDefault, interactionModeAll)) - .isEqualTo(InteractionMode.ALL); + .isEqualTo(InteractionMode.ALL); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeDefault, interactionModeInteractive)) - .isEqualTo(InteractionMode.INTERACTIVE); + .isEqualTo(InteractionMode.INTERACTIVE); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeDefault, interactionModeNoninteractive)) - .isEqualTo(InteractionMode.NONINTERACTIVE); + .isEqualTo(InteractionMode.NONINTERACTIVE); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeAll, interactionModeInteractive)) - .isEqualTo(InteractionMode.INTERACTIVE); + .isEqualTo(InteractionMode.INTERACTIVE); assertThat(CommandAnnotationUtils.deduceInteractionMode(interactionModeAll, interactionModeNoninteractive)) - .isEqualTo(InteractionMode.NONINTERACTIVE); + .isEqualTo(InteractionMode.NONINTERACTIVE); assertThat( CommandAnnotationUtils.deduceInteractionMode(interactionModeInteractive, interactionModeNoninteractive)) - .isEqualTo(InteractionMode.NONINTERACTIVE); + .isEqualTo(InteractionMode.NONINTERACTIVE); assertThat( CommandAnnotationUtils.deduceInteractionMode(interactionModeNoninteractive, interactionModeInteractive)) - .isEqualTo(InteractionMode.INTERACTIVE); + .isEqualTo(InteractionMode.INTERACTIVE); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrarTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrarTests.java index 59efc8bc6..7ea194954 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrarTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationBeanRegistrarTests.java @@ -28,6 +28,7 @@ class CommandRegistrationBeanRegistrarTests { private final BeanDefinitionRegistry registry = new DefaultListableBeanFactory(); + private final CommandRegistrationBeanRegistrar registrar = new CommandRegistrationBeanRegistrar(registry); @Test @@ -41,9 +42,8 @@ void registerWhenNotAlreadyRegisteredAddBeanDefinition() { @Test void registerWhenNoAnnotationThrowsException() { - assertThatIllegalStateException() - .isThrownBy(() -> this.registrar.register(NoAnnotationCommand.class)) - .withMessageContaining("No Command annotation found"); + assertThatIllegalStateException().isThrownBy(() -> this.registrar.register(NoAnnotationCommand.class)) + .withMessageContaining("No Command annotation found"); } @Test @@ -59,6 +59,7 @@ void registerWhenNotAlreadyRegisteredAddMethodBeanDefinition() { @Command static class BeanCommand { + } @Command @@ -67,8 +68,11 @@ static class BeanWithMethodCommand { @Command void method() { } + } static class NoAnnotationCommand { + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java index 95263b736..f1550dd44 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/annotation/support/CommandRegistrationFactoryBeanTests.java @@ -37,94 +37,97 @@ class CommandRegistrationFactoryBeanTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + private final static String BEAN = "commandBean"; + private final static String FACTORYBEAN = "commandRegistrationFactoryBean"; + private final static String FACTORYBEANREF = "&" + FACTORYBEAN; @Test void hiddenOnClassLevel() { - configCommon(HiddenOnClassBean.class, new HiddenOnClassBean()) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.isHidden()).isTrue(); - }); + configCommon(HiddenOnClassBean.class, new HiddenOnClassBean()).run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.isHidden()).isTrue(); + }); } @Command(hidden = true) private static class HiddenOnClassBean { @Command - void command(){ + void command() { } + } @Test void commandCommonThings() { - configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(1); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); - assertThat(registration.getGroup()).isEqualTo("group2"); - }); - configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod(), "command2", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one three"); - assertThat(registration.getAliases()).hasSize(2); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); - assertThat(registration.getAliases().get(1).getCommand()).isEqualTo("three five"); - assertThat(registration.getGroup()).isEqualTo("group2"); - }); + configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod(), "command1", new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(1); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); + assertThat(registration.getGroup()).isEqualTo("group2"); + }); + configCommon(OnBothClassAndMethod.class, new OnBothClassAndMethod(), "command2", new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one three"); + assertThat(registration.getAliases()).hasSize(2); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); + assertThat(registration.getAliases().get(1).getCommand()).isEqualTo("three five"); + assertThat(registration.getGroup()).isEqualTo("group2"); + }); } @Command(command = "one", alias = "three", group = "group1") private static class OnBothClassAndMethod { @Command(command = "two", alias = "four", group = "group2") - void command1(){ + void command1() { } @Command(command = "three", alias = { "four", "five" }, group = "group2") - void command2(){ + void command2() { } + } @Test void setsRequiredOption() { configCommon(RequiredOption.class, new RequiredOption(), "command1", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions()).hasSize(1); - assertThat(registration.getOptions().get(0).isRequired()).isTrue(); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions()).hasSize(1); + assertThat(registration.getOptions().get(0).isRequired()).isTrue(); + }); configCommon(RequiredOption.class, new RequiredOption(), "command2", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions()).hasSize(1); - assertThat(registration.getOptions().get(0).isRequired()).isFalse(); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions()).hasSize(1); + assertThat(registration.getOptions().get(0).isRequired()).isFalse(); + }); } @Command @@ -137,20 +140,21 @@ void command1(@Option(required = true) String arg) { @Command void command2(@Option(required = false) String arg) { } + } @Test void setsAvailabilitySupplier() { - configCommon(AvailabilityIndicator.class, new AvailabilityIndicator(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getAvailability()).isNotNull(); - assertThat(registration.getAvailability().getReason()).isEqualTo("fakereason"); - }); + configCommon(AvailabilityIndicator.class, new AvailabilityIndicator(), "command1", new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getAvailability()).isNotNull(); + assertThat(registration.getAvailability().getReason()).isEqualTo("fakereason"); + }); } @Command @@ -165,63 +169,68 @@ void command1() { public AvailabilityProvider testAvailability() { return () -> Availability.unavailable("fakereason"); } - } + } @Test void setsOptionValuesWithBoolean() { - configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command1", new Class[] { boolean.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); - }); - configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command2", new Class[] { Boolean.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); - }); - configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command3", new Class[] { Boolean.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); - }); - configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command4", new Class[] { Boolean.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); - }); - configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command5", new Class[] { boolean.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); - assertThat(registration.getOptions().get(0).isRequired()).isFalse(); - assertThat(registration.getOptions().get(0).getDefaultValue()).isEqualTo("false"); - }); + configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command1", + new Class[] { boolean.class }) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); + }); + configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command2", + new Class[] { Boolean.class }) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); + }); + configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command3", + new Class[] { Boolean.class }) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); + }); + configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command4", + new Class[] { Boolean.class }) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); + }); + configCommon(OptionValuesWithBoolean.class, new OptionValuesWithBoolean(), "command5", + new Class[] { boolean.class }) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); + assertThat(registration.getOptions().get(0).isRequired()).isFalse(); + assertThat(registration.getOptions().get(0).getDefaultValue()).isEqualTo("false"); + }); } @Command @@ -246,19 +255,20 @@ void command4(Boolean arg) { @Command void command5(boolean arg) { } + } @Test void setsOptionWithCompletion() { configCommon(OptionWithCompletion.class, new OptionWithCompletion(), "command1", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getCompletion()).isNotNull(); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getCompletion()).isNotNull(); + }); } @Command @@ -280,45 +290,45 @@ CompletionProvider completionProvider() { @Test void setsOptionWithArity() { configCommon(OptionWithArity.class, new OptionWithArity(), "command1", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(1); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(1); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); + }); configCommon(OptionWithArity.class, new OptionWithArity(), "command2", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(1); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(1); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1); + }); configCommon(OptionWithArity.class, new OptionWithArity(), "command3", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(2); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(2); + }); configCommon(OptionWithArity.class, new OptionWithArity(), "command4", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); - assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(2); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0); + assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(2); + }); } @Command @@ -339,19 +349,20 @@ void command3(@Option(longNames = "arg", arityMax = 2) String arg) { @Command void command4(@Option(longNames = "arg", arityMax = 2, arity = OptionArity.EXACTLY_ONE) String arg) { } + } @Test void setsOptionWithLabel() { configCommon(OptionWithLabel.class, new OptionWithLabel(), "command1", new Class[] { String.class }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getOptions().get(0).getLabel()).isEqualTo("label"); - }); + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getOptions().get(0).getLabel()).isEqualTo("label"); + }); } @Command @@ -360,6 +371,7 @@ private static class OptionWithLabel { @Command void command1(@Option(longNames = "arg", label = "label") String arg) { } + } private ApplicationContextRunner configCommon(Class type, T bean) { @@ -367,14 +379,15 @@ private ApplicationContextRunner configCommon(Class type, T bean) { } private ApplicationContextRunner configCommon(Class type, T bean, String method, Class[] parameters) { - return this.contextRunner - .withBean(BEAN, type, () -> bean) - .withBean(FACTORYBEAN, CommandRegistrationFactoryBean.class, () -> new CommandRegistrationFactoryBean(), bd -> { - bd.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_BEAN_TYPE, type); - bd.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_BEAN_NAME, BEAN); - bd.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_METHOD_NAME, method); - bd.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_METHOD_PARAMETERS, parameters); - }); + return this.contextRunner.withBean(BEAN, type, () -> bean) + .withBean(FACTORYBEAN, CommandRegistrationFactoryBean.class, () -> new CommandRegistrationFactoryBean(), + bd -> { + bd.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_BEAN_TYPE, type); + bd.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_BEAN_NAME, BEAN); + bd.getPropertyValues().add(CommandRegistrationFactoryBean.COMMAND_METHOD_NAME, method); + bd.getPropertyValues() + .add(CommandRegistrationFactoryBean.COMMAND_METHOD_PARAMETERS, parameters); + }); } @Nested @@ -382,178 +395,188 @@ class Aliases { @Test void aliasOnlyOnMethod() { - configCommon(AliasOnlyOnMethod.class, new AliasOnlyOnMethod(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(1); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("four"); - }); + configCommon(AliasOnlyOnMethod.class, new AliasOnlyOnMethod(), "command1", new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(1); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("four"); + }); } @Command(command = "one") private static class AliasOnlyOnMethod { @Command(command = "two", alias = "four") - void command1(){ + void command1() { } + } @Test void aliasOnlyOnClass() { - configCommon(AliasOnlyOnClass.class, new AliasOnlyOnClass(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(0); - }); + configCommon(AliasOnlyOnClass.class, new AliasOnlyOnClass(), "command1", new Class[] {}).run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(0); + }); } @Command(command = "one", alias = "three") private static class AliasOnlyOnClass { @Command(command = "two") - void command1(){ + void command1() { } + } @Test void aliasOnlyOnMethodMultiCommandString() { - configCommon(AliasOnlyOnMethodMultiCommandString.class, new AliasOnlyOnMethodMultiCommandString(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(1); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("four five"); - }); + configCommon(AliasOnlyOnMethodMultiCommandString.class, new AliasOnlyOnMethodMultiCommandString(), + "command1", new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(1); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("four five"); + }); } @Command(command = "one") private static class AliasOnlyOnMethodMultiCommandString { @Command(command = "two", alias = "four five") - void command1(){ + void command1() { } + } @Test void aliasOnlyOnMethodMultiCommandArray() { - configCommon(AliasOnlyOnMethodMultiCommandArray.class, new AliasOnlyOnMethodMultiCommandArray(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(2); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("four"); - assertThat(registration.getAliases().get(1).getCommand()).isEqualTo("five"); - }); + configCommon(AliasOnlyOnMethodMultiCommandArray.class, new AliasOnlyOnMethodMultiCommandArray(), "command1", + new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(2); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("four"); + assertThat(registration.getAliases().get(1).getCommand()).isEqualTo("five"); + }); } @Command(command = "one") private static class AliasOnlyOnMethodMultiCommandArray { - @Command(command = "two", alias = {"four", "five"}) - void command1(){ + @Command(command = "two", alias = { "four", "five" }) + void command1() { } + } @Test void aliasOnBothMethodStringEmpty() { - configCommon(AliasOnBothMethodStringEmpty.class, new AliasOnBothMethodStringEmpty(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(1); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three"); - }); + configCommon(AliasOnBothMethodStringEmpty.class, new AliasOnBothMethodStringEmpty(), "command1", + new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(1); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three"); + }); } @Command(command = "one", alias = "three") private static class AliasOnBothMethodStringEmpty { @Command(command = "two", alias = "") - void command1(){ + void command1() { } + } @Test void aliasOnBoth() { - configCommon(AliasOnBoth.class, new AliasOnBoth(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(1); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); - }); + configCommon(AliasOnBoth.class, new AliasOnBoth(), "command1", new Class[] {}).run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(1); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("three four"); + }); } @Command(command = "one", alias = "three") private static class AliasOnBoth { @Command(command = "two", alias = "four") - void command1(){ + void command1() { } + } @Test void aliasWithCommandOnBothMethodStringEmpty() { - configCommon(AliasWithCommandOnBothMethodStringEmpty.class, new AliasWithCommandOnBothMethodStringEmpty(), "command1", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one"); - assertThat(registration.getAliases()).hasSize(1); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("ten"); - }); - configCommon(AliasWithCommandOnBothMethodStringEmpty.class, new AliasWithCommandOnBothMethodStringEmpty(), "command2", new Class[] { }) - .run((context) -> { - CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, - CommandRegistrationFactoryBean.class); - assertThat(fb).isNotNull(); - CommandRegistration registration = fb.getObject(); - assertThat(registration).isNotNull(); - assertThat(registration.getCommand()).isEqualTo("one two"); - assertThat(registration.getAliases()).hasSize(1); - assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("ten twelve"); - }); + configCommon(AliasWithCommandOnBothMethodStringEmpty.class, new AliasWithCommandOnBothMethodStringEmpty(), + "command1", new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one"); + assertThat(registration.getAliases()).hasSize(1); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("ten"); + }); + configCommon(AliasWithCommandOnBothMethodStringEmpty.class, new AliasWithCommandOnBothMethodStringEmpty(), + "command2", new Class[] {}) + .run((context) -> { + CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF, + CommandRegistrationFactoryBean.class); + assertThat(fb).isNotNull(); + CommandRegistration registration = fb.getObject(); + assertThat(registration).isNotNull(); + assertThat(registration.getCommand()).isEqualTo("one two"); + assertThat(registration.getAliases()).hasSize(1); + assertThat(registration.getAliases().get(0).getCommand()).isEqualTo("ten twelve"); + }); } @Command(command = "one", alias = "ten") private static class AliasWithCommandOnBothMethodStringEmpty { @Command(command = "", alias = "") - void command1(){ + void command1() { } @Command(command = "two", alias = "twelve") - void command2(){ + void command2() { } + } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/invocation/InvocableShellMethodTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/invocation/InvocableShellMethodTests.java index 30ae665a7..2f602fa48 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/invocation/InvocableShellMethodTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/invocation/InvocableShellMethodTests.java @@ -40,5 +40,7 @@ private static class Handler { public String handle(Integer intArg, String stringArg) { return intArg + "-" + stringArg; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AbstractParsingTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AbstractParsingTests.java index fe5b2a580..4fcb3a5b7 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AbstractParsingTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AbstractParsingTests.java @@ -33,297 +33,322 @@ abstract class AbstractParsingTests { static final CommandRegistration ROOT1 = CommandRegistration.builder() .command("root1") .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT1_UP = CommandRegistration.builder() .command("ROOT1") .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT2 = CommandRegistration.builder() .command("root2") .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT2_SUB1 = CommandRegistration.builder() - .command("root2", "sub1") - .withOption() - .longNames("arg1") - .and() - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + .command("root2", "sub1") + .withOption() + .longNames("arg1") + .and() + .withTarget() + .consumer(ctx -> { + }) + .and() + .build(); static final CommandRegistration ROOT2_SUB2 = CommandRegistration.builder() - .command("root2", "sub2") - .withOption() - .longNames("arg1") - .and() - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + .command("root2", "sub2") + .withOption() + .longNames("arg1") + .and() + .withTarget() + .consumer(ctx -> { + }) + .and() + .build(); static final CommandRegistration ROOT2_SUB1_SUB2 = CommandRegistration.builder() - .command("root2", "sub1", "sub2") - .withOption() - .longNames("arg1") - .and() - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + .command("root2", "sub1", "sub2") + .withOption() + .longNames("arg1") + .and() + .withTarget() + .consumer(ctx -> { + }) + .and() + .build(); static final CommandRegistration ROOT2_SUB1_SUB3 = CommandRegistration.builder() - .command("root2", "sub1", "sub3") - .withOption() - .longNames("arg1") - .and() - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + .command("root2", "sub1", "sub3") + .withOption() + .longNames("arg1") + .and() + .withTarget() + .consumer(ctx -> { + }) + .and() + .build(); static final CommandRegistration ROOT2_SUB1_SUB4 = CommandRegistration.builder() - .command("root2", "sub1", "sub4") - .withOption() - .longNames("arg1") - .and() - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + .command("root2", "sub1", "sub4") + .withOption() + .longNames("arg1") + .and() + .withTarget() + .consumer(ctx -> { + }) + .and() + .build(); static final CommandRegistration ROOT3 = CommandRegistration.builder() .command("root3") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT3_OPTION_ARG1_ARG2 = CommandRegistration.builder() .command("root3") .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withOption() - .longNames("arg2") - .and() + .longNames("arg2") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT3_SHORT_OPTION_A = CommandRegistration.builder() .command("root3") .withOption() - .shortNames('a') - .and() + .shortNames('a') + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT3_SHORT_OPTION_A_B = CommandRegistration.builder() .command("root3") .withOption() - .shortNames('a') - .and() + .shortNames('a') + .and() .withOption() - .shortNames('b') - .and() + .shortNames('b') + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT3_SHORT_OPTION_A_B_REQUIRED = CommandRegistration.builder() .command("root3") .withOption() - .shortNames('a') - .required() - .and() + .shortNames('a') + .required() + .and() .withOption() - .required() - .shortNames('b') - .and() + .required() + .shortNames('b') + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT4 = CommandRegistration.builder() .command("root4") .withOption() - .longNames("arg1") - .required() - .and() + .longNames("arg1") + .required() + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT5 = CommandRegistration.builder() .command("root5") .withOption() - .longNames("arg1") - .required() - .and() + .longNames("arg1") + .required() + .and() .withOption() - .longNames("arg2") - .required() - .and() + .longNames("arg2") + .required() + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT6_OPTION_INT = CommandRegistration.builder() .command("root6") .withOption() - .longNames("arg1") - .type(int.class) - .required() - .and() + .longNames("arg1") + .type(int.class) + .required() + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT6_OPTION_INTARRAY = CommandRegistration.builder() .command("root6") .withOption() - .longNames("arg1") - .type(int[].class) - .required() - .and() + .longNames("arg1") + .type(int[].class) + .required() + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT6_OPTION_DEFAULT_VALUE = CommandRegistration.builder() .command("root6") .withOption() - .longNames("arg1") - .defaultValue("defaultvalue") - .and() + .longNames("arg1") + .defaultValue("defaultvalue") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT7_POSITIONAL_ONE_ARG_STRING = CommandRegistration.builder() .command("root7") .withOption() - .longNames("arg1") - .type(String.class) - .position(0) - .and() + .longNames("arg1") + .type(String.class) + .position(0) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT7_POSITIONAL_TWO_ARG_STRING = CommandRegistration.builder() .command("root7") .withOption() - .longNames("arg1") - .type(String.class) - .position(0) - .and() + .longNames("arg1") + .type(String.class) + .position(0) + .and() .withOption() - .longNames("arg2") - .type(String.class) - .position(1) - .and() + .longNames("arg2") + .type(String.class) + .position(1) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT7_POSITIONAL_ONE_ARG_STRING_DEFAULT = CommandRegistration.builder() .command("root7") .withOption() - .longNames("arg1") - .defaultValue("arg1default") - .type(String.class) - .position(0) - .and() + .longNames("arg1") + .defaultValue("arg1default") + .type(String.class) + .position(0) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT7_POSITIONAL_TWO_ARG_STRING_DEFAULT = CommandRegistration.builder() .command("root7") .withOption() - .longNames("arg1") - .defaultValue("arg1default") - .type(String.class) - .arity(OptionArity.EXACTLY_ONE) - .position(0) - .and() + .longNames("arg1") + .defaultValue("arg1default") + .type(String.class) + .arity(OptionArity.EXACTLY_ONE) + .position(0) + .and() .withOption() - .longNames("arg2") - .defaultValue("arg2default") - .type(String.class) - .arity(OptionArity.EXACTLY_ONE) - .position(1) - .and() + .longNames("arg2") + .defaultValue("arg2default") + .type(String.class) + .arity(OptionArity.EXACTLY_ONE) + .position(1) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); - static final CommandRegistration ROOT7_POSITIONAL_TWO_ARG_STRING_DEFAULT_ONE_NODEFAULT = CommandRegistration.builder() + static final CommandRegistration ROOT7_POSITIONAL_TWO_ARG_STRING_DEFAULT_ONE_NODEFAULT = CommandRegistration + .builder() .command("root7") .withOption() - .longNames("arg1") - .defaultValue("arg1default") - .type(String.class) - .arity(OptionArity.EXACTLY_ONE) - .position(0) - .and() + .longNames("arg1") + .defaultValue("arg1default") + .type(String.class) + .arity(OptionArity.EXACTLY_ONE) + .position(0) + .and() .withOption() - .longNames("arg2") - .defaultValue("arg2default") - .type(String.class) - .arity(OptionArity.EXACTLY_ONE) - .position(1) - .and() + .longNames("arg2") + .defaultValue("arg2default") + .type(String.class) + .arity(OptionArity.EXACTLY_ONE) + .position(1) + .and() .withOption() - .longNames("arg3") - .type(String.class) - .arity(OptionArity.EXACTLY_ONE) - .position(2) - .and() + .longNames("arg3") + .type(String.class) + .arity(OptionArity.EXACTLY_ONE) + .position(2) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); static final CommandRegistration ROOT8_ONE_ARG_ARITYEONE_STRING = CommandRegistration.builder() .command("root8") .withOption() - .longNames("arg1") - .type(String.class) - .arity(OptionArity.EXACTLY_ONE) - .position(0) - .and() + .longNames("arg1") + .type(String.class) + .arity(OptionArity.EXACTLY_ONE) + .position(0) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); Map registrations = new HashMap<>(); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AstTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AstTests.java index 798322458..f84f28120 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AstTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/AstTests.java @@ -35,12 +35,11 @@ void createsCommandNode() { AstResult result = ast(root1); assertThat(result).isNotNull(); - assertThat(result.nonterminalNodes()).satisfiesExactly( - node -> { - assertThat(node).isInstanceOf(CommandNode.class); - CommandNode cn = (CommandNode)node; - assertThat(cn.getCommand()).isEqualTo("root1"); - }); + assertThat(result.nonterminalNodes()).satisfiesExactly(node -> { + assertThat(node).isInstanceOf(CommandNode.class); + CommandNode cn = (CommandNode) node; + assertThat(cn.getCommand()).isEqualTo("root1"); + }); } @Test @@ -54,36 +53,28 @@ void createsMultipleCommandNodes() { AstResult result = ast(root1, sub1, sub2, arg1, value1); assertThat(result).isNotNull(); - assertThat(result.nonterminalNodes()).satisfiesExactly( - n1 -> { - assertThat(n1).isInstanceOf(CommandNode.class); - CommandNode cn1 = (CommandNode)n1; - assertThat(cn1.getCommand()).isEqualTo("root1"); - assertThat(cn1.getChildren()).satisfiesExactly( - n2 -> { - assertThat(n2).isInstanceOf(CommandNode.class); - CommandNode cn2 = (CommandNode)n2; - assertThat(cn2.getCommand()).isEqualTo("sub1"); - assertThat(cn2.getChildren()).satisfiesExactly( - n3 -> { - assertThat(n3).isInstanceOf(CommandNode.class); - CommandNode cn3 = (CommandNode)n3; - assertThat(cn3.getCommand()).isEqualTo("sub2"); - assertThat(cn3.getChildren()).satisfiesExactly( - n4 -> { - assertThat(n4).isInstanceOf(OptionNode.class); - OptionNode on4 = (OptionNode)n4; - assertThat(on4.getChildren()).satisfiesExactly( - n5 -> { - assertThat(n5).isInstanceOf(OptionArgumentNode.class); - } - ); - } - ); - } - ); + assertThat(result.nonterminalNodes()).satisfiesExactly(n1 -> { + assertThat(n1).isInstanceOf(CommandNode.class); + CommandNode cn1 = (CommandNode) n1; + assertThat(cn1.getCommand()).isEqualTo("root1"); + assertThat(cn1.getChildren()).satisfiesExactly(n2 -> { + assertThat(n2).isInstanceOf(CommandNode.class); + CommandNode cn2 = (CommandNode) n2; + assertThat(cn2.getCommand()).isEqualTo("sub1"); + assertThat(cn2.getChildren()).satisfiesExactly(n3 -> { + assertThat(n3).isInstanceOf(CommandNode.class); + CommandNode cn3 = (CommandNode) n3; + assertThat(cn3.getCommand()).isEqualTo("sub2"); + assertThat(cn3.getChildren()).satisfiesExactly(n4 -> { + assertThat(n4).isInstanceOf(OptionNode.class); + OptionNode on4 = (OptionNode) n4; + assertThat(on4.getChildren()).satisfiesExactly(n5 -> { + assertThat(n5).isInstanceOf(OptionArgumentNode.class); + }); }); + }); }); + }); } @Test @@ -97,15 +88,12 @@ void createsOptionNodeNoOptionArg() { assertThat(result.nonterminalNodes()).hasSize(1); assertThat(result.nonterminalNodes().get(0)).isInstanceOf(CommandNode.class); assertThat(result.nonterminalNodes().get(0)).satisfies(n -> { - CommandNode cn = (CommandNode)n; + CommandNode cn = (CommandNode) n; assertThat(cn.getCommand()).isEqualTo("root3"); assertThat(cn.getChildren()).hasSize(1); - assertThat(cn.getChildren()) - .filteredOn(on -> on instanceof OptionNode) - .extracting(on -> { - return ((OptionNode)on).getName(); - }) - .containsExactly("--arg1"); + assertThat(cn.getChildren()).filteredOn(on -> on instanceof OptionNode).extracting(on -> { + return ((OptionNode) on).getName(); + }).containsExactly("--arg1"); }); } @@ -121,15 +109,12 @@ void createsOptionNodeWithOptionArg() { assertThat(result.nonterminalNodes()).hasSize(1); assertThat(result.nonterminalNodes().get(0)).isInstanceOf(CommandNode.class); assertThat(result.nonterminalNodes().get(0)).satisfies(n -> { - CommandNode cn = (CommandNode)n; + CommandNode cn = (CommandNode) n; assertThat(cn.getCommand()).isEqualTo("root3"); assertThat(cn.getChildren()).hasSize(1); - assertThat(cn.getChildren()) - .filteredOn(on -> on instanceof OptionNode) - .extracting(on -> { - return ((OptionNode)on).getName(); - }) - .containsExactly("--arg1"); + assertThat(cn.getChildren()).filteredOn(on -> on instanceof OptionNode).extracting(on -> { + return ((OptionNode) on).getName(); + }).containsExactly("--arg1"); OptionNode on = (OptionNode) cn.getChildren().get(0); assertThat(on.getChildren()).hasSize(1); OptionArgumentNode oan = (OptionArgumentNode) on.getChildren().get(0); @@ -151,15 +136,12 @@ void createsOptionNodesWithTwoOptionArg() { assertThat(result.nonterminalNodes()).hasSize(1); assertThat(result.nonterminalNodes().get(0)).isInstanceOf(CommandNode.class); assertThat(result.nonterminalNodes().get(0)).satisfies(n -> { - CommandNode cn = (CommandNode)n; + CommandNode cn = (CommandNode) n; assertThat(cn.getCommand()).isEqualTo("root3"); assertThat(cn.getChildren()).hasSize(2); - assertThat(cn.getChildren()) - .filteredOn(on -> on instanceof OptionNode) - .extracting(on -> { - return ((OptionNode)on).getName(); - }) - .containsExactly("--arg1", "--arg2"); + assertThat(cn.getChildren()).filteredOn(on -> on instanceof OptionNode).extracting(on -> { + return ((OptionNode) on).getName(); + }).containsExactly("--arg1", "--arg2"); OptionNode on1 = (OptionNode) cn.getChildren().get(0); assertThat(on1.getChildren()).hasSize(1); OptionArgumentNode oan1 = (OptionArgumentNode) on1.getChildren().get(0); @@ -183,15 +165,12 @@ void createsOptionNodeWithShortOptionArg() { assertThat(result.nonterminalNodes()).hasSize(1); assertThat(result.nonterminalNodes().get(0)).isInstanceOf(CommandNode.class); assertThat(result.nonterminalNodes().get(0)).satisfies(n -> { - CommandNode cn = (CommandNode)n; + CommandNode cn = (CommandNode) n; assertThat(cn.getCommand()).isEqualTo("root3"); assertThat(cn.getChildren()).hasSize(1); - assertThat(cn.getChildren()) - .filteredOn(on -> on instanceof OptionNode) - .extracting(on -> { - return ((OptionNode)on).getName(); - }) - .containsExactly("-a"); + assertThat(cn.getChildren()).filteredOn(on -> on instanceof OptionNode).extracting(on -> { + return ((OptionNode) on).getName(); + }).containsExactly("-a"); OptionNode on = (OptionNode) cn.getChildren().get(0); assertThat(on.getChildren()).hasSize(1); OptionArgumentNode oan = (OptionArgumentNode) on.getChildren().get(0); @@ -213,15 +192,12 @@ void createsOptionNodesWithTwoShortOptionArg() { assertThat(result.nonterminalNodes()).hasSize(1); assertThat(result.nonterminalNodes().get(0)).isInstanceOf(CommandNode.class); assertThat(result.nonterminalNodes().get(0)).satisfies(n -> { - CommandNode cn = (CommandNode)n; + CommandNode cn = (CommandNode) n; assertThat(cn.getCommand()).isEqualTo("root3"); assertThat(cn.getChildren()).hasSize(2); - assertThat(cn.getChildren()) - .filteredOn(on -> on instanceof OptionNode) - .extracting(on -> { - return ((OptionNode)on).getName(); - }) - .containsExactly("-a", "-b"); + assertThat(cn.getChildren()).filteredOn(on -> on instanceof OptionNode).extracting(on -> { + return ((OptionNode) on).getName(); + }).containsExactly("-a", "-b"); OptionNode on1 = (OptionNode) cn.getChildren().get(0); assertThat(on1.getChildren()).hasSize(1); OptionArgumentNode oan1 = (OptionArgumentNode) on1.getChildren().get(0); @@ -245,15 +221,12 @@ void createOptionNodesWhenNoOptionArguments() { assertThat(result.nonterminalNodes()).hasSize(1); assertThat(result.nonterminalNodes().get(0)).isInstanceOf(CommandNode.class); assertThat(result.nonterminalNodes().get(0)).satisfies(n -> { - CommandNode cn = (CommandNode)n; + CommandNode cn = (CommandNode) n; assertThat(cn.getCommand()).isEqualTo("root3"); assertThat(cn.getChildren()).hasSize(2); - assertThat(cn.getChildren()) - .filteredOn(on -> on instanceof OptionNode) - .extracting(on -> { - return ((OptionNode)on).getName(); - }) - .containsExactly("--arg1", "--arg2"); + assertThat(cn.getChildren()).filteredOn(on -> on instanceof OptionNode).extracting(on -> { + return ((OptionNode) on).getName(); + }).containsExactly("--arg1", "--arg2"); }); } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/CommandModelTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/CommandModelTests.java index eb0180701..9d30b20dc 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/CommandModelTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/CommandModelTests.java @@ -48,9 +48,8 @@ void oneRootCommand() { @Test void oneRootCommandCaseInsensitive() { register(ROOT1_UP); - ParserConfig configuration = new ParserConfig() - .disable(Feature.CASE_SENSITIVE_COMMANDS) - .disable(Feature.CASE_SENSITIVE_OPTIONS); + ParserConfig configuration = new ParserConfig().disable(Feature.CASE_SENSITIVE_COMMANDS) + .disable(Feature.CASE_SENSITIVE_OPTIONS); CommandModel model = commandModel(configuration); Map tokens = model.getValidRootTokens(); @@ -80,12 +79,11 @@ void onePlainSubCommand() { assertThat(root1).isNotNull(); assertThat(root1.getChildren()).hasSize(1); assertThat(root1.registration).isNull(); - assertThat(root1.getChildren()).satisfiesExactly( - sub1 -> { - assertThat(sub1).isNotNull(); - assertThat(sub1.getChildren()).isEmpty(); - assertThat(sub1.registration).isNotNull(); - }); + assertThat(root1.getChildren()).satisfiesExactly(sub1 -> { + assertThat(sub1).isNotNull(); + assertThat(sub1.getChildren()).isEmpty(); + assertThat(sub1.registration).isNotNull(); + }); }); } @@ -117,19 +115,17 @@ void onePlainSubCommand2() { assertThat(token.getType()).isEqualTo(TokenType.COMMAND); }); }); - assertThat(root1.getChildren()).satisfiesExactlyInAnyOrder( - sub1 -> { - assertThat(sub1.command).isEqualTo("sub1"); - assertThat(sub1).isNotNull(); - assertThat(sub1.getChildren()).isEmpty(); - assertThat(sub1.registration).isNotNull(); - }, - sub2 -> { - assertThat(sub2.command).isEqualTo("sub2"); - assertThat(sub2).isNotNull(); - assertThat(sub2.getChildren()).isEmpty(); - assertThat(sub2.registration).isNotNull(); - }); + assertThat(root1.getChildren()).satisfiesExactlyInAnyOrder(sub1 -> { + assertThat(sub1.command).isEqualTo("sub1"); + assertThat(sub1).isNotNull(); + assertThat(sub1.getChildren()).isEmpty(); + assertThat(sub1.registration).isNotNull(); + }, sub2 -> { + assertThat(sub2.command).isEqualTo("sub2"); + assertThat(sub2).isNotNull(); + assertThat(sub2.getChildren()).isEmpty(); + assertThat(sub2.registration).isNotNull(); + }); }); } @@ -159,25 +155,19 @@ void onePlainSubCommand3() { assertThat(token.getType()).isEqualTo(TokenType.COMMAND); }); }); - assertThat(root1.getChildren()).satisfiesExactlyInAnyOrder( - sub1 -> { - assertThat(sub1.command).isEqualTo("sub1"); - assertThat(sub1.getChildren()).satisfiesExactlyInAnyOrder( - sub2 -> { - assertThat(sub2.getChildren()).isEmpty(); - }, - sub3 -> { - assertThat(sub3.getChildren()).isEmpty(); - }, - sub4 -> { - assertThat(sub4.getChildren()).isEmpty(); - } - ); - // assertThat(sub1).isNotNull(); - // assertThat(sub1.getChildren()).isEmpty(); - // assertThat(sub1.registration).isNotNull(); - } - ); + assertThat(root1.getChildren()).satisfiesExactlyInAnyOrder(sub1 -> { + assertThat(sub1.command).isEqualTo("sub1"); + assertThat(sub1.getChildren()).satisfiesExactlyInAnyOrder(sub2 -> { + assertThat(sub2.getChildren()).isEmpty(); + }, sub3 -> { + assertThat(sub3.getChildren()).isEmpty(); + }, sub4 -> { + assertThat(sub4.getChildren()).isEmpty(); + }); + // assertThat(sub1).isNotNull(); + // assertThat(sub1.getChildren()).isEmpty(); + // assertThat(sub1.registration).isNotNull(); + }); }); } @@ -195,10 +185,9 @@ void shouldResolveParentCommand() { register(ROOT2_SUB1_SUB2); CommandModel model = commandModel(); - assertThat(model.resolve(Arrays.asList("root2"))).satisfies( - info -> { - assertThat(info.registration).isNotNull(); - } - ); + assertThat(model.resolve(Arrays.asList("root2"))).satisfies(info -> { + assertThat(info.registration).isNotNull(); + }); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/LexerTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/LexerTests.java index 87f633d35..cc6022d54 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/LexerTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/LexerTests.java @@ -42,16 +42,12 @@ void rootCommandNoOptions() { register(ROOT1); List tokens = tokenize("root1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root1"); + }); } - } + } @Nested class CaseSensitivity { @@ -59,54 +55,43 @@ class CaseSensitivity { @Test void commandRegUpperCommandLower() { register(ROOT1_UP); - ParserConfig config = new ParserConfig() - .disable(Feature.CASE_SENSITIVE_COMMANDS) - .disable(Feature.CASE_SENSITIVE_OPTIONS); + ParserConfig config = new ParserConfig().disable(Feature.CASE_SENSITIVE_COMMANDS) + .disable(Feature.CASE_SENSITIVE_OPTIONS); List tokens = tokenize(lexer(config), "root1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root1"); + }); } @Test void commandRegLowerCommandUpper() { register(ROOT1); - ParserConfig config = new ParserConfig() - .disable(Feature.CASE_SENSITIVE_COMMANDS) - .disable(Feature.CASE_SENSITIVE_OPTIONS); + ParserConfig config = new ParserConfig().disable(Feature.CASE_SENSITIVE_COMMANDS) + .disable(Feature.CASE_SENSITIVE_OPTIONS); List tokens = tokenize(lexer(config), "Root1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("Root1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("Root1"); + }); } } - // @Test // void commandWithCaseInsensitiveInArguments() { - // register(ROOT1); - // ParserConfig configuration = new ParserConfig() - // .setOptionsCaseSensitive(false); - // List tokens = tokenize(lexer(configuration), "ROOT1"); - - // assertThat(tokens).satisfiesExactly( - // token -> { - // ParserAssertions.assertThat(token) - // .isType(TokenType.COMMAND) - // .hasPosition(0) - // .hasValue("ROOT1"); - // }); + // register(ROOT1); + // ParserConfig configuration = new ParserConfig() + // .setOptionsCaseSensitive(false); + // List tokens = tokenize(lexer(configuration), "ROOT1"); + + // assertThat(tokens).satisfiesExactly( + // token -> { + // ParserAssertions.assertThat(token) + // .isType(TokenType.COMMAND) + // .hasPosition(0) + // .hasValue("ROOT1"); + // }); // } @Test @@ -115,13 +100,9 @@ void rootCommandWithChildGetsRootForRoot() { register(ROOT2_SUB1); List tokens = tokenize("root1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root1"); + }); } @Test @@ -129,19 +110,11 @@ void subCommandLevel1WithoutRoot() { register(ROOT2_SUB1); List tokens = tokenize("root2", "sub1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root2"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(1) - .hasValue("sub1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root2"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(1).hasValue("sub1"); + }); } @Test @@ -149,25 +122,13 @@ void subCommandLevel2WithoutRoot() { register(ROOT2_SUB1_SUB2); List tokens = tokenize("root2", "sub1", "sub2"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root2"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(1) - .hasValue("sub1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(2) - .hasValue("sub2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root2"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(1).hasValue("sub1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(2).hasValue("sub2"); + }); } @Test @@ -175,37 +136,17 @@ void subCommandLevel2WithoutRootWithOption() { register(ROOT2_SUB1_SUB2); List tokens = tokenize("root2", "sub1", "sub2", "--arg1", "xxx"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root2"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(1) - .hasValue("sub1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(2) - .hasValue("sub2"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(3) - .hasValue("--arg1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.ARGUMENT) - .hasPosition(4) - .hasValue("xxx"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root2"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(1).hasValue("sub1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(2).hasValue("sub2"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(3).hasValue("--arg1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.ARGUMENT).hasPosition(4).hasValue("xxx"); + }); } @Test @@ -213,19 +154,11 @@ void definedOptionShouldBeOptionAfterCommand() { register(ROOT3); List tokens = tokenize("root3", "--arg1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root3"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("--arg1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root3"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("--arg1"); + }); } @Test @@ -233,19 +166,11 @@ void notDefinedOptionShouldBeOptionAfterCommand() { register(ROOT3); List tokens = tokenize("root3", "--arg2"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root3"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("--arg2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root3"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("--arg2"); + }); } @Test @@ -253,25 +178,13 @@ void notDefinedOptionShouldBeOptionAfterDefinedOption() { register(ROOT3); List tokens = tokenize("root3", "--arg1", "--arg2"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root3"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("--arg1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(2) - .hasValue("--arg2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root3"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("--arg1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(2).hasValue("--arg2"); + }); } @Test @@ -279,31 +192,15 @@ void notDefinedOptionShouldBeOptionAfterDefinedOptionHavingArgument() { register(ROOT3); List tokens = tokenize("root3", "--arg1", "value1", "--arg2"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root3"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("--arg1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.ARGUMENT) - .hasPosition(2) - .hasValue("value1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(3) - .hasValue("--arg2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root3"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("--arg1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.ARGUMENT).hasPosition(2).hasValue("value1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(3).hasValue("--arg2"); + }); } @Test @@ -311,25 +208,13 @@ void optionsWithoutValuesFromRoot() { register(ROOT5); List tokens = tokenize("root5", "--arg1", "--arg2"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root5"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("--arg1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(2) - .hasValue("--arg2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root5"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("--arg1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(2).hasValue("--arg2"); + }); } @Test @@ -337,37 +222,17 @@ void optionsWithValuesFromRoot() { register(ROOT5); List tokens = tokenize("root5", "--arg1", "value1", "--arg2", "value2"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root5"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("--arg1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.ARGUMENT) - .hasPosition(2) - .hasValue("value1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(3) - .hasValue("--arg2"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.ARGUMENT) - .hasPosition(4) - .hasValue("value2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root5"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("--arg1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.ARGUMENT).hasPosition(2).hasValue("value1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(3).hasValue("--arg2"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.ARGUMENT).hasPosition(4).hasValue("value2"); + }); } @Test @@ -375,25 +240,13 @@ void shortOptionWithValuesFromRoot() { register(ROOT3_SHORT_OPTION_A); List tokens = tokenize("root3", "-a", "value1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root3"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("-a"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.ARGUMENT) - .hasPosition(2) - .hasValue("value1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root3"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("-a"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.ARGUMENT).hasPosition(2).hasValue("value1"); + }); } @Test @@ -401,37 +254,17 @@ void shortOptionsWithValuesFromRoot() { register(ROOT3_SHORT_OPTION_A_B); List tokens = tokenize("root3", "-a", "value1", "-b", "value2"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(0) - .hasValue("root3"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(1) - .hasValue("-a"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.ARGUMENT) - .hasPosition(2) - .hasValue("value1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.OPTION) - .hasPosition(3) - .hasValue("-b"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.ARGUMENT) - .hasPosition(4) - .hasValue("value2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(0).hasValue("root3"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(1).hasValue("-a"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.ARGUMENT).hasPosition(2).hasValue("value1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.OPTION).hasPosition(3).hasValue("-b"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.ARGUMENT).hasPosition(4).hasValue("value2"); + }); } @Test @@ -439,8 +272,8 @@ void optionValueFromRoot() { register(ROOT3); List tokens = tokenize("root3", "--arg1", "value1"); - assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND, TokenType.OPTION, - TokenType.ARGUMENT); + assertThat(tokens).extracting(Token::getType) + .containsExactly(TokenType.COMMAND, TokenType.OPTION, TokenType.ARGUMENT); } @Nested @@ -451,9 +284,10 @@ void doubleDashAddsCommandArguments() { register(ROOT3); List tokens = tokenize("root3", "--", "arg1"); - assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND, TokenType.DOUBLEDASH, - TokenType.ARGUMENT); + assertThat(tokens).extracting(Token::getType) + .containsExactly(TokenType.COMMAND, TokenType.DOUBLEDASH, TokenType.ARGUMENT); } + } @Test @@ -461,45 +295,34 @@ void commandArgsWithoutOption() { register(ROOT3); List tokens = tokenize("root3", "value1", "value2"); - assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND, TokenType.ARGUMENT, - TokenType.ARGUMENT); + assertThat(tokens).extracting(Token::getType) + .containsExactly(TokenType.COMMAND, TokenType.ARGUMENT, TokenType.ARGUMENT); } @Nested class ShortOptions { @ParameterizedTest - @ValueSource(strings = { - "-1", - "-1a", - "-a1", - "-ab1", - "-ab1c" - }) + @ValueSource(strings = { "-1", "-1a", "-a1", "-ab1", "-ab1c" }) void shouldNotBeOptionWhenDoesntLookLikeShortPosix(String arg) { register(ROOT6_OPTION_INT); List tokens = tokenize("root6", "--arg1", arg); - assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND, TokenType.OPTION, - TokenType.ARGUMENT); + assertThat(tokens).extracting(Token::getType) + .containsExactly(TokenType.COMMAND, TokenType.OPTION, TokenType.ARGUMENT); } @ParameterizedTest - @ValueSource(strings = { - "-a", - "-ab", - "-abc", - "--abc" - }) + @ValueSource(strings = { "-a", "-ab", "-abc", "--abc" }) void shouldBeOptionWhenLooksLikeShortPosix(String arg) { register(ROOT6_OPTION_INT); List tokens = tokenize("root6", "--arg1", arg); - assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND, TokenType.OPTION, - TokenType.OPTION); + assertThat(tokens).extracting(Token::getType) + .containsExactly(TokenType.COMMAND, TokenType.OPTION, TokenType.OPTION); } - } + } @Nested class Directives { @@ -510,19 +333,11 @@ void directiveWithCommand() { ParserConfig config = new ParserConfig().enable(Feature.ALLOW_DIRECTIVES); List tokens = tokenize(lexer(config), "[fake]", "root1"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.DIRECTIVE) - .hasPosition(0) - .hasValue("fake"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.COMMAND) - .hasPosition(1) - .hasValue("root1"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.DIRECTIVE).hasPosition(0).hasValue("fake"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.COMMAND).hasPosition(1).hasValue("root1"); + }); } @Test @@ -531,13 +346,9 @@ void hasOneDirective() { ParserConfig config = new ParserConfig().enable(Feature.ALLOW_DIRECTIVES); List tokens = tokenize(lexer(config), "[fake]"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.DIRECTIVE) - .hasPosition(0) - .hasValue("fake"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.DIRECTIVE).hasPosition(0).hasValue("fake"); + }); } @Test @@ -546,34 +357,24 @@ void hasMultipleDirectives() { ParserConfig config = new ParserConfig().enable(Feature.ALLOW_DIRECTIVES); List tokens = tokenize(lexer(config), "[fake1][fake2]"); - assertThat(tokens).satisfiesExactly( - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.DIRECTIVE) - .hasPosition(0) - .hasValue("fake1"); - }, - token -> { - ParserAssertions.assertThat(token) - .isType(TokenType.DIRECTIVE) - .hasPosition(0) - .hasValue("fake2"); - }); + assertThat(tokens).satisfiesExactly(token -> { + ParserAssertions.assertThat(token).isType(TokenType.DIRECTIVE).hasPosition(0).hasValue("fake1"); + }, token -> { + ParserAssertions.assertThat(token).isType(TokenType.DIRECTIVE).hasPosition(0).hasValue("fake2"); + }); } @Test void errorIfDirectivesDisabledAndIgnoreDisabled() { - ParserConfig config = new ParserConfig() - .disable(Feature.ALLOW_DIRECTIVES) - .disable(Feature.IGNORE_DIRECTIVES); - LexerResult result = tokenizeAsResult(lexer(config),"[fake]"); + ParserConfig config = new ParserConfig().disable(Feature.ALLOW_DIRECTIVES) + .disable(Feature.IGNORE_DIRECTIVES); + LexerResult result = tokenizeAsResult(lexer(config), "[fake]"); assertThat(result.messageResults()).isNotEmpty(); } @Test void noErrorIfDirectivesDisabledAndIgnoreEnabled() { - ParserConfig config = new ParserConfig() - .enable(Feature.IGNORE_DIRECTIVES); + ParserConfig config = new ParserConfig().enable(Feature.IGNORE_DIRECTIVES); LexerResult result = tokenizeAsResult(lexer(config), "[fake]"); assertThat(result.messageResults()).isEmpty(); } @@ -585,6 +386,7 @@ void ignoreDirectiveIfDisabled() { assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND); } + } @Nested @@ -593,15 +395,15 @@ class ParserMessages { @Test void hasErrorMessageWithoutArguments() { LexerResult result = tokenizeAsResult("--"); - assertThat(result.messageResults()).satisfiesExactly( - message -> { - assertThat(message.parserMessage().getCode()).isEqualTo(1000); - assertThat(message.position()).isEqualTo(0); - }, - message -> { - assertThat(message.parserMessage().getCode()).isEqualTo(1000); - assertThat(message.position()).isEqualTo(0); - }); + assertThat(result.messageResults()).satisfiesExactly(message -> { + assertThat(message.parserMessage().getCode()).isEqualTo(1000); + assertThat(message.position()).isEqualTo(0); + }, message -> { + assertThat(message.parserMessage().getCode()).isEqualTo(1000); + assertThat(message.position()).isEqualTo(0); + }); } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserAssertions.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserAssertions.java index 7a65f6b59..8fd548abd 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserAssertions.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserAssertions.java @@ -28,4 +28,5 @@ public static ParserMessageAssert assertThat(ParserMessage message) { public static MessageResultAssert assertThat(MessageResult result) { return new MessageResultAssert(result); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserConfigTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserConfigTests.java index 1ea9c896d..0a75051c1 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserConfigTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserConfigTests.java @@ -42,4 +42,5 @@ void configureStates() { config.enable(Feature.ALLOW_DIRECTIVES); assertThat(config.isEnabled(Feature.ALLOW_DIRECTIVES)).isTrue(); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserTests.java index 5ec3a1759..0f77b9224 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/ParserTests.java @@ -51,16 +51,13 @@ void commandArgumentsGetsAddedWhenNoOptions() { register(ROOT1); ParseResult result = parse("root1", "arg1", "arg2"); - assertThat(result.argumentResults()).satisfiesExactly( - ar -> { - assertThat(ar.value()).isEqualTo("arg1"); - assertThat(ar.position()).isEqualTo(0); - }, - ar -> { - assertThat(ar.value()).isEqualTo("arg2"); - assertThat(ar.position()).isEqualTo(1); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(ar -> { + assertThat(ar.value()).isEqualTo("arg1"); + assertThat(ar.position()).isEqualTo(0); + }, ar -> { + assertThat(ar.value()).isEqualTo("arg2"); + assertThat(ar.position()).isEqualTo(1); + }); } @Test @@ -68,17 +65,15 @@ void commandArgumentsGetsAddedAfterDoubleDash() { register(ROOT3); ParseResult result = parse("root3", "--arg1", "value1", "--", "arg1", "arg2"); - assertThat(result.argumentResults()).satisfiesExactly( - ar -> { - assertThat(ar.value()).isEqualTo("arg1"); - assertThat(ar.position()).isEqualTo(0); - }, - ar -> { - assertThat(ar.value()).isEqualTo("arg2"); - assertThat(ar.position()).isEqualTo(1); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(ar -> { + assertThat(ar.value()).isEqualTo("arg1"); + assertThat(ar.position()).isEqualTo(0); + }, ar -> { + assertThat(ar.value()).isEqualTo("arg2"); + assertThat(ar.position()).isEqualTo(1); + }); } + } @Nested @@ -116,7 +111,8 @@ void optionValueFailsFromStringToInteger() { assertThat(result.optionResults().get(0).value()).isEqualTo("x"); assertThat(result.messageResults()).isNotEmpty(); assertThat(result.messageResults()).satisfiesExactly(ms -> { - // "2002E:(pos 0): Illegal option value 'x', reason 'Failed to convert from type [java.lang.String] to type [int] for value 'x''" + // "2002E:(pos 0): Illegal option value 'x', reason 'Failed to convert + // from type [java.lang.String] to type [int] for value 'x''" assertThat(ms.getMessage()).contains("Failed to convert"); }); } @@ -155,26 +151,20 @@ void shouldHaveErrorResult2() { ParseResult result = parse("root4", "--arg1", "--arg2"); assertThat(result).isNotNull(); - assertThat(result.messageResults()).satisfiesExactlyInAnyOrder( - message -> { - ParserAssertions.assertThat(message.parserMessage()).hasCode(2000).hasType(ParserMessage.Type.ERROR); - }, - message -> { - ParserAssertions.assertThat(message.parserMessage()).hasCode(2001).hasType(ParserMessage.Type.ERROR); - } - ); + assertThat(result.messageResults()).satisfiesExactlyInAnyOrder(message -> { + ParserAssertions.assertThat(message.parserMessage()).hasCode(2000).hasType(ParserMessage.Type.ERROR); + }, message -> { + ParserAssertions.assertThat(message.parserMessage()).hasCode(2001).hasType(ParserMessage.Type.ERROR); + }); } static Stream shouldHaveErrorForUnrecognisedOption() { - return Stream.of( - RegAndArgs.of(ROOT1, "root1", "--arg1"), - RegAndArgs.of(ROOT3, "root3", "--arg2", "--arg1"), - RegAndArgs.of(ROOT3, "root3", "--arg1", "--arg2"), - RegAndArgs.of(ROOT3, "root3", "--arg2", "fake1", "--arg1"), - RegAndArgs.of(ROOT3, "root3", "--arg1", "--arg2", "fake1"), - RegAndArgs.of(ROOT3, "root3", "--arg2", "fake1", "--arg1", "fake2"), - RegAndArgs.of(ROOT3, "root3", "--arg1", "fake2", "--arg2", "fake1") - ); + return Stream.of(RegAndArgs.of(ROOT1, "root1", "--arg1"), RegAndArgs.of(ROOT3, "root3", "--arg2", "--arg1"), + RegAndArgs.of(ROOT3, "root3", "--arg1", "--arg2"), + RegAndArgs.of(ROOT3, "root3", "--arg2", "fake1", "--arg1"), + RegAndArgs.of(ROOT3, "root3", "--arg1", "--arg2", "fake1"), + RegAndArgs.of(ROOT3, "root3", "--arg2", "fake1", "--arg1", "fake2"), + RegAndArgs.of(ROOT3, "root3", "--arg1", "fake2", "--arg2", "fake1")); } @ParameterizedTest @@ -182,19 +172,19 @@ static Stream shouldHaveErrorForUnrecognisedOption() { void shouldHaveErrorForUnrecognisedOption(RegAndArgs regAndArgs) { register(regAndArgs.reg()); ParseResult result = parse(regAndArgs.args()); - assertThat(result.messageResults()).satisfiesExactlyInAnyOrder( - message -> { - ParserAssertions.assertThat(message.parserMessage()).hasCode(2001).hasType(ParserMessage.Type.ERROR); - } - ); + assertThat(result.messageResults()).satisfiesExactlyInAnyOrder(message -> { + ParserAssertions.assertThat(message.parserMessage()).hasCode(2001).hasType(ParserMessage.Type.ERROR); + }); } @Test void lexerMessageShouldGetPropagated() { ParseResult parse = parse("--"); - assertThat(parse.messageResults()).extracting(ms -> ms.parserMessage().getCode()).containsExactly(1000, 1000); + assertThat(parse.messageResults()).extracting(ms -> ms.parserMessage().getCode()) + .containsExactly(1000, 1000); } + } @Nested @@ -232,17 +222,16 @@ void multipleDirectivesWithCommand() { ParserConfig config = new ParserConfig().enable(Feature.ALLOW_DIRECTIVES); ParseResult result = parse(lexer(config), "[foo][bar:value]", "root3"); - assertThat(result.directiveResults()).satisfiesExactly( - d -> { - assertThat(d.name()).isEqualTo("foo"); - assertThat(d.value()).isNull(); - }, - d -> { - assertThat(d.name()).isEqualTo("bar"); - assertThat(d.value()).isEqualTo("value"); - }); + assertThat(result.directiveResults()).satisfiesExactly(d -> { + assertThat(d.name()).isEqualTo("foo"); + assertThat(d.value()).isNull(); + }, d -> { + assertThat(d.name()).isEqualTo("bar"); + assertThat(d.value()).isEqualTo("value"); + }); assertThat(result.messageResults()).isEmpty(); } + } @Nested @@ -285,11 +274,9 @@ void shouldFindLongOptionArgument() { assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); assertThat(result.optionResults()).isNotEmpty(); - assertThat(result.optionResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("value1"); - } - ); + assertThat(result.optionResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("value1"); + }); assertThat(result.messageResults()).isEmpty(); } @@ -300,18 +287,16 @@ void shouldFindTwoLongOptionArgument() { assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); assertThat(result.optionResults()).isNotEmpty(); - assertThat(result.optionResults()).satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("value1"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); - assertThat(r.value()).isEqualTo("value2"); - } - ); + assertThat(result.optionResults()).satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("value1"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); + assertThat(r.value()).isEqualTo("value2"); + }); assertThat(result.messageResults()).isEmpty(); } + } @Nested @@ -324,12 +309,10 @@ void shouldFindShortOption() { assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); assertThat(result.optionResults()).isNotEmpty(); - assertThat(result.optionResults()).satisfiesExactly( - r -> { - assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'a' }); - assertThat(r.value()).isNull(); - } - ); + assertThat(result.optionResults()).satisfiesExactly(r -> { + assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'a' }); + assertThat(r.value()).isNull(); + }); assertThat(result.messageResults()).isEmpty(); } @@ -340,12 +323,10 @@ void shouldFindShortOptionWithArg() { assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); assertThat(result.optionResults()).isNotEmpty(); - assertThat(result.optionResults()).satisfiesExactly( - r -> { - assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'a' }); - assertThat(r.value()).isEqualTo("aaa"); - } - ); + assertThat(result.optionResults()).satisfiesExactly(r -> { + assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'a' }); + assertThat(r.value()).isEqualTo("aaa"); + }); assertThat(result.messageResults()).isEmpty(); } @@ -356,16 +337,13 @@ void shouldFindShortOptions() { assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); assertThat(result.optionResults()).isNotEmpty(); - assertThat(result.optionResults()).satisfiesExactly( - r -> { - assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'a' }); - assertThat(r.value()).isEqualTo("aaa"); - }, - r -> { - assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'b' }); - assertThat(r.value()).isEqualTo("bbb"); - } - ); + assertThat(result.optionResults()).satisfiesExactly(r -> { + assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'a' }); + assertThat(r.value()).isEqualTo("aaa"); + }, r -> { + assertThat(r.option().getShortNames()).isEqualTo(new Character[] { 'b' }); + assertThat(r.value()).isEqualTo("bbb"); + }); assertThat(result.messageResults()).isEmpty(); } @@ -387,9 +365,8 @@ class CaseSensitivity { @Test void shouldFindRegistrationRegUpperCommandLower() { register(ROOT1_UP); - ParserConfig config = new ParserConfig() - .disable(Feature.CASE_SENSITIVE_COMMANDS) - .disable(Feature.CASE_SENSITIVE_OPTIONS); + ParserConfig config = new ParserConfig().disable(Feature.CASE_SENSITIVE_COMMANDS) + .disable(Feature.CASE_SENSITIVE_OPTIONS); ParseResult result = parse(config, "root1"); assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); @@ -399,9 +376,8 @@ void shouldFindRegistrationRegUpperCommandLower() { @Test void shouldFindRegistrationRegUpperCommandUpper() { register(ROOT1_UP); - ParserConfig config = new ParserConfig() - .disable(Feature.CASE_SENSITIVE_COMMANDS) - .disable(Feature.CASE_SENSITIVE_OPTIONS); + ParserConfig config = new ParserConfig().disable(Feature.CASE_SENSITIVE_COMMANDS) + .disable(Feature.CASE_SENSITIVE_OPTIONS); ParseResult result = parse(config, "Root1"); assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); @@ -411,9 +387,8 @@ void shouldFindRegistrationRegUpperCommandUpper() { @Test void shouldFindRegistrationRegLowerCommandUpper() { register(ROOT1); - ParserConfig config = new ParserConfig() - .disable(Feature.CASE_SENSITIVE_COMMANDS) - .disable(Feature.CASE_SENSITIVE_OPTIONS); + ParserConfig config = new ParserConfig().disable(Feature.CASE_SENSITIVE_COMMANDS) + .disable(Feature.CASE_SENSITIVE_OPTIONS); ParseResult result = parse(config, "Root1"); assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); @@ -423,19 +398,15 @@ void shouldFindRegistrationRegLowerCommandUpper() { @Test void shouldFindLongOptionRegLowerCommandUpper() { register(ROOT3); - ParserConfig config = new ParserConfig() - .disable(Feature.CASE_SENSITIVE_COMMANDS) - .disable(Feature.CASE_SENSITIVE_OPTIONS) - ; + ParserConfig config = new ParserConfig().disable(Feature.CASE_SENSITIVE_COMMANDS) + .disable(Feature.CASE_SENSITIVE_OPTIONS); ParseResult result = parse(config, "root3", "--Arg1", "value1"); assertThat(result).isNotNull(); assertThat(result.commandRegistration()).isNotNull(); assertThat(result.optionResults()).isNotEmpty(); - assertThat(result.optionResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("value1"); - } - ); + assertThat(result.optionResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("value1"); + }); assertThat(result.messageResults()).isEmpty(); } @@ -448,12 +419,11 @@ class DefaultValues { void shouldAddOptionIfItHasDefaultValue() { register(ROOT6_OPTION_DEFAULT_VALUE); ParseResult result = parse("root6"); - assertThat(result.optionResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("defaultvalue"); - } - ); + assertThat(result.optionResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("defaultvalue"); + }); } + } @Nested @@ -463,28 +433,23 @@ class Positional { void shouldGetPositionalArgWhenOneAsString() { register(ROOT7_POSITIONAL_ONE_ARG_STRING); ParseResult result = parse("root7", "a"); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("a"); - assertThat(r.position()).isEqualTo(0); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("a"); + assertThat(r.position()).isEqualTo(0); + }); } @Test void shouldGetPositionalArgWhenTwoAsString() { register(ROOT7_POSITIONAL_TWO_ARG_STRING); ParseResult result = parse("root7", "a", "b"); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("a"); - assertThat(r.position()).isEqualTo(0); - }, - r -> { - assertThat(r.value()).isEqualTo("b"); - assertThat(r.position()).isEqualTo(1); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("a"); + assertThat(r.position()).isEqualTo(0); + }, r -> { + assertThat(r.value()).isEqualTo("b"); + assertThat(r.position()).isEqualTo(1); + }); } @Test @@ -493,12 +458,10 @@ void noArgsGetsOnlyDefault() { ParseResult result = parse("root7"); assertThat(result.messageResults()).isEmpty(); assertThat(result.argumentResults()).isEmpty(); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("arg1default"); - } - ); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("arg1default"); + }); } @Test @@ -506,18 +469,14 @@ void positionOverridesDefault() { register(ROOT7_POSITIONAL_ONE_ARG_STRING_DEFAULT); ParseResult result = parse("root7", "a"); assertThat(result.messageResults()).isEmpty(); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("a"); - assertThat(r.position()).isEqualTo(0); - } - ); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("a"); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("a"); + assertThat(r.position()).isEqualTo(0); + }); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("a"); + }); } @Test @@ -526,16 +485,13 @@ void noArgsGetsOnlyDefaults() { ParseResult result = parse("root7"); assertThat(result.messageResults()).isEmpty(); assertThat(result.argumentResults()).isEmpty(); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("arg1default"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); - assertThat(r.value()).isEqualTo("arg2default"); - } - ); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("arg1default"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); + assertThat(r.value()).isEqualTo("arg2default"); + }); } @Test @@ -543,22 +499,17 @@ void positionOverridesDefaultKeepsDefault() { register(ROOT7_POSITIONAL_TWO_ARG_STRING_DEFAULT); ParseResult result = parse("root7", "a"); assertThat(result.messageResults()).isEmpty(); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("a"); - assertThat(r.position()).isEqualTo(0); - } - ); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("a"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); - assertThat(r.value()).isEqualTo("arg2default"); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("a"); + assertThat(r.position()).isEqualTo(0); + }); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("a"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); + assertThat(r.value()).isEqualTo("arg2default"); + }); } @Test @@ -566,26 +517,20 @@ void positionOverridesDefaultsKeepsDefault() { register(ROOT7_POSITIONAL_TWO_ARG_STRING_DEFAULT); ParseResult result = parse("root7", "a", "b"); assertThat(result.messageResults()).isEmpty(); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("a"); - assertThat(r.position()).isEqualTo(0); - }, - r -> { - assertThat(r.value()).isEqualTo("b"); - assertThat(r.position()).isEqualTo(1); - } - ); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("a"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); - assertThat(r.value()).isEqualTo("b"); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("a"); + assertThat(r.position()).isEqualTo(0); + }, r -> { + assertThat(r.value()).isEqualTo("b"); + assertThat(r.position()).isEqualTo(1); + }); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("a"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); + assertThat(r.value()).isEqualTo("b"); + }); } @Test @@ -593,22 +538,17 @@ void positionOverridesDefaultsKeepsDefaultWhenOption() { register(ROOT7_POSITIONAL_TWO_ARG_STRING_DEFAULT); ParseResult result = parse("root7", "--arg1", "a", "b"); assertThat(result.messageResults()).isEmpty(); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("b"); - assertThat(r.position()).isEqualTo(0); - } - ); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("a"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); - assertThat(r.value()).isEqualTo("b"); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("b"); + assertThat(r.position()).isEqualTo(0); + }); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("a"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); + assertThat(r.value()).isEqualTo("b"); + }); } @Test @@ -618,26 +558,20 @@ void positionWithLastHavingNoDefault() { result = parse("root7", "--arg1", "a", "--arg2", "b", "c"); assertThat(result.messageResults()).isEmpty(); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("c"); - assertThat(r.position()).isEqualTo(0); - } - ); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("a"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); - assertThat(r.value()).isEqualTo("b"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg3" }); - assertThat(r.value()).isEqualTo("c"); - } - ); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("c"); + assertThat(r.position()).isEqualTo(0); + }); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("a"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); + assertThat(r.value()).isEqualTo("b"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg3" }); + assertThat(r.value()).isEqualTo("c"); + }); } @Test @@ -646,48 +580,38 @@ void tooManyArgsInMiddleShouldCreateError() { ParseResult result; result = parse("root7", "--arg1", "a", "b", "--arg2", "c", "d"); - assertThat(result.messageResults()).satisfiesExactlyInAnyOrder( - message -> { - ParserAssertions.assertThat(message.parserMessage()).hasCode(2004).hasType(ParserMessage.Type.ERROR); - } - ); - assertThat(result.argumentResults()).satisfiesExactly( - r -> { - assertThat(r.value()).isEqualTo("b"); - assertThat(r.position()).isEqualTo(0); - }, - r -> { - assertThat(r.value()).isEqualTo("d"); - assertThat(r.position()).isEqualTo(0); - } - ); - assertThat(result.optionResults()).isNotNull().satisfiesExactly( - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); - assertThat(r.value()).isEqualTo("a"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); - assertThat(r.value()).isEqualTo("c"); - }, - r -> { - assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg3" }); - assertThat(r.value()).isEqualTo("b"); - } - ); + assertThat(result.messageResults()).satisfiesExactlyInAnyOrder(message -> { + ParserAssertions.assertThat(message.parserMessage()).hasCode(2004).hasType(ParserMessage.Type.ERROR); + }); + assertThat(result.argumentResults()).satisfiesExactly(r -> { + assertThat(r.value()).isEqualTo("b"); + assertThat(r.position()).isEqualTo(0); + }, r -> { + assertThat(r.value()).isEqualTo("d"); + assertThat(r.position()).isEqualTo(0); + }); + assertThat(result.optionResults()).isNotNull().satisfiesExactly(r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg1" }); + assertThat(r.value()).isEqualTo("a"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg2" }); + assertThat(r.value()).isEqualTo("c"); + }, r -> { + assertThat(r.option().getLongNames()).isEqualTo(new String[] { "arg3" }); + assertThat(r.value()).isEqualTo("b"); + }); } @Test void notEnoughOptionArgumentsShouldHaveCorrectCount() { register(ROOT8_ONE_ARG_ARITYEONE_STRING); ParseResult result = parse("root8", "--arg1"); - assertThat(result.messageResults()).satisfiesExactlyInAnyOrder( - message -> { - ParserAssertions.assertThat(message.parserMessage()).hasCode(2003).hasType(ParserMessage.Type.ERROR); - ParserAssertions.assertThat(message).hasPosition(0).hasInserts("arg1", 1); - } - ); + assertThat(result.messageResults()).satisfiesExactlyInAnyOrder(message -> { + ParserAssertions.assertThat(message.parserMessage()).hasCode(2003).hasType(ParserMessage.Type.ERROR); + ParserAssertions.assertThat(message).hasPosition(0).hasInserts("arg1", 1); + }); } } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/TokenAssert.java b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/TokenAssert.java index 5c5e3ea58..fc1f23298 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/parser/TokenAssert.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/parser/TokenAssert.java @@ -42,4 +42,5 @@ public TokenAssert hasValue(String value) { assertThat(actual.getValue()).isEqualTo(value); return this; } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/support/OptionNameModifierSupportTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/support/OptionNameModifierSupportTests.java index ca8360b48..74d090069 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/support/OptionNameModifierSupportTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/support/OptionNameModifierSupportTests.java @@ -23,46 +23,26 @@ class OptionNameModifierSupportTests { @ParameterizedTest - @CsvSource({ - "camel case,camelCase", - "camel_case,camelCase", - "camel-case,camelCase", - "camelCase,camelCase", - "CamelCase,camelCase" - }) + @CsvSource({ "camel case,camelCase", "camel_case,camelCase", "camel-case,camelCase", "camelCase,camelCase", + "CamelCase,camelCase" }) void testCamel(String name, String expected) { assertThat(camel(name)).isEqualTo(expected); } @ParameterizedTest - @CsvSource({ - "pascal-case,PascalCase", - "pascal_case,PascalCase", - "pascalCase,PascalCase", - "PascalCase,PascalCase" - }) + @CsvSource({ "pascal-case,PascalCase", "pascal_case,PascalCase", "pascalCase,PascalCase", "PascalCase,PascalCase" }) void testPascal(String name, String expected) { assertThat(pascal(name)).isEqualTo(expected); } @ParameterizedTest - @CsvSource({ - "kebabCase,kebab-case", - "kebab_case,kebab-case", - "kebab_Case,kebab-case", - "Kebab_case,kebab-case" - }) + @CsvSource({ "kebabCase,kebab-case", "kebab_case,kebab-case", "kebab_Case,kebab-case", "Kebab_case,kebab-case" }) void testKebab(String name, String expected) { assertThat(kebab(name)).isEqualTo(expected); } @ParameterizedTest - @CsvSource({ - "snakeCase,snake_case", - "snake_case,snake_case", - "snake_Case,snake_case", - "Snake_case,snake_case" - }) + @CsvSource({ "snakeCase,snake_case", "snake_case,snake_case", "snake_Case,snake_case", "Snake_case,snake_case" }) void testSnake(String name, String expected) { assertThat(snake(name)).isEqualTo(expected); } @@ -82,4 +62,5 @@ private String snake(String name) { private String pascal(String name) { return OptionNameModifierSupport.toPascalCase(name); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolverTests.java b/spring-shell-core/src/test/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolverTests.java index e30bae613..daff243ca 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolverTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/completion/RegistrationOptionsCompletionResolverTests.java @@ -35,16 +35,18 @@ void completesAllOptions() { CommandRegistration registration = CommandRegistration.builder() .command("hello world") .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withOption() - .longNames("arg2") - .and() + .longNames("arg2") + .and() .build(); - CompletionContext ctx = new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), registration, null); + CompletionContext ctx = new CompletionContext(Arrays.asList("hello", "world", ""), 2, "".length(), registration, + null); List proposals = resolver.apply(ctx); assertThat(proposals).isNotNull(); assertThat(proposals).hasSize(2); @@ -55,16 +57,18 @@ void completesNonExistingOptions() { CommandRegistration registration = CommandRegistration.builder() .command("hello world") .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withOption() - .longNames("arg2") - .and() + .longNames("arg2") + .and() .build(); - CompletionContext ctx = new CompletionContext(Arrays.asList("hello", "world", "--arg1", ""), 2, "".length(), registration, null); + CompletionContext ctx = new CompletionContext(Arrays.asList("hello", "world", "--arg1", ""), 2, "".length(), + registration, null); List proposals = resolver.apply(ctx); assertThat(proposals).isNotNull(); assertThat(proposals).hasSize(1); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/AbstractShellTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/AbstractShellTests.java index b13095cdb..c4a92317d 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/AbstractShellTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/AbstractShellTests.java @@ -44,14 +44,21 @@ public abstract class AbstractShellTests { - private ExecutorService executorService; - private PipedInputStream pipedInputStream; - private PipedOutputStream pipedOutputStream; - private LinkedBlockingQueue bytesQueue; + private ExecutorService executorService; + + private PipedInputStream pipedInputStream; + + private PipedOutputStream pipedOutputStream; + + private LinkedBlockingQueue bytesQueue; + private ByteArrayOutputStream consoleOut; + private Terminal terminal; + private TemplateExecutor templateExecutor; - private ResourceLoader resourceLoader; + + private ResourceLoader resourceLoader; @BeforeEach public void setup() throws Exception { @@ -76,22 +83,23 @@ public ThemeSettings getSettings() { ThemeResolver themeResolver = new ThemeResolver(themeRegistry, "dump"); templateExecutor = new TemplateExecutor(themeResolver); - resourceLoader = new DefaultResourceLoader(); + resourceLoader = new DefaultResourceLoader(); - pipedInputStream.connect(pipedOutputStream); + pipedInputStream.connect(pipedOutputStream); terminal = new DumbTerminal("terminal", "ansi", pipedInputStream, consoleOut, StandardCharsets.UTF_8); - terminal.setSize(new Size(80, 24)); - - executorService.execute(() -> { - try { - while (true) { - byte[] take = bytesQueue.take(); - pipedOutputStream.write(take); - pipedOutputStream.flush(); - } - } catch (Exception e) { - } - }); + terminal.setSize(new Size(80, 24)); + + executorService.execute(() -> { + try { + while (true) { + byte[] take = bytesQueue.take(); + pipedOutputStream.write(take); + pipedOutputStream.flush(); + } + } + catch (Exception e) { + } + }); } @AfterEach @@ -104,95 +112,99 @@ protected void write(byte[] bytes) { } protected String consoleOut() { - return AttributedString.fromAnsi(consoleOut.toString()).toString(); + return AttributedString.fromAnsi(consoleOut.toString()).toString(); } protected Terminal getTerminal() { return terminal; } - protected ResourceLoader getResourceLoader() { - return resourceLoader; - } + protected ResourceLoader getResourceLoader() { + return resourceLoader; + } + + protected TemplateExecutor getTemplateExecutor() { + return templateExecutor; + } - protected TemplateExecutor getTemplateExecutor() { - return templateExecutor; - } + protected class TestBuffer { - protected class TestBuffer { - private final ByteArrayOutputStream out = new ByteArrayOutputStream(); + private final ByteArrayOutputStream out = new ByteArrayOutputStream(); - public TestBuffer() { - } + public TestBuffer() { + } - public TestBuffer(String str) { - append(str); - } + public TestBuffer(String str) { + append(str); + } - public TestBuffer(char[] chars) { - append(new String(chars)); - } + public TestBuffer(char[] chars) { + append(new String(chars)); + } - @Override - public String toString() { - try { - return out.toString(StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } + @Override + public String toString() { + try { + return out.toString(StandardCharsets.UTF_8.name()); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } - public TestBuffer cr() { + public TestBuffer cr() { return append("\r"); - } + } - public TestBuffer backspace() { - return append(del()); - } + public TestBuffer backspace() { + return append(del()); + } - public TestBuffer backspace(int count) { - TestBuffer buf = this; - for (int i = 0; i < count; i++) { - buf = backspace(); - } - return buf; - } + public TestBuffer backspace(int count) { + TestBuffer buf = this; + for (int i = 0; i < count; i++) { + buf = backspace(); + } + return buf; + } public TestBuffer down() { return append("\033[B"); - } + } public TestBuffer ctrl(char let) { - return append(KeyMap.ctrl(let)); - } + return append(KeyMap.ctrl(let)); + } - public TestBuffer ctrlE() { - return ctrl('E'); - } + public TestBuffer ctrlE() { + return ctrl('E'); + } - public TestBuffer ctrlY() { - return ctrl('Y'); - } + public TestBuffer ctrlY() { + return ctrl('Y'); + } public TestBuffer space() { return append(" "); - } - - public byte[] getBytes() { - return out.toByteArray(); - } - - public TestBuffer append(final String str) { - for (byte b : str.getBytes(StandardCharsets.UTF_8)) { - append(b); - } - return this; - } - - public TestBuffer append(final int i) { - // consoleOut.reset(); - out.write((byte) i); - return this; - } + } + + public byte[] getBytes() { + return out.toByteArray(); + } + + public TestBuffer append(final String str) { + for (byte b : str.getBytes(StandardCharsets.UTF_8)) { + append(b); + } + return this; + } + + public TestBuffer append(final int i) { + // consoleOut.reset(); + out.write((byte) i); + return this; + } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/ConfirmationInputTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/ConfirmationInputTests.java index a1afc60d4..22b8cf26a 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/ConfirmationInputTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/ConfirmationInputTests.java @@ -41,7 +41,9 @@ public class ConfirmationInputTests extends AbstractShellTests { private ExecutorService service; + private CountDownLatch latch1; + private AtomicReference result1; @BeforeEach @@ -176,8 +178,7 @@ public void testUserInputShown() throws InterruptedException, IOException { TestBuffer testBuffer = new TestBuffer().append("N"); write(testBuffer.getBytes()); - await().atMost(Duration.ofSeconds(4)) - .untilAsserted(() -> assertThat(consoleOut()).contains("N")); + await().atMost(Duration.ofSeconds(4)).untilAsserted(() -> assertThat(consoleOut()).contains("N")); testBuffer = new TestBuffer().cr(); write(testBuffer.getBytes()); @@ -239,4 +240,5 @@ public void testResultUserInputInvalidInput() throws InterruptedException, IOExc assertThat(run1Context).isNotNull(); assertThat(run1Context.getResultValue()).isNull(); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/MultiItemSelectorTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/MultiItemSelectorTests.java index a6b004202..ea6069fee 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/MultiItemSelectorTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/MultiItemSelectorTests.java @@ -45,24 +45,43 @@ public class MultiItemSelectorTests extends AbstractShellTests { private static SimplePojo SIMPLE_POJO_1 = SimplePojo.of("data1"); + private static SimplePojo SIMPLE_POJO_2 = SimplePojo.of("data2"); + private static SimplePojo SIMPLE_POJO_3 = SimplePojo.of("data3"); + private static SimplePojo SIMPLE_POJO_4 = SimplePojo.of("data4"); + private static SimplePojo SIMPLE_POJO_5 = SimplePojo.of("data5"); + private static SimplePojo SIMPLE_POJO_6 = SimplePojo.of("data6"); + private static SimplePojo SIMPLE_POJO_7 = SimplePojo.of("data7"); + private static SimplePojo SIMPLE_POJO_8 = SimplePojo.of("data8"); + private static SelectorItem SELECTOR_ITEM_1 = SelectorItem.of("simplePojo1", SIMPLE_POJO_1); + private static SelectorItem SELECTOR_ITEM_2 = SelectorItem.of("simplePojo2", SIMPLE_POJO_2); + private static SelectorItem SELECTOR_ITEM_3 = SelectorItem.of("simplePojo3", SIMPLE_POJO_3); + private static SelectorItem SELECTOR_ITEM_4 = SelectorItem.of("simplePojo4", SIMPLE_POJO_4); + private static SelectorItem SELECTOR_ITEM_5 = SelectorItem.of("simplePojo5", SIMPLE_POJO_5); + private static SelectorItem SELECTOR_ITEM_6 = SelectorItem.of("simplePojo6", SIMPLE_POJO_6); - private static SelectorItem SELECTOR_ITEM_7 = SelectorItem.of("simplePojo7", SIMPLE_POJO_7, false, false); - private static SelectorItem SELECTOR_ITEM_8 = SelectorItem.of("simplePojo8", SIMPLE_POJO_8, false, true); + + private static SelectorItem SELECTOR_ITEM_7 = SelectorItem.of("simplePojo7", SIMPLE_POJO_7, false, + false); + + private static SelectorItem SELECTOR_ITEM_8 = SelectorItem.of("simplePojo8", SIMPLE_POJO_8, false, + true); private ExecutorService service; + private CountDownLatch latch; + private AtomicReference>> result; @BeforeEach @@ -99,8 +118,8 @@ void testNoTty() throws Exception { public void testItemsShown() { scheduleSelect(); await().atMost(Duration.ofSeconds(4)) - .untilAsserted(() -> assertStringOrderThat(consoleOut()).containsInOrder("simplePojo1", "simplePojo2", - "simplePojo3", "simplePojo4")); + .untilAsserted(() -> assertStringOrderThat(consoleOut()).containsInOrder("simplePojo1", "simplePojo2", + "simplePojo3", "simplePojo4")); } @Test @@ -108,15 +127,16 @@ public void testMaxItems() { scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_2, SELECTOR_ITEM_3, SELECTOR_ITEM_4, SELECTOR_ITEM_5, SELECTOR_ITEM_6), 6); await().atMost(Duration.ofSeconds(4)) - .untilAsserted(() -> assertStringOrderThat(consoleOut()).containsInOrder("simplePojo1", "simplePojo2", - "simplePojo3", "simplePojo4", "simplePojo5", "simplePojo6")); + .untilAsserted(() -> assertStringOrderThat(consoleOut()).containsInOrder("simplePojo1", "simplePojo2", + "simplePojo3", "simplePojo4", "simplePojo5", "simplePojo6")); } @Test public void testItemsShownWithDisabled() { scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_7)); await().atMost(Duration.ofSeconds(4)) - .untilAsserted(() -> assertStringOrderThat(consoleOut()).containsInOrder("[ ] simplePojo1", "[ ] simplePojo7")); + .untilAsserted( + () -> assertStringOrderThat(consoleOut()).containsInOrder("[ ] simplePojo1", "[ ] simplePojo7")); } @Test @@ -206,7 +226,7 @@ public void testSelectLastBackwards() throws InterruptedException { Stream datas = selected.stream().map(SelectorItem::getItem).map(SimplePojo::getData); assertThat(datas).containsExactlyInAnyOrder("data4"); } - + @Test public void testDefaultSelection() throws InterruptedException { scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_2, SELECTOR_ITEM_7, SELECTOR_ITEM_8)); @@ -224,8 +244,7 @@ public void testDefaultSelection() throws InterruptedException { } private void scheduleSelect() { - scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_2, SELECTOR_ITEM_3, - SELECTOR_ITEM_4)); + scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_2, SELECTOR_ITEM_3, SELECTOR_ITEM_4)); } private void scheduleSelect(Terminal terminal) { @@ -242,8 +261,8 @@ private void scheduleSelect(List> items, Integer maxIte } private void scheduleSelect(List> items, Integer maxItems, Terminal terminal) { - MultiItemSelector> selector = new MultiItemSelector<>(terminal, - items, "testSimple", null); + MultiItemSelector> selector = new MultiItemSelector<>(terminal, items, + "testSimple", null); selector.setResourceLoader(new DefaultResourceLoader()); selector.setTemplateExecutor(getTemplateExecutor()); @@ -263,6 +282,7 @@ private void awaitLatch() throws InterruptedException { } private static class SimplePojo { + String data; SimplePojo(String data) { @@ -281,5 +301,7 @@ static SimplePojo of(String data) { public String toString() { return data; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/PathInputTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/PathInputTests.java index d9875706b..8adddfe9c 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/PathInputTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/PathInputTests.java @@ -44,9 +44,13 @@ public class PathInputTests extends AbstractShellTests { private ExecutorService service; + private CountDownLatch latch1; + private AtomicReference result1; + private FileSystem fileSystem; + private Function pathProvider; @BeforeEach @@ -129,4 +133,5 @@ public void testResultUserInput() throws InterruptedException, IOException { assertThat(run1Context.getResultValue()).isNotNull(); assertThat(run1Context.getResultValue().toString()).contains("tmp"); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/PathSearchTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/PathSearchTests.java index f9f30ffe5..538ac6b57 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/PathSearchTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/PathSearchTests.java @@ -32,65 +32,34 @@ public class PathSearchTests { static Stream testParts() { - return Stream.of( - Arguments.of("0", new int[] { 0 }, - Arrays.asList(PartText.of("0", true))), - Arguments.of("01", new int[] { 0, 1 }, - Arrays.asList( - PartText.of("0", true), - PartText.of("1", true))), - Arguments.of("012", new int[] { 0, 1, 2 }, - Arrays.asList( - PartText.of("0", true), - PartText.of("1", true), - PartText.of("2", true))), - Arguments.of("0123456789", new int[0], - Arrays.asList(PartText.of("0123456789", false))), - Arguments.of("0123456789", new int[] { 0 }, - Arrays.asList( - PartText.of("0", true), - PartText.of("123456789", false))), - Arguments.of("0123456789", new int[] { 1 }, - Arrays.asList( - PartText.of("0", false), - PartText.of("1", true), - PartText.of("23456789", false))), - Arguments.of("0123456789", new int[] { 9 }, - Arrays.asList( - PartText.of("012345678", false), - PartText.of("9", true))), - Arguments.of("0123456789", new int[] { 2, 5 }, - Arrays.asList( - PartText.of("01", false), - PartText.of("2", true), - PartText.of("34", false), - PartText.of("5", true), - PartText.of("6789", false))), - Arguments.of("0123456789", new int[] { 2, 3 }, - Arrays.asList( - PartText.of("01", false), - PartText.of("2", true), - PartText.of("3", true), - PartText.of("456789", false))), - Arguments.of("0123456789", new int[] { 8, 9 }, - Arrays.asList( - PartText.of("01234567", false), - PartText.of("8", true), - PartText.of("9", true))), - Arguments.of("spring-shell-core/build/test-results/test/TEST-org.springframework.shell.support.search.FuzzyMatchV2SearchMatchAlgorithmTests.xml", new int[] { 13, 33, 59, 67, 73 }, - Arrays.asList( - PartText.of("spring-shell-", false), - PartText.of("c", true), - PartText.of("ore/build/test-resu", false), - PartText.of("l", true), - PartText.of("ts/test/TEST-org.springfr", false), - PartText.of("a", true), - PartText.of("mework.", false), - PartText.of("s", true), - PartText.of("hell.", false), - PartText.of("s", true), - PartText.of("upport.search.FuzzyMatchV2SearchMatchAlgorithmTests.xml", false))) - ); + return Stream.of(Arguments.of("0", new int[] { 0 }, Arrays.asList(PartText.of("0", true))), + Arguments.of("01", new int[] { 0, 1 }, Arrays.asList(PartText.of("0", true), PartText.of("1", true))), + Arguments.of("012", new int[] { 0, 1, 2 }, + Arrays.asList(PartText.of("0", true), PartText.of("1", true), PartText.of("2", true))), + Arguments.of("0123456789", new int[0], Arrays.asList(PartText.of("0123456789", false))), + Arguments.of("0123456789", new int[] { 0 }, + Arrays.asList(PartText.of("0", true), PartText.of("123456789", false))), + Arguments.of("0123456789", new int[] { 1 }, + Arrays.asList(PartText.of("0", false), PartText.of("1", true), PartText.of("23456789", false))), + Arguments.of("0123456789", new int[] { 9 }, + Arrays.asList(PartText.of("012345678", false), PartText.of("9", true))), + Arguments.of("0123456789", new int[] { 2, 5 }, + Arrays.asList(PartText.of("01", false), PartText.of("2", true), PartText.of("34", false), + PartText.of("5", true), PartText.of("6789", false))), + Arguments.of("0123456789", new int[] { 2, 3 }, + Arrays.asList(PartText.of("01", false), PartText.of("2", true), PartText.of("3", true), + PartText.of("456789", false))), + Arguments.of("0123456789", new int[] { 8, 9 }, + Arrays.asList(PartText.of("01234567", false), PartText.of("8", true), PartText.of("9", true))), + Arguments.of( + "spring-shell-core/build/test-results/test/TEST-org.springframework.shell.support.search.FuzzyMatchV2SearchMatchAlgorithmTests.xml", + new int[] { 13, 33, 59, 67, 73 }, + Arrays.asList(PartText.of("spring-shell-", false), PartText.of("c", true), + PartText.of("ore/build/test-resu", false), PartText.of("l", true), + PartText.of("ts/test/TEST-org.springfr", false), PartText.of("a", true), + PartText.of("mework.", false), PartText.of("s", true), PartText.of("hell.", false), + PartText.of("s", true), + PartText.of("upport.search.FuzzyMatchV2SearchMatchAlgorithmTests.xml", false)))); } @ParameterizedTest @@ -104,4 +73,5 @@ void testParts(String text, int[] positions, List parts) { assertThat(res.get(i).isMatch()).isEqualTo(parts.get(i).isMatch()); } } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/ShellAssertions.java b/spring-shell-core/src/test/java/org/springframework/shell/component/ShellAssertions.java index b6f8c9b50..273eeeb3d 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/ShellAssertions.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/ShellAssertions.java @@ -51,8 +51,9 @@ public StringOrderAssert containsInOrder(String... expected) { } if (!isSorted(indexes)) { String expectedStr = Stream.of(expected).collect(Collectors.joining(",")); - String indexStr = IntStream.of(indexes).mapToObj(i -> ((Integer) i).toString()) - .collect(Collectors.joining(",")); + String indexStr = IntStream.of(indexes) + .mapToObj(i -> ((Integer) i).toString()) + .collect(Collectors.joining(",")); failWithMessage("Items [%s] are in wrong order, indexes are [%s], output is [%s]", expectedStr, indexStr, actual); } @@ -66,5 +67,7 @@ private boolean isSorted(int[] array) { } return true; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/SingleItemSelectorTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/SingleItemSelectorTests.java index d87de7983..b3e6b3c55 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/SingleItemSelectorTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/SingleItemSelectorTests.java @@ -45,20 +45,33 @@ public class SingleItemSelectorTests extends AbstractShellTests { private static SimplePojo SIMPLE_POJO_1 = SimplePojo.of("data1"); + private static SimplePojo SIMPLE_POJO_2 = SimplePojo.of("data2"); + private static SimplePojo SIMPLE_POJO_3 = SimplePojo.of("data3"); + private static SimplePojo SIMPLE_POJO_4 = SimplePojo.of("data4"); + private static SimplePojo SIMPLE_POJO_5 = SimplePojo.of("data5"); + private static SimplePojo SIMPLE_POJO_6 = SimplePojo.of("data6"); + private static SelectorItem SELECTOR_ITEM_1 = SelectorItem.of("simplePojo1", SIMPLE_POJO_1); + private static SelectorItem SELECTOR_ITEM_2 = SelectorItem.of("simplePojo2", SIMPLE_POJO_2); + private static SelectorItem SELECTOR_ITEM_3 = SelectorItem.of("simplePojo3", SIMPLE_POJO_3); + private static SelectorItem SELECTOR_ITEM_4 = SelectorItem.of("simplePojo4", SIMPLE_POJO_4); + private static SelectorItem SELECTOR_ITEM_5 = SelectorItem.of("simplePojo5", SIMPLE_POJO_5); + private static SelectorItem SELECTOR_ITEM_6 = SelectorItem.of("simplePojo6", SIMPLE_POJO_6); private ExecutorService service; + private CountDownLatch latch; + private AtomicReference>> result; @BeforeEach @@ -81,10 +94,10 @@ public void cleanupMulti() { @Test public void testItemsShownFirstHovered() { scheduleSelect(); - await().atMost(Duration.ofSeconds(4)) - .untilAsserted(() -> { - assertStringOrderThat(consoleOut()).containsInOrder("> simplePojo1", "simplePojo2", "simplePojo3", "simplePojo4"); - }); + await().atMost(Duration.ofSeconds(4)).untilAsserted(() -> { + assertStringOrderThat(consoleOut()).containsInOrder("> simplePojo1", "simplePojo2", "simplePojo3", + "simplePojo4"); + }); } @@ -93,8 +106,8 @@ public void testMaxItems() { scheduleSelect(Arrays.asList(SELECTOR_ITEM_1, SELECTOR_ITEM_2, SELECTOR_ITEM_3, SELECTOR_ITEM_4, SELECTOR_ITEM_5, SELECTOR_ITEM_6), 6); await().atMost(Duration.ofSeconds(4)) - .untilAsserted(() -> assertStringOrderThat(consoleOut()).containsInOrder("simplePojo1", "simplePojo2", - "simplePojo3", "simplePojo4", "simplePojo5", "simplePojo6")); + .untilAsserted(() -> assertStringOrderThat(consoleOut()).containsInOrder("simplePojo1", "simplePojo2", + "simplePojo3", "simplePojo4", "simplePojo5", "simplePojo6")); } @Test @@ -192,8 +205,8 @@ private void scheduleSelect(List> items, Integer maxIte } private void scheduleSelect(List> items, Integer maxItems, Terminal terminal) { - SingleItemSelector> selector = new SingleItemSelector<>(terminal, - items, "testSimple", null); + SingleItemSelector> selector = new SingleItemSelector<>(terminal, items, + "testSimple", null); selector.setResourceLoader(new DefaultResourceLoader()); selector.setTemplateExecutor(getTemplateExecutor()); @@ -217,6 +230,7 @@ private boolean awaitLatch(int seconds) throws InterruptedException { } private static class SimplePojo { + String data; SimplePojo(String data) { @@ -235,5 +249,7 @@ static SimplePojo of(String data) { public String toString() { return data; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java index a0cf26e02..e3fd52d84 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/StringInputTests.java @@ -38,9 +38,13 @@ public class StringInputTests extends AbstractShellTests { private ExecutorService service; + private CountDownLatch latch1; + private CountDownLatch latch2; + private AtomicReference result1; + private AtomicReference result2; @BeforeEach @@ -242,4 +246,5 @@ public void testPassingViaContext() throws InterruptedException { assertThat(run1Context.getResultValue()).isEqualTo("component1ResultValue"); assertThat(run2Context.getResultValue()).isEqualTo("component1ResultValue"); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/context/ComponentContextTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/context/ComponentContextTests.java index 95d13596e..105b0f877 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/context/ComponentContextTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/context/ComponentContextTests.java @@ -45,4 +45,5 @@ public void testBasics() { context.get("foo", Integer.class); }).isInstanceOf(IllegalArgumentException.class); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/AbstractShellTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/AbstractShellTests.java index d8d657bae..e78478882 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/AbstractShellTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/AbstractShellTests.java @@ -44,14 +44,21 @@ public abstract class AbstractShellTests { - private ExecutorService executorService; - private PipedInputStream pipedInputStream; - private PipedOutputStream pipedOutputStream; - private LinkedBlockingQueue bytesQueue; + private ExecutorService executorService; + + private PipedInputStream pipedInputStream; + + private PipedOutputStream pipedOutputStream; + + private LinkedBlockingQueue bytesQueue; + private ByteArrayOutputStream consoleOut; + private Terminal terminal; + private TemplateExecutor templateExecutor; - private ResourceLoader resourceLoader; + + private ResourceLoader resourceLoader; @BeforeEach public void setup() throws Exception { @@ -76,22 +83,23 @@ public ThemeSettings getSettings() { ThemeResolver themeResolver = new ThemeResolver(themeRegistry, "default"); templateExecutor = new TemplateExecutor(themeResolver); - resourceLoader = new DefaultResourceLoader(); + resourceLoader = new DefaultResourceLoader(); - pipedInputStream.connect(pipedOutputStream); + pipedInputStream.connect(pipedOutputStream); terminal = new DumbTerminal("terminal", "ansi", pipedInputStream, consoleOut, StandardCharsets.UTF_8); - terminal.setSize(new Size(1, 1)); - - executorService.execute(() -> { - try { - while (true) { - byte[] take = bytesQueue.take(); - pipedOutputStream.write(take); - pipedOutputStream.flush(); - } - } catch (Exception e) { - } - }); + terminal.setSize(new Size(1, 1)); + + executorService.execute(() -> { + try { + while (true) { + byte[] take = bytesQueue.take(); + pipedOutputStream.write(take); + pipedOutputStream.flush(); + } + } + catch (Exception e) { + } + }); } @AfterEach @@ -104,95 +112,99 @@ protected void write(byte[] bytes) { } protected String consoleOut() { - return AttributedString.fromAnsi(consoleOut.toString()).toString(); + return AttributedString.fromAnsi(consoleOut.toString()).toString(); } protected Terminal getTerminal() { return terminal; } - protected ResourceLoader getResourceLoader() { - return resourceLoader; - } + protected ResourceLoader getResourceLoader() { + return resourceLoader; + } + + protected TemplateExecutor getTemplateExecutor() { + return templateExecutor; + } - protected TemplateExecutor getTemplateExecutor() { - return templateExecutor; - } + protected class TestBuffer { - protected class TestBuffer { - private final ByteArrayOutputStream out = new ByteArrayOutputStream(); + private final ByteArrayOutputStream out = new ByteArrayOutputStream(); - public TestBuffer() { - } + public TestBuffer() { + } - public TestBuffer(String str) { - append(str); - } + public TestBuffer(String str) { + append(str); + } - public TestBuffer(char[] chars) { - append(new String(chars)); - } + public TestBuffer(char[] chars) { + append(new String(chars)); + } - @Override - public String toString() { - try { - return out.toString(StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } + @Override + public String toString() { + try { + return out.toString(StandardCharsets.UTF_8.name()); + } + catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } - public TestBuffer cr() { + public TestBuffer cr() { return append("\r"); - } + } - public TestBuffer backspace() { - return append(del()); - } + public TestBuffer backspace() { + return append(del()); + } - public TestBuffer backspace(int count) { - TestBuffer buf = this; - for (int i = 0; i < count; i++) { - buf = backspace(); - } - return buf; - } + public TestBuffer backspace(int count) { + TestBuffer buf = this; + for (int i = 0; i < count; i++) { + buf = backspace(); + } + return buf; + } public TestBuffer down() { return append("\033[B"); - } + } public TestBuffer ctrl(char let) { - return append(KeyMap.ctrl(let)); - } + return append(KeyMap.ctrl(let)); + } - public TestBuffer ctrlE() { - return ctrl('E'); - } + public TestBuffer ctrlE() { + return ctrl('E'); + } - public TestBuffer ctrlY() { - return ctrl('Y'); - } + public TestBuffer ctrlY() { + return ctrl('Y'); + } public TestBuffer space() { return append(" "); - } - - public byte[] getBytes() { - return out.toByteArray(); - } - - public TestBuffer append(final String str) { - for (byte b : str.getBytes(StandardCharsets.UTF_8)) { - append(b); - } - return this; - } - - public TestBuffer append(final int i) { - // consoleOut.reset(); - out.write((byte) i); - return this; - } + } + + public byte[] getBytes() { + return out.toByteArray(); + } + + public TestBuffer append(final String str) { + for (byte b : str.getBytes(StandardCharsets.UTF_8)) { + append(b); + } + return this; + } + + public TestBuffer append(final int i) { + // consoleOut.reset(); + out.write((byte) i); + return this; + } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java index 3510a38cf..da9aed26c 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/flow/ComponentFlowTests.java @@ -44,28 +44,28 @@ public void testSimpleFlow() throws InterruptedException { List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); ComponentFlow wizard = ComponentFlow.builder() - .terminal(getTerminal()) - .resourceLoader(getResourceLoader()) - .templateExecutor(getTemplateExecutor()) - .withStringInput("field1") - .name("Field1") - .defaultValue("defaultField1Value") - .and() - .withStringInput("field2") - .name("Field2") - .and() - .withPathInput("path1") - .name("Path1") - .and() - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .and() - .withMultiItemSelector("multi1") - .name("Multi1") - .selectItems(multi1SelectItems) - .and() - .build(); + .terminal(getTerminal()) + .resourceLoader(getResourceLoader()) + .templateExecutor(getTemplateExecutor()) + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .and() + .withStringInput("field2") + .name("Field2") + .and() + .withPathInput("path1") + .name("Path1") + .and() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .and() + .withMultiItemSelector("multi1") + .name("Multi1") + .selectItems(multi1SelectItems) + .and() + .build(); ExecutorService service = Executors.newFixedThreadPool(1); CountDownLatch latch = new CountDownLatch(1); @@ -113,54 +113,54 @@ public void testSkipsGivenComponents() throws InterruptedException { ComponentFlow wizard = ComponentFlow.builder() .terminal(getTerminal()) .withStringInput("id1") - .name("name") - .resultValue("value1") - .resultMode(ResultMode.ACCEPT) - .and() + .name("name") + .resultValue("value1") + .resultMode(ResultMode.ACCEPT) + .and() .withPathInput("id2") - .name("name") - .resultValue("value2") - .resultMode(ResultMode.ACCEPT) - .and() + .name("name") + .resultValue("value2") + .resultMode(ResultMode.ACCEPT) + .and() .withSingleItemSelector("id3") - .resultValue("value3") - .resultMode(ResultMode.ACCEPT) - .and() + .resultValue("value3") + .resultMode(ResultMode.ACCEPT) + .and() .withMultiItemSelector("id4") - .resultValues(Arrays.asList("value4")) - .resultMode(ResultMode.ACCEPT) - .and() + .resultValues(Arrays.asList("value4")) + .resultMode(ResultMode.ACCEPT) + .and() .withConfirmationInput("id5") - .resultValue(false) - .resultMode(ResultMode.ACCEPT) - .and() + .resultValue(false) + .resultMode(ResultMode.ACCEPT) + .and() .build(); - ExecutorService service = Executors.newFixedThreadPool(1); - CountDownLatch latch = new CountDownLatch(1); - AtomicReference result = new AtomicReference<>(); + ExecutorService service = Executors.newFixedThreadPool(1); + CountDownLatch latch = new CountDownLatch(1); + AtomicReference result = new AtomicReference<>(); - service.execute(() -> { - result.set(wizard.run()); - latch.countDown(); - }); + service.execute(() -> { + result.set(wizard.run()); + latch.countDown(); + }); - latch.await(4, TimeUnit.SECONDS); - ComponentFlowResult inputWizardResult = result.get(); - assertThat(inputWizardResult).isNotNull(); + latch.await(4, TimeUnit.SECONDS); + ComponentFlowResult inputWizardResult = result.get(); + assertThat(inputWizardResult).isNotNull(); - String id1 = inputWizardResult.getContext().get("id1"); - Path id2 = inputWizardResult.getContext().get("id2"); - String id3 = inputWizardResult.getContext().get("id3"); - List id4 = inputWizardResult.getContext().get("id4"); - Boolean id5 = inputWizardResult.getContext().get("id5"); + String id1 = inputWizardResult.getContext().get("id1"); + Path id2 = inputWizardResult.getContext().get("id2"); + String id3 = inputWizardResult.getContext().get("id3"); + List id4 = inputWizardResult.getContext().get("id4"); + Boolean id5 = inputWizardResult.getContext().get("id5"); - assertThat(id1).isEqualTo("value1"); - assertThat(id2.toString()).contains("value2"); - assertThat(id3).isEqualTo("value3"); - assertThat(id4).containsExactlyInAnyOrder("value4"); - assertThat(id5).isFalse(); - } + assertThat(id1).isEqualTo("value1"); + assertThat(id2.toString()).contains("value2"); + assertThat(id3).isEqualTo("value3"); + assertThat(id4).containsExactlyInAnyOrder("value4"); + assertThat(id5).isFalse(); + } @Test public void testChoosesDynamicallyShouldJumpOverAndStop() throws InterruptedException { @@ -169,21 +169,21 @@ public void testChoosesDynamicallyShouldJumpOverAndStop() throws InterruptedExce .resourceLoader(getResourceLoader()) .templateExecutor(getTemplateExecutor()) .withStringInput("id1") - .name("name") - .next(ctx -> ctx.get("id1")) - .and() + .name("name") + .next(ctx -> ctx.get("id1")) + .and() .withStringInput("id2") - .name("name") - .resultValue("value2") - .resultMode(ResultMode.ACCEPT) - .next(ctx -> null) - .and() + .name("name") + .resultValue("value2") + .resultMode(ResultMode.ACCEPT) + .next(ctx -> null) + .and() .withStringInput("id3") - .name("name") - .resultValue("value3") - .resultMode(ResultMode.ACCEPT) - .next(ctx -> null) - .and() + .name("name") + .resultValue("value3") + .resultMode(ResultMode.ACCEPT) + .next(ctx -> null) + .and() .build(); ExecutorService service = Executors.newFixedThreadPool(1); @@ -217,21 +217,21 @@ public void testChoosesDynamicallyShouldNotContinueToNext() throws InterruptedEx .resourceLoader(getResourceLoader()) .templateExecutor(getTemplateExecutor()) .withStringInput("id1") - .name("name") - .next(ctx -> ctx.get("id1")) - .and() + .name("name") + .next(ctx -> ctx.get("id1")) + .and() .withStringInput("id2") - .name("name") - .resultValue("value2") - .resultMode(ResultMode.ACCEPT) - .next(ctx -> null) - .and() + .name("name") + .resultValue("value2") + .resultMode(ResultMode.ACCEPT) + .next(ctx -> null) + .and() .withStringInput("id3") - .name("name") - .resultValue("value3") - .resultMode(ResultMode.ACCEPT) - .next(ctx -> null) - .and() + .name("name") + .resultValue("value3") + .resultMode(ResultMode.ACCEPT) + .next(ctx -> null) + .and() .build(); ExecutorService service = Executors.newFixedThreadPool(1); @@ -265,21 +265,21 @@ public void testChoosesNonExistingComponent() throws InterruptedException { .resourceLoader(getResourceLoader()) .templateExecutor(getTemplateExecutor()) .withStringInput("id1") - .name("name") - .next(ctx -> ctx.get("id1")) - .and() + .name("name") + .next(ctx -> ctx.get("id1")) + .and() .withStringInput("id2") - .name("name") - .resultValue("value2") - .resultMode(ResultMode.ACCEPT) - .next(ctx -> null) - .and() + .name("name") + .resultValue("value2") + .resultMode(ResultMode.ACCEPT) + .next(ctx -> null) + .and() .withStringInput("id3") - .name("name") - .resultValue("value3") - .resultMode(ResultMode.ACCEPT) - .next(ctx -> null) - .and() + .name("name") + .resultValue("value3") + .resultMode(ResultMode.ACCEPT) + .next(ctx -> null) + .and() .build(); ExecutorService service = Executors.newFixedThreadPool(1); @@ -312,15 +312,15 @@ public void testAutoShowsDefault() throws InterruptedException { single1SelectItems.put("key1", "value1"); single1SelectItems.put("key2", "value2"); ComponentFlow wizard = ComponentFlow.builder() - .terminal(getTerminal()) - .resourceLoader(getResourceLoader()) - .templateExecutor(getTemplateExecutor()) - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .defaultSelect("key2") - .and() - .build(); + .terminal(getTerminal()) + .resourceLoader(getResourceLoader()) + .templateExecutor(getTemplateExecutor()) + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .defaultSelect("key2") + .and() + .build(); ExecutorService service = Executors.newFixedThreadPool(1); CountDownLatch latch = new CountDownLatch(1); @@ -350,14 +350,8 @@ public void testBuilderSingleTypes() { selectItems2.put("key2", "value2"); selectItems2.put("key3", "value3"); - Builder builder1 = ComponentFlow.builder() - .withSingleItemSelector("field1") - .selectItems(selectItems1) - .and(); - Builder builder2 = ComponentFlow.builder() - .withSingleItemSelector("field2") - .selectItems(selectItems2) - .and(); + Builder builder1 = ComponentFlow.builder().withSingleItemSelector("field1").selectItems(selectItems1).and(); + Builder builder2 = ComponentFlow.builder().withSingleItemSelector("field2").selectItems(selectItems2).and(); List field1 = (List) ReflectionTestUtils.getField(builder1, "singleItemSelectors"); @@ -371,4 +365,5 @@ public void testBuilderSingleTypes() { assertThat(selectItems11).hasSize(2); assertThat(selectItems21).hasSize(2); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/support/SelectorListTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/support/SelectorListTests.java index d4a4b8e3d..18abfd8d9 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/support/SelectorListTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/support/SelectorListTests.java @@ -243,6 +243,7 @@ void upWhenLessItemsThanMax() { private static class TestItem implements Nameable { String name; + TestItem(String name) { this.name = name; } @@ -251,22 +252,22 @@ private static class TestItem implements Nameable { public String getName() { return name; } + } List items(int count) { - return IntStream.range(0, count) - .mapToObj(i -> { - return new TestItem("name" + i); - }) - .collect(Collectors.toList()); + return IntStream.range(0, count).mapToObj(i -> { + return new TestItem("name" + i); + }).collect(Collectors.toList()); } @SuppressWarnings("rawtypes") InstanceOfAssertFactory> SELECTOR_LIST = selectorList(TestItem.class); @SuppressWarnings("rawtypes") - static InstanceOfAssertFactory> selectorList(Class resultType) { - return new InstanceOfAssertFactory<>(SelectorList.class, SelectorListAssertions:: assertThat); + static InstanceOfAssertFactory> selectorList( + Class resultType) { + return new InstanceOfAssertFactory<>(SelectorList.class, SelectorListAssertions::assertThat); } static class SelectorListAssertions { @@ -274,6 +275,7 @@ static class SelectorListAssertions { public static SelectorListAssert assertThat(SelectorList actual) { return new SelectorListAssert<>(actual); } + } static class SelectorListAssert extends AbstractAssert, SelectorList> { @@ -284,7 +286,8 @@ public SelectorListAssert(SelectorList actual) { public SelectorListAssert namesContainsExactly(String... names) { isNotNull(); - List actualNames = actual.getProjection().stream() + List actualNames = actual.getProjection() + .stream() .map(i -> i.getName()) .collect(Collectors.toList()); assertThat(actualNames).containsExactly(names); @@ -293,7 +296,8 @@ public SelectorListAssert namesContainsExactly(String... names) { public SelectorListAssert selectedContainsExactly(Boolean... selected) { isNotNull(); - List actualSelected = actual.getProjection().stream() + List actualSelected = actual.getProjection() + .stream() .map(i -> i.isSelected()) .collect(Collectors.toList()); assertThat(actualSelected).containsExactly(selected); @@ -305,5 +309,7 @@ public SelectorListAssert hasProjectionSize(int size) { assertThat(actual.getProjection()).hasSize(size); return this; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssert.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssert.java index 131e2a760..944d4d6a2 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssert.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssert.java @@ -29,8 +29,8 @@ import static org.assertj.core.api.Assertions.assertThat; /** - * Asserts for {@link Screen}. This is a work-in-progress implementation and - * relevant parts are copied into spring-shell-test. + * Asserts for {@link Screen}. This is a work-in-progress implementation and relevant + * parts are copied into spring-shell-test. * * @author Janne Valkealahti */ @@ -42,7 +42,6 @@ public ScreenAssert(Screen actual) { /** * Verifies that the actual {@link Screen} has a cursor visible. - * * @return this assertion object */ public ScreenAssert hasCursorVisible() { @@ -55,7 +54,6 @@ public ScreenAssert hasCursorVisible() { /** * Verifies that the actual {@link Screen} has a cursor in a given position. - * * @param x a x position in a screen * @param y a y position in a screen * @return this assertion object @@ -72,7 +70,6 @@ public ScreenAssert hasCursorInPosition(int x, int y) { /** * Verifies that the actual {@link Screen} has a foreground color in a position. - * * @param x a x position in a screen * @param y a y position in a screen * @param color the color @@ -84,15 +81,14 @@ public ScreenAssert hasForegroundColor(int x, int y, int color) { ScreenItem i = items[y][x]; int expectedColor = i.getForeground(); if (expectedColor != color) { - failWithMessage("Expecting a Screen to have foreground color <%s> position <%s,%s> but was <%s>", color, x, y, - expectedColor); + failWithMessage("Expecting a Screen to have foreground color <%s> position <%s,%s> but was <%s>", color, x, + y, expectedColor); } return this; } /** * Verifies that the actual {@link Screen} has a foreground style in a position. - * * @param x a x position in a screen * @param y a y position in a screen * @param color the style @@ -105,14 +101,13 @@ public ScreenAssert hasStyle(int x, int y, int style) { int expectedStyle = i.getStyle(); if (expectedStyle != style) { failWithMessage("Expecting a Screen to have style <%s> position <%s,%s> but was <%s>", style, x, y, - expectedStyle); + expectedStyle); } return this; } /** * Verifies that the actual {@link Screen} has a background color in a position. - * * @param x a x position in a screen * @param y a y position in a screen * @param color the color @@ -124,19 +119,18 @@ public ScreenAssert hasBackgroundColor(int x, int y, int color) { ScreenItem i = items[y][x]; int expectedColor = i.getBackground(); if (expectedColor != color) { - failWithMessage("Expecting a Screen to have background color <%s> position <%s,%s> but was <%s>", color, x, y, - expectedColor); + failWithMessage("Expecting a Screen to have background color <%s> position <%s,%s> but was <%s>", color, x, + y, expectedColor); } return this; } /** - * Verifies that a given bounded box is legal for a screen and that characters - * along border look like border characters. - * + * Verifies that a given bounded box is legal for a screen and that characters along + * border look like border characters. * @param x a x position in a screen * @param y a y position in a screen - * @param width a width in a screen + * @param width a width in a screen * @param height a height in a screen * @return this assertion object */ @@ -145,12 +139,11 @@ public ScreenAssert hasBorder(int x, int y, int width, int height) { } /** - * Verifies that a given bounded box is legal for a screen and that characters - * along border doesn't look like border characters. - * + * Verifies that a given bounded box is legal for a screen and that characters along + * border doesn't look like border characters. * @param x a x position in a screen * @param y a y position in a screen - * @param width a width in a screen + * @param width a width in a screen * @param height a height in a screen * @return this assertion object */ @@ -161,7 +154,6 @@ public ScreenAssert hasNoBorder(int x, int y, int width, int height) { /** * Verifies that a given text can be found from a screen coordinates following * horizontal width. - * * @param text a text to verify * @param x a x position of a text * @param y a y position of a text @@ -187,7 +179,6 @@ public ScreenAssert hasHorizontalText(String text, int x, int y, int width) { /** * Verifies that a given text can not be found from a screen coordinates following * horizontal width. - * * @param text a text to verify * @param x a x position of a text * @param y a y position of a text @@ -223,7 +214,8 @@ private String screenError(int x, int y, int width, int height) { Screen clip = actual.clip(x, y, width, height); if (clip instanceof DisplayLines dl2) { List screenLines2 = dl2.getScreenLines(); - buf.append(String.format("%nhave border in bounded box x=%s y=%s width=%s height=%s, was:%n", x, y, width, height)); + buf.append(String.format("%nhave border in bounded box x=%s y=%s width=%s height=%s, was:%n", x, y, + width, height)); for (AttributedString line : screenLines2) { buf.append(String.format("%n %s", AttributedString.stripAnsi(line.toString()))); } @@ -323,4 +315,5 @@ private void checkBounds(ScreenItem[][] content, int x, int y, int width, int he failWithMessage("Can't assert position x %s as width is %s", x, content[0].length); } } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssertTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssertTests.java index 4f9300df7..96493f497 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssertTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/ScreenAssertTests.java @@ -54,7 +54,8 @@ void hasForegroundColorShouldFail() { screen.writerBuilder().color(Color.RED).build().text("test", 0, 0); assertThatExceptionOfType(AssertionError.class) .isThrownBy(() -> assertThat(forScreen(screen)).hasForegroundColor(0, 0, Color.BLUE)) - .withMessageContaining("Expecting a Screen to have foreground color <255> position <0,0> but was <16711680>"); + .withMessageContaining( + "Expecting a Screen to have foreground color <255> position <0,0> but was <16711680>"); } @Test @@ -151,12 +152,13 @@ void hasNoHorizontalText() { // @Test // void xxx() { - // Screen screen = new Screen(5, 5); - // screen.printBorder(0, 0, 5, 5); - // assertThat(forScreen(screen)).hasBorder(0, 0, 5, 4); + // Screen screen = new Screen(5, 5); + // screen.printBorder(0, 0, 5, 5); + // assertThat(forScreen(screen)).hasBorder(0, 0, 5, 4); // } private AssertProvider forScreen(Screen screen) { return () -> new ScreenAssert(screen); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java index 4f1e042d0..b7e9c0867 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AbstractViewTests.java @@ -36,10 +36,15 @@ public class AbstractViewTests { protected Screen screen24x80; + protected Screen screen1x80; + protected Screen screen7x10; + protected Screen screen10x10; + protected Screen screen0x0; + protected DefaultEventLoop eventLoop; @BeforeEach @@ -74,16 +79,12 @@ protected void configure(View view) { if (view instanceof AbstractView v) { v.setEventLoop(eventLoop); } - eventLoop.onDestroy(eventLoop.mouseEvents() - .doOnNext(m -> { - view.getMouseHandler().handle(MouseHandler.argsOf(m)); - }) - .subscribe()); - eventLoop.onDestroy(eventLoop.keyEvents() - .doOnNext(m -> { - view.getKeyHandler().handle(KeyHandler.argsOf(m)); - }) - .subscribe()); + eventLoop.onDestroy(eventLoop.mouseEvents().doOnNext(m -> { + view.getMouseHandler().handle(MouseHandler.argsOf(m)); + }).subscribe()); + eventLoop.onDestroy(eventLoop.keyEvents().doOnNext(m -> { + view.getKeyHandler().handle(KeyHandler.argsOf(m)); + }).subscribe()); } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AppViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AppViewTests.java index 150d16554..e612b63bf 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AppViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/AppViewTests.java @@ -108,6 +108,7 @@ void shouldOfferKeysToMainIfMenuHaveNoFocus() { verify(smain).getKeyHandler(); verify(smenu, never()).getKeyHandler(); } + } @Nested @@ -180,6 +181,7 @@ void onlyStatusVisible() { verify(main).setRect(0, 0, 80, 23); verify(status).setRect(0, 23, 80, 1); } + } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/BoxViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/BoxViewTests.java index 199f35d7c..bd5beb46c 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/BoxViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/BoxViewTests.java @@ -97,4 +97,5 @@ void mouseClickOutOfBounds() { assertThat(r.capture()).isEqualTo(view); }); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ButtonViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ButtonViewTests.java index 7e804a315..e3fed4765 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ButtonViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ButtonViewTests.java @@ -35,6 +35,7 @@ class ButtonViewTests extends AbstractViewTests { static final String TEXT_FIELD = "text"; static final String ACTION_FIELD = "action"; + private ButtonView view; @Nested @@ -56,7 +57,8 @@ void text() { @Test void textAndAction() { - view = new ButtonView("text", () -> {}); + view = new ButtonView("text", () -> { + }); assertThat(getStringField(view, TEXT_FIELD)).isEqualTo("text"); assertThat(getRunnableField(view, ACTION_FIELD)).isNotNull(); } @@ -65,7 +67,8 @@ void textAndAction() { void canSetTextAndAction() { view = new ButtonView(); view.setText("text"); - view.setAction(() -> {}); + view.setAction(() -> { + }); assertThat(getStringField(view, TEXT_FIELD)).isEqualTo("text"); assertThat(getRunnableField(view, ACTION_FIELD)).isNotNull(); } @@ -86,12 +89,8 @@ void setup() { void handlesMouseClick() { MouseEvent click = mouseClick(1, 1); - Flux actions = eventLoop - .viewEvents(ButtonViewSelectEvent.class); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux actions = eventLoop.viewEvents(ButtonViewSelectEvent.class); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); MouseHandlerResult result = handleMouseClick(view, click); @@ -103,12 +102,8 @@ void handlesMouseClick() { @Test void handlesKeyEnter() { - Flux actions = eventLoop - .viewEvents(ButtonViewSelectEvent.class); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux actions = eventLoop.viewEvents(ButtonViewSelectEvent.class); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); KeyHandlerResult result = handleKey(view, KeyEvent.Key.Enter); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/DialogViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/DialogViewTests.java index c21b57abf..b3e548bdc 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/DialogViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/DialogViewTests.java @@ -64,18 +64,10 @@ void setup() { void handlesMouseClick() { MouseEvent click = mouseClick(1, 6); - Flux actions1 = eventLoop - .viewEvents(ButtonViewSelectEvent.class); - Flux actions2 = eventLoop - .viewEvents(DialogViewCloseEvent.class); - StepVerifier verifier1 = StepVerifier.create(actions1) - .expectNextCount(1) - .thenCancel() - .verifyLater(); - StepVerifier verifier2 = StepVerifier.create(actions2) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux actions1 = eventLoop.viewEvents(ButtonViewSelectEvent.class); + Flux actions2 = eventLoop.viewEvents(DialogViewCloseEvent.class); + StepVerifier verifier1 = StepVerifier.create(actions1).expectNextCount(1).thenCancel().verifyLater(); + StepVerifier verifier2 = StepVerifier.create(actions2).expectNextCount(1).thenCancel().verifyLater(); MouseHandlerResult result = handleMouseClick(view, click); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/GridViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/GridViewTests.java index 455be78bb..5a8a8a0cd 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/GridViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/GridViewTests.java @@ -28,7 +28,6 @@ class GridViewTests extends AbstractViewTests { - @Nested class ItemPositions { @@ -579,6 +578,7 @@ void simpleNestedGridWithBorders() { verify(grid2).setRect(1, 1, 78, 22); verify(box).setRect(2, 2, 76, 20); } + } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java index e771e9cc0..be9839bdc 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/InputViewTests.java @@ -33,6 +33,7 @@ class InputViewTests extends AbstractViewTests { private static final String CURSOR_INDEX_FIELD = "cursorIndex"; + private static final String CURSOR_POSITION_METHOD = "cursorPosition"; InputView view; @@ -221,12 +222,8 @@ void setup() { @Test void handlesKeyEnter() { - Flux actions = eventLoop - .viewEvents(ViewDoneEvent.class); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux actions = eventLoop.viewEvents(ViewDoneEvent.class); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); KeyHandlerResult result = handleKey(view, KeyEvent.Key.Enter); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java index bcd6ab043..46d72a827 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ListViewTests.java @@ -49,13 +49,17 @@ class ListViewTests extends AbstractViewTests { - private final static ParameterizedTypeReference> LISTVIEW_STRING_TYPEREF - = new ParameterizedTypeReference>() {}; + private final static ParameterizedTypeReference> LISTVIEW_STRING_TYPEREF = new ParameterizedTypeReference>() { + }; private static final String SELECTED_FIELD = "selected"; + private static final String START_FIELD = "start"; + private static final String POSITION_FIELD = "pos"; + private static final String SCROLL_METHOD = "scrollIndex"; + ListView view; ThemeResolver themeResolver; @@ -89,7 +93,6 @@ public String highlight() { themeResolver = new ThemeResolver(themeRegistry, "default"); } - @Nested class Events { @@ -100,12 +103,8 @@ void arrowKeysMoveActive() { view.setRect(0, 0, 80, 24); view.setItems(Arrays.asList("item1", "item2")); - Flux> actions = eventLoop - .viewEvents(LISTVIEW_STRING_TYPEREF); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux> actions = eventLoop.viewEvents(LISTVIEW_STRING_TYPEREF); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); KeyEvent eventDown = KeyEvent.of(Key.CursorDown); KeyHandlerResult result = view.getKeyHandler().handle(KeyHandler.argsOf(eventDown)); @@ -125,12 +124,8 @@ void mouseWheelMoveActive() { view.setRect(0, 0, 80, 24); view.setItems(Arrays.asList("item1", "item2")); - Flux> actions = eventLoop - .viewEvents(LISTVIEW_STRING_TYPEREF); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux> actions = eventLoop.viewEvents(LISTVIEW_STRING_TYPEREF); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); MouseEvent eventDown = mouseWheelDown(0, 0); MouseHandlerResult result = view.getMouseHandler().handle(MouseHandler.argsOf(eventDown)); @@ -150,12 +145,8 @@ void mouseClickMoveActive() { view.setRect(0, 0, 80, 24); view.setItems(Arrays.asList("item1", "item2")); - Flux> actions = eventLoop - .viewEvents(LISTVIEW_STRING_TYPEREF); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux> actions = eventLoop.viewEvents(LISTVIEW_STRING_TYPEREF); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); MouseEvent event01 = mouseClick(0, 1); view.getMouseHandler().handle(MouseHandler.argsOf(event01)); @@ -535,6 +526,7 @@ public void draw(Screen screen) { writer.text(String.format("pre-%s-post", getItem()), rect.x(), rect.y()); writer.background(rect, getBackgroundColor()); } + } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java index 1cb8f706c..97e6553cb 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuBarViewTests.java @@ -34,6 +34,7 @@ class MenuBarViewTests extends AbstractViewTests { private static final String SELECTED_FIELD = "activeItemIndex"; + private static final String MENUVIEW_FIELD = "currentMenuView"; @Nested @@ -59,6 +60,7 @@ void hotkeys() { item = MenuBarItem.of("title").setHotKey(Key.f); assertThat(item.getHotKey()).isEqualTo(Key.f); } + } @Nested @@ -117,7 +119,7 @@ void hasBorder() { // @Nested // class Selection { - // MenuBarView view; + // MenuBarView view; // } @@ -236,14 +238,9 @@ void arrowKeysMoveBetweenDifferentMenus() { @Test void menuHasPositionRelativeToHeader() { - MenuBarView view = new MenuBarView(new MenuBarItem[] { - new MenuBarItem("menu1", new MenuItem[] { - new MenuItem("sub11") - }), - new MenuBarItem("menu2", new MenuItem[] { - new MenuItem("sub21") - }) - }); + MenuBarView view = new MenuBarView( + new MenuBarItem[] { new MenuBarItem("menu1", new MenuItem[] { new MenuItem("sub11") }), + new MenuBarItem("menu2", new MenuItem[] { new MenuItem("sub21") }) }); configure(view); view.setRect(0, 0, 20, 1); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java index 295ea823e..2f98030f4 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/MenuViewTests.java @@ -45,7 +45,9 @@ class MenuViewTests extends AbstractViewTests { private static final String SELECTED_FIELD = "activeItemIndex"; + private static final String RADIO_ACTIVE_FIELD = "radioActive"; + private static final String CHECKED_ACTIVE_FIELD = "checkedActive"; ThemeResolver themeResolver; @@ -87,43 +89,29 @@ class Construction { void constructView() { MenuView view; - view = new MenuView(new MenuItem[] { - MenuItem.of("sub1"), - MenuItem.of("sub2") - }); + view = new MenuView(new MenuItem[] { MenuItem.of("sub1"), MenuItem.of("sub2") }); assertThat(view.getItems()).hasSize(2); - view = new MenuView(new MenuItem[] { - new MenuItem("sub1"), - new MenuItem("sub2") - }); + view = new MenuView(new MenuItem[] { new MenuItem("sub1"), new MenuItem("sub2") }); assertThat(view.getItems()).hasSize(2); - view = new MenuView(new MenuItem[] { - MenuItem.of("sub1", MenuItemCheckStyle.RADIO), - MenuItem.of("sub2", MenuItemCheckStyle.RADIO) - }); + view = new MenuView(new MenuItem[] { MenuItem.of("sub1", MenuItemCheckStyle.RADIO), + MenuItem.of("sub2", MenuItemCheckStyle.RADIO) }); assertThat(view.getItems()).hasSize(2); - view = new MenuView(new MenuItem[] { - new MenuItem("sub1", MenuItemCheckStyle.RADIO), - new MenuItem("sub2", MenuItemCheckStyle.RADIO) - }); + view = new MenuView(new MenuItem[] { new MenuItem("sub1", MenuItemCheckStyle.RADIO), + new MenuItem("sub2", MenuItemCheckStyle.RADIO) }); assertThat(view.getItems()).hasSize(2); - view = new MenuView(new MenuItem[] { - new MenuItem("sub1", MenuItemCheckStyle.RADIO, null, true), - new MenuItem("sub2", MenuItemCheckStyle.RADIO, null, false) - }); + view = new MenuView(new MenuItem[] { new MenuItem("sub1", MenuItemCheckStyle.RADIO, null, true), + new MenuItem("sub2", MenuItemCheckStyle.RADIO, null, false) }); assertThat(view.getItems()).hasSize(2); MenuItem radioActive = (MenuItem) ReflectionTestUtils.getField(view, RADIO_ACTIVE_FIELD); assertThat(radioActive).isNotNull(); assertThat(radioActive.getTitle()).isEqualTo("sub1"); - view = new MenuView(new MenuItem[] { - new MenuItem("sub1", MenuItemCheckStyle.CHECKED, null, true), - new MenuItem("sub2", MenuItemCheckStyle.CHECKED, null, true) - }); + view = new MenuView(new MenuItem[] { new MenuItem("sub1", MenuItemCheckStyle.CHECKED, null, true), + new MenuItem("sub2", MenuItemCheckStyle.CHECKED, null, true) }); assertThat(view.getItems()).hasSize(2); Set checkedActive = (Set) ReflectionTestUtils.getField(view, CHECKED_ACTIVE_FIELD); assertThat(checkedActive).isNotNull(); @@ -133,7 +121,8 @@ void constructView() { @Test void constructItem() { MenuItem item; - Runnable runnable = () -> {}; + Runnable runnable = () -> { + }; item = new MenuItem("title", MenuItemCheckStyle.RADIO, runnable, true); assertThat(item.getTitle()).isEqualTo("title"); @@ -152,10 +141,9 @@ void constructItem() { void constructUsingRunnable() { MenuView view; - view = new MenuView(new MenuItem[] { - MenuItem.of("sub1", MenuItemCheckStyle.RADIO, () -> {}), - MenuItem.of("sub2", MenuItemCheckStyle.RADIO, () -> {}) - }); + view = new MenuView(new MenuItem[] { MenuItem.of("sub1", MenuItemCheckStyle.RADIO, () -> { + }), MenuItem.of("sub2", MenuItemCheckStyle.RADIO, () -> { + }) }); assertThat(view.getItems()).hasSize(2); } @@ -220,10 +208,7 @@ class Selection { @BeforeEach void setup() { - view = new MenuView(new MenuItem[] { - MenuItem.of("sub1"), - MenuItem.of("sub2") - }); + view = new MenuView(new MenuItem[] { MenuItem.of("sub1"), MenuItem.of("sub2") }); configure(view); view.setRect(0, 0, 10, 10); } @@ -290,17 +275,24 @@ void selectionShouldNotMoveOutOfBounds() { void canSelectManually() { } + } @Nested class Checked { MenuItem sub1; + MenuItem sub2; + MenuItem sub3; + MenuItem sub4; + MenuItem sub5; + MenuItem sub6; + MenuView view; @BeforeEach @@ -382,10 +374,7 @@ class Events { @BeforeEach void setup() { - view = new MenuView(new MenuItem[] { - MenuItem.of("sub1"), - MenuItem.of("sub2") - }); + view = new MenuView(new MenuItem[] { MenuItem.of("sub1"), MenuItem.of("sub2") }); configure(view); view.setRect(0, 0, 10, 10); } @@ -395,11 +384,8 @@ void handlesMouseClickInItem() { MouseEvent click = mouseClick(0, 2); Flux actions = eventLoop - .viewEvents(MenuViewSelectedItemChangedEvent.class); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + .viewEvents(MenuViewSelectedItemChangedEvent.class); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); MouseHandlerResult result = handleMouseClick(view, click); @@ -414,12 +400,8 @@ void handlesMouseClickInItem() { @Test void keySelectSendsEvent() { - Flux actions = eventLoop - .viewEvents(MenuViewOpenSelectedItemEvent.class); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + Flux actions = eventLoop.viewEvents(MenuViewOpenSelectedItemEvent.class); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); handleKey(view, Key.Enter); verifier.verify(Duration.ofSeconds(1)); @@ -428,11 +410,8 @@ void keySelectSendsEvent() { @Test void selectionChangedSendsEvent() { Flux actions = eventLoop - .viewEvents(MenuViewSelectedItemChangedEvent.class); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + .viewEvents(MenuViewSelectedItemChangedEvent.class); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); handleKey(view, Key.CursorDown); verifier.verify(Duration.ofSeconds(1)); @@ -442,14 +421,12 @@ void selectionChangedSendsEvent() { @Nested class Visual { + MenuView view; @BeforeEach void setup() { - view = new MenuView(new MenuItem[] { - MenuItem.of("sub1"), - MenuItem.of("sub2") - }); + view = new MenuView(new MenuItem[] { MenuItem.of("sub1"), MenuItem.of("sub2") }); configure(view); view.setRect(0, 0, 10, 10); } @@ -463,6 +440,7 @@ void hasDefaultItemSelected() { view.draw(screen24x80); assertThat(forScreen(screen24x80)).hasHorizontalText("sub1", 0, 1, 5); } + } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ProgressViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ProgressViewTests.java index 1c5f45da4..273321f3e 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ProgressViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/ProgressViewTests.java @@ -146,14 +146,8 @@ void plainStartStop() { Flux startEvents = eventLoop.viewEvents(ProgressViewStartEvent.class); Flux endEvents = eventLoop.viewEvents(ProgressViewEndEvent.class); - StepVerifier startVerifier = StepVerifier.create(startEvents) - .expectNextCount(1) - .thenCancel() - .verifyLater(); - StepVerifier endVerifier = StepVerifier.create(endEvents) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier startVerifier = StepVerifier.create(startEvents).expectNextCount(1).thenCancel().verifyLater(); + StepVerifier endVerifier = StepVerifier.create(endEvents).expectNextCount(1).thenCancel().verifyLater(); view.start(); view.stop(); @@ -164,10 +158,7 @@ void plainStartStop() { @Test void stateChangeWithTickValue() { Flux changeEvents = eventLoop.viewEvents(ProgressViewStateChangeEvent.class); - StepVerifier verifier = StepVerifier.create(changeEvents) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier = StepVerifier.create(changeEvents).expectNextCount(1).thenCancel().verifyLater(); view.setTickValue(1); verifier.verify(Duration.ofSeconds(1)); @@ -196,4 +187,5 @@ private static List getViewItems(ProgressView view) { List items = (List) ReflectionTestUtils.getField(view, "items"); return items; } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/StatusBarViewTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/StatusBarViewTests.java index b517aec61..db967b377 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/StatusBarViewTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/control/StatusBarViewTests.java @@ -47,9 +47,7 @@ void constructView() { view = new StatusBarView(); assertThat(view.getItems()).hasSize(0); - view = new StatusBarView(new StatusItem[] { - new StatusItem("item1") - }); + view = new StatusBarView(new StatusItem[] { new StatusItem("item1") }); assertThat(view.getItems()).hasSize(1); view = new StatusBarView(Arrays.asList(new StatusItem("item1"))); @@ -75,20 +73,19 @@ void hotkeys() { item = StatusItem.of("title").setHotKey(Key.f); assertThat(item.getHotKey()).isEqualTo(Key.f); } + } @Nested class Internal { StatusBarView view; + StatusItem item; @Test void itemPosition() { - view = new StatusBarView(new StatusItem[] { - new StatusItem("item1"), - new StatusItem("item2") - }); + view = new StatusBarView(new StatusItem[] { new StatusItem("item1"), new StatusItem("item2") }); view.setRect(0, 0, 10, 1); item = (StatusItem) ReflectionTestUtils.invokeMethod(view, "itemAt", 0, 0); @@ -106,13 +103,21 @@ void itemPosition() { class Sorting { StatusItem p_0_1; + StatusItem p_0_2; + StatusItem p_0_3; + StatusItem p_1_1; + StatusItem p_2_1; + StatusItem n_0_1; + StatusItem n_0_2; + StatusItem n_0_3; + StatusBarView view; @BeforeEach @@ -284,9 +289,7 @@ class Events { @BeforeEach void setup() { - view = new StatusBarView(new StatusItem[] { - new StatusItem("item1") - }); + view = new StatusBarView(new StatusItem[] { new StatusItem("item1") }); configure(view); view.setRect(0, 0, 20, 1); } @@ -296,11 +299,8 @@ void handlesMouseClickInItem() { MouseEvent click = mouseClick(1, 0); Flux actions = eventLoop - .viewEvents(StatusBarViewOpenSelectedItemEvent.class); - StepVerifier verifier = StepVerifier.create(actions) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + .viewEvents(StatusBarViewOpenSelectedItemEvent.class); + StepVerifier verifier = StepVerifier.create(actions).expectNextCount(1).thenCancel().verifyLater(); MouseHandlerResult result = handleMouseClick(view, click); @@ -313,7 +313,6 @@ void handlesMouseClickInItem() { verifier.verify(Duration.ofSeconds(1)); } - } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/DefaultEventLoopTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/DefaultEventLoopTests.java index 1564b111f..c78f98bad 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/DefaultEventLoopTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/DefaultEventLoopTests.java @@ -37,6 +37,7 @@ class DefaultEventLoopTests { private final static Logger log = LoggerFactory.getLogger(DefaultEventLoopTests.class); + private DefaultEventLoop loop; @AfterEach @@ -45,7 +46,8 @@ void clean() { // TODO: gh898 try { loop.destroy(); - } catch (Exception e) { + } + catch (Exception e) { log.error("Error calling loop destroy", e); } } @@ -61,10 +63,7 @@ void eventsGetIntoSingleSubscriber() { initDefault(); Message message = MessageBuilder.withPayload("TEST").build(); - StepVerifier verifier1 = StepVerifier.create(loop.events()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.events()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(message); verifier1.verify(Duration.ofSeconds(1)); @@ -75,15 +74,9 @@ void eventsGetIntoMultipleSubscriber() { initDefault(); Message message = MessageBuilder.withPayload("TEST").build(); - StepVerifier verifier1 = StepVerifier.create(loop.events()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.events()).expectNextCount(1).thenCancel().verifyLater(); - StepVerifier verifier2 = StepVerifier.create(loop.events()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier2 = StepVerifier.create(loop.events()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(message); verifier1.verify(Duration.ofSeconds(1)); @@ -96,10 +89,7 @@ void canDispatchFlux() { Message message = MessageBuilder.withPayload("TEST").build(); Flux> flux = Flux.just(message); - StepVerifier verifier1 = StepVerifier.create(loop.events()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.events()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(flux); verifier1.verify(Duration.ofSeconds(1)); @@ -111,16 +101,12 @@ void canDispatchMono() { Message message = MessageBuilder.withPayload("TEST").build(); Mono> mono = Mono.just(message); - StepVerifier verifier1 = StepVerifier.create(loop.events()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.events()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(mono); verifier1.verify(Duration.ofSeconds(1)); } - @Test void dispatchNoSubscribersDoesNotError() { initDefault(); @@ -132,9 +118,7 @@ void dispatchNoSubscribersDoesNotError() { @Test void subsribtionCompletesWhenLoopDestroyed() { initDefault(); - StepVerifier verifier1 = StepVerifier.create(loop.events()) - .expectComplete() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.events()).expectComplete().verifyLater(); loop.destroy(); verifier1.verify(Duration.ofSeconds(1)); @@ -151,11 +135,10 @@ public boolean canProcess(Message message) { @Override public Flux> process(Message message) { - Message m = MessageBuilder.fromMessage(message) - .setHeader("count", count++) - .build(); + Message m = MessageBuilder.fromMessage(message).setHeader("count", count++).build(); return Flux.just(m); } + } @Test @@ -163,21 +146,15 @@ void processorCreatesSameMessagesForAll() { TestEventLoopProcessor processor = new TestEventLoopProcessor(); loop = new DefaultEventLoop(Arrays.asList(processor)); - StepVerifier verifier1 = StepVerifier.create(loop.events()) - .assertNext(m -> { - Integer count = m.getHeaders().get("count", Integer.class); - assertThat(count).isEqualTo(0); - }) - .thenCancel() - .verifyLater(); - - StepVerifier verifier2 = StepVerifier.create(loop.events()) - .assertNext(m -> { - Integer count = m.getHeaders().get("count", Integer.class); - assertThat(count).isEqualTo(0); - }) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.events()).assertNext(m -> { + Integer count = m.getHeaders().get("count", Integer.class); + assertThat(count).isEqualTo(0); + }).thenCancel().verifyLater(); + + StepVerifier verifier2 = StepVerifier.create(loop.events()).assertNext(m -> { + Integer count = m.getHeaders().get("count", Integer.class); + assertThat(count).isEqualTo(0); + }).thenCancel().verifyLater(); Message message = MessageBuilder.withPayload("TEST").build(); loop.dispatch(message); @@ -190,22 +167,21 @@ void taskRunnableShouldExecute() { initDefault(); TestRunnable task = new TestRunnable(); Message message = ShellMessageBuilder.withPayload(task).setEventType(EventLoop.Type.TASK).build(); - StepVerifier verifier1 = StepVerifier.create(loop.events()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.events()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(message); verifier1.verify(Duration.ofSeconds(1)); assertThat(task.count).isEqualTo(1); } static class TestRunnable implements Runnable { + int count = 0; @Override public void run() { count++; } + } @Test @@ -215,10 +191,7 @@ void keyEvents() { KeyEvent event = KeyEvent.of(KeyEvent.Key.a); Message message = ShellMessageBuilder.ofKeyEvent(event); - StepVerifier verifier1 = StepVerifier.create(loop.keyEvents()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.keyEvents()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(message); verifier1.verify(Duration.ofSeconds(1)); @@ -229,16 +202,12 @@ void mouseEvents() { initDefault(); org.jline.terminal.MouseEvent jlineMouseEvent = new org.jline.terminal.MouseEvent( - org.jline.terminal.MouseEvent.Type.Released, - org.jline.terminal.MouseEvent.Button.Button1, + org.jline.terminal.MouseEvent.Type.Released, org.jline.terminal.MouseEvent.Button.Button1, EnumSet.noneOf(org.jline.terminal.MouseEvent.Modifier.class), 0, 0); MouseEvent event = MouseEvent.of(jlineMouseEvent); Message message = ShellMessageBuilder.ofMouseEvent(event); - StepVerifier verifier1 = StepVerifier.create(loop.mouseEvents()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.mouseEvents()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(message); verifier1.verify(Duration.ofSeconds(1)); @@ -250,10 +219,7 @@ void systemEvents() { Message message = ShellMessageBuilder.ofRedraw(); - StepVerifier verifier1 = StepVerifier.create(loop.systemEvents()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.systemEvents()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(message); verifier1.verify(Duration.ofSeconds(1)); @@ -265,10 +231,7 @@ void signalEvents() { Message message = ShellMessageBuilder.ofSignal("WINCH"); - StepVerifier verifier1 = StepVerifier.create(loop.signalEvents()) - .expectNextCount(1) - .thenCancel() - .verifyLater(); + StepVerifier verifier1 = StepVerifier.create(loop.signalEvents()).expectNextCount(1).thenCancel().verifyLater(); loop.dispatch(message); verifier1.verify(Duration.ofSeconds(1)); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyEventTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyEventTests.java index 0987a32cd..1c88c6159 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyEventTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyEventTests.java @@ -50,7 +50,6 @@ void isKey2() { assertThat(KeyEvent.of(Key.A).isKey()).isTrue(); assertThat(KeyEvent.of(Key.Backspace).isKey()).isFalse(); - } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyHandlerTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyHandlerTests.java index a5993e1e2..6779746cb 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyHandlerTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/KeyHandlerTests.java @@ -25,6 +25,7 @@ class KeyHandlerTests { private static final KeyEvent EVENT = KeyEvent.of(Key.x); + private static final KeyHandlerArgs ARGS = KeyHandler.argsOf(EVENT); @Test @@ -60,6 +61,7 @@ void handlesOtherIfThisDoesNotConsume() { private static class TestKeyHandler implements KeyHandler { boolean willConsume; + int calls; TestKeyHandler(boolean willConsume) { @@ -73,4 +75,5 @@ public KeyHandlerResult handle(KeyHandlerArgs args) { } } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/MouseHandlerTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/MouseHandlerTests.java index 8a4a716da..eca35c80d 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/MouseHandlerTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/event/MouseHandlerTests.java @@ -24,6 +24,7 @@ class MouseHandlerTests { private static final MouseEvent EVENT = MouseEvent.of(0, 0, 0); + private static final MouseHandlerArgs ARGS = MouseHandler.argsOf(EVENT); @Test @@ -59,6 +60,7 @@ void handlesOtherIfThisDoesNotConsume() { private static class TestMouseHandler implements MouseHandler { boolean willConsume; + int calls; TestMouseHandler(boolean willConsume) { diff --git a/spring-shell-core/src/test/java/org/springframework/shell/component/view/geom/RectangleTests.java b/spring-shell-core/src/test/java/org/springframework/shell/component/view/geom/RectangleTests.java index 1d5ffebb1..9a65a8f17 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/component/view/geom/RectangleTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/component/view/geom/RectangleTests.java @@ -42,4 +42,5 @@ void isEmpty() { rect = new Rectangle(1, 1, 1, 1); assertThat(rect.isEmpty()).isFalse(); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/jline/ExtendedDefaultParserTests.java b/spring-shell-core/src/test/java/org/springframework/shell/jline/ExtendedDefaultParserTests.java index 38ad5f627..104882ae8 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/jline/ExtendedDefaultParserTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/jline/ExtendedDefaultParserTests.java @@ -28,6 +28,7 @@ public class ExtendedDefaultParserTests { private final ExtendedDefaultParser springParser = new ExtendedDefaultParser(); + private final DefaultParser jlineParser = new DefaultParser(); static Stream args() { @@ -35,53 +36,38 @@ static Stream args() { // We've left these tests here to show issues // differences between DefaultParser and // ExtendedDefaultParser. relates gh517 - return Stream.of( - Arguments.of(0, 1, 0, 0, "one"), - Arguments.of(3, 1, 0, 3, "one "), - Arguments.of(4, 2, 1, 0, "one "), - - Arguments.of(0, 2, 0, 0, "one two"), - Arguments.of(1, 2, 0, 1, "one two"), - Arguments.of(2, 2, 0, 2, "one two"), - Arguments.of(3, 2, 0, 3, "one two"), - Arguments.of(7, 2, 1, 3, "one two"), - Arguments.of(7, 2, 1, 3, "one two "), - Arguments.of(8, 3, 2, 0, "one two "), - - Arguments.of(0, 1, 0, 0, "'one'"), - // Arguments.of(5, 1, 0, 3, "'one' "), - Arguments.of(6, 2, 1, 0, "'one' "), - - Arguments.of(0, 1, 0, 0, "'one'"), - Arguments.of(1, 1, 0, 0, "'one'"), - Arguments.of(2, 1, 0, 1, "'one'"), - Arguments.of(3, 1, 0, 2, "'one'"), - Arguments.of(4, 1, 0, 3, "'one'"), - // Arguments.of(5, 1, 0, 3, "'one'"), - - Arguments.of(0, 1, 0, 0, "'one' "), - Arguments.of(1, 1, 0, 0, "'one' "), - Arguments.of(2, 1, 0, 1, "'one' "), - Arguments.of(3, 1, 0, 2, "'one' "), - Arguments.of(4, 1, 0, 3, "'one' "), - // Arguments.of(5, 1, 0, 3, "'one' "), - Arguments.of(6, 2, 1, 0, "'one' "), - - Arguments.of(0, 1, 0, 0, "\"one\""), - Arguments.of(1, 1, 0, 0, "\"one\""), - Arguments.of(2, 1, 0, 1, "\"one\""), - Arguments.of(3, 1, 0, 2, "\"one\""), - Arguments.of(4, 1, 0, 3, "\"one\""), - // Arguments.of(5, 1, 0, 3, "\"one\""), - - Arguments.of(0, 1, 0, 0, "\"one\" "), - Arguments.of(1, 1, 0, 0, "\"one\" "), - Arguments.of(2, 1, 0, 1, "\"one\" "), - Arguments.of(3, 1, 0, 2, "\"one\" "), - Arguments.of(4, 1, 0, 3, "\"one\" "), - // Arguments.of(5, 1, 0, 3, "\"one\" "), - Arguments.of(6, 2, 1, 0, "\"one\" ") - ); + return Stream.of(Arguments.of(0, 1, 0, 0, "one"), Arguments.of(3, 1, 0, 3, "one "), + Arguments.of(4, 2, 1, 0, "one "), + + Arguments.of(0, 2, 0, 0, "one two"), Arguments.of(1, 2, 0, 1, "one two"), + Arguments.of(2, 2, 0, 2, "one two"), Arguments.of(3, 2, 0, 3, "one two"), + Arguments.of(7, 2, 1, 3, "one two"), Arguments.of(7, 2, 1, 3, "one two "), + Arguments.of(8, 3, 2, 0, "one two "), + + Arguments.of(0, 1, 0, 0, "'one'"), + // Arguments.of(5, 1, 0, 3, "'one' "), + Arguments.of(6, 2, 1, 0, "'one' "), + + Arguments.of(0, 1, 0, 0, "'one'"), Arguments.of(1, 1, 0, 0, "'one'"), Arguments.of(2, 1, 0, 1, "'one'"), + Arguments.of(3, 1, 0, 2, "'one'"), Arguments.of(4, 1, 0, 3, "'one'"), + // Arguments.of(5, 1, 0, 3, "'one'"), + + Arguments.of(0, 1, 0, 0, "'one' "), Arguments.of(1, 1, 0, 0, "'one' "), + Arguments.of(2, 1, 0, 1, "'one' "), Arguments.of(3, 1, 0, 2, "'one' "), + Arguments.of(4, 1, 0, 3, "'one' "), + // Arguments.of(5, 1, 0, 3, "'one' "), + Arguments.of(6, 2, 1, 0, "'one' "), + + Arguments.of(0, 1, 0, 0, "\"one\""), Arguments.of(1, 1, 0, 0, "\"one\""), + Arguments.of(2, 1, 0, 1, "\"one\""), Arguments.of(3, 1, 0, 2, "\"one\""), + Arguments.of(4, 1, 0, 3, "\"one\""), + // Arguments.of(5, 1, 0, 3, "\"one\""), + + Arguments.of(0, 1, 0, 0, "\"one\" "), Arguments.of(1, 1, 0, 0, "\"one\" "), + Arguments.of(2, 1, 0, 1, "\"one\" "), Arguments.of(3, 1, 0, 2, "\"one\" "), + Arguments.of(4, 1, 0, 3, "\"one\" "), + // Arguments.of(5, 1, 0, 3, "\"one\" "), + Arguments.of(6, 2, 1, 0, "\"one\" ")); } @ParameterizedTest @@ -101,4 +87,5 @@ void testJlineDefaultParser(int cursor, int words, int wordIndex, int wordCursor assertThat(parse.wordIndex()).as("wordIndex").isEqualTo(wordIndex); assertThat(parse.wordCursor()).as("wordCursor").isEqualTo(wordCursor); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/jline/FileInputProviderTests.java b/spring-shell-core/src/test/java/org/springframework/shell/jline/FileInputProviderTests.java index 317649878..5fcca7b12 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/jline/FileInputProviderTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/jline/FileInputProviderTests.java @@ -32,21 +32,19 @@ class FileInputProviderTests { private final ExtendedDefaultParser springParser = new ExtendedDefaultParser(); + private final DefaultParser jlineParser = new DefaultParser(); + private FileInputProvider fileInputProvider; static Stream regularLinesUnclosedQuotes() { - return Stream.of( - Arguments.of("Regular line with unclosed 'quote"), - Arguments.of("Regular line with unclosed \"quote") - ); + return Stream.of(Arguments.of("Regular line with unclosed 'quote"), + Arguments.of("Regular line with unclosed \"quote")); } static Stream commentsUnclosedQuotes() { - return Stream.of( - Arguments.of("//Commented line with unclosed 'quote"), - Arguments.of("//Commented line with unclosed \"quote") - ); + return Stream.of(Arguments.of("//Commented line with unclosed 'quote"), + Arguments.of("//Commented line with unclosed \"quote")); } @ParameterizedTest @@ -98,4 +96,5 @@ void shouldNotThrowOnUnclosedQuoteExtendedParser(String line) { fileInputProvider.readInput(); }); } + } \ No newline at end of file diff --git a/spring-shell-core/src/test/java/org/springframework/shell/jline/GenericResultHandlerServiceTests.java b/spring-shell-core/src/test/java/org/springframework/shell/jline/GenericResultHandlerServiceTests.java index 389d9561c..815bbb2ca 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/jline/GenericResultHandlerServiceTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/jline/GenericResultHandlerServiceTests.java @@ -33,7 +33,8 @@ public void testSimpleHandling() { resultHandlerService.addResultHandler(integerResultHandler); resultHandlerService.handle("string"); assertThat(stringResultHandler.result).isEqualTo("string"); - assertThat(integerResultHandler.result).isNull();; + assertThat(integerResultHandler.result).isNull(); + ; resultHandlerService.handle(0); assertThat(integerResultHandler.result).isEqualTo(0); } @@ -55,6 +56,7 @@ private static class StringResultHandler implements ResultHandler { public void handleResult(String result) { this.result = result; } + } private static class IntegerResultHandler implements ResultHandler { @@ -65,6 +67,7 @@ private static class IntegerResultHandler implements ResultHandler { public void handleResult(Integer result) { this.result = result; } + } private static class ObjectResultHandler implements ResultHandler { @@ -75,5 +78,7 @@ private static class ObjectResultHandler implements ResultHandler { public void handleResult(Object result) { this.result = result; } + } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/jline/InteractiveShellRunnerTests.java b/spring-shell-core/src/test/java/org/springframework/shell/jline/InteractiveShellRunnerTests.java index 98bab6a34..3cf218c23 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/jline/InteractiveShellRunnerTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/jline/InteractiveShellRunnerTests.java @@ -41,127 +41,127 @@ @Disabled("Hands intermittently") public class InteractiveShellRunnerTests { - private PipedOutputStream outIn; - private InteractiveShellRunner.JLineInputProvider jLineInputProvider; - - - private PromptProvider dummyPromptProvider() { - return () -> new AttributedString("dummy-shell:>", AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW)); - } - - private void initForShortcutKeyTest() throws Exception { - PipedInputStream in = new PipedInputStream(); - outIn = new PipedOutputStream(in); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ExternalTerminal terminal = new ExternalTerminal("foo", "ansi", in, out, StandardCharsets.UTF_8); - Attributes attributes = terminal.getAttributes(); - attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true); - attributes.setControlChar(Attributes.ControlChar.VINTR, 3); - terminal.setAttributes(attributes); - LineReaderBuilder builder = - LineReaderBuilder.builder() - .terminal(terminal); - - LineReader lineReader = builder.build(); - jLineInputProvider = new InteractiveShellRunner.JLineInputProvider(lineReader, dummyPromptProvider()); - } - - @Test - public void testClearWithCtrlC() throws Exception { - - initForShortcutKeyTest(); - - CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch endLatch = new CountDownLatch(1); - Thread writeThread = new Thread(() -> { - try { - startLatch.await(); - outIn.write('a'); - outIn.write(3); - endLatch.await(); - } catch (Exception e) { - e.printStackTrace(); - } - }); - Thread readThread = new Thread(() -> { - assertThatNoException().isThrownBy(() -> assertThat(jLineInputProvider.readInput().rawText()).isEqualTo("")); - endLatch.countDown(); - }); - readThread.start(); - startLatch.countDown(); - writeThread.start(); - - readThread.join(); - writeThread.join(); - } - - - @Test - public void testExitWithCtrlC() throws Exception { - - initForShortcutKeyTest(); - - CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch endLatch = new CountDownLatch(1); - Thread writeThread = new Thread(() -> { - try { - startLatch.await(); - outIn.write(3); - endLatch.await(); - } catch (Exception e) { - e.printStackTrace(); - } - }); - Thread readThread = new Thread(() -> { - assertThatThrownBy(jLineInputProvider::readInput).isInstanceOf(ExitRequest.class); - endLatch.countDown(); - }); - readThread.start(); - startLatch.countDown(); - writeThread.start(); - - readThread.join(); - writeThread.join(); - } - - @Test - public void testExitWithCtrlD() throws Exception { - - initForShortcutKeyTest(); - - CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch endLatch = new CountDownLatch(1); - Thread writeThread = new Thread(() -> { - try { - startLatch.await(); - outIn.write(4); - endLatch.await(); - } catch (Exception e) { - e.printStackTrace(); - } - }); - Thread readThread = new Thread(() -> { - assertThatThrownBy(jLineInputProvider::readInput).isInstanceOf(ExitRequest.class); - endLatch.countDown(); - }); - readThread.start(); - startLatch.countDown(); - writeThread.start(); - - readThread.join(); - writeThread.join(); - } + private PipedOutputStream outIn; + private InteractiveShellRunner.JLineInputProvider jLineInputProvider; + + private PromptProvider dummyPromptProvider() { + return () -> new AttributedString("dummy-shell:>", AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW)); + } + + private void initForShortcutKeyTest() throws Exception { + PipedInputStream in = new PipedInputStream(); + outIn = new PipedOutputStream(in); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ExternalTerminal terminal = new ExternalTerminal("foo", "ansi", in, out, StandardCharsets.UTF_8); + Attributes attributes = terminal.getAttributes(); + attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true); + attributes.setControlChar(Attributes.ControlChar.VINTR, 3); + terminal.setAttributes(attributes); + LineReaderBuilder builder = LineReaderBuilder.builder().terminal(terminal); + + LineReader lineReader = builder.build(); + jLineInputProvider = new InteractiveShellRunner.JLineInputProvider(lineReader, dummyPromptProvider()); + } + + @Test + public void testClearWithCtrlC() throws Exception { + + initForShortcutKeyTest(); + + CountDownLatch startLatch = new CountDownLatch(1); + CountDownLatch endLatch = new CountDownLatch(1); + Thread writeThread = new Thread(() -> { + try { + startLatch.await(); + outIn.write('a'); + outIn.write(3); + endLatch.await(); + } + catch (Exception e) { + e.printStackTrace(); + } + }); + Thread readThread = new Thread(() -> { + assertThatNoException() + .isThrownBy(() -> assertThat(jLineInputProvider.readInput().rawText()).isEqualTo("")); + endLatch.countDown(); + }); + readThread.start(); + startLatch.countDown(); + writeThread.start(); + + readThread.join(); + writeThread.join(); + } + + @Test + public void testExitWithCtrlC() throws Exception { + + initForShortcutKeyTest(); + + CountDownLatch startLatch = new CountDownLatch(1); + CountDownLatch endLatch = new CountDownLatch(1); + Thread writeThread = new Thread(() -> { + try { + startLatch.await(); + outIn.write(3); + endLatch.await(); + } + catch (Exception e) { + e.printStackTrace(); + } + }); + Thread readThread = new Thread(() -> { + assertThatThrownBy(jLineInputProvider::readInput).isInstanceOf(ExitRequest.class); + endLatch.countDown(); + }); + readThread.start(); + startLatch.countDown(); + writeThread.start(); + + readThread.join(); + writeThread.join(); + } + + @Test + public void testExitWithCtrlD() throws Exception { + + initForShortcutKeyTest(); + + CountDownLatch startLatch = new CountDownLatch(1); + CountDownLatch endLatch = new CountDownLatch(1); + Thread writeThread = new Thread(() -> { + try { + startLatch.await(); + outIn.write(4); + endLatch.await(); + } + catch (Exception e) { + e.printStackTrace(); + } + }); + Thread readThread = new Thread(() -> { + assertThatThrownBy(jLineInputProvider::readInput).isInstanceOf(ExitRequest.class); + endLatch.countDown(); + }); + readThread.start(); + startLatch.countDown(); + writeThread.start(); + + readThread.join(); + writeThread.join(); + } @Test void oldApiCanRunReturnFalse() { - InteractiveShellRunner runner = new InteractiveShellRunner(null, null, null, null); + InteractiveShellRunner runner = new InteractiveShellRunner(null, null, null, null); assertThat(runner.canRun(ofApplicationArguments())).isFalse(); } @Test void oldApiRunThrows() { - InteractiveShellRunner runner = new InteractiveShellRunner(null, null, null, null); + InteractiveShellRunner runner = new InteractiveShellRunner(null, null, null, null); assertThatThrownBy(() -> { runner.run(ofApplicationArguments()); }); diff --git a/spring-shell-core/src/test/java/org/springframework/shell/jline/ScriptShellRunnerTests.java b/spring-shell-core/src/test/java/org/springframework/shell/jline/ScriptShellRunnerTests.java index c5b06c21c..0596c88a9 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/jline/ScriptShellRunnerTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/jline/ScriptShellRunnerTests.java @@ -60,7 +60,7 @@ void shouldRunWhenFirstArgHavingFile(@TempDir Path workingDir) throws Exception Path file = Files.createFile(path); String pathStr = file.toAbsolutePath().toString(); ScriptShellRunner runner = new ScriptShellRunner(null, shell); - assertThat(runner.run(new String[]{"@" + pathStr})).isTrue(); + assertThat(runner.run(new String[] { "@" + pathStr })).isTrue(); } @Test @@ -86,4 +86,5 @@ private static String[] ofArgs(String... args) { } return a; } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/result/CommandNotFoundResultHandlerTests.java b/spring-shell-core/src/test/java/org/springframework/shell/result/CommandNotFoundResultHandlerTests.java index 7302eea23..ebde0c7f9 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/result/CommandNotFoundResultHandlerTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/result/CommandNotFoundResultHandlerTests.java @@ -93,4 +93,5 @@ void customProviderGetsContext() { String string = out.toString(); assertThat(string).contains("hitrueonetwotruetext"); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/style/PartsTextRendererTests.java b/spring-shell-core/src/test/java/org/springframework/shell/style/PartsTextRendererTests.java index 29c39cbe1..f7bfb1f24 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/style/PartsTextRendererTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/style/PartsTextRendererTests.java @@ -31,7 +31,9 @@ class PartsTextRendererTests { private static Locale LOCALE = Locale.getDefault(); + private static PartsTextRenderer renderer; + private static ThemeResolver themeResolver; @BeforeAll @@ -53,185 +55,81 @@ public ThemeSettings getSettings() { } static PartsText of() { - return PartsText.of( - PartText.of("012", false), - PartText.of("3456", true), - PartText.of("789", false) - ); + return PartsText.of(PartText.of("012", false), PartText.of("3456", true), PartText.of("789", false)); } static Stream test() { return Stream.of( - Arguments.of( - "width:10,prefix:2,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("01234567", false) - ), - "01234567"), - Arguments.of( - "width:10,prefix:2,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("0123456789", false) - ), - "012345.."), - Arguments.of( - "width:10,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("01234", false), - PartText.of("56789", true) - ), - "0123456789"), - Arguments.of( - "width:10,prefix:2,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("012", false), - PartText.of("3456", true), - PartText.of("789", false) - ), - "012345.."), - Arguments.of( - "width:12,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abcdefghijkl"), - Arguments.of( - "width:11,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abcdefghi.."), - Arguments.of( - "width:10,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abcdefgh.."), - Arguments.of( - "width:9,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abcdefg.."), - Arguments.of( - "width:8,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abcdef.."), - Arguments.of( - "width:7,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abcde.."), - Arguments.of( - "width:6,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abcd.."), - Arguments.of( - "width:5,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "abc.."), - Arguments.of( - "width:4,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "ab.."), - Arguments.of( - "width:3,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("a", false), - PartText.of("b", true), - PartText.of("cd", false), - PartText.of("efg", true), - PartText.of("h", false), - PartText.of("i", true), - PartText.of("jkl", true) - ), - "a.."), - Arguments.of( - "width:3,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("abcdefg", false), - PartText.of("hijklmn", true) - ), - "a.."), - Arguments.of( - "width:126,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", - PartsText.of( - PartText.of("e2e/spring-shell-e2e-tests/node_modules/@babel/plugin-syntax-types", false), - PartText.of("c", true), - PartText.of("ript/test/fixtures/disa", false), - PartText.of("l", true), - PartText.of("low-jsx-ambiguity/type-parameter-un", false), - PartText.of("a", true), - PartText.of("mbiguou", false), - PartText.of("s", true), - PartText.of("/output.j", false), - PartText.of("s", true) - ), - "e2e/spring-shell-e2e-tests/node_modules/@babel/plugin-syntax-typescript/test/fixtures/disallow-jsx-ambiguity/type-parameter-..") - ); + Arguments.of("width:10,prefix:2,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("01234567", false)), "01234567"), + Arguments.of("width:10,prefix:2,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("0123456789", false)), "012345.."), + Arguments.of("width:10,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("01234", false), PartText.of("56789", true)), "0123456789"), + Arguments.of("width:10,prefix:2,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("012", false), PartText.of("3456", true), PartText.of("789", false)), + "012345.."), + Arguments.of("width:12,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abcdefghijkl"), + Arguments.of("width:11,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abcdefghi.."), + Arguments.of("width:10,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abcdefgh.."), + Arguments.of("width:9,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abcdefg.."), + Arguments.of("width:8,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abcdef.."), + Arguments.of("width:7,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abcde.."), + Arguments.of("width:6,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abcd.."), + Arguments.of("width:5,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "abc.."), + Arguments.of("width:4,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "ab.."), + Arguments.of("width:3,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("a", false), PartText.of("b", true), PartText.of("cd", false), + PartText.of("efg", true), PartText.of("h", false), PartText.of("i", true), + PartText.of("jkl", true)), + "a.."), + Arguments.of("width:3,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of(PartText.of("abcdefg", false), PartText.of("hijklmn", true)), "a.."), + Arguments.of("width:126,prefix:0,textStyle:style-item-selector,matchStyle:style-level-warn", + PartsText.of( + PartText.of("e2e/spring-shell-e2e-tests/node_modules/@babel/plugin-syntax-types", + false), + PartText.of("c", true), PartText.of("ript/test/fixtures/disa", false), + PartText.of("l", true), PartText.of("low-jsx-ambiguity/type-parameter-un", false), + PartText.of("a", true), PartText.of("mbiguou", false), PartText.of("s", true), + PartText.of("/output.j", false), PartText.of("s", true)), + "e2e/spring-shell-e2e-tests/node_modules/@babel/plugin-syntax-typescript/test/fixtures/disallow-jsx-ambiguity/type-parameter-..")); } @ParameterizedTest diff --git a/spring-shell-core/src/test/java/org/springframework/shell/style/StringToStyleExpressionRendererTests.java b/spring-shell-core/src/test/java/org/springframework/shell/style/StringToStyleExpressionRendererTests.java index 9a6a08580..92064eee8 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/style/StringToStyleExpressionRendererTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/style/StringToStyleExpressionRendererTests.java @@ -29,6 +29,7 @@ class StringToStyleExpressionRendererTests { private static Locale LOCALE = Locale.getDefault(); + private static StringToStyleExpressionRenderer renderer; @BeforeAll @@ -56,11 +57,9 @@ void emptyFormatReturnsValue() { } static Stream truncate() { - return Stream.of( - Arguments.of("0123456789", "truncate-width:6-prefix:2", "01.."), - Arguments.of("0123456789", "truncate-width:6-prefix:0", "0123.."), - Arguments.of("0123456789", "truncate-width:11-prefix:0", "0123456789") - ); + return Stream.of(Arguments.of("0123456789", "truncate-width:6-prefix:2", "01.."), + Arguments.of("0123456789", "truncate-width:6-prefix:0", "0123.."), + Arguments.of("0123456789", "truncate-width:11-prefix:0", "0123456789")); } @ParameterizedTest @@ -68,4 +67,5 @@ static Stream truncate() { void truncate(String value, String expression, String expected) { assertThat(renderer.toString(value, expression, LOCALE)).isEqualTo(expected); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/style/TemplateExecutorTests.java b/spring-shell-core/src/test/java/org/springframework/shell/style/TemplateExecutorTests.java index 939c3c35f..fc25396f1 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/style/TemplateExecutorTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/style/TemplateExecutorTests.java @@ -74,9 +74,8 @@ public void testWithTheme() { Map attributes = new HashMap<>(); attributes.put("foo", "bar"); AttributedString result = executor.render(template, attributes); - AttributedString equalTo = new AttributedStringBuilder() - .append("bar", AttributedStyle.DEFAULT.bold()) - .toAttributedString(); + AttributedString equalTo = new AttributedStringBuilder().append("bar", AttributedStyle.DEFAULT.bold()) + .toAttributedString(); assertThat(result).isEqualTo(equalTo); } @@ -90,4 +89,5 @@ public void testNullDontStyle() { AttributedString equalTo = new AttributedStringBuilder().append("bar").toAttributedString(); assertThat(result).isEqualTo(equalTo); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeRegistryTests.java b/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeRegistryTests.java index 2b398c153..641b473e9 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeRegistryTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeRegistryTests.java @@ -29,4 +29,5 @@ public void test() { assertThat(registry.get("name1")).isSameAs(theme); assertThat(registry.get("name2")).isNull(); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeResolverTests.java b/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeResolverTests.java index 84246a9c3..a370a79b9 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeResolverTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeResolverTests.java @@ -52,7 +52,7 @@ public void styleExpression() { assertThat(themeResolver.resolveStyleTag(StyleSettings.TAG_TITLE)).isEqualTo("bold"); assertThat(themeResolver.resolveStyle("bold")).isEqualTo(AttributedStyle.BOLD); assertThat(themeResolver.evaluateExpression("@{bold foo}")) - .isEqualTo(new AttributedString("foo", AttributedStyle.BOLD)); + .isEqualTo(new AttributedString("foo", AttributedStyle.BOLD)); } @Test diff --git a/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeSettingsTests.java b/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeSettingsTests.java index fcce4b502..8cddd0454 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeSettingsTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/style/ThemeSettingsTests.java @@ -40,24 +40,15 @@ public void testGeneratedStyle() { } @ParameterizedTest - @ValueSource(strings = { - StyleSettings.TAG_TITLE, - StyleSettings.TAG_VALUE, - StyleSettings.TAG_LIST_KEY, - StyleSettings.TAG_LIST_VALUE, - StyleSettings.TAG_LEVEL_INFO, - StyleSettings.TAG_LEVEL_WARN, - StyleSettings.TAG_LEVEL_ERROR, - StyleSettings.TAG_ITEM_ENABLED, - StyleSettings.TAG_ITEM_DISABLED, - StyleSettings.TAG_ITEM_SELECTED, - StyleSettings.TAG_ITEM_UNSELECTED, - StyleSettings.TAG_ITEM_SELECTOR, - StyleSettings.TAG_HIGHLIGHT, - StyleSettings.TAG_BACKGROUND }) + @ValueSource(strings = { StyleSettings.TAG_TITLE, StyleSettings.TAG_VALUE, StyleSettings.TAG_LIST_KEY, + StyleSettings.TAG_LIST_VALUE, StyleSettings.TAG_LEVEL_INFO, StyleSettings.TAG_LEVEL_WARN, + StyleSettings.TAG_LEVEL_ERROR, StyleSettings.TAG_ITEM_ENABLED, StyleSettings.TAG_ITEM_DISABLED, + StyleSettings.TAG_ITEM_SELECTED, StyleSettings.TAG_ITEM_UNSELECTED, StyleSettings.TAG_ITEM_SELECTOR, + StyleSettings.TAG_HIGHLIGHT, StyleSettings.TAG_BACKGROUND }) public void testTags(String tag) { ThemeSettings themeSettings = ThemeSettings.defaults(); String resolveTag = themeSettings.styles().resolveTag(tag); assertThat(resolveTag).isNotNull(); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithmTests.java b/spring-shell-core/src/test/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithmTests.java index 125a2d8d7..871dea244 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithmTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/support/search/ExactMatchNaiveSearchMatchAlgorithmTests.java @@ -32,28 +32,23 @@ class ExactMatchNaiveSearchMatchAlgorithmTests { static Stream testExactMatch() { - return Stream.of( - Arguments.of(true, false, true, "fooBarbaz", "oBA", false, -1, -1, new int[] {}, - 0), - Arguments.of(true, false, true, "fooBarbaz", "fooBarbazz", false, -1, -1, new int[] {}, - 0), - Arguments.of(false, false, true, "fooBarbaz", "oBA", false, 2, 5, new int[] { 2, 3, 4 }, - SCORE_MATCH * 3 + BONUS_CAMEL123 + BONUS_CONSECUTIVE), - Arguments.of(false, false, true, "/AutomatorDocument.icns", "rdoc", false, 9, 13, new int[] { 9, 10, 11, 12 }, - SCORE_MATCH * 4 + BONUS_CAMEL123 + BONUS_CONSECUTIVE * 2), - Arguments.of(false, false, true, "/man1/zshcompctl.1", "zshc", false, 6, 10, new int[] { 6, 7, 8, 9 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY_DELIMITER * (BONUS_FIRST_CHAR_MULTIPLIER + 3)), - Arguments.of(false, false, true, "/.oh-my-zsh/cache", "zsh/c", false, 8, 13, new int[] { 8, 9, 10, 11, 12 }, - SCORE_MATCH * 5 + BONUS_BOUNDARY * (BONUS_FIRST_CHAR_MULTIPLIER + 3) + BONUS_BOUNDARY_DELIMITER), - Arguments.of(false, false, true, "fooBarbaz", "o", false, 1, 2, new int[] { 1 }, - SCORE_MATCH * 1), - Arguments.of(false, false, true, "/tmp/test/11/file11.txt", "e", false, 6, 7, new int[] { 6 }, - SCORE_MATCH * 1), - Arguments.of(false, true, true, "Só Danço Samba", "So", false, 0, 2, new int[] { 0, 1 }, - 62), - Arguments.of(false, true, true, "Danço", "danco", false, 0, 5, new int[] { 0, 1, 2, 3, 4 }, - 140) - ); + return Stream.of(Arguments.of(true, false, true, "fooBarbaz", "oBA", false, -1, -1, new int[] {}, 0), + Arguments.of(true, false, true, "fooBarbaz", "fooBarbazz", false, -1, -1, new int[] {}, 0), + Arguments.of(false, false, true, "fooBarbaz", "oBA", false, 2, 5, new int[] { 2, 3, 4 }, + SCORE_MATCH * 3 + BONUS_CAMEL123 + BONUS_CONSECUTIVE), + Arguments.of(false, false, true, "/AutomatorDocument.icns", "rdoc", false, 9, 13, + new int[] { 9, 10, 11, 12 }, SCORE_MATCH * 4 + BONUS_CAMEL123 + BONUS_CONSECUTIVE * 2), + Arguments.of(false, false, true, "/man1/zshcompctl.1", "zshc", false, 6, 10, new int[] { 6, 7, 8, 9 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY_DELIMITER * (BONUS_FIRST_CHAR_MULTIPLIER + 3)), + Arguments.of(false, false, true, "/.oh-my-zsh/cache", "zsh/c", false, 8, 13, + new int[] { 8, 9, 10, 11, 12 }, + SCORE_MATCH * 5 + BONUS_BOUNDARY * (BONUS_FIRST_CHAR_MULTIPLIER + 3) + + BONUS_BOUNDARY_DELIMITER), + Arguments.of(false, false, true, "fooBarbaz", "o", false, 1, 2, new int[] { 1 }, SCORE_MATCH * 1), + Arguments.of(false, false, true, "/tmp/test/11/file11.txt", "e", false, 6, 7, new int[] { 6 }, + SCORE_MATCH * 1), + Arguments.of(false, true, true, "Só Danço Samba", "So", false, 0, 2, new int[] { 0, 1 }, 62), + Arguments.of(false, true, true, "Danço", "danco", false, 0, 5, new int[] { 0, 1, 2, 3, 4 }, 140)); } @ParameterizedTest @@ -70,4 +65,5 @@ void testExactMatch(boolean caseSensitive, boolean normalize, boolean forward, S assertThat(result.getScore()).isEqualTo(score); assertThat(result.getPositions()).containsExactly(positions); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithmTests.java b/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithmTests.java index 8d71acd72..ae9a0fc31 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithmTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV1SearchMatchAlgorithmTests.java @@ -39,48 +39,55 @@ class FuzzyMatchV1SearchMatchAlgorithmTests { static Stream testFuzzyMatchV1() { return Stream.of( - Arguments.of(false, false, "fooBarbaz1", "oBZ", true, 2, 9, new int[] { 2, 3, 8 }, - SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), - Arguments.of(false, false, "foo bar baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + - 2 * SCORE_GAP_START + 4 * SCORE_GAP_EXTENSION), - Arguments.of(false, false, "/AutomatorDocument.icns", "rdoc", true, 9, 13, new int[] { 9, 10, 11, 12 }, - SCORE_MATCH * 4 + BONUS_CAMEL123 + BONUS_CONSECUTIVE * 2), - Arguments.of(false, false, "/man1/zshcompctl.1", "zshc", true, 6, 10, new int[] { 6, 7, 8, 9 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY_DELIMITER * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_DELIMITER * 3), - Arguments.of(false, false, "/.oh-my-zsh/cache", "zshc", true, 8, 13, new int[] { 8, 9, 10 ,12 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY * 2 + SCORE_GAP_START + BONUS_BOUNDARY_DELIMITER), - Arguments.of(false, false, "ab0123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, - SCORE_MATCH * 5 + BONUS_CONSECUTIVE * 3 + SCORE_GAP_START + SCORE_GAP_EXTENSION), - Arguments.of(false, false, "abc123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, - SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + BONUS_CONSECUTIVE + SCORE_GAP_START + SCORE_GAP_EXTENSION), - Arguments.of(false, false, "foo/bar/baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), - Arguments.of(false, false, "fooBarBaz", "fbb", true, 0, 7, new int[] { 0, 3, 6 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), - Arguments.of(false, false, "foo barbaz", "fbb", true, 0, 8, new int[] { 0, 4, 7 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE +SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 3), - Arguments.of(false, false, "fooBar Baz", "foob", true, 0, 4, new int[] { 0, 1, 2, 3 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 3), - Arguments.of(false, false, "xFoo-Bar Baz", "foo-b", true, 1, 6, new int[] { 1, 2, 3, 4, 5 }, - SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + BONUS_NON_WORD + BONUS_BOUNDARY), - Arguments.of(true, false, "fooBarbaz", "oBz", true, 2, 9, new int[] { 2, 3, 8 }, - SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), - Arguments.of(true, false, "Foo/Bar/Baz", "FBB", true, 0, 9, new int[] { 0, 4, 8 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), - Arguments.of(true, false, "FooBarBaz", "FBB", true, 0, 7, new int[] { 0, 3, 6 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), - Arguments.of(true, false, "FooBar Baz", "FooB", true, 0, 4, new int[] { 0, 1, 2, 3 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + Math.max(BONUS_CAMEL123, BONUS_BOUNDARY_WHITE)), - Arguments.of(true, false, "foo-bar", "o-ba", true, 2, 6, new int[] { 2, 3, 4, 5 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY * 3), - Arguments.of(true, false, "fooBarbaz", "oBZ", true, -1, -1, new int[0], - 0), - Arguments.of(true, false, "Foo Bar Baz", "fbb", true, -1, -1, new int[0], - 0), - Arguments.of(true, false, "fooBarbaz", "fooBarbazz", true, -1, -1, new int[0], - 0) - ); + Arguments.of(false, false, "fooBarbaz1", "oBZ", true, 2, 9, new int[] { 2, 3, 8 }, + SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), + Arguments.of(false, false, "foo bar baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + + 2 * SCORE_GAP_START + 4 * SCORE_GAP_EXTENSION), + Arguments.of(false, false, "/AutomatorDocument.icns", "rdoc", true, 9, 13, new int[] { 9, 10, 11, 12 }, + SCORE_MATCH * 4 + BONUS_CAMEL123 + BONUS_CONSECUTIVE * 2), + Arguments.of(false, false, "/man1/zshcompctl.1", "zshc", true, 6, 10, new int[] { 6, 7, 8, 9 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY_DELIMITER * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_DELIMITER * 3), + Arguments.of(false, false, "/.oh-my-zsh/cache", "zshc", true, 8, 13, new int[] { 8, 9, 10, 12 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY * 2 + + SCORE_GAP_START + BONUS_BOUNDARY_DELIMITER), + Arguments.of(false, false, "ab0123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, + SCORE_MATCH * 5 + BONUS_CONSECUTIVE * 3 + SCORE_GAP_START + SCORE_GAP_EXTENSION), + Arguments.of(false, false, "abc123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, + SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + BONUS_CONSECUTIVE + SCORE_GAP_START + SCORE_GAP_EXTENSION), + Arguments.of(false, false, "foo/bar/baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), + Arguments.of(false, false, "fooBarBaz", "fbb", true, 0, 7, new int[] { 0, 3, 6 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), + Arguments.of(false, false, "foo barbaz", "fbb", true, 0, 8, new int[] { 0, 4, 7 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE + + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 3), + Arguments.of(false, false, "fooBar Baz", "foob", true, 0, 4, new int[] { 0, 1, 2, 3 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_WHITE * 3), + Arguments.of(false, false, "xFoo-Bar Baz", "foo-b", true, 1, 6, new int[] { 1, 2, 3, 4, 5 }, + SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + BONUS_NON_WORD + BONUS_BOUNDARY), + Arguments.of(true, false, "fooBarbaz", "oBz", true, 2, 9, new int[] { 2, 3, 8 }, + SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), + Arguments.of(true, false, "Foo/Bar/Baz", "FBB", true, 0, 9, new int[] { 0, 4, 8 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), + Arguments.of(true, false, "FooBarBaz", "FBB", true, 0, 7, new int[] { 0, 3, 6 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), + Arguments.of(true, false, "FooBar Baz", "FooB", true, 0, 4, new int[] { 0, 1, 2, 3 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + + Math.max(BONUS_CAMEL123, BONUS_BOUNDARY_WHITE)), + Arguments.of(true, false, "foo-bar", "o-ba", true, 2, 6, new int[] { 2, 3, 4, 5 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY * 3), + Arguments.of(true, false, "fooBarbaz", "oBZ", true, -1, -1, new int[0], 0), + Arguments.of(true, false, "Foo Bar Baz", "fbb", true, -1, -1, new int[0], 0), + Arguments.of(true, false, "fooBarbaz", "fooBarbazz", true, -1, -1, new int[0], 0)); } @ParameterizedTest @@ -105,20 +112,19 @@ void testFuzzyMatchV1(boolean caseSensitive, boolean normalize, String text, Str assertThat(result.getPositions()).containsExactly(positions); } - static Stream testFuzzyMatchV1Backward() { return Stream.of( - Arguments.of(false, true, "foobar fb", "fb", 0, 4, new int[] { 0, 3 }, - SCORE_MATCH * 2 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + SCORE_GAP_START + SCORE_GAP_EXTENSION), - Arguments.of(false, false, "foobar fb", "fb", 7, 9, new int[] { 7, 8 }, - SCORE_MATCH * 2 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE) - ); + Arguments.of(false, true, "foobar fb", "fb", 0, 4, new int[] { 0, 3 }, + SCORE_MATCH * 2 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + SCORE_GAP_START + + SCORE_GAP_EXTENSION), + Arguments.of(false, false, "foobar fb", "fb", 7, 9, new int[] { 7, 8 }, + SCORE_MATCH * 2 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE)); } @ParameterizedTest @MethodSource - void testFuzzyMatchV1Backward(boolean caseSensitive, boolean forward, String text, String pattern, int start, - int end, int[] positions, int score) { + void testFuzzyMatchV1Backward(boolean caseSensitive, boolean forward, String text, String pattern, int start, + int end, int[] positions, int score) { if (!caseSensitive) { pattern = pattern.toLowerCase(); } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithmTests.java b/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithmTests.java index 0c8959ecf..86c731c0c 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithmTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/support/search/FuzzyMatchV2SearchMatchAlgorithmTests.java @@ -39,48 +39,55 @@ class FuzzyMatchV2SearchMatchAlgorithmTests { static Stream testFuzzyMatchV2() { return Stream.of( - Arguments.of(false, false, "fooBarbaz1", "oBZ", true, 2, 9, new int[] { 2, 3, 8 }, - SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), - Arguments.of(false, false, "foo bar baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + - 2 * SCORE_GAP_START + 4 * SCORE_GAP_EXTENSION), - Arguments.of(false, false, "/AutomatorDocument.icns", "rdoc", true, 9, 13, new int[] { 9, 10, 11, 12 }, - SCORE_MATCH * 4 + BONUS_CAMEL123 + BONUS_CONSECUTIVE * 2), - Arguments.of(false, false, "/man1/zshcompctl.1", "zshc", true, 6, 10, new int[] { 6, 7, 8, 9 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY_DELIMITER * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_DELIMITER * 3), - Arguments.of(false, false, "/.oh-my-zsh/cache", "zshc", true, 8, 13, new int[] { 8, 9, 10 ,12 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY * 2 + SCORE_GAP_START + BONUS_BOUNDARY_DELIMITER), - Arguments.of(false, false, "ab0123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, - SCORE_MATCH * 5 + BONUS_CONSECUTIVE * 3 + SCORE_GAP_START + SCORE_GAP_EXTENSION), - Arguments.of(false, false, "abc123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, - SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + BONUS_CONSECUTIVE + SCORE_GAP_START + SCORE_GAP_EXTENSION), - Arguments.of(false, false, "foo/bar/baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), - Arguments.of(false, false, "fooBarBaz", "fbb", true, 0, 7, new int[] { 0, 3, 6 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), - Arguments.of(false, false, "foo barbaz", "fbb", true, 0, 8, new int[] { 0, 4, 7 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE +SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 3), - Arguments.of(false, false, "fooBar Baz", "foob", true, 0, 4, new int[] { 0, 1, 2, 3 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 3), - Arguments.of(false, false, "xFoo-Bar Baz", "foo-b", true, 1, 6, new int[] { 1, 2, 3, 4, 5 }, - SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + BONUS_NON_WORD + BONUS_BOUNDARY), - Arguments.of(true, false, "fooBarbaz", "oBz", true, 2, 9, new int[] { 2, 3, 8 }, - SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), - Arguments.of(true, false, "Foo/Bar/Baz", "FBB", true, 0, 9, new int[] { 0, 4, 8 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), - Arguments.of(true, false, "FooBarBaz", "FBB", true, 0, 7, new int[] { 0, 3, 6 }, - SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), - Arguments.of(true, false, "FooBar Baz", "FooB", true, 0, 4, new int[] { 0, 1, 2, 3 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + Math.max(BONUS_CAMEL123, BONUS_BOUNDARY_WHITE)), - Arguments.of(true, false, "foo-bar", "o-ba", true, 2, 6, new int[] { 2, 3, 4, 5 }, - SCORE_MATCH * 4 + BONUS_BOUNDARY * 3), - Arguments.of(true, false, "fooBarbaz", "oBZ", true, -1, -1, new int[0], - 0), - Arguments.of(true, false, "Foo Bar Baz", "fbb", true, -1, -1, new int[0], - 0), - Arguments.of(true, false, "fooBarbaz", "fooBarbazz", true, -1, -1, new int[0], - 0) - ); + Arguments.of(false, false, "fooBarbaz1", "oBZ", true, 2, 9, new int[] { 2, 3, 8 }, + SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), + Arguments.of(false, false, "foo bar baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + + 2 * SCORE_GAP_START + 4 * SCORE_GAP_EXTENSION), + Arguments.of(false, false, "/AutomatorDocument.icns", "rdoc", true, 9, 13, new int[] { 9, 10, 11, 12 }, + SCORE_MATCH * 4 + BONUS_CAMEL123 + BONUS_CONSECUTIVE * 2), + Arguments.of(false, false, "/man1/zshcompctl.1", "zshc", true, 6, 10, new int[] { 6, 7, 8, 9 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY_DELIMITER * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_DELIMITER * 3), + Arguments.of(false, false, "/.oh-my-zsh/cache", "zshc", true, 8, 13, new int[] { 8, 9, 10, 12 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY * 2 + + SCORE_GAP_START + BONUS_BOUNDARY_DELIMITER), + Arguments.of(false, false, "ab0123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, + SCORE_MATCH * 5 + BONUS_CONSECUTIVE * 3 + SCORE_GAP_START + SCORE_GAP_EXTENSION), + Arguments.of(false, false, "abc123 456", "12356", true, 3, 10, new int[] { 3, 4, 5, 8, 9 }, + SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + BONUS_CONSECUTIVE + SCORE_GAP_START + SCORE_GAP_EXTENSION), + Arguments.of(false, false, "foo/bar/baz", "fbb", true, 0, 9, new int[] { 0, 4, 8 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), + Arguments.of(false, false, "fooBarBaz", "fbb", true, 0, 7, new int[] { 0, 3, 6 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), + Arguments.of(false, false, "foo barbaz", "fbb", true, 0, 8, new int[] { 0, 4, 7 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE + + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 3), + Arguments.of(false, false, "fooBar Baz", "foob", true, 0, 4, new int[] { 0, 1, 2, 3 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_WHITE * 3), + Arguments.of(false, false, "xFoo-Bar Baz", "foo-b", true, 1, 6, new int[] { 1, 2, 3, 4, 5 }, + SCORE_MATCH * 5 + BONUS_CAMEL123 * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + BONUS_NON_WORD + BONUS_BOUNDARY), + Arguments.of(true, false, "fooBarbaz", "oBz", true, 2, 9, new int[] { 2, 3, 8 }, + SCORE_MATCH * 3 + BONUS_CAMEL123 + SCORE_GAP_START + SCORE_GAP_EXTENSION * 3), + Arguments.of(true, false, "Foo/Bar/Baz", "FBB", true, 0, 9, new int[] { 0, 4, 8 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + + BONUS_BOUNDARY_DELIMITER * 2 + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 4), + Arguments.of(true, false, "FooBarBaz", "FBB", true, 0, 7, new int[] { 0, 3, 6 }, + SCORE_MATCH * 3 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_CAMEL123 * 2 + + SCORE_GAP_START * 2 + SCORE_GAP_EXTENSION * 2), + Arguments.of(true, false, "FooBar Baz", "FooB", true, 0, 4, new int[] { 0, 1, 2, 3 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY_WHITE * BONUS_FIRST_CHAR_MULTIPLIER + BONUS_BOUNDARY_WHITE * 2 + + Math.max(BONUS_CAMEL123, BONUS_BOUNDARY_WHITE)), + Arguments.of(true, false, "foo-bar", "o-ba", true, 2, 6, new int[] { 2, 3, 4, 5 }, + SCORE_MATCH * 4 + BONUS_BOUNDARY * 3), + Arguments.of(true, false, "fooBarbaz", "oBZ", true, -1, -1, new int[0], 0), + Arguments.of(true, false, "Foo Bar Baz", "fbb", true, -1, -1, new int[0], 0), + Arguments.of(true, false, "fooBarbaz", "fooBarbazz", true, -1, -1, new int[0], 0)); } @ParameterizedTest @@ -106,22 +113,16 @@ void testFuzzyMatchV2(boolean caseSensitive, boolean normalize, String text, Str } static Stream testFuzzyMatchV2Normalize() { - return Stream.of( - Arguments.of(false, true, "Só Danço Samba", "So", false, 0, 2, new int[] { 0, 1 }, - 62), - Arguments.of(false, true, "Só Danço Samba", "sodc", false, 0, 7, new int[] { 0, 1, 3, 6 }, - 97), - Arguments.of(false, false, "So Danco Samba", "sodc", false, 0, 7, new int[] { 0, 1, 3, 6 }, - 97), - Arguments.of(false, true, "Danço", "danco", false, 0, 5, new int[] { 0, 1, 2, 3, 4 }, - 140) - ); + return Stream.of(Arguments.of(false, true, "Só Danço Samba", "So", false, 0, 2, new int[] { 0, 1 }, 62), + Arguments.of(false, true, "Só Danço Samba", "sodc", false, 0, 7, new int[] { 0, 1, 3, 6 }, 97), + Arguments.of(false, false, "So Danco Samba", "sodc", false, 0, 7, new int[] { 0, 1, 3, 6 }, 97), + Arguments.of(false, true, "Danço", "danco", false, 0, 5, new int[] { 0, 1, 2, 3, 4 }, 140)); } @ParameterizedTest @MethodSource - void testFuzzyMatchV2Normalize(boolean caseSensitive, boolean normalize, String text, String pattern, boolean withPos, - int start, int end, int[] positions, int score) { + void testFuzzyMatchV2Normalize(boolean caseSensitive, boolean normalize, String text, String pattern, + boolean withPos, int start, int end, int[] positions, int score) { if (!caseSensitive) { pattern = pattern.toLowerCase(); } @@ -139,19 +140,20 @@ void testFuzzyMatchV2Normalize(boolean caseSensitive, boolean normalize, String static Stream testFuzzyMatchV2Extra() { return Stream.of( - Arguments.of(false, true, "/tmp/test/suomi/o.txt", "oo", false, 12, 17, new int[] { 12, 16 }, - SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), - Arguments.of(false, true, "/tmp/test/suomi/ö.txt", "oo", false, 12, 17, new int[] { 12, 16 }, - SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), - Arguments.of(false, true, "/tmp/test/suomi/O.txt", "oo", false, 12, 17, new int[] { 12, 16 }, - SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), - Arguments.of(false, true, "/tmp/test/suomi/Ö.txt", "oo", false, 12, 17, new int[] { 12, 16 }, - SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), - Arguments.of(false, true, "spring-shell-core/build/test-results/test/TEST-org.springframework.shell.support.search.FuzzyMatchV2SearchMatchAlgorithmTests.xml", "class", false, 13, 74, new int[] { 13, 33, 59, 67, 73 }, - 48), - Arguments.of(false, true, "e2e/spring-shell-e2e-tests/node_modules/@babel/plugin-syntax-typescript/test/fixtures/disallow-jsx-ambiguity/type-parameter-unambiguous/output.js", "class", false, 66, 145, new int[] { 66, 90, 126, 134, 144 }, - 28) - ); + Arguments.of(false, true, "/tmp/test/suomi/o.txt", "oo", false, 12, 17, new int[] { 12, 16 }, + SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), + Arguments.of(false, true, "/tmp/test/suomi/ö.txt", "oo", false, 12, 17, new int[] { 12, 16 }, + SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), + Arguments.of(false, true, "/tmp/test/suomi/O.txt", "oo", false, 12, 17, new int[] { 12, 16 }, + SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), + Arguments.of(false, true, "/tmp/test/suomi/Ö.txt", "oo", false, 12, 17, new int[] { 12, 16 }, + SCORE_MATCH * 2 + BONUS_BOUNDARY_DELIMITER + SCORE_GAP_START + SCORE_GAP_EXTENSION * 2), + Arguments.of(false, true, + "spring-shell-core/build/test-results/test/TEST-org.springframework.shell.support.search.FuzzyMatchV2SearchMatchAlgorithmTests.xml", + "class", false, 13, 74, new int[] { 13, 33, 59, 67, 73 }, 48), + Arguments.of(false, true, + "e2e/spring-shell-e2e-tests/node_modules/@babel/plugin-syntax-typescript/test/fixtures/disallow-jsx-ambiguity/type-parameter-unambiguous/output.js", + "class", false, 66, 145, new int[] { 66, 90, 126, 134, 144 }, 28)); } @ParameterizedTest @@ -172,4 +174,5 @@ void testFuzzyMatchV2Extra(boolean caseSensitive, boolean normalize, String text assertThat(result.getScore()).isEqualTo(score); assertThat(result.getPositions()).containsExactly(positions); } + } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/support/search/NormalizeTests.java b/spring-shell-core/src/test/java/org/springframework/shell/support/search/NormalizeTests.java index 26372d12e..7727461fc 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/support/search/NormalizeTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/support/search/NormalizeTests.java @@ -21,14 +21,15 @@ class NormalizeTests { - @Test - void testNormalizeMap() { - assertThat(Normalize.normalized.get('á')).isEqualTo('a'); - assertThat(Normalize.normalized.get('ự')).isEqualTo('u'); - } + @Test + void testNormalizeMap() { + assertThat(Normalize.normalized.get('á')).isEqualTo('a'); + assertThat(Normalize.normalized.get('ự')).isEqualTo('u'); + } + + @Test + void testNormalizeFunction() { + assertThat(Normalize.normalizeRunes("abcáự")).isEqualTo("abcau"); + } - @Test - void testNormalizeFunction() { - assertThat(Normalize.normalizeRunes("abcáự")).isEqualTo("abcau"); - } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/support/search/SearchMatchTests.java b/spring-shell-core/src/test/java/org/springframework/shell/support/search/SearchMatchTests.java index 78bafaf43..aaa48a788 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/support/search/SearchMatchTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/support/search/SearchMatchTests.java @@ -23,11 +23,7 @@ public class SearchMatchTests { @Test void testAlgoType() { - SearchMatch searchMatch = SearchMatch.builder() - .caseSensitive(true) - .normalize(true) - .forward(true) - .build(); + SearchMatch searchMatch = SearchMatch.builder().caseSensitive(true).normalize(true).forward(true).build(); assertThat(searchMatch).isNotNull(); SearchMatchResult result = null; @@ -37,4 +33,5 @@ void testAlgoType() { result = searchMatch.match("fake", "'fake"); assertThat(result.getAlgorithm()).isInstanceOf(ExactMatchNaiveSearchMatchAlgorithm.class); } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/AnnotationRegistrationSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/AnnotationRegistrationSnippets.java index e6abee872..0c0b39ffe 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/AnnotationRegistrationSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/AnnotationRegistrationSnippets.java @@ -27,6 +27,7 @@ static class MyCommands { @ShellMethod public void mycommand() { } + } // end::snippet1[] @@ -38,5 +39,7 @@ public int add(int a, int b) { return a + b; } // end::snippet2[] + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/BoxViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/BoxViewSnippets.java index af81a44e8..0cd65df0d 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/BoxViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/BoxViewSnippets.java @@ -25,12 +25,12 @@ void dump1() { // tag::sample[] BoxView view = new BoxView(); view.setDrawFunction((screen, rect) -> { - screen.writerBuilder().build() - .text("hi", 0, 0); + screen.writerBuilder().build().text("hi", 0, 0); return rect; }); // end::sample[] } + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ButtonViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ButtonViewSnippets.java index 511fa5f77..cfcffaba4 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ButtonViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ButtonViewSnippets.java @@ -30,6 +30,7 @@ void dump1() { }); // end::sample[] } + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAnnotationSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAnnotationSnippets.java index 6e24bd26e..9eb6e1b60 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAnnotationSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAnnotationSnippets.java @@ -21,46 +21,53 @@ class CommandAnnotationSnippets { - class Dump1 { + class Dump1 { - // tag::enablecommand-with-class[] - @EnableCommand(Example.class) - class App { - } - // end::enablecommand-with-class[] + // tag::enablecommand-with-class[] + @EnableCommand(Example.class) + class App { + + } + // end::enablecommand-with-class[] - // tag::command-anno-in-method[] - class Example { + // tag::command-anno-in-method[] + class Example { - @Command(command = "example") - public String example() { - return "Hello"; - } + @Command(command = "example") + public String example() { + return "Hello"; } - // end::command-anno-in-method[] + } + // end::command-anno-in-method[] + + } - class Dump2 { + class Dump2 { - // tag::command-anno-in-class[] - @Command(command = "parent") - class Example { + // tag::command-anno-in-class[] + @Command(command = "parent") + class Example { - @Command(command = "example") - public String example() { - return "Hello"; - } + @Command(command = "example") + public String example() { + return "Hello"; } - // end::command-anno-in-class[] + } + // end::command-anno-in-class[] - class Dump3 { + } + + class Dump3 { + + // tag::commandscan-no-args[] + @CommandScan + class App { - // tag::commandscan-no-args[] - @CommandScan - class App { - } - // end::commandscan-no-args[] } + // end::commandscan-no-args[] + + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAvailabilitySnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAvailabilitySnippets.java index b14211003..ccb798ae9 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAvailabilitySnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandAvailabilitySnippets.java @@ -33,6 +33,7 @@ class CommandAvailabilitySnippets { class Dump1 { + // tag::availability-method-in-shellcomponent[] @ShellComponent public class MyCommands { @@ -51,15 +52,16 @@ public void download() { } public Availability downloadAvailability() { - return connected - ? Availability.available() - : Availability.unavailable("you are not connected"); + return connected ? Availability.available() : Availability.unavailable("you are not connected"); } + } // end::availability-method-in-shellcomponent[] + } class Dump2 { + boolean connected; // tag::availability-method-name-in-shellcomponent[] @@ -69,15 +71,16 @@ public void download() { } public Availability availabilityCheck() { // <1> - return connected - ? Availability.available() - : Availability.unavailable("you are not connected"); + return connected ? Availability.available() : Availability.unavailable("you are not connected"); } // end::availability-method-name-in-shellcomponent[] + } class Dump3 { + boolean connected; + // tag::availability-method-name-multi-in-shellcomponent[] @ShellMethod("Download the nuclear codes.") public void download() { @@ -87,14 +90,13 @@ public void download() { public void disconnect() { } - @ShellMethodAvailability({"download", "disconnect"}) + @ShellMethodAvailability({ "download", "disconnect" }) public Availability availabilityCheck() { - return connected - ? Availability.available() - : Availability.unavailable("you are not connected"); + return connected ? Availability.available() : Availability.unavailable("you are not connected"); } // end::availability-method-name-multi-in-shellcomponent[] + } // tag::availability-method-default-value-in-shellcomponent[] @@ -103,50 +105,50 @@ public class Toggles { @ShellMethodAvailability public Availability availabilityOnWeekdays() { - return Calendar.getInstance().get(DAY_OF_WEEK) == SUNDAY - ? Availability.available() - : Availability.unavailable("today is not Sunday"); + return Calendar.getInstance().get(DAY_OF_WEEK) == SUNDAY ? Availability.available() + : Availability.unavailable("today is not Sunday"); } @ShellMethod - public void foo() {} + public void foo() { + } @ShellMethod - public void bar() {} + public void bar() { + } + } // end::availability-method-default-value-in-shellcomponent[] class Dump4 { - // tag::availability-method-annotation[] - @Command - class MyCommands { - private boolean connected; + // tag::availability-method-annotation[] + @Command + class MyCommands { - @Command(command = "connect") - public void connect(String user, String password) { - connected = true; - } + private boolean connected; + @Command(command = "connect") + public void connect(String user, String password) { + connected = true; + } - @Command(command = "download") - @CommandAvailability(provider = "downloadAvailability") - public void download( - ) { - // do something - } + @Command(command = "download") + @CommandAvailability(provider = "downloadAvailability") + public void download() { + // do something + } + + @Bean + public AvailabilityProvider downloadAvailability() { + return () -> connected ? Availability.available() : Availability.unavailable("you are not connected"); + } - @Bean - public AvailabilityProvider downloadAvailability() { - return () -> connected - ? Availability.available() - : Availability.unavailable("you are not connected"); } - } - // end::availability-method-annotation[] - } + // end::availability-method-annotation[] + } class Dump5 { @@ -154,40 +156,30 @@ class Dump5 { private boolean connected; @Bean - public CommandRegistration connect( - CommandRegistration.BuilderSupplier builder) { + public CommandRegistration connect(CommandRegistration.BuilderSupplier builder) { return builder.get() .command("connect") .withOption() - .longNames("connected") - .required() - .type(boolean.class) - .and() + .longNames("connected") + .required() + .type(boolean.class) + .and() .withTarget() - .consumer(ctx -> { - boolean connected = ctx.getOptionValue("connected"); - this.connected = connected; - }) - .and() + .consumer(ctx -> { + boolean connected = ctx.getOptionValue("connected"); + this.connected = connected; + }) + .and() .build(); } @Bean - public CommandRegistration download( - CommandRegistration.BuilderSupplier builder) { - return builder.get() - .command("download") - .availability(() -> { - return connected - ? Availability.available() - : Availability.unavailable("you are not connected"); - }) - .withTarget() - .consumer(ctx -> { - // do something - }) - .and() - .build(); + public CommandRegistration download(CommandRegistration.BuilderSupplier builder) { + return builder.get().command("download").availability(() -> { + return connected ? Availability.available() : Availability.unavailable("you are not connected"); + }).withTarget().consumer(ctx -> { + // do something + }).and().build(); } // end::availability-method-programmatic[] diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandCatalogSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandCatalogSnippets.java index 03dec5bbb..0983e2fa5 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandCatalogSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandCatalogSnippets.java @@ -36,12 +36,11 @@ void dump1() { // tag::snippet2[] static class CustomCommandResolver implements CommandResolver { + List registrations = new ArrayList<>(); CustomCommandResolver() { - CommandRegistration resolved = CommandRegistration.builder() - .command("resolve command") - .build(); + CommandRegistration resolved = CommandRegistration.builder().command("resolve command").build(); registrations.add(resolved); } @@ -49,6 +48,7 @@ static class CustomCommandResolver implements CommandResolver { public List resolve() { return registrations; } + } // end::snippet2[] @@ -57,11 +57,11 @@ static class CustomCommandCatalogCustomizer implements CommandCatalogCustomizer @Override public void customize(CommandCatalog commandCatalog) { - CommandRegistration registration = CommandRegistration.builder() - .command("resolve command") - .build(); + CommandRegistration registration = CommandRegistration.builder().command("resolve command").build(); commandCatalog.register(registration); } + } // end::snippet3[] + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandNotFoundSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandNotFoundSnippets.java index c8e78e77e..7cc0d8d32 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandNotFoundSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandNotFoundSnippets.java @@ -40,6 +40,7 @@ public String apply(ProviderContext context) { String text = context.text(); return "My custom message"; } + } // end::custom-provider[] @@ -58,6 +59,7 @@ CommandNotFoundMessageProvider provider2() { return ctx -> "My custom message"; } // end::provider-bean-2[] + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationAliasSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationAliasSnippets.java index 422ae6474..1fd8406f5 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationAliasSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationAliasSnippets.java @@ -26,12 +26,12 @@ CommandRegistration commandRegistration() { .command("mycommand") // define alias as myalias .withAlias() - .command("myalias") - .and() + .command("myalias") + .and() // define alias as myalias1 and myalias2 .withAlias() - .command("myalias1", "myalias2") - .and() + .command("myalias1", "myalias2") + .and() .build(); } // end::builder[] @@ -45,8 +45,10 @@ class MyCommands { @Command(command = "mycommand", alias = "myalias") void myCommand() { } + } // end::command1[] + } class Dump2 { @@ -58,8 +60,10 @@ class MyCommands { @Command(command = "mycommand", alias = { "myalias1", "myalias2" }) void myCommand() { } + } // end::command2[] + } class Dump3 { @@ -71,8 +75,10 @@ class MyCommands { @Command(command = "mycommand") void myCommand() { } + } // end::command3[] + } class Dump4 { @@ -84,8 +90,10 @@ class MyCommands { @Command(command = "mycommand", alias = "myalias2") void myCommand() { } + } // end::command4[] + } class Dump5 { @@ -101,7 +109,10 @@ void myMainCommand() { @Command(command = "mysubcommand", alias = "mysubalias") void mySubCommand() { } + } // end::command5[] + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationBeanSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationBeanSnippets.java index 63770f3bb..59d7160fa 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationBeanSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationBeanSnippets.java @@ -22,28 +22,29 @@ public class CommandRegistrationBeanSnippets { class Dump1 { + // tag::plain[] @Bean CommandRegistration commandRegistration() { - return CommandRegistration.builder() - .command("mycommand") - .build(); + return CommandRegistration.builder().command("mycommand").build(); } // end::plain[] + } class Dump2 { + // tag::fromsupplier[] @Bean CommandRegistration commandRegistration(CommandRegistration.BuilderSupplier builder) { - return builder.get() - .command("mycommand") - .build(); + return builder.get().command("mycommand").build(); } // end::fromsupplier[] + } class Dump3 { + // tag::customizer[] @Bean CommandRegistrationCustomizer commandRegistrationCustomizerExample() { @@ -52,5 +53,7 @@ CommandRegistrationCustomizer commandRegistrationCustomizerExample() { }; } // end::customizer[] + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationHelpOptionsSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationHelpOptionsSnippets.java index 188d8c1fa..061257f13 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationHelpOptionsSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationHelpOptionsSnippets.java @@ -21,20 +21,22 @@ class CommandRegistrationHelpOptionsSnippets { class Dump1 { + // tag::defaults[] @Bean CommandRegistration commandRegistration() { return CommandRegistration.builder() .command("mycommand") .withHelpOptions() - .enabled(true) - .longNames("help") - .shortNames('h') - .command("help") - .and() + .enabled(true) + .longNames("help") + .shortNames('h') + .command("help") + .and() .build(); } // end::defaults[] + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationInteractionModeSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationInteractionModeSnippets.java index c97ebe87f..30b597494 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationInteractionModeSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationInteractionModeSnippets.java @@ -42,6 +42,7 @@ static class Dump1 { public void mycommand() { } // end::snippet2[] + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationSnippets.java index 6b9cd6ec6..101e96b5e 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandRegistrationSnippets.java @@ -21,21 +21,14 @@ public class CommandRegistrationSnippets { void dump1() { // tag::snippet1[] - CommandRegistration.builder() - .withOption() - .longNames("myopt") - .and() - .build(); + CommandRegistration.builder().withOption().longNames("myopt").and().build(); // end::snippet1[] } void dump2() { // tag::snippet2[] - CommandRegistration.builder() - .withOption() - .shortNames('s') - .and() - .build(); + CommandRegistration.builder().withOption().shortNames('s').and().build(); // end::snippet2[] } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandTargetSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandTargetSnippets.java index c00dbf2c9..25a600f37 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandTargetSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CommandTargetSnippets.java @@ -25,6 +25,7 @@ public static class CommandPojo { String command(String arg) { return arg; } + } // end::snippet11[] @@ -34,47 +35,31 @@ void dump1() { CommandRegistration.builder() .command("command") .withTarget() - .method(pojo, "command") - .and() + .method(pojo, "command") + .and() .withOption() - .longNames("arg") - .and() + .longNames("arg") + .and() .build(); // end::snippet12[] } void dump2() { // tag::snippet2[] - CommandRegistration.builder() - .command("command") - .withTarget() - .function(ctx -> { - String arg = ctx.getOptionValue("arg"); - return String.format("hi, arg value is '%s'", arg); - }) - .and() - .withOption() - .longNames("arg") - .and() - .build(); + CommandRegistration.builder().command("command").withTarget().function(ctx -> { + String arg = ctx.getOptionValue("arg"); + return String.format("hi, arg value is '%s'", arg); + }).and().withOption().longNames("arg").and().build(); // end::snippet2[] } void dump3() { // tag::snippet3[] - CommandRegistration.builder() - .command("command") - .withTarget() - .consumer(ctx -> { - String arg = ctx.getOptionValue("arg"); - ctx.getTerminal().writer() - .println(String.format("hi, arg value is '%s'", arg)); - }) - .and() - .withOption() - .longNames("arg") - .and() - .build(); + CommandRegistration.builder().command("command").withTarget().consumer(ctx -> { + String arg = ctx.getOptionValue("arg"); + ctx.getTerminal().writer().println(String.format("hi, arg value is '%s'", arg)); + }).and().withOption().longNames("arg").and().build(); // end::snippet3[] } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CompletionSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CompletionSnippets.java index 60b13fb5d..3af278d56 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/CompletionSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/CompletionSnippets.java @@ -31,16 +31,9 @@ public class CompletionSnippets { // tag::builder-1[] void dump1() { - CommandRegistration.builder() - .withOption() - .longNames("arg1") - .completion(ctx -> { - return Arrays.asList("val1", "val2").stream() - .map(CompletionProposal::new) - .collect(Collectors.toList()); - }) - .and() - .build(); + CommandRegistration.builder().withOption().longNames("arg1").completion(ctx -> { + return Arrays.asList("val1", "val2").stream().map(CompletionProposal::new).collect(Collectors.toList()); + }).and().build(); } // end::builder-1[] @@ -49,10 +42,9 @@ static class MyValuesCompletionResolver implements CompletionResolver { @Override public List apply(CompletionContext t) { - return Arrays.asList("val1", "val2").stream() - .map(CompletionProposal::new) - .collect(Collectors.toList()); + return Arrays.asList("val1", "val2").stream().map(CompletionProposal::new).collect(Collectors.toList()); } + } // end::resolver-1[] @@ -61,21 +53,21 @@ static class MyValuesProvider implements ValueProvider { @Override public List complete(CompletionContext completionContext) { - return Arrays.asList("val1", "val2").stream() - .map(CompletionProposal::new) - .collect(Collectors.toList()); + return Arrays.asList("val1", "val2").stream().map(CompletionProposal::new).collect(Collectors.toList()); } + } // end::provider-1[] static class Dump1 { + // tag::anno-method[] @ShellMethod(value = "complete", key = "complete") - public String complete( - @ShellOption(valueProvider = MyValuesProvider.class) String arg1) - { + public String complete(@ShellOption(valueProvider = MyValuesProvider.class) String arg1) { return "You said " + arg1; } // end::anno-method[] + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ErrorHandlingSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ErrorHandlingSnippets.java index a7ae0440a..50752080d 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ErrorHandlingSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ErrorHandlingSnippets.java @@ -36,6 +36,7 @@ static class CustomException extends RuntimeException implements ExitCodeGenerat public int getExitCode() { return 0; } + } // end::my-exception-class[] @@ -49,16 +50,13 @@ public CommandHandlingResult resolve(Exception e) { } return null; } + } // end::my-exception-resolver-class[] void dump1() { // tag::example1[] - CommandRegistration.builder() - .withErrorHandling() - .resolver(new CustomExceptionResolver()) - .and() - .build(); + CommandRegistration.builder().withErrorHandling().resolver(new CustomExceptionResolver()).and().build(); // end::example1[] } @@ -72,6 +70,7 @@ CommandHandlingResult errorHandler(Exception e) { return CommandHandlingResult.of("Hi, handled exception\n", 42); } // end::exception-resolver-with-type-in-annotation[] + } static class Dump2 { @@ -82,6 +81,7 @@ CommandHandlingResult errorHandler(RuntimeException e) { return CommandHandlingResult.of("Hi, handled custom exception\n", 42); } // end::exception-resolver-with-type-in-method[] + } static class Dump3 { @@ -92,6 +92,7 @@ CustomExceptionResolver customExceptionResolver() { return new CustomExceptionResolver(); } // end::my-exception-resolver-class-as-bean[] + } static class Dump4 { @@ -103,6 +104,7 @@ String errorHandler(Exception e) { return "Hi, handled exception"; } // end::exception-resolver-with-exitcode-annotation[] + } static class Dump5 { @@ -112,10 +114,12 @@ static class Dump5 { @ExitCode(code = 5) void errorHandler(Exception e, Terminal terminal) { PrintWriter writer = terminal.writer(); - String msg = "Hi, handled exception " + e.toString(); + String msg = "Hi, handled exception " + e.toString(); writer.println(msg); writer.flush(); } // end::exception-resolver-with-void[] + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/EventLoopSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/EventLoopSnippets.java index 37d447ea3..1cc6f232a 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/EventLoopSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/EventLoopSnippets.java @@ -43,11 +43,9 @@ void keyEvents() { // tag::keyevents[] TerminalUI ui = new TerminalUI(terminal); EventLoop eventLoop = ui.getEventLoop(); - eventLoop.keyEvents() - .doOnNext(event -> { - // do something with key event - }) - .subscribe(); + eventLoop.keyEvents().doOnNext(event -> { + // do something with key event + }).subscribe(); // end::keyevents[] } @@ -58,6 +56,7 @@ void onDestroy() { eventLoop.onDestroy(eventLoop.events().subscribe()); // end::ondestroy[] } + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ExitCodeSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ExitCodeSnippets.java index 6c4587822..77f3f3823 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ExitCodeSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ExitCodeSnippets.java @@ -32,22 +32,19 @@ static class MyException extends RuntimeException { public int getCode() { return code; } + } // end::my-exception-class[] void dump1() { // tag::example1[] - CommandRegistration.builder() - .withExitCode() - .map(MyException.class, 3) - .map(t -> { - if (t instanceof MyException) { - return ((MyException) t).getCode(); - } - return 0; - }) - .and() - .build(); + CommandRegistration.builder().withExitCode().map(MyException.class, 3).map(t -> { + if (t instanceof MyException) { + return ((MyException) t).getCode(); + } + return 0; + }).and().build(); // end::example1[] } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java index fad1cc23c..415ce8c8f 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java @@ -37,36 +37,36 @@ public void runFlow() { SelectItem.of("key2", "value2")); List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); - ComponentFlow flow = componentFlowBuilder.clone().reset() - .withStringInput("field1") - .name("Field1") - .defaultValue("defaultField1Value") - .and() - .withStringInput("field2") - .name("Field2") - .and() - .withConfirmationInput("confirmation1") - .name("Confirmation1") - .and() - .withPathInput("path1") - .name("Path1") - .and() - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .and() - .withMultiItemSelector("multi1") - .name("Multi1") - .selectItems(multi1SelectItems) - .and() - .build(); + ComponentFlow flow = componentFlowBuilder.clone() + .reset() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .and() + .withStringInput("field2") + .name("Field2") + .and() + .withConfirmationInput("confirmation1") + .name("Confirmation1") + .and() + .withPathInput("path1") + .name("Path1") + .and() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .and() + .withMultiItemSelector("multi1") + .name("Multi1") + .selectItems(multi1SelectItems) + .and() + .build(); flow.run(); } } // end::snippet1[] - // tag::snippet2[] static class FlowSampleConditional { @@ -77,23 +77,24 @@ public void runFlow() { Map single1SelectItems = new HashMap<>(); single1SelectItems.put("Field1", "field1"); single1SelectItems.put("Field2", "field2"); - ComponentFlow flow = componentFlowBuilder.clone().reset() - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .next(ctx -> ctx.getResultItem().get().getItem()) - .and() - .withStringInput("field1") - .name("Field1") - .defaultValue("defaultField1Value") - .next(ctx -> null) - .and() - .withStringInput("field2") - .name("Field2") - .defaultValue("defaultField2Value") - .next(ctx -> null) - .and() - .build(); + ComponentFlow flow = componentFlowBuilder.clone() + .reset() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .next(ctx -> ctx.getResultItem().get().getItem()) + .and() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .next(ctx -> null) + .and() + .withStringInput("field2") + .name("Field2") + .defaultValue("defaultField2Value") + .next(ctx -> null) + .and() + .build(); flow.run(); } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/GridViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/GridViewSnippets.java index 797a908a9..16da9255e 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/GridViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/GridViewSnippets.java @@ -35,6 +35,7 @@ void dump1() { grid.addItem(new BoxView(), 1, 1, 1, 1, 0, 0); // end::snippet1[] } + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/InputViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/InputViewSnippets.java index 9e2b99cc8..924852539 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/InputViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/InputViewSnippets.java @@ -28,6 +28,7 @@ void dump1() { String text = input.getInputText(); // end::sample[] } + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ListViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ListViewSnippets.java index dc0dc8db7..5f9110d69 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ListViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ListViewSnippets.java @@ -41,6 +41,7 @@ void dump2() { ListView view = new ListView<>(ItemStyle.CHECKED); // end::snippet2[] } + } // tag::listcell[] @@ -60,6 +61,7 @@ public void draw(Screen screen) { writer.text(getItem().name(), rect.x(), rect.y()); writer.background(rect, getBackgroundColor()); } + } // end::listcell[] @@ -71,6 +73,7 @@ void dump1() { view.setCellFactory((list, item) -> new ExampleListCell(item)); // end::uselistcell[] } + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/MenuBarViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/MenuBarViewSnippets.java index 9d0602f8c..55d7e0276 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/MenuBarViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/MenuBarViewSnippets.java @@ -29,17 +29,17 @@ class Dump1 { @SuppressWarnings("unused") void dump1() { // tag::snippet1[] - Runnable quitAction = () -> {}; - Runnable aboutAction = () -> {}; + Runnable quitAction = () -> { + }; + Runnable aboutAction = () -> { + }; MenuBarView menuBar = MenuBarView.of( - MenuBarItem.of("File", - MenuItem.of("Quit", MenuItemCheckStyle.NOCHECK, quitAction)) - .setHotKey(Key.f | KeyMask.AltMask), - MenuBarItem.of("Help", - MenuItem.of("About", MenuItemCheckStyle.NOCHECK, aboutAction)) - ); + MenuBarItem.of("File", MenuItem.of("Quit", MenuItemCheckStyle.NOCHECK, quitAction)) + .setHotKey(Key.f | KeyMask.AltMask), + MenuBarItem.of("Help", MenuItem.of("About", MenuItemCheckStyle.NOCHECK, aboutAction))); // end::snippet1[] } } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionSnippets.java index 51c191c2c..49e67e738 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionSnippets.java @@ -29,156 +29,156 @@ public class OptionSnippets { class Dump1Legacy { + // tag::option-with-annotation[] @ShellMethod public String example(@ShellOption(value = { "--arg" }) String arg1) { return "Hello " + arg1; } // end::option-with-annotation[] + } class Dump1 { + // tag::option-with-option-annotation[] @Command public String example(@Option(longNames = "arg") String arg1) { return "Hello " + arg1; } // end::option-with-option-annotation[] + } class Dump7 { + // tag::option-with-annotation-without-prefix[] @ShellMethod public String example(@ShellOption(value = { "arg" }) String arg1) { return "Hello " + arg1; } // end::option-with-annotation-without-prefix[] + } class Dump2 { + // tag::option-without-annotation[] @ShellMethod public String example(String arg1) { return "Hello " + arg1; } // end::option-without-annotation[] + } class Dump3 { + // tag::option-with-annotation-shortarg[] - public String example( - @ShellOption(value = { "-a" }) String arg1, - @ShellOption(value = { "-b" }) String arg2, - @ShellOption(value = { "-c" }) String arg3 - ) { + public String example(@ShellOption(value = { "-a" }) String arg1, @ShellOption(value = { "-b" }) String arg2, + @ShellOption(value = { "-c" }) String arg3) { return "Hello " + arg1; } // end::option-with-annotation-shortarg[] + } class Dump4 { + // tag::option-with-annotation-arity[] public String example(@ShellOption(arity = 1) String arg1) { return "Hello " + arg1; } // end::option-with-annotation-arity[] + } class Dump5 { + // tag::option-with-annotation-optional[] - public String example( - @ShellOption(defaultValue = ShellOption.NULL) String arg1 - ) { + public String example(@ShellOption(defaultValue = ShellOption.NULL) String arg1) { return "Hello " + arg1; } // end::option-with-annotation-optional[] + } class Dump6 { + // tag::option-with-annotation-default[] - public String example( - @ShellOption(defaultValue = "defaultValue") String arg1 - ) { + public String example(@ShellOption(defaultValue = "defaultValue") String arg1) { return "Hello " + arg1; } // end::option-with-annotation-default[] + } @SuppressWarnings("unused") public void dump1() { // tag::option-registration-longarg[] - CommandRegistration registration = CommandRegistration.builder() - .withOption() - .longNames("arg1") - .and() - .build(); + CommandRegistration registration = CommandRegistration.builder().withOption().longNames("arg1").and().build(); // end::option-registration-longarg[] // tag::option-registration-shortarg[] CommandRegistration.builder() .withOption() - .shortNames('a') - .and() + .shortNames('a') + .and() .withOption() - .shortNames('b') - .and() + .shortNames('b') + .and() .withOption() - .shortNames('c') - .and() + .shortNames('c') + .and() .build(); // end::option-registration-shortarg[] // tag::option-registration-shortargbooleans[] CommandRegistration.builder() .withOption() - .shortNames('a') - .type(boolean.class) - .and() + .shortNames('a') + .type(boolean.class) + .and() .withOption() - .shortNames('b') - .type(boolean.class) - .and() + .shortNames('b') + .type(boolean.class) + .and() .withOption() - .shortNames('c') - .type(boolean.class) - .and() + .shortNames('c') + .type(boolean.class) + .and() .build(); // end::option-registration-shortargbooleans[] // tag::option-registration-arityenum[] - CommandRegistration.builder() - .withOption() - .longNames("arg1") - .arity(OptionArity.EXACTLY_ONE) - .and() - .build(); + CommandRegistration.builder().withOption().longNames("arg1").arity(OptionArity.EXACTLY_ONE).and().build(); // end::option-registration-arityenum[] // // tag::option-registration-arityints[] // CommandRegistration.builder() - // .withOption() - // .longNames("arg1") - // .arity(0, 1) - // .and() - // .build(); + // .withOption() + // .longNames("arg1") + // .arity(0, 1) + // .and() + // .build(); // // end::option-registration-arityints[] // tag::option-registration-aritystrings-sample[] CommandRegistration.builder() .command("arity-errors") .withOption() - .longNames("arg1") - .type(String[].class) - .required() - .arity(1, 2) - .and() + .longNames("arg1") + .type(String[].class) + .required() + .arity(1, 2) + .and() .withTarget() - .function(ctx -> { - String[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + Arrays.asList(arg1); - }) - .and() + .function(ctx -> { + String[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + Arrays.asList(arg1); + }) + .and() .build(); // end::option-registration-aritystrings-sample[] @@ -186,18 +186,18 @@ public void dump1() { CommandRegistration.builder() .command("arity-strings-2") .withOption() - .longNames("arg1") - .required() - .type(String[].class) - .arity(0, 2) - .position(0) - .and() + .longNames("arg1") + .required() + .type(String[].class) + .arity(0, 2) + .position(0) + .and() .withTarget() - .function(ctx -> { - String[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + Arrays.asList(arg1); - }) - .and() + .function(ctx -> { + String[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + Arrays.asList(arg1); + }) + .and() .build(); // end::option-registration-aritystrings-position[] @@ -205,70 +205,51 @@ public void dump1() { CommandRegistration.builder() .command("arity-strings-1") .withOption() - .longNames("arg1") - .required() - .type(String[].class) - .arity(0, 2) - .and() + .longNames("arg1") + .required() + .type(String[].class) + .arity(0, 2) + .and() .withTarget() - .function(ctx -> { - String[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + Arrays.asList(arg1); - }) - .and() + .function(ctx -> { + String[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + Arrays.asList(arg1); + }) + .and() .build(); // end::option-registration-aritystrings-noposition[] // tag::option-registration-optional[] - CommandRegistration.builder() - .withOption() - .longNames("arg1") - .required() - .and() - .build(); + CommandRegistration.builder().withOption().longNames("arg1").required().and().build(); // end::option-registration-optional[] // tag::option-registration-positional[] - CommandRegistration.builder() - .withOption() - .longNames("arg1") - .position(0) - .and() - .build(); + CommandRegistration.builder().withOption().longNames("arg1").position(0).and().build(); // end::option-registration-positional[] // tag::option-registration-default[] - CommandRegistration.builder() - .withOption() - .longNames("arg1") - .defaultValue("defaultValue") - .and() - .build(); + CommandRegistration.builder().withOption().longNames("arg1").defaultValue("defaultValue").and().build(); // end::option-registration-default[] // tag::option-registration-label[] CommandRegistration.builder() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withOption() - .longNames("arg2") - .label("MYLABEL") - .and() + .longNames("arg2") + .label("MYLABEL") + .and() .build(); // end::option-registration-label[] // tag::option-registration-naming-case-req[] - CommandRegistration.builder() - .withOption() - .longNames("arg1") - .nameModifier(name -> "x" + name) - .and() - .build(); + 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() { @@ -278,12 +259,9 @@ OptionNameModifier sampleOptionNameModifier() { // 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 - ) {} + 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[] } @@ -292,40 +270,30 @@ static class LegacyAnnotation { // tag::option-registration-zeroorone-legacyannotation[] @ShellMethod(key = "example") - String zeroOrOne( - @ShellOption(arity = 1) String arg) - { + String zeroOrOne(@ShellOption(arity = 1) String arg) { return String.format("Hi '%s'", arg); } // end::option-registration-zeroorone-legacyannotation[] // tag::option-registration-zerooronewithminmax-legacyannotation[] @ShellMethod(key = "example") - String zeroOrOneWithMinMax( - @ShellOption(arity = 1) String arg) - { + String zeroOrOneWithMinMax(@ShellOption(arity = 1) String arg) { return String.format("Hi '%s'", arg); } // end::option-registration-zerooronewithminmax-legacyannotation[] // tag::option-optional-legacyannotation[] - void optionalOption( - @ShellOption(defaultValue = ShellOption.NULL) String arg - ) { + void optionalOption(@ShellOption(defaultValue = ShellOption.NULL) String arg) { } // end::option-optional-legacyannotation[] // tag::option-mandatory-legacyannotation[] - void mandatoryOption( - @ShellOption() String arg - ) { + void mandatoryOption(@ShellOption() String arg) { } // end::option-mandatory-legacyannotation[] // tag::option-default-legacyannotation[] - void defaultOption( - @ShellOption(defaultValue = "default") String arg - ) { + void defaultOption(@ShellOption(defaultValue = "default") String arg) { } // end::option-default-legacyannotation[] @@ -335,47 +303,35 @@ static class Annotation { // tag::option-registration-zeroorone-annotation[] @Command(command = "example") - String zeroOrOne( - @Option(arity = OptionArity.ZERO_OR_ONE) String arg) - { + String zeroOrOne(@Option(arity = OptionArity.ZERO_OR_ONE) String arg) { return String.format("Hi '%s'", arg); } // end::option-registration-zeroorone-annotation[] // tag::option-registration-zerooronewithminmax-annotation[] @Command(command = "example") - String zeroOrOneWithMinMax( - @Option(arityMin = 0, arityMax = 1) String arg) - { + String zeroOrOneWithMinMax(@Option(arityMin = 0, arityMax = 1) String arg) { return String.format("Hi '%s'", arg); } // end::option-registration-zerooronewithminmax-annotation[] // tag::option-optional-annotation[] - void optionalOption( - @Option(required = false) String arg - ) { + void optionalOption(@Option(required = false) String arg) { } // end::option-optional-annotation[] // tag::option-mandatory-annotation[] - void mandatoryOption( - @Option(required = true) String arg - ) { + void mandatoryOption(@Option(required = true) String arg) { } // end::option-mandatory-annotation[] // tag::option-default-annotation[] - void defaultOption( - @Option(defaultValue = "default") String arg - ) { + void defaultOption(@Option(defaultValue = "default") String arg) { } // end::option-default-annotation[] // tag::option-label-annotation[] - void labelOption( - @Option(label = "MYLABEL") String arg - ) { + void labelOption(@Option(label = "MYLABEL") String arg) { } // end::option-label-annotation[] @@ -388,9 +344,9 @@ CommandRegistration zeroOrOne() { return CommandRegistration.builder() .command("example") .withOption() - .longNames("arg") - .arity(OptionArity.ZERO_OR_ONE) - .and() + .longNames("arg") + .arity(OptionArity.ZERO_OR_ONE) + .and() .build(); } // end::option-registration-zeroorone-programmatic[] @@ -400,9 +356,9 @@ CommandRegistration zeroOrOneWithMinMax() { return CommandRegistration.builder() .command("example") .withOption() - .longNames("arg") - .arity(0, 1) - .and() + .longNames("arg") + .arity(0, 1) + .and() .build(); } // end::option-registration-zerooronewithminmax-programmatic[] @@ -412,9 +368,9 @@ CommandRegistration optionalOption() { return CommandRegistration.builder() .command("optionalOption") .withOption() - .longNames("arg") - .required(false) - .and() + .longNames("arg") + .required(false) + .and() .build(); } // end::option-optional-programmatic[] @@ -424,9 +380,9 @@ CommandRegistration mandatoryOption() { return CommandRegistration.builder() .command("optionalOption") .withOption() - .longNames("arg") - .required() - .and() + .longNames("arg") + .required() + .and() .build(); } // end::option-mandatory-programmatic[] @@ -436,22 +392,19 @@ CommandRegistration defaultOption() { return CommandRegistration.builder() .command("defaultOption") .withOption() - .longNames("arg") - .defaultValue("default") - .and() + .longNames("arg") + .defaultValue("default") + .and() .build(); } // end::option-default-programmatic[] // tag::option-label-programmatic[] CommandRegistration labelOption() { - return CommandRegistration.builder() - .withOption() - .longNames("arg") - .label("MYLABEL") - .and() - .build(); + return CommandRegistration.builder().withOption().longNames("arg").label("MYLABEL").and().build(); } // end::option-label-programmatic[] + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionTypesSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionTypesSnippets.java index 3046c0893..fb017122e 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionTypesSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/OptionTypesSnippets.java @@ -21,111 +21,130 @@ class OptionTypesSnippets { class Dump1 { + // tag::option-type-boolean-anno[] - String example( - @ShellOption() boolean arg1, - @ShellOption(defaultValue = "true") boolean arg2, - @ShellOption(defaultValue = "false") boolean arg3, - @ShellOption() Boolean arg4, - @ShellOption(defaultValue = "true") Boolean arg5, - @ShellOption(defaultValue = "false") Boolean arg6 - ) { - return String.format("arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s", - arg1, arg2, arg3, arg4, arg5, arg6); + String example(@ShellOption() boolean arg1, @ShellOption(defaultValue = "true") boolean arg2, + @ShellOption(defaultValue = "false") boolean arg3, @ShellOption() Boolean arg4, + @ShellOption(defaultValue = "true") Boolean arg5, @ShellOption(defaultValue = "false") Boolean arg6) { + return String.format("arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s", arg1, arg2, arg3, arg4, arg5, arg6); } + // end::option-type-boolean-anno[] void dump() { - // tag::option-type-boolean-reg[] - CommandRegistration.builder() - .command("example") - .withOption() - .longNames("arg1").type(boolean.class).and() - .withOption() - .longNames("arg2").type(boolean.class).defaultValue("true").and() - .withOption() - .longNames("arg3").type(boolean.class).defaultValue("false").and() - .withOption() - .longNames("arg4").type(Boolean.class).and() - .withOption() - .longNames("arg5").type(Boolean.class).defaultValue("true").and() - .withOption() - .longNames("arg6").type(Boolean.class).defaultValue("false").and() - .withTarget() + // tag::option-type-boolean-reg[] + CommandRegistration.builder() + .command("example") + .withOption() + .longNames("arg1") + .type(boolean.class) + .and() + .withOption() + .longNames("arg2") + .type(boolean.class) + .defaultValue("true") + .and() + .withOption() + .longNames("arg3") + .type(boolean.class) + .defaultValue("false") + .and() + .withOption() + .longNames("arg4") + .type(Boolean.class) + .and() + .withOption() + .longNames("arg5") + .type(Boolean.class) + .defaultValue("true") + .and() + .withOption() + .longNames("arg6") + .type(Boolean.class) + .defaultValue("false") + .and() + .withTarget() .function(ctx -> { - boolean arg1 = ctx.hasMappedOption("arg1") - ? ctx.getOptionValue("arg1") - : false; + boolean arg1 = ctx.hasMappedOption("arg1") ? ctx.getOptionValue("arg1") : false; boolean arg2 = ctx.getOptionValue("arg2"); boolean arg3 = ctx.getOptionValue("arg3"); Boolean arg4 = ctx.getOptionValue("arg4"); Boolean arg5 = ctx.getOptionValue("arg5"); Boolean arg6 = ctx.getOptionValue("arg6"); - return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s", - arg1, arg2, arg3, arg4, arg5, arg6); + return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s", arg1, arg2, arg3, + arg4, arg5, arg6); }) .and() - .build(); - // end::option-type-boolean-reg[] + .build(); + // end::option-type-boolean-reg[] } + } class Dump2 { + // tag::option-type-integer-anno[] String example(@ShellOption(value = "arg1") int arg1) { return "Hello " + arg1; } + // end::option-type-integer-anno[] void dump() { - // tag::option-type-integer-reg[] - CommandRegistration.builder() - .command("example") - .withOption() + // tag::option-type-integer-reg[] + CommandRegistration.builder() + .command("example") + .withOption() .longNames("arg1") .type(int.class) .required() .and() - .withTarget() + .withTarget() .function(ctx -> { boolean arg1 = ctx.getOptionValue("arg1"); return "Hello " + arg1; }) .and() - .build(); - // end::option-type-integer-reg[] + .build(); + // end::option-type-integer-reg[] } + } class Dump3 { + // tag::option-type-string-anno[] String example(@ShellOption(value = "arg1") String arg1) { return "Hello " + arg1; } + // end::option-type-string-anno[] void dump() { - // tag::option-type-string-reg[] - CommandRegistration.builder() - .command("example") - .withOption() + // tag::option-type-string-reg[] + CommandRegistration.builder() + .command("example") + .withOption() .longNames("arg1") .type(String.class) .required() .and() - .withTarget() + .withTarget() .function(ctx -> { String arg1 = ctx.getOptionValue("arg1"); return "Hello " + arg1; }) .and() - .build(); - // end::option-type-string-reg[] + .build(); + // end::option-type-string-reg[] } + } class Dump4 { // tag::option-type-enum-class[] enum OptionTypeEnum { - ONE,TWO,THREE + + ONE, TWO, THREE + } // end::option-type-enum-class[] @@ -133,50 +152,56 @@ enum OptionTypeEnum { String example(@ShellOption(value = "arg1") OptionTypeEnum arg1) { return "Hello " + arg1; } + // end::option-type-enum-anno[] void dump() { - // tag::option-type-enum-reg[] - CommandRegistration.builder() - .command("example") - .withOption() + // tag::option-type-enum-reg[] + CommandRegistration.builder() + .command("example") + .withOption() .longNames("arg1") .type(OptionTypeEnum.class) .required() .and() - .withTarget() + .withTarget() .function(ctx -> { OptionTypeEnum arg1 = ctx.getOptionValue("arg1"); return "Hello " + arg1; }) .and() - .build(); - // end::option-type-enum-reg[] + .build(); + // end::option-type-enum-reg[] } + } class Dump5 { + // tag::option-type-string-array-anno[] String example(@ShellOption(value = "arg1") String[] arg1) { return "Hello " + arg1; } + // end::option-type-string-array-anno[] void dump() { - // tag::option-type-string-array-reg[] - CommandRegistration.builder() - .command("example") - .withOption() + // tag::option-type-string-array-reg[] + CommandRegistration.builder() + .command("example") + .withOption() .longNames("arg1") .type(String[].class) .required() .and() - .withTarget() + .withTarget() .function(ctx -> { String[] arg1 = ctx.getOptionValue("arg1"); return "Hello " + arg1; }) .and() - .build(); - // end::option-type-string-array-reg[] + .build(); + // end::option-type-string-array-reg[] } + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ProgressViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ProgressViewSnippets.java index 5ba49c0d2..66f1ff172 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ProgressViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ProgressViewSnippets.java @@ -32,10 +32,9 @@ void dump1() { void dump2() { // tag::allmixedalignandsize[] - ProgressView view = new ProgressView( - ProgressViewItem.ofText(10, HorizontalAlign.LEFT), - ProgressViewItem.ofSpinner(3, HorizontalAlign.LEFT), - ProgressViewItem.ofPercent(0, HorizontalAlign.RIGHT)); + ProgressView view = new ProgressView(ProgressViewItem.ofText(10, HorizontalAlign.LEFT), + ProgressViewItem.ofSpinner(3, HorizontalAlign.LEFT), + ProgressViewItem.ofPercent(0, HorizontalAlign.RIGHT)); view.start(); // end::allmixedalignandsize[] } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/SearchAlgorithmsSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/SearchAlgorithmsSnippets.java index b6aee0151..8dd351075 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/SearchAlgorithmsSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/SearchAlgorithmsSnippets.java @@ -23,21 +23,13 @@ class SearchAlgorithmsSnippets { @SuppressWarnings("unused") void dump1() { // tag::builder[] - SearchMatch searchMatch = SearchMatch.builder() - .caseSensitive(false) - .normalize(false) - .forward(true) - .build(); + SearchMatch searchMatch = SearchMatch.builder().caseSensitive(false).normalize(false).forward(true).build(); // end::builder[] } void dump2() { // tag::simple[] - SearchMatch searchMatch = SearchMatch.builder() - .caseSensitive(false) - .normalize(false) - .forward(true) - .build(); + SearchMatch searchMatch = SearchMatch.builder().caseSensitive(false).normalize(false).forward(true).build(); SearchMatchResult result = searchMatch.match("foo bar baz", "fbb"); diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ShortOptionSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ShortOptionSnippets.java index fb116e713..6de61d27a 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ShortOptionSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ShortOptionSnippets.java @@ -27,22 +27,19 @@ static class LegacyAnnotation { // tag::option-type-string-legacyannotation[] @ShellMethod(key = "example") - String stringWithShortOption( - @ShellOption(value = { "--arg", "-a" }) String arg) { + String stringWithShortOption(@ShellOption(value = { "--arg", "-a" }) String arg) { return String.format("Hi '%s'", arg); } // end::option-type-string-legacyannotation[] // tag::option-type-multiple-booleans-legacyannotation[] @ShellMethod(key = "example") - public String multipleBooleans( - @ShellOption(value = "-a") boolean a, - @ShellOption(value = "-b") boolean b, - @ShellOption(value = "-c") boolean c) - { + public String multipleBooleans(@ShellOption(value = "-a") boolean a, @ShellOption(value = "-b") boolean b, + @ShellOption(value = "-c") boolean c) { return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); } // end::option-type-multiple-booleans-legacyannotation[] + } // @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) @@ -50,74 +47,60 @@ static class Annotation { // tag::option-type-string-annotation[] @Command(command = "example") - String stringWithShortOption( - @Option(longNames = "arg", shortNames = 'a', required = true) String arg) { + String stringWithShortOption(@Option(longNames = "arg", shortNames = 'a', required = true) String arg) { return String.format("Hi '%s'", arg); } // end::option-type-string-annotation[] // tag::option-type-multiple-booleans-annotation[] @Command(command = "example") - public String multipleBooleans( - @Option(shortNames = 'a') boolean a, - @Option(shortNames = 'b') boolean b, + public String multipleBooleans(@Option(shortNames = 'a') boolean a, @Option(shortNames = 'b') boolean b, @Option(shortNames = 'c') boolean c) { return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); } // end::option-type-multiple-booleans-annotation[] + } static class Registration { // tag::option-type-string-programmatic[] CommandRegistration stringWithShortOption() { - return CommandRegistration.builder() - .command("example") - .withTarget() - .function(ctx -> { - String arg = ctx.hasMappedOption("arg") ? ctx.getOptionValue("arg") : null; - return String.format("Hi arg='%s'", arg); - }) - .and() - .withOption() - .longNames("arg") - .shortNames('a') - .required() - .and() - .build(); + return CommandRegistration.builder().command("example").withTarget().function(ctx -> { + String arg = ctx.hasMappedOption("arg") ? ctx.getOptionValue("arg") : null; + return String.format("Hi arg='%s'", arg); + }).and().withOption().longNames("arg").shortNames('a').required().and().build(); } // end::option-type-string-programmatic[] // tag::option-type-multiple-booleans-programmatic[] CommandRegistration multipleBooleans() { - return CommandRegistration.builder() - .command("example") - .withTarget() - .function(ctx -> { - Boolean a = ctx.hasMappedOption("a") ? ctx.getOptionValue("a") : null; - Boolean b = ctx.hasMappedOption("b") ? ctx.getOptionValue("b") : null; - Boolean c = ctx.hasMappedOption("c") ? ctx.getOptionValue("c") : null; - return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); - }) - .and() + return CommandRegistration.builder().command("example").withTarget().function(ctx -> { + Boolean a = ctx.hasMappedOption("a") ? ctx.getOptionValue("a") : null; + Boolean b = ctx.hasMappedOption("b") ? ctx.getOptionValue("b") : null; + Boolean c = ctx.hasMappedOption("c") ? ctx.getOptionValue("c") : null; + return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); + }) + .and() .withOption() - .shortNames('a') - .type(boolean.class) - .defaultValue("false") - .and() + .shortNames('a') + .type(boolean.class) + .defaultValue("false") + .and() .withOption() - .shortNames('b') - .type(boolean.class) - .defaultValue("false") - .and() + .shortNames('b') + .type(boolean.class) + .defaultValue("false") + .and() .withOption() - .shortNames('c') - .type(boolean.class) - .defaultValue("false") - .and() + .shortNames('c') + .type(boolean.class) + .defaultValue("false") + .and() .build(); } // end::option-type-multiple-booleans-programmatic[] + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/StatusBarViewSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/StatusBarViewSnippets.java index f64ec2356..00e348478 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/StatusBarViewSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/StatusBarViewSnippets.java @@ -36,10 +36,12 @@ void items() { // tag::items[] StatusItem item1 = StatusBarView.StatusItem.of("Item1"); - Runnable action1 = () -> {}; + Runnable action1 = () -> { + }; StatusItem item2 = StatusBarView.StatusItem.of("Item2", action1); - Runnable action2 = () -> {}; + Runnable action2 = () -> { + }; StatusItem item3 = StatusBarView.StatusItem.of("Item3", action2, KeyEvent.Key.f10); StatusBarView statusBar = new StatusBarView(); @@ -49,14 +51,9 @@ void items() { void viaArray() { // tag::viaarray[] - new StatusBarView(new StatusItem[] { - StatusItem.of("Item1"), - StatusItem.of("Item2") - .setAction(() -> {}), - StatusItem.of("Item3") - .setAction(() -> {}) - .setHotKey(Key.f10) - }); + new StatusBarView(new StatusItem[] { StatusItem.of("Item1"), StatusItem.of("Item2").setAction(() -> { + }), StatusItem.of("Item3").setAction(() -> { + }).setHotKey(Key.f10) }); // end::viaarray[] } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/TerminalUiSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/TerminalUiSnippets.java index 3a14e9000..6d5ee5246 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/TerminalUiSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/TerminalUiSnippets.java @@ -41,15 +41,14 @@ void sample() { BoxView view = new BoxView(); ui.configure(view); view.setDrawFunction((screen, rect) -> { - screen.writerBuilder() - .build() - .text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); + screen.writerBuilder().build().text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); return rect; }); ui.setRoot(view, true); ui.run(); } // end::introsample[] + } class Sample3 { @@ -64,15 +63,15 @@ void sample() { ui.configure(view); ui.setRoot(view, true); EventLoop eventLoop = ui.getEventLoop(); - eventLoop.keyEvents() - .subscribe(event -> { - if (event.getPlainKey() == Key.q && event.hasCtrl()) { - eventLoop.dispatch(ShellMessageBuilder.ofInterrupt()); - } - }); + eventLoop.keyEvents().subscribe(event -> { + if (event.getPlainKey() == Key.q && event.hasCtrl()) { + eventLoop.dispatch(ShellMessageBuilder.ofInterrupt()); + } + }); ui.run(); } // end::exitingfromloop[] + } @SuppressWarnings("unused") @@ -87,6 +86,7 @@ void sample() { // do something with ui } // end::uibuilderautowire[] + } class SampleConfigureView { @@ -99,6 +99,7 @@ void sample() { ui.configure(view); } // end::configureview[] + } class SampleUiLoop { @@ -110,6 +111,7 @@ void sample() { ui.run(); } // end::uirun[] + } class SampleUiModal { @@ -125,6 +127,7 @@ void sample() { ui.setModal(null); } // end::uimodal[] + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/TestingSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/TestingSnippets.java index 3fe081631..e3d79532d 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/TestingSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/TestingSnippets.java @@ -42,21 +42,18 @@ class InteractiveTestSample { @Test void test() { - InteractiveShellSession session = client - .interactive() - .run(); + InteractiveShellSession session = client.interactive().run(); await().atMost(2, TimeUnit.SECONDS).untilAsserted(() -> { - ShellAssertions.assertThat(session.screen()) - .containsText("shell"); + ShellAssertions.assertThat(session.screen()).containsText("shell"); }); session.write(session.writeSequence().text("help").carriageReturn().build()); await().atMost(2, TimeUnit.SECONDS).untilAsserted(() -> { - ShellAssertions.assertThat(session.screen()) - .containsText("AVAILABLE COMMANDS"); + ShellAssertions.assertThat(session.screen()).containsText("AVAILABLE COMMANDS"); }); } + } // end::testing-shelltest-interactive[] @@ -70,34 +67,36 @@ class NonInteractiveTestSample { @Test void test() { - NonInteractiveShellSession session = client - .nonInterative("help") - .run(); + NonInteractiveShellSession session = client.nonInterative("help").run(); await().atMost(2, TimeUnit.SECONDS).untilAsserted(() -> { - ShellAssertions.assertThat(session.screen()) - .containsText("AVAILABLE COMMANDS"); + ShellAssertions.assertThat(session.screen()).containsText("AVAILABLE COMMANDS"); }); } + } // end::testing-shelltest-noninteractive[] class Dump1 { // tag::testing-shelltest-dimensions-props[] - @ShellTest(properties = { - "spring.shell.test.terminal-width=120", - "spring.shell.test.terminal-height=40" - }) - class ShellSettingsSample {} + @ShellTest(properties = { "spring.shell.test.terminal-width=120", "spring.shell.test.terminal-height=40" }) + class ShellSettingsSample { + + } // end::testing-shelltest-dimensions-props[] + } + class Dump2 { // tag::testing-shelltest-dimensions-field[] @ShellTest(terminalWidth = 120, terminalHeight = 40) - class ShellSettingsSample {} + class ShellSettingsSample { + + } // end::testing-shelltest-dimensions-field[] + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ThemingSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ThemingSnippets.java index 87988ee3f..d9c0dee87 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/ThemingSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/ThemingSnippets.java @@ -36,6 +36,7 @@ static class MyStyleSettings extends StyleSettings { public String highlight() { return super.highlight(); } + } // end::custom-style-class[] @@ -46,6 +47,7 @@ static class MyFigureSettings extends FigureSettings { public String error() { return super.error(); } + } // end::custom-figure-class[] @@ -61,6 +63,7 @@ public StyleSettings styles() { public FigureSettings figures() { return new MyFigureSettings(); } + } // end::custom-theme-class[] @@ -82,6 +85,7 @@ public ThemeSettings getSettings() { } }; } + } // end::custom-theme-config[] @@ -102,6 +106,7 @@ void resolve() { // character i.e. U+2716 Heavy Multiplication X Emoji, cross } // end::using-theme-resolver[] + } } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/UiComponentSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/UiComponentSnippets.java index 40b0dc29c..6b08f91e5 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/UiComponentSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/UiComponentSnippets.java @@ -48,6 +48,7 @@ public class UiComponentSnippets { // tag::snippet1[] class StringInputCustomRenderer implements Function> { + @Override public List apply(StringInputContext context) { AttributedStringBuilder builder = new AttributedStringBuilder(); @@ -56,7 +57,7 @@ public List apply(StringInputContext context) { if (context.getResultValue() != null) { builder.append(context.getResultValue()); } - else { + else { String input = context.getInput(); if (StringUtils.hasText(input)) { builder.append(input); @@ -67,10 +68,12 @@ public List apply(StringInputContext context) { } return Arrays.asList(builder.toAttributedString()); } + } // end::snippet1[] class Dump1 extends AbstractShellComponent { + // tag::snippet2[] @ShellMethod(key = "component stringcustom", value = "String input", group = "Components") public String stringInputCustom(boolean mask) { @@ -85,9 +88,11 @@ public String stringInputCustom(boolean mask) { return "Got value " + context.getResultValue(); } // end::snippet2[] + } class Dump2 { + // tag::snippet3[] @ShellComponent public class ComponentCommands extends AbstractShellComponent { @@ -103,11 +108,14 @@ public String stringInput(boolean mask) { StringInputContext context = component.run(StringInputContext.empty()); return "Got value " + context.getResultValue(); } + } // end::snippet3[] + } class Dump3 { + // tag::snippet4[] @ShellComponent public class ComponentCommands extends AbstractShellComponent { @@ -120,11 +128,14 @@ public String pathInput() { PathInputContext context = component.run(PathInputContext.empty()); return "Got value " + context.getResultValue(); } + } // end::snippet4[] + } class Dump4 { + // tag::snippet5[] @ShellComponent public class ComponentCommands extends AbstractShellComponent { @@ -137,11 +148,14 @@ public String confirmationInput(boolean no) { ConfirmationInputContext context = component.run(ConfirmationInputContext.empty()); return "Got value " + context.getResultValue(); } + } // end::snippet5[] + } class Dump5 { + // tag::snippet6[] @ShellComponent public class ComponentCommands extends AbstractShellComponent { @@ -156,15 +170,18 @@ public String singleSelector() { component.setResourceLoader(getResourceLoader()); component.setTemplateExecutor(getTemplateExecutor()); SingleItemSelectorContext> context = component - .run(SingleItemSelectorContext.empty()); + .run(SingleItemSelectorContext.empty()); String result = context.getResultItem().flatMap(si -> Optional.ofNullable(si.getItem())).get(); return "Got value " + result; } + } // end::snippet6[] + } class Dump6 { + // tag::snippet7[] @ShellComponent public class ComponentCommands extends AbstractShellComponent { @@ -180,17 +197,21 @@ public String multiSelector() { component.setResourceLoader(getResourceLoader()); component.setTemplateExecutor(getTemplateExecutor()); MultiItemSelectorContext> context = component - .run(MultiItemSelectorContext.empty()); - String result = context.getResultItems().stream() - .map(si -> si.getItem()) - .collect(Collectors.joining(",")); + .run(MultiItemSelectorContext.empty()); + String result = context.getResultItems() + .stream() + .map(si -> si.getItem()) + .collect(Collectors.joining(",")); return "Got value " + result; } + } // end::snippet7[] + } class Dump7 { + @ShellComponent public class ComponentCommands extends AbstractShellComponent { @@ -207,14 +228,17 @@ public String singleSelector() { component.setResourceLoader(getResourceLoader()); component.setTemplateExecutor(getTemplateExecutor()); SingleItemSelectorContext> context = component - .run(SingleItemSelectorContext.empty()); + .run(SingleItemSelectorContext.empty()); String result = context.getResultItem().flatMap(si -> Optional.ofNullable(si.getItem())).get(); return "Got value " + result; } + } + } class Dump8 { + @ShellComponent public class ComponentCommands extends AbstractShellComponent { @@ -236,6 +260,9 @@ public String pathSearch() { return "Got value " + context.getResultValue(); // end::snippet9[] } + } + } + } diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/WritingSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/WritingSnippets.java index dc2709d4e..c26e09f9c 100644 --- a/spring-shell-docs/src/test/java/org/springframework/shell/docs/WritingSnippets.java +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/WritingSnippets.java @@ -37,6 +37,7 @@ public void example() { terminal.writer().flush(); } // end::legacyanno-terminal-writer[] + } class Dump2 { @@ -48,19 +49,16 @@ public void example(CommandContext ctx) { ctx.getTerminal().writer().flush(); } // end::anno-terminal-writer[] + } void dump1() { // tag::reg-terminal-writer[] - CommandRegistration.builder() - .command("example") - .withTarget() - .consumer(ctx -> { - ctx.getTerminal().writer().println("hi"); - ctx.getTerminal().writer().flush(); - }) - .and() - .build(); + CommandRegistration.builder().command("example").withTarget().consumer(ctx -> { + ctx.getTerminal().writer().println("hi"); + ctx.getTerminal().writer().flush(); + }).and().build(); // end::reg-terminal-writer[] } + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java index 347e75c6d..f4f0fcf69 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/Catalog.java @@ -62,30 +62,41 @@ import org.springframework.util.StringUtils; /** - * Catalog app logic. Builds a simple application ui where scenarios can be - * selected and run. + * Catalog app logic. Builds a simple application ui where scenarios can be selected and + * run. * * @author Janne Valkealahti */ public class Catalog { // ref types helping with deep nested generics from events - private final static ParameterizedTypeReference> LISTVIEW_SCENARIO_TYPEREF - = new ParameterizedTypeReference>() {}; - private final static ParameterizedTypeReference> LISTVIEW_STRING_TYPEREF - = new ParameterizedTypeReference>() {}; + private final static ParameterizedTypeReference> LISTVIEW_SCENARIO_TYPEREF = new ParameterizedTypeReference>() { + }; + + private final static ParameterizedTypeReference> LISTVIEW_STRING_TYPEREF = new ParameterizedTypeReference>() { + }; + private final static Logger log = LoggerFactory.getLogger(Catalog.class); // mapping from category name to scenarios(can belong to multiple categories) private final Map> categoryMap = new TreeMap<>(); + private ScenarioContext currentScenarioContext = null; + private TerminalUI ui; + private ListView categories; + private ListView scenarios; + private AppView app; + private EventLoop eventLoop; + private ThemeResolver themeResolver; + private String activeThemeName = "default"; + private TerminalUIBuilder terminalUIBuilder; public Catalog(TerminalUIBuilder terminalUIBuilder, ThemeResolver themeResolver, List scenarios) { @@ -127,21 +138,19 @@ public void run() { // handle logic to switch between main scenario browser // and currently active scenario - eventLoop.onDestroy(eventLoop.keyEvents() - .doOnNext(m -> { - if (m.getPlainKey() == Key.q && m.hasCtrl()) { - if (currentScenarioContext != null) { - currentScenarioContext.stop(); - currentScenarioContext = null; - ui.setRoot(app, true); - ui.setFocus(categories); - } - else { - requestQuit(); - } + eventLoop.onDestroy(eventLoop.keyEvents().doOnNext(m -> { + if (m.getPlainKey() == Key.q && m.hasCtrl()) { + if (currentScenarioContext != null) { + currentScenarioContext.stop(); + currentScenarioContext = null; + ui.setRoot(app, true); + ui.setFocus(categories); } - }) - .subscribe()); + else { + requestQuit(); + } + } + }).subscribe()); // start main scenario browser ui.setRoot(app, true); @@ -171,42 +180,38 @@ private AppView buildScenarioBrowser(EventLoop eventLoop, TerminalUI component) component.configure(app); // handle event when scenario is chosen - eventLoop.onDestroy(eventLoop.viewEvents(LISTVIEW_SCENARIO_TYPEREF, scenarios) - .subscribe(event -> { - ScenarioContext context = event.args().item().scenario().configure(ui).buildContext(); - ui.configure(context.view()); - component.setRoot(context.view(), true); - context.start(); - currentScenarioContext = context; - })); - + eventLoop.onDestroy(eventLoop.viewEvents(LISTVIEW_SCENARIO_TYPEREF, scenarios).subscribe(event -> { + ScenarioContext context = event.args().item().scenario().configure(ui).buildContext(); + ui.configure(context.view()); + component.setRoot(context.view(), true); + context.start(); + currentScenarioContext = context; + })); // handle event when category selection is changed - eventLoop.onDestroy(eventLoop.viewEvents(LISTVIEW_STRING_TYPEREF, categories) - .subscribe(event -> { - if (event.args().item() != null) { - String selected = event.args().item(); - List list = categoryMap.get(selected); - scenarios.setItems(list); - } - })); + eventLoop.onDestroy(eventLoop.viewEvents(LISTVIEW_STRING_TYPEREF, categories).subscribe(event -> { + if (event.args().item() != null) { + String selected = event.args().item(); + List list = categoryMap.get(selected); + scenarios.setItems(list); + } + })); // handle focus change between lists - eventLoop.onDestroy(eventLoop.viewEvents(AppViewEvent.class, app) - .subscribe(event -> { - switch (event.args().direction()) { - case NEXT -> ui.setFocus(scenarios); - case PREVIOUS -> ui.setFocus(categories); - } - } - )); + eventLoop.onDestroy(eventLoop.viewEvents(AppViewEvent.class, app).subscribe(event -> { + switch (event.args().direction()) { + case NEXT -> ui.setFocus(scenarios); + case PREVIOUS -> ui.setFocus(categories); + } + })); return app; } private ListView buildCategorySelector() { ListView categories = new ListView<>(); - categories.shortcut(Key.a | KeyMask.CtrlMask, () -> {}); + categories.shortcut(Key.a | KeyMask.CtrlMask, () -> { + }); ui.configure(categories); List items = List.copyOf(categoryMap.keySet()); @@ -238,11 +243,13 @@ protected void drawContent(Screen screen) { Writer writer = screen.writerBuilder().style(getStyle()).color(getForegroundColor()).build(); writer.text(String.format("%-20s %s", getItem().name(), getItem().description()), rect.x(), rect.y()); } + } private ListView buildScenarioSelector() { ListView scenarios = new ListView<>(); - scenarios.shortcut(Key.s | KeyMask.CtrlMask, () -> {}); + scenarios.shortcut(Key.s | KeyMask.CtrlMask, () -> { + }); ui.configure(scenarios); scenarios.setTitle("Scenarios (CTRL+S)"); scenarios.setFocusedTitleStyle(ScreenItem.STYLE_BOLD); @@ -269,7 +276,10 @@ private DialogView buildAboutDialog() { BoxView content = new BoxView(); content.setDrawFunction((screen, rect) -> { - screen.writerBuilder().layer(1).build().text("Catalog Sample App", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); + screen.writerBuilder() + .layer(1) + .build() + .text("Catalog Sample App", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); return rect; }); DialogView dialog = new DialogView(content, button); @@ -285,21 +295,14 @@ private void about() { private MenuBarView buildMenuBar(EventLoop eventLoop) { Runnable quitAction = () -> requestQuit(); Runnable aboutAction = () -> about(); - MenuItem[] themeItems = themeResolver.themeNames().stream() - .map(tn -> { - return MenuItem.of(tn, MenuItemCheckStyle.RADIO, styleAction(tn), "default".equals(tn)); - }) - .toArray(MenuItem[]::new); + MenuItem[] themeItems = themeResolver.themeNames().stream().map(tn -> { + return MenuItem.of(tn, MenuItemCheckStyle.RADIO, styleAction(tn), "default".equals(tn)); + }).toArray(MenuItem[]::new); MenuBarView menuBar = MenuBarView.of( - MenuBarItem.of("File", - MenuItem.of("Quit", MenuItemCheckStyle.NOCHECK, quitAction)) - .setHotKey(Key.f | KeyMask.AltMask), - MenuBarItem.of("Theme", - themeItems) - .setHotKey(Key.t | KeyMask.AltMask), - MenuBarItem.of("Help", - MenuItem.of("About", MenuItemCheckStyle.NOCHECK, aboutAction)) - ); + MenuBarItem.of("File", MenuItem.of("Quit", MenuItemCheckStyle.NOCHECK, quitAction)) + .setHotKey(Key.f | KeyMask.AltMask), + MenuBarItem.of("Theme", themeItems).setHotKey(Key.t | KeyMask.AltMask), + MenuBarItem.of("Help", MenuItem.of("About", MenuItemCheckStyle.NOCHECK, aboutAction))); ui.configure(menuBar); return menuBar; @@ -308,14 +311,13 @@ private MenuBarView buildMenuBar(EventLoop eventLoop) { private StatusBarView buildStatusBar(EventLoop eventLoop) { Runnable quitAction = () -> requestQuit(); Runnable visibilyAction = () -> app.toggleStatusBarVisibility(); - StatusBarView statusBar = new StatusBarView(new StatusItem[] { - StatusItem.of("CTRL-Q Quit", quitAction), - StatusItem.of("F10 Status Bar", visibilyAction, KeyEvent.Key.f10) - }); + StatusBarView statusBar = new StatusBarView(new StatusItem[] { StatusItem.of("CTRL-Q Quit", quitAction), + StatusItem.of("F10 Status Bar", visibilyAction, KeyEvent.Key.f10) }); ui.configure(statusBar); return statusBar; } - private record ScenarioData(Scenario scenario, String name, String description, String[] category){}; + private record ScenarioData(Scenario scenario, String name, String description, String[] category) { + }; } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogCommand.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogCommand.java index d4f3ab715..c2cbf34af 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogCommand.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogCommand.java @@ -32,7 +32,9 @@ public class CatalogCommand extends AbstractShellComponent { private final List scenarios; + private final TerminalUIBuilder terminalUIBuilder; + private final ThemeResolver themeResolver; public CatalogCommand(List scenarios, TerminalUIBuilder terminalUIBuilder, ThemeResolver themeResolver) { @@ -46,4 +48,5 @@ public void catalog() { Catalog catalog = new Catalog(terminalUIBuilder, themeResolver, scenarios); catalog.run(); } + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogConfiguration.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogConfiguration.java index 25d8b8962..52236c005 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogConfiguration.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/CatalogConfiguration.java @@ -34,6 +34,7 @@ public Theme customTheme() { public String getName() { return "custom"; } + @Override public ThemeSettings getSettings() { return new CustomThemeSettings(); @@ -42,9 +43,11 @@ public ThemeSettings getSettings() { } static class CustomThemeSettings extends ThemeSettings { + CustomThemeSettings() { super(new CustomStyleSettings(), FigureSettings.defaults()); } + } static class CustomStyleSettings extends StyleSettings { diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/AbstractScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/AbstractScenario.java index 2df704dbc..c7ea941c2 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/AbstractScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/AbstractScenario.java @@ -29,9 +29,13 @@ public abstract class AbstractScenario implements Scenario { private TerminalUI ui; + private ViewService viewService; + private EventLoop eventloop; + private ThemeResolver themeResolver; + private String themeName; protected ViewService getViewService() { @@ -74,4 +78,5 @@ protected void configure(View view) { ui.configure(view); } } + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/Scenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/Scenario.java index b600fa57d..955b884f2 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/Scenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/Scenario.java @@ -29,16 +29,20 @@ public interface Scenario { // Common category names public static final String CATEGORY_ALL = "All Scenarios"; + public static final String CATEGORY_LISTVIEW = "ListView"; + public static final String CATEGORY_PROGRESSVIEW = "ProgressView"; + public static final String CATEGORY_BOXVIEW = "BoxView"; + public static final String CATEGORY_LAYOUT = "Layout"; + public static final String CATEGORY_OTHER = "Other"; /** - * Build a {@link View} to be shown with a scenario. Prefer {@link #buildContext()} - * as this method will be deprecated and renamed. - * + * Build a {@link View} to be shown with a scenario. Prefer {@link #buildContext()} as + * this method will be deprecated and renamed. * @return view of a scenario * @see #buildContext() */ @@ -46,7 +50,6 @@ public interface Scenario { /** * Build a {@link ScenarioContext} wrapping needed view and lifecycle methods. - * * @return a scenario context */ default ScenarioContext buildContext() { @@ -55,15 +58,14 @@ default ScenarioContext buildContext() { /** * Configure scenario. - * * @param ui the terminal ui * @return scenario for chaining */ Scenario configure(TerminalUI ui); /** - * Context represents a build {@code View} and lifecycle methods called by a - * catalog app. + * Context represents a build {@code View} and lifecycle methods called by a catalog + * app. * * For simple {@link View} without any need for lifecycle methods, just call * {@link #of(View)}. @@ -72,14 +74,13 @@ public interface ScenarioContext { /** * Get a view represented by a {@link Scenario}. - * * @return a scenario view */ View view(); /** - * Called by a {@link Catalog} when its ready to show a {@link View} build from - * a {@link Scenario}. + * Called by a {@link Catalog} when its ready to show a {@link View} build from a + * {@link Scenario}. */ void start(); @@ -92,7 +93,6 @@ public interface ScenarioContext { /** * Utility method to build a {@code ScenarioContext} of {@link View} without * lifecycle callbacks. - * * @param view the main view * @return a scenario context */ @@ -102,7 +102,6 @@ public static ScenarioContext of(View view) { /** * Utility method to build a {@code ScenarioContext}. - * * @param view the main view * @param start the start callback * @param stop the stop callback diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/ScenarioComponent.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/ScenarioComponent.java index 718cded35..53647706c 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/ScenarioComponent.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/ScenarioComponent.java @@ -25,9 +25,8 @@ import org.springframework.stereotype.Indexed; /** - * Annotation needed for a scenarios to get hooked up into a catalog app. - * Typically all fields in this annotation needs to have content to get attached - * into a catalog app. + * Annotation needed for a scenarios to get hooked up into a catalog app. Typically all + * fields in this annotation needs to have content to get attached into a catalog app. * * @author Janne Valkealahti */ @@ -40,22 +39,20 @@ /** * Define a name of a scenario. - * * @return name of a scenario */ String name() default ""; /** * Define a short description of a scenario. - * * @return short description of a scenario */ String description() default ""; /** * Define a categories of a scenario. - * * @return categories of a scenario */ String[] category() default {}; + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/DrawFunctionScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/DrawFunctionScenario.java index 9adaed491..9faae5717 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/DrawFunctionScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/DrawFunctionScenario.java @@ -23,8 +23,8 @@ import org.springframework.shell.samples.catalog.scenario.Scenario; import org.springframework.shell.samples.catalog.scenario.ScenarioComponent; -@ScenarioComponent(name = "Draw Function", description = "BoxView DrawFunction", category = { - Scenario.CATEGORY_BOXVIEW }) +@ScenarioComponent(name = "Draw Function", description = "BoxView DrawFunction", + category = { Scenario.CATEGORY_BOXVIEW }) public class DrawFunctionScenario extends AbstractScenario { @Override @@ -36,4 +36,5 @@ public View build() { }); return view; } + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/SimpleBoxViewScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/SimpleBoxViewScenario.java index b557813bd..26a7524ff 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/SimpleBoxViewScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/box/SimpleBoxViewScenario.java @@ -24,8 +24,8 @@ import org.springframework.shell.samples.catalog.scenario.Scenario; import org.springframework.shell.samples.catalog.scenario.ScenarioComponent; -@ScenarioComponent(name = "Simple boxview", description = "BoxView color and style", category = { - Scenario.CATEGORY_BOXVIEW }) +@ScenarioComponent(name = "Simple boxview", description = "BoxView color and style", + category = { Scenario.CATEGORY_BOXVIEW }) public class SimpleBoxViewScenario extends AbstractScenario { @Override @@ -40,4 +40,5 @@ public View build() { box.setTitleAlign(HorizontalAlign.CENTER); return box; } + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/CheckedListViewScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/CheckedListViewScenario.java index 177eafb56..6985089ca 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/CheckedListViewScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/CheckedListViewScenario.java @@ -24,7 +24,8 @@ import org.springframework.shell.samples.catalog.scenario.Scenario; import org.springframework.shell.samples.catalog.scenario.ScenarioComponent; -@ScenarioComponent(name = "Radio List", description = "Items with radio states", category = { Scenario.CATEGORY_LISTVIEW }) +@ScenarioComponent(name = "Radio List", description = "Items with radio states", + category = { Scenario.CATEGORY_LISTVIEW }) public class CheckedListViewScenario extends AbstractScenario { @Override diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/RadioListViewScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/RadioListViewScenario.java index 98037d5c9..2411cc48e 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/RadioListViewScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/listview/RadioListViewScenario.java @@ -24,7 +24,8 @@ import org.springframework.shell.samples.catalog.scenario.Scenario; import org.springframework.shell.samples.catalog.scenario.ScenarioComponent; -@ScenarioComponent(name = "Checked List", description = "Items with checked states", category = { Scenario.CATEGORY_LISTVIEW }) +@ScenarioComponent(name = "Checked List", description = "Items with checked states", + category = { Scenario.CATEGORY_LISTVIEW }) public class RadioListViewScenario extends AbstractScenario { @Override diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/ClockScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/ClockScenario.java index c682bc7ae..ec6bfba17 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/ClockScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/ClockScenario.java @@ -55,8 +55,7 @@ public View build() { // dispatch dates as messages Flux> dates = Flux.interval(Duration.ofSeconds(1)).map(l -> { String date = new Date().toString(); - Message message = MessageBuilder - .withPayload(date) + Message message = MessageBuilder.withPayload(date) .setHeader(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.USER) .build(); return message; @@ -89,50 +88,50 @@ public View build() { AtomicReference hAlign = new AtomicReference<>(HorizontalAlign.CENTER); AtomicReference vAlign = new AtomicReference<>(VerticalAlign.CENTER); - getEventloop().onDestroy(getEventloop().keyEvents() - .subscribe(event -> { - switch (event.key()) { - case Key.CursorDown -> { - if (vAlign.get() == VerticalAlign.TOP) { - vAlign.set(VerticalAlign.CENTER); - } - else if (vAlign.get() == VerticalAlign.CENTER) { - vAlign.set(VerticalAlign.BOTTOM); - } + getEventloop().onDestroy(getEventloop().keyEvents().subscribe(event -> { + switch (event.key()) { + case Key.CursorDown -> { + if (vAlign.get() == VerticalAlign.TOP) { + vAlign.set(VerticalAlign.CENTER); } - case Key.CursorUp -> { - if (vAlign.get() == VerticalAlign.BOTTOM) { - vAlign.set(VerticalAlign.CENTER); - } - else if (vAlign.get() == VerticalAlign.CENTER) { - vAlign.set(VerticalAlign.TOP); - } + else if (vAlign.get() == VerticalAlign.CENTER) { + vAlign.set(VerticalAlign.BOTTOM); } - case Key.CursorLeft -> { - if (hAlign.get() == HorizontalAlign.RIGHT) { - hAlign.set(HorizontalAlign.CENTER); - } - else if (hAlign.get() == HorizontalAlign.CENTER) { - hAlign.set(HorizontalAlign.LEFT); - } + } + case Key.CursorUp -> { + if (vAlign.get() == VerticalAlign.BOTTOM) { + vAlign.set(VerticalAlign.CENTER); + } + else if (vAlign.get() == VerticalAlign.CENTER) { + vAlign.set(VerticalAlign.TOP); } - case Key.CursorRight -> { - Message animStart = MessageBuilder - .withPayload("") - .setHeader(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.SYSTEM) - .setHeader("animationstart", true) - .build(); - getEventloop().dispatch(animStart); + } + case Key.CursorLeft -> { + if (hAlign.get() == HorizontalAlign.RIGHT) { + hAlign.set(HorizontalAlign.CENTER); } - }; + else if (hAlign.get() == HorizontalAlign.CENTER) { + hAlign.set(HorizontalAlign.LEFT); + } + } + case Key.CursorRight -> { + Message animStart = MessageBuilder.withPayload("") + .setHeader(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.SYSTEM) + .setHeader("animationstart", true) + .build(); + getEventloop().dispatch(animStart); + } + } + ; - })); + })); // draw current date root.setDrawFunction((screen, rect) -> { int a = animX.get(); Rectangle r = new Rectangle(rect.x() + 1 + a, rect.y() + 1, rect.width() - 2, rect.height() - 2); - // Rectangle r = new View.Rectangle(rect.x() + 1, rect.y() + 1, rect.width() - 2, rect.height() - 2); + // Rectangle r = new View.Rectangle(rect.x() + 1, rect.y() + 1, rect.width() - + // 2, rect.height() - 2); String s = ref.get(); if (s != null) { screen.writerBuilder().build().text(s, r, hAlign.get(), vAlign.get()); @@ -141,4 +140,5 @@ else if (hAlign.get() == HorizontalAlign.CENTER) { }); return root; } + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/DialogScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/DialogScenario.java index b461e6db7..16684f4d1 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/DialogScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/DialogScenario.java @@ -25,8 +25,7 @@ import org.springframework.shell.samples.catalog.scenario.Scenario; import org.springframework.shell.samples.catalog.scenario.ScenarioComponent; -@ScenarioComponent(name = "Dialog", description = "Modal dialog", category = { - Scenario.CATEGORY_OTHER }) +@ScenarioComponent(name = "Dialog", description = "Modal dialog", category = { Scenario.CATEGORY_OTHER }) public class DialogScenario extends AbstractScenario { private Runnable dialogAction = () -> { @@ -46,7 +45,10 @@ private DialogView buildDialog() { configure(button); BoxView content = new BoxView(); content.setDrawFunction((screen, rect) -> { - screen.writerBuilder().layer(1).build().text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); + screen.writerBuilder() + .layer(1) + .build() + .text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); return rect; }); DialogView dialog = new DialogView(content, button); diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/MultiInputViewScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/MultiInputViewScenario.java index 807b75144..610d3e282 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/MultiInputViewScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/MultiInputViewScenario.java @@ -23,7 +23,8 @@ import org.springframework.shell.samples.catalog.scenario.Scenario; import org.springframework.shell.samples.catalog.scenario.ScenarioComponent;; -@ScenarioComponent(name = "Multi inputview", description = "Multi InputView sample", category = { Scenario.CATEGORY_OTHER }) +@ScenarioComponent(name = "Multi inputview", description = "Multi InputView sample", + category = { Scenario.CATEGORY_OTHER }) public class MultiInputViewScenario extends AbstractScenario { @Override diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/SnakeGameScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/SnakeGameScenario.java index 469a28945..fd656bf09 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/SnakeGameScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/other/SnakeGameScenario.java @@ -33,15 +33,13 @@ /** * Scenario implementing a classic snake game. * - * Demonstrates how we can just use box view to draw something - * manually with its draw function. + * Demonstrates how we can just use box view to draw something manually with its draw + * function. * - * Game logic. - * 1. Snake starts in a center, initial direction needs arrow key - * 2. Arrows control snake direction - * 3. Eating a food crows a snake, new food is generated - * 4. Game ends if snake eats itself or goes out of bounds - * 5. Game ends if perfect score is established + * Game logic. 1. Snake starts in a center, initial direction needs arrow key 2. Arrows + * control snake direction 3. Eating a food crows a snake, new food is generated 4. Game + * ends if snake eats itself or goes out of bounds 5. Game ends if perfect score is + * established * * @author Janne Valkealahti */ @@ -57,27 +55,24 @@ public View build() { // we're outside of a view so no bindings, // just subscribe to events and handle what is needed. - getEventloop().onDestroy(getEventloop().keyEvents() - .subscribe(event -> { - Integer direction = switch (event.key()) { - case Key.CursorDown -> 1; - case Key.CursorUp -> -1; - case Key.CursorLeft -> -2; - case Key.CursorRight -> 2; - default -> 0; - }; - if (direction != null) { - snakeGame.update(direction); - } - })); + getEventloop().onDestroy(getEventloop().keyEvents().subscribe(event -> { + Integer direction = switch (event.key()) { + case Key.CursorDown -> 1; + case Key.CursorUp -> -1; + case Key.CursorLeft -> -2; + case Key.CursorRight -> 2; + default -> 0; + }; + if (direction != null) { + snakeGame.update(direction); + } + })); // schedule game updates - getEventloop().onDestroy(Flux.interval(Duration.ofMillis(500)) - .subscribe(l -> { - snakeGame.update(0); - getEventloop().dispatch(ShellMessageBuilder.ofRedraw()); - } - )); + getEventloop().onDestroy(Flux.interval(Duration.ofMillis(500)).subscribe(l -> { + snakeGame.update(0); + getEventloop().dispatch(ShellMessageBuilder.ofRedraw()); + })); // draw game area view.setDrawFunction((screen, rect) -> { @@ -88,7 +83,9 @@ public View build() { } private static class SnakeGame { + Board board; + Game game; SnakeGame(int rows, int cols) { @@ -133,10 +130,13 @@ else if (cell.type == -1) { } } } + } private static class Cell { + final int row, col; + // 0 - empty, > 0 - snake, < 0 - food int type; @@ -145,10 +145,13 @@ private static class Cell { this.col = col; this.type = type; } + } private static class Board { + final int rows, cols; + Cell[][] cells; Board(int rows, int cols, Cell initial) { @@ -174,10 +177,13 @@ void food() { } cells[row][column].type = -1; } + } private static class Snake { + LinkedList cells = new LinkedList<>(); + Cell head; Snake(Cell cell) { @@ -204,13 +210,19 @@ boolean checkCrash(Cell next) { } return false; } + } private static class Game { + Snake snake; + Board board; + int direction; + int points; + boolean gameOver; Game(Snake snake, Board board) { @@ -268,5 +280,7 @@ else if (direction == -1) { } return board.cells[row][col]; } + } + } diff --git a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/progress/SimpleProgressViewScenario.java b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/progress/SimpleProgressViewScenario.java index c9721e764..3262a5045 100644 --- a/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/progress/SimpleProgressViewScenario.java +++ b/spring-shell-samples/spring-shell-sample-catalog/src/main/java/org/springframework/shell/samples/catalog/scenario/progress/SimpleProgressViewScenario.java @@ -35,8 +35,8 @@ import org.springframework.shell.samples.catalog.scenario.Scenario; import org.springframework.shell.samples.catalog.scenario.ScenarioComponent; -@ScenarioComponent(name = "Simple progressview", description = "ProgressView sample", category = { - Scenario.CATEGORY_PROGRESSVIEW }) +@ScenarioComponent(name = "Simple progressview", description = "ProgressView sample", + category = { Scenario.CATEGORY_PROGRESSVIEW }) public class SimpleProgressViewScenario extends AbstractScenario { @Override @@ -71,8 +71,7 @@ private ContextData buildContextData() { EventLoop eventLoop = getEventloop(); Flux> ticks = Flux.interval(Duration.ofMillis(500)).take(100).map(l -> { - Message message = MessageBuilder - .withPayload(l) + Message message = MessageBuilder.withPayload(l) .setHeader(ShellMessageHeaderAccessor.EVENT_TYPE, EventLoop.Type.USER) .setHeader("SimpleProgressViewScenario", "") .build(); diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/SpringShellSample.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/SpringShellSample.java index a65b34fd8..b53a70bcc 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/SpringShellSample.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/SpringShellSample.java @@ -28,7 +28,9 @@ /** * Main entry point for the application. * - *

    Creates the application context and start the REPL.

    + *

    + * Creates the application context and start the REPL. + *

    * * @author Eric Bottard * @author Janne Valkealahti @@ -49,4 +51,5 @@ public static void main(String[] args) throws Exception { public PromptProvider myPromptProvider() { return () -> new AttributedString("my-shell:>", AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW)); } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/AliasCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/AliasCommands.java index 368e16716..405e961df 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/AliasCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/AliasCommands.java @@ -37,14 +37,14 @@ public CommandRegistration regMain1() { .group("Alias Commands") .description(DESCRIPTION) .withAlias() - .command("alias", "reg", "main2") - .group("Alias Commands") - .and() + .command("alias", "reg", "main2") + .group("Alias Commands") + .and() .withTarget() - .function(ctx -> { - return "Hello regMain1"; - }) - .and() + .function(ctx -> { + return "Hello regMain1"; + }) + .and() .build(); } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/Commands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/Commands.java index c5398b4a0..abd0ca292 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/Commands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/Commands.java @@ -86,4 +86,5 @@ public Iterator iterator() { }; return iterable; } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/CompleteCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/CompleteCommands.java index dc58fdbaa..5b4ec555a 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/CompleteCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/CompleteCommands.java @@ -39,27 +39,27 @@ CommandRegistration completeCommandRegistration1() { .description("complete sample1") .group("Complete Commands") .withOption() - .longNames("arg1") - .completion(ctx -> { - CompletionProposal p1 = new CompletionProposal("arg1hi1"); - CompletionProposal p2 = new CompletionProposal("arg1hi2"); - return Arrays.asList(p1, p2); - }) - .and() + .longNames("arg1") + .completion(ctx -> { + CompletionProposal p1 = new CompletionProposal("arg1hi1"); + CompletionProposal p2 = new CompletionProposal("arg1hi2"); + return Arrays.asList(p1, p2); + }) + .and() .withOption() - .longNames("arg2") - .completion(ctx -> { - CompletionProposal p1 = new CompletionProposal("arg2hi1"); - CompletionProposal p2 = new CompletionProposal("arg2hi2"); - return Arrays.asList(p1, p2); - }) - .and() + .longNames("arg2") + .completion(ctx -> { + CompletionProposal p1 = new CompletionProposal("arg2hi1"); + CompletionProposal p2 = new CompletionProposal("arg2hi2"); + return Arrays.asList(p1, p2); + }) + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return String.format("hi, arg1 value is '%s'", arg1); - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return String.format("hi, arg1 value is '%s'", arg1); + }) + .and() .build(); } @@ -75,16 +75,14 @@ FunnyValuesProvider funnyValuesProvider() { static class FunnyValuesProvider implements ValueProvider { - private final static String[] VALUES = new String[] { - "hello world", - "I am quoting \"The Daily Mail\"", - "10 \\ 3 = 3" - }; + private final static String[] VALUES = new String[] { "hello world", "I am quoting \"The Daily Mail\"", + "10 \\ 3 = 3" }; @Override public List complete(CompletionContext completionContext) { return Arrays.stream(VALUES).map(CompletionProposal::new).collect(Collectors.toList()); } + } @Bean @@ -94,21 +92,21 @@ CommandRegistration completeCommandRegistration3() { .description("complete sample3") .group("Complete Commands") .withOption() - .longNames("arg1") - .type(MyEnums.class) - .completion(ctx -> { - CompletionProposal p1 = new CompletionProposal(MyEnums.E1.toString()); - CompletionProposal p2 = new CompletionProposal(MyEnums.E2.toString()); - CompletionProposal p3 = new CompletionProposal(MyEnums.E3.toString()); - return Arrays.asList(p1, p2, p3); - }) - .and() + .longNames("arg1") + .type(MyEnums.class) + .completion(ctx -> { + CompletionProposal p1 = new CompletionProposal(MyEnums.E1.toString()); + CompletionProposal p2 = new CompletionProposal(MyEnums.E2.toString()); + CompletionProposal p3 = new CompletionProposal(MyEnums.E3.toString()); + return Arrays.asList(p1, p2, p3); + }) + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return String.format("You said '%s'", arg1); - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return String.format("You said '%s'", arg1); + }) + .and() .build(); } @@ -118,6 +116,9 @@ public String completeCommandSample4(@ShellOption(valueProvider = EnumValueProvi } static enum MyEnums { + E1, E2, E3 + } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java index 266cdc986..8cee8e860 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentCommands.java @@ -70,13 +70,11 @@ public String pathInput() { } @ShellMethod(key = "component path search", value = "Path search", group = "Components") - public String pathSearch( - @ShellOption(defaultValue = ShellOption.NULL) Integer maxPathsShow, - @ShellOption(defaultValue = ShellOption.NULL) Integer maxPathsSearch, - @ShellOption(defaultValue = "true") boolean searchForward, - @ShellOption(defaultValue = "false") boolean searchCaseSensitive, - @ShellOption(defaultValue = "false") boolean searchNormalize - ) { + public String pathSearch(@ShellOption(defaultValue = ShellOption.NULL) Integer maxPathsShow, + @ShellOption(defaultValue = ShellOption.NULL) Integer maxPathsSearch, + @ShellOption(defaultValue = "true") boolean searchForward, + @ShellOption(defaultValue = "false") boolean searchCaseSensitive, + @ShellOption(defaultValue = "false") boolean searchNormalize) { PathSearchConfig config = new PathSearch.PathSearchConfig(); if (maxPathsShow != null) { config.setMaxPathsShow(maxPathsShow); @@ -104,9 +102,7 @@ public String confirmationInput(boolean no) { } @ShellMethod(key = "component single", value = "Single selector", group = "Components") - public String singleSelector( - @ShellOption(defaultValue = ShellOption.NULL) Boolean longKeys - ) { + public String singleSelector(@ShellOption(defaultValue = ShellOption.NULL) Boolean longKeys) { List> items = new ArrayList<>(); items.add(SelectorItem.of("key1", "value1")); items.add(SelectorItem.of("key2", "value2")); @@ -114,20 +110,18 @@ public String singleSelector( items.add(SelectorItem.of("key3 long long long long long", "value3")); items.add(SelectorItem.of("key4 long long long long long long long long long long", "value4")); } - SingleItemSelector> component = new SingleItemSelector<>(getTerminal(), - items, "testSimple", null); + SingleItemSelector> component = new SingleItemSelector<>(getTerminal(), items, + "testSimple", null); component.setResourceLoader(getResourceLoader()); component.setTemplateExecutor(getTemplateExecutor()); SingleItemSelectorContext> context = component - .run(SingleItemSelectorContext.empty()); + .run(SingleItemSelectorContext.empty()); String result = context.getResultItem().flatMap(si -> Optional.ofNullable(si.getItem())).get(); return "Got value " + result; } @ShellMethod(key = "component multi", value = "Multi selector", group = "Components") - public String multiSelector( - @ShellOption(defaultValue = ShellOption.NULL) Boolean longKeys - ) { + public String multiSelector(@ShellOption(defaultValue = ShellOption.NULL) Boolean longKeys) { List> items = new ArrayList<>(); items.add(SelectorItem.of("key1", "value1")); items.add(SelectorItem.of("key2", "value2", false, true)); @@ -136,15 +130,13 @@ public String multiSelector( items.add(SelectorItem.of("key4 long long long long long", "value4", false, true)); items.add(SelectorItem.of("key5 long long long long long long long long long long", "value5")); } - MultiItemSelector> component = new MultiItemSelector<>(getTerminal(), - items, "testSimple", null); + MultiItemSelector> component = new MultiItemSelector<>(getTerminal(), items, + "testSimple", null); component.setResourceLoader(getResourceLoader()); component.setTemplateExecutor(getTemplateExecutor()); MultiItemSelectorContext> context = component - .run(MultiItemSelectorContext.empty()); - String result = context.getResultItems().stream() - .map(si -> si.getItem()) - .collect(Collectors.joining(",")); + .run(MultiItemSelectorContext.empty()); + String result = context.getResultItems().stream().map(si -> si.getItem()).collect(Collectors.joining(",")); return "Got value " + result; } @@ -172,7 +164,7 @@ public List apply(StringInputContext context) { if (context.getResultValue() != null) { builder.append(context.getResultValue()); } - else { + else { String input = context.getInput(); if (StringUtils.hasText(input)) { builder.append(input); @@ -184,5 +176,7 @@ public List apply(StringInputContext context) { return Arrays.asList(builder.toAttributedString()); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java index 696c1e001..32b8886d2 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentFlowCommands.java @@ -54,201 +54,204 @@ public void showcase1() { single1SelectItems.put("key2", "value2"); List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); - ComponentFlow flow = componentFlowBuilder.clone().reset() - .withStringInput("field1") - .name("Field1") - .defaultValue("defaultField1Value") - .and() - .withStringInput("field2") - .name("Field2") - .and() - .withConfirmationInput("confirmation1") - .name("Confirmation1") - .and() - .withPathInput("path1") - .name("Path1") - .and() - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .and() - .withMultiItemSelector("multi1") - .name("Multi1") - .selectItems(multi1SelectItems) - .and() - .build(); + ComponentFlow flow = componentFlowBuilder.clone() + .reset() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .and() + .withStringInput("field2") + .name("Field2") + .and() + .withConfirmationInput("confirmation1") + .name("Confirmation1") + .and() + .withPathInput("path1") + .name("Path1") + .and() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .and() + .withMultiItemSelector("multi1") + .name("Multi1") + .selectItems(multi1SelectItems) + .and() + .build(); flow.run(); } @ShellMethod(key = "flow showcase2", value = "Showcase with options", group = "Flow") - public String showcase2( - @ShellOption(help = "Field1 value", defaultValue = ShellOption.NULL) String field1, - @ShellOption(help = "Field2 value", defaultValue = ShellOption.NULL) String field2, - @ShellOption(help = "Confirmation1 value", defaultValue = ShellOption.NULL) Boolean confirmation1, - @ShellOption(help = "Path1 value", defaultValue = ShellOption.NULL) String path1, - @ShellOption(help = "Single1 value", defaultValue = ShellOption.NULL) String single1, - @ShellOption(help = "Multi1 value", defaultValue = ShellOption.NULL) List multi1 - ) { + public String showcase2(@ShellOption(help = "Field1 value", defaultValue = ShellOption.NULL) String field1, + @ShellOption(help = "Field2 value", defaultValue = ShellOption.NULL) String field2, + @ShellOption(help = "Confirmation1 value", defaultValue = ShellOption.NULL) Boolean confirmation1, + @ShellOption(help = "Path1 value", defaultValue = ShellOption.NULL) String path1, + @ShellOption(help = "Single1 value", defaultValue = ShellOption.NULL) String single1, + @ShellOption(help = "Multi1 value", defaultValue = ShellOption.NULL) List multi1) { Map single1SelectItems = new HashMap<>(); single1SelectItems.put("key1", "value1"); single1SelectItems.put("key2", "value2"); List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); List multi1ResultValues = multi1 != null ? multi1 : new ArrayList<>(); - ComponentFlow flow = componentFlowBuilder.clone().reset() - .withStringInput("field1") + ComponentFlow flow = componentFlowBuilder.clone() + .reset() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .resultValue(field1) + .resultMode(ResultMode.ACCEPT) + .and() + .withStringInput("field2") + .name("Field2") + .resultValue(field2) + .resultMode(ResultMode.ACCEPT) + .and() + .withConfirmationInput("confirmation1") + .name("Confirmation1") + .resultValue(confirmation1) + .resultMode(ResultMode.ACCEPT) + .and() + .withPathInput("path1") + .name("Path1") + .resultValue(path1) + .resultMode(ResultMode.ACCEPT) + .and() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .resultValue(single1) + .resultMode(ResultMode.ACCEPT) + .and() + .withMultiItemSelector("multi1") + .name("Multi1") + .selectItems(multi1SelectItems) + .resultValues(multi1ResultValues) + .resultMode(ResultMode.ACCEPT) + .and() + .build(); + ComponentFlowResult result = flow.run(); + StringBuilder buf = new StringBuilder(); + result.getContext().stream().forEach(e -> { + buf.append(e.getKey()); + buf.append(" = "); + buf.append(e.getValue()); + buf.append("\n"); + }); + return buf.toString(); + } + + @Bean + public CommandRegistration showcaseRegistration() { + return CommandRegistration.builder() + .command("flow", "showcase3") + .description("Showcase") + .withOption() + .longNames("field1") + .and() + .withOption() + .longNames("field2") + .and() + .withOption() + .longNames("confirmation1") + .type(Boolean.class) + .and() + .withOption() + .longNames("path1") + .and() + .withOption() + .longNames("single1") + .and() + .withOption() + .longNames("multi1") + .and() + .withTarget() + .consumer(ctx -> { + + String field1 = ctx.getOptionValue("field1"); + String field2 = ctx.getOptionValue("field2"); + Boolean confirmation1 = ctx.getOptionValue("confirmation1"); + String path1 = ctx.getOptionValue("path1"); + String single1 = ctx.getOptionValue("single1"); + String asdf = ctx.getOptionValue("multi1"); + List multi1 = new ArrayList<>(); + if (StringUtils.hasText(asdf)) { + multi1.add(asdf); + } + + Map single1SelectItems = new HashMap<>(); + single1SelectItems.put("key1", "value1"); + single1SelectItems.put("key2", "value2"); + List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), + SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); + ComponentFlow flow = componentFlowBuilder.clone() + .reset() + .withStringInput("field1") .name("Field1") .defaultValue("defaultField1Value") .resultValue(field1) .resultMode(ResultMode.ACCEPT) .and() - .withStringInput("field2") + .withStringInput("field2") .name("Field2") .resultValue(field2) .resultMode(ResultMode.ACCEPT) .and() - .withConfirmationInput("confirmation1") + .withConfirmationInput("confirmation1") .name("Confirmation1") .resultValue(confirmation1) .resultMode(ResultMode.ACCEPT) .and() - .withPathInput("path1") + .withPathInput("path1") .name("Path1") .resultValue(path1) .resultMode(ResultMode.ACCEPT) .and() - .withSingleItemSelector("single1") + .withSingleItemSelector("single1") .name("Single1") .selectItems(single1SelectItems) .resultValue(single1) .resultMode(ResultMode.ACCEPT) .and() - .withMultiItemSelector("multi1") + .withMultiItemSelector("multi1") .name("Multi1") .selectItems(multi1SelectItems) - .resultValues(multi1ResultValues) + .resultValues(multi1) .resultMode(ResultMode.ACCEPT) .and() - .build(); - ComponentFlowResult result = flow.run(); - StringBuilder buf = new StringBuilder(); - result.getContext().stream().forEach(e -> { - buf.append(e.getKey()); - buf.append(" = "); - buf.append(e.getValue()); - buf.append("\n"); - }); - return buf.toString(); - } - - @Bean - public CommandRegistration showcaseRegistration() { - return CommandRegistration.builder() - .command("flow", "showcase3") - .description("Showcase") - .withOption() - .longNames("field1") - .and() - .withOption() - .longNames("field2") - .and() - .withOption() - .longNames("confirmation1") - .type(Boolean.class) - .and() - .withOption() - .longNames("path1") - .and() - .withOption() - .longNames("single1") - .and() - .withOption() - .longNames("multi1") - .and() - .withTarget() - .consumer(ctx -> { - - String field1 = ctx.getOptionValue("field1"); - String field2 = ctx.getOptionValue("field2"); - Boolean confirmation1 = ctx.getOptionValue("confirmation1"); - String path1 = ctx.getOptionValue("path1"); - String single1 = ctx.getOptionValue("single1"); - String asdf = ctx.getOptionValue("multi1"); - List multi1 = new ArrayList<>(); - if (StringUtils.hasText(asdf)) { - multi1.add(asdf); - } + .build(); + ComponentFlowResult result = flow.run(); - Map single1SelectItems = new HashMap<>(); - single1SelectItems.put("key1", "value1"); - single1SelectItems.put("key2", "value2"); - List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), - SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); - ComponentFlow flow = componentFlowBuilder.clone().reset() - .withStringInput("field1") - .name("Field1") - .defaultValue("defaultField1Value") - .resultValue(field1) - .resultMode(ResultMode.ACCEPT) - .and() - .withStringInput("field2") - .name("Field2") - .resultValue(field2) - .resultMode(ResultMode.ACCEPT) - .and() - .withConfirmationInput("confirmation1") - .name("Confirmation1") - .resultValue(confirmation1) - .resultMode(ResultMode.ACCEPT) - .and() - .withPathInput("path1") - .name("Path1") - .resultValue(path1) - .resultMode(ResultMode.ACCEPT) - .and() - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .resultValue(single1) - .resultMode(ResultMode.ACCEPT) - .and() - .withMultiItemSelector("multi1") - .name("Multi1") - .selectItems(multi1SelectItems) - .resultValues(multi1) - .resultMode(ResultMode.ACCEPT) - .and() - .build(); - ComponentFlowResult result = flow.run(); - - boolean hasTty = !((ctx.getTerminal() instanceof DumbTerminal) && ctx.getTerminal().getSize().getRows() == 0); - if (hasTty) { - StringBuilder buf = new StringBuilder(); - result.getContext().stream().forEach(e -> { - buf.append(e.getKey()); - buf.append(" = "); - buf.append(e.getValue()); - buf.append("\n"); - }); - ctx.getTerminal().writer().print(buf.toString()); - ctx.getTerminal().writer().flush(); - } - else { - List errors = new ArrayList<>(); - result.getContext().stream().forEach(e -> { - if (e.getValue() == null) { - errors.add(CommandParserException.of(String.format("Missing option, longnames='%s'", e.getKey()))); - } - }); - if (!result.getContext().containsKey("single1")) { - errors.add(CommandParserException.of("Missing option, longnames='single'")); - } - if (!errors.isEmpty()) { - throw CommandParserExceptionsException.of("Missing options", errors); + boolean hasTty = !((ctx.getTerminal() instanceof DumbTerminal) + && ctx.getTerminal().getSize().getRows() == 0); + if (hasTty) { + StringBuilder buf = new StringBuilder(); + result.getContext().stream().forEach(e -> { + buf.append(e.getKey()); + buf.append(" = "); + buf.append(e.getValue()); + buf.append("\n"); + }); + ctx.getTerminal().writer().print(buf.toString()); + ctx.getTerminal().writer().flush(); + } + else { + List errors = new ArrayList<>(); + result.getContext().stream().forEach(e -> { + if (e.getValue() == null) { + errors.add(CommandParserException + .of(String.format("Missing option, longnames='%s'", e.getKey()))); } + }); + if (!result.getContext().containsKey("single1")) { + errors.add(CommandParserException.of("Missing option, longnames='single'")); } - }) - .and() + if (!errors.isEmpty()) { + throw CommandParserExceptionsException.of("Missing options", errors); + } + } + }) + .and() .build(); } @@ -257,42 +260,43 @@ public void conditional() { Map single1SelectItems = new HashMap<>(); single1SelectItems.put("Field1", "field1"); single1SelectItems.put("Field2", "field2"); - ComponentFlow flow = componentFlowBuilder.clone().reset() - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .next(ctx -> ctx.getResultItem().get().getItem()) - .and() - .withStringInput("field1") - .name("Field1") - .defaultValue("defaultField1Value") - .next(ctx -> null) - .and() - .withStringInput("field2") - .name("Field2") - .defaultValue("defaultField2Value") - .next(ctx -> null) - .and() - .build(); + ComponentFlow flow = componentFlowBuilder.clone() + .reset() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .next(ctx -> ctx.getResultItem().get().getItem()) + .and() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .next(ctx -> null) + .and() + .withStringInput("field2") + .name("Field2") + .defaultValue("defaultField2Value") + .next(ctx -> null) + .and() + .build(); flow.run(); } @ShellMethod(key = "flow autoselect", value = "Autoselect item", group = "Flow") - public void autoselect( - @ShellOption(defaultValue = "Field3") String defaultValue - ) { + public void autoselect(@ShellOption(defaultValue = "Field3") String defaultValue) { Map single1SelectItems = IntStream.range(1, 10) .boxed() .collect(Collectors.toMap(i -> "Field" + i, i -> "field" + i)); - ComponentFlow flow = componentFlowBuilder.clone().reset() - .withSingleItemSelector("single1") - .name("Single1") - .selectItems(single1SelectItems) - .defaultSelect(defaultValue) - .sort((o1, o2) -> o1.getName().compareTo(o2.getName())) - .and() - .build(); + ComponentFlow flow = componentFlowBuilder.clone() + .reset() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .defaultSelect(defaultValue) + .sort((o1, o2) -> o1.getName().compareTo(o2.getName())) + .and() + .build(); flow.run(); } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentUiCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentUiCommands.java index 1722a5181..c2220a17e 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentUiCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ComponentUiCommands.java @@ -39,9 +39,7 @@ public void tui1() { BoxView view = new BoxView(); view.setShowBorder(true); view.setDrawFunction((screen, rect) -> { - screen.writerBuilder() - .build() - .text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); + screen.writerBuilder().build().text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); return rect; }); ui.setRoot(view, true); @@ -55,9 +53,7 @@ public void tui2() { view.setRect(0, 0, 40, 5); view.setShowBorder(true); view.setDrawFunction((screen, rect) -> { - screen.writerBuilder() - .build() - .text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); + screen.writerBuilder().build().text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); return rect; }); ui.setRoot(view, false); @@ -70,9 +66,7 @@ public void tui3() { BoxView view = new BoxView(); view.setShowBorder(true); view.setDrawFunction((screen, rect) -> { - screen.writerBuilder() - .build() - .text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); + screen.writerBuilder().build().text("Hello World", rect, HorizontalAlign.CENTER, VerticalAlign.CENTER); return rect; }); ui.setRoot(view, false); @@ -90,21 +84,15 @@ public String stringInput() { } @Command(command = "componentui progress") - public void progress( - @Option(defaultValue = "desc") String description, - @Option(defaultValue = "true") boolean textEnabled, - @Option(defaultValue = "true") boolean spinnerEnabled, - @Option(defaultValue = "true") boolean percentEnabled, - @Option(defaultValue = "0") int textSize, - @Option(defaultValue = "0") int spinnerSize, - @Option(defaultValue = "0") int percentSize, - @Option(defaultValue = "CENTER") HorizontalAlign textAlign, - @Option(defaultValue = "CENTER") HorizontalAlign spinnerAlign, - @Option(defaultValue = "CENTER") HorizontalAlign percentAlign, - @Option(defaultValue = "-1") int logMessagesRate, - @Option(defaultValue = "200") long advanceSleep, - @Option(defaultValue = "false") boolean logMessagesSleep - ) { + public void progress(@Option(defaultValue = "desc") String description, + @Option(defaultValue = "true") boolean textEnabled, @Option(defaultValue = "true") boolean spinnerEnabled, + @Option(defaultValue = "true") boolean percentEnabled, @Option(defaultValue = "0") int textSize, + @Option(defaultValue = "0") int spinnerSize, @Option(defaultValue = "0") int percentSize, + @Option(defaultValue = "CENTER") HorizontalAlign textAlign, + @Option(defaultValue = "CENTER") HorizontalAlign spinnerAlign, + @Option(defaultValue = "CENTER") HorizontalAlign percentAlign, + @Option(defaultValue = "-1") int logMessagesRate, @Option(defaultValue = "200") long advanceSleep, + @Option(defaultValue = "false") boolean logMessagesSleep) { ArrayList items = new ArrayList<>(); if (textEnabled) { items.add(ProgressViewItem.ofText(textSize, textAlign)); @@ -172,7 +160,8 @@ public void progress( private static void sleep(long millis) { try { Thread.sleep(millis); - } catch (InterruptedException e) { + } + catch (InterruptedException e) { } } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ConversionExample.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ConversionExample.java index e8d8642d1..c9bdb2313 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ConversionExample.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ConversionExample.java @@ -32,6 +32,7 @@ public Object conversionExample(DomainObject object) { } class DomainObject { + private final String value; DomainObject(String value) { @@ -46,6 +47,7 @@ public String getValue() { public String toString() { return "DomainObject [value=" + value + "]"; } + } @Component @@ -55,4 +57,5 @@ class CustomDomainConverter implements Converter { public DomainObject convert(String source) { return new DomainObject(source); } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/DynamicCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/DynamicCommands.java index 3d1f6aa81..524964de7 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/DynamicCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/DynamicCommands.java @@ -62,4 +62,5 @@ public Availability dangerousAvailability() { return connected && authenticated ? Availability.available() : Availability.unavailable("you failed to authenticate. Try 'sesame'."); } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/FunctionCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/FunctionCommands.java index 1912d6288..be38bd181 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/FunctionCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/FunctionCommands.java @@ -29,14 +29,14 @@ public CommandRegistration commandRegistration1() { .description("function sample") .group("Function Commands") .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return String.format("hi, arg1 value is '%s'", arg1); - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return String.format("hi, arg1 value is '%s'", arg1); + }) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); } @@ -47,25 +47,25 @@ public CommandRegistration commandRegistration2() { .description("function sample") .group("Function Commands") .withTarget() - .function(ctx -> { - Boolean a = ctx.getOptionValue("a"); - Boolean b = ctx.getOptionValue("b"); - Boolean c = ctx.getOptionValue("c"); - return String.format("hi, boolean values for a, b, c are '%s' '%s' '%s'", a, b, c); - }) - .and() + .function(ctx -> { + Boolean a = ctx.getOptionValue("a"); + Boolean b = ctx.getOptionValue("b"); + Boolean c = ctx.getOptionValue("c"); + return String.format("hi, boolean values for a, b, c are '%s' '%s' '%s'", a, b, c); + }) + .and() .withOption() - .shortNames('a') - .type(boolean.class) - .and() + .shortNames('a') + .type(boolean.class) + .and() .withOption() - .shortNames('b') - .type(boolean.class) - .and() + .shortNames('b') + .type(boolean.class) + .and() .withOption() - .shortNames('c') - .type(boolean.class) - .and() + .shortNames('c') + .type(boolean.class) + .and() .build(); } @@ -76,15 +76,14 @@ public CommandRegistration commandRegistration3() { .description("function sample") .group("Function Commands") .withTarget() - .consumer(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - ctx.getTerminal().writer() - .println(String.format("hi, arg1 value is '%s'", arg1)); - }) - .and() + .consumer(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + ctx.getTerminal().writer().println(String.format("hi, arg1 value is '%s'", arg1)); + }) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); } @@ -95,14 +94,16 @@ public CommandRegistration commandRegistration4() { .description("function sample") .group("Function Commands") .withTarget() - .consumer(ctx -> { - ctx.getTerminal().writer() - .println(String.format("hi, command is '%s'", ctx.getCommandRegistration().getCommand())); - }) - .and() + .consumer(ctx -> { + ctx.getTerminal() + .writer() + .println(String.format("hi, command is '%s'", ctx.getCommandRegistration().getCommand())); + }) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/RegisterCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/RegisterCommands.java index b518e47e0..eca1530fb 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/RegisterCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/RegisterCommands.java @@ -28,9 +28,13 @@ public class RegisterCommands extends AbstractShellComponent { private final static String GROUP = "Register Commands"; + private final PojoMethods pojoMethods = new PojoMethods(); + private final CommandRegistration registered1; + private final CommandRegistration registered2; + private final CommandRegistration registered3; public RegisterCommands() { @@ -39,43 +43,43 @@ public RegisterCommands() { .group(GROUP) .description("registered1 command") .withTarget() - .method(pojoMethods, "registered1") - .and() + .method(pojoMethods, "registered1") + .and() .build(); registered2 = CommandRegistration.builder() .command("register registered2") .description("registered2 command") .group(GROUP) .withTarget() - .method(pojoMethods, "registered2") - .and() + .method(pojoMethods, "registered2") + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); registered3 = CommandRegistration.builder() .command("register registered3") .description("registered3 command") .group(GROUP) .withTarget() - .method(pojoMethods, "registered3") - .and() + .method(pojoMethods, "registered3") + .and() .build(); } - @ShellMethod(key = "register add", value = "Register commands", group = GROUP) - public String register() { + @ShellMethod(key = "register add", value = "Register commands", group = GROUP) + public String register() { getCommandCatalog().register(registered1, registered2, registered3); registerFunctionCommand("register registered4"); return "Registered commands registered1, registered2, registered3, registered4"; - } + } - @ShellMethod(key = "register remove", value = "Deregister commands", group = GROUP) - public String deregister() { + @ShellMethod(key = "register remove", value = "Deregister commands", group = GROUP) + public String deregister() { getCommandCatalog().unregister("register registered1", "register registered2", "register registered3", "register registered4"); return "Deregistered commands registered1, registered2, registered3, registered4"; - } + } private void registerFunctionCommand(String command) { Function function = ctx -> { @@ -87,11 +91,11 @@ private void registerFunctionCommand(String command) { .description("registered4 command") .group(GROUP) .withTarget() - .function(function) - .and() + .function(function) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); getCommandCatalog().register(registration); } @@ -112,5 +116,7 @@ public String registered2(String arg1) { public String registered3(@ShellOption(defaultValue = ShellOption.NULL) String arg1) { return "registered3" + arg1; } + } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ResolvedCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ResolvedCommands.java index 6adde4b39..85edce0c5 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ResolvedCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ResolvedCommands.java @@ -42,12 +42,14 @@ Server1CommandResolver server1CommandResolver() { Server2CommandResolver server2CommandResolver() { return new Server2CommandResolver(); } + } @ShellComponent public static class ResolvedCommandsCommands { private final Server1CommandResolver server1CommandResolver; + private final Server2CommandResolver server2CommandResolver; ResolvedCommandsCommands(Server1CommandResolver server1CommandResolver, @@ -79,11 +81,13 @@ public String server2Disable() { server2CommandResolver.enabled = false; return "Disabled server2"; } + } static class Server1CommandResolver implements CommandResolver { private final List registrations = new ArrayList<>(); + boolean enabled = false; Server1CommandResolver() { @@ -92,10 +96,10 @@ static class Server1CommandResolver implements CommandResolver { .group(GROUP) .description("server1 command1") .withTarget() - .function(ctx -> { - return "hi from server1 command1"; - }) - .and() + .function(ctx -> { + return "hi from server1 command1"; + }) + .and() .build(); registrations.add(resolved1); } @@ -104,11 +108,13 @@ static class Server1CommandResolver implements CommandResolver { public List resolve() { return enabled ? registrations : Collections.emptyList(); } + } static class Server2CommandResolver implements CommandResolver { private final List registrations = new ArrayList<>(); + boolean enabled = false; Server2CommandResolver() { @@ -117,20 +123,20 @@ static class Server2CommandResolver implements CommandResolver { .group(GROUP) .description("server2 command1") .withTarget() - .function(ctx -> { - return "hi from server2 command1"; - }) - .and() + .function(ctx -> { + return "hi from server2 command1"; + }) + .and() .build(); CommandRegistration resolved2 = CommandRegistration.builder() .command("resolve server2 command2") .group(GROUP) .description("server2 command2") .withTarget() - .function(ctx -> { - return "hi from server2 command2"; - }) - .and() + .function(ctx -> { + return "hi from server2 command2"; + }) + .and() .build(); registrations.add(resolved1); registrations.add(resolved2); @@ -140,5 +146,7 @@ static class Server2CommandResolver implements CommandResolver { public List resolve() { return enabled ? registrations : Collections.emptyList(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/TableCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/TableCommands.java index 81b8a4972..d2b250274 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/TableCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/TableCommands.java @@ -25,11 +25,11 @@ @ShellComponent public class TableCommands { - private static final String TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " + - "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " + - "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " + - "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " + - "non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + private static final String TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " + + "ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " + + "laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in " + + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " + + "non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; @ShellMethod(value = "Showcase Table rendering", group = "Tables") public Table table() { @@ -57,4 +57,5 @@ public boolean matches(int row, int column, TableModel model) { } }; } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ThemeCommands.java b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ThemeCommands.java index d74121c8e..30741871d 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ThemeCommands.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/main/java/org/springframework/shell/samples/standard/ThemeCommands.java @@ -36,12 +36,16 @@ public class ThemeCommands { List colorGround = Arrays.asList("fg", "bg"); + List colors = Arrays.asList("black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"); + List named = Arrays.asList("default", "bold", "faint", "italic", "underline", "blink", "inverse", "inverseneg", "conceal", "crossedout", "hidden"); + List rgbRedHue = Arrays.asList("#ff0000", "#ff4000", "#ff8000", "#ffbf00", "#ffff00", "#bfff00", "#80ff00", "#40ff00", "#00ff00", "#00ff40", "#00ff80", "#00ffbf", "#00ffff", "#00bfff", "#0080ff", "#0040ff", "#0000ff", "#4000ff", "#8000ff", "#bf00ff", "#ff00ff", "#ff00bf", "#ff0080", "#ff0040", "#ff0000"); + List themeTags = Arrays.asList(StyleSettings.TAG_TITLE, StyleSettings.TAG_VALUE, StyleSettings.TAG_LIST_KEY, StyleSettings.TAG_LIST_VALUE, StyleSettings.TAG_LEVEL_INFO, StyleSettings.TAG_LEVEL_WARN, StyleSettings.TAG_LEVEL_ERROR, StyleSettings.TAG_ITEM_ENABLED, StyleSettings.TAG_ITEM_DISABLED, @@ -53,53 +57,48 @@ public class ThemeCommands { @ShellMethod(key = "theme showcase values", value = "Showcase colors and styles", group = "Styles") public AttributedString showcaseValues() { AttributedStringBuilder builder = new AttributedStringBuilder(); - combinations1().stream() - .forEach(spec -> { - AttributedStyle style = themeResolver.resolveStyle(spec); - AttributedString styledStr = new AttributedString(spec, style); - builder.append(String.format("%-25s", spec)); - builder.append(" "); - builder.append(styledStr); - builder.append("\n"); - }); + combinations1().stream().forEach(spec -> { + AttributedStyle style = themeResolver.resolveStyle(spec); + AttributedString styledStr = new AttributedString(spec, style); + builder.append(String.format("%-25s", spec)); + builder.append(" "); + builder.append(styledStr); + builder.append("\n"); + }); return builder.toAttributedString(); } @ShellMethod(key = "theme showcase rgb", value = "Showcase colors and styles with rgb", group = "Styles") public AttributedString showcaseRgb() { AttributedStringBuilder builder = new AttributedStringBuilder(); - combinations2().stream() - .forEach(spec -> { - AttributedStyle style = themeResolver.resolveStyle(spec); - AttributedString styledStr = new AttributedString(spec, style); - builder.append(String.format("%-25s", spec)); - builder.append(" "); - builder.append(styledStr); - builder.append("\n"); - }); + combinations2().stream().forEach(spec -> { + AttributedStyle style = themeResolver.resolveStyle(spec); + AttributedString styledStr = new AttributedString(spec, style); + builder.append(String.format("%-25s", spec)); + builder.append(" "); + builder.append(styledStr); + builder.append("\n"); + }); return builder.toAttributedString(); } @ShellMethod(key = "theme style list", value = "List styles", group = "Styles") public AttributedString styleList() { AttributedStringBuilder builder = new AttributedStringBuilder(); - themeTags.stream() - .forEach(tag -> { - String resolvedStyle = themeResolver.resolveStyleTag(tag); - AttributedStyle style = themeResolver.resolveStyle(resolvedStyle); - AttributedString styledStr = new AttributedString(tag, style); - builder.append(String.format("%-25s", tag)); - builder.append(" "); - builder.append(styledStr); - builder.append("\n"); - }); + themeTags.stream().forEach(tag -> { + String resolvedStyle = themeResolver.resolveStyleTag(tag); + AttributedStyle style = themeResolver.resolveStyle(resolvedStyle); + AttributedString styledStr = new AttributedString(tag, style); + builder.append(String.format("%-25s", tag)); + builder.append(" "); + builder.append(styledStr); + builder.append("\n"); + }); return builder.toAttributedString(); } @ShellMethod(key = "theme style resolve", value = "Resolve given style", group = "Styles") - public AttributedString styleResolve( - @ShellOption(value = "--spec", defaultValue = "default") String spec - ) { + public AttributedString styleResolve(@ShellOption(value = "--spec", defaultValue = "default") String spec) { AttributedStringBuilder builder = new AttributedStringBuilder(); AttributedStyle style = themeResolver.resolveStyle(spec); AttributedString styledStr = new AttributedString(spec, style); @@ -110,8 +109,7 @@ public AttributedString styleResolve( @ShellMethod(key = "theme expression resolve", value = "Resolve given style expression", group = "Styles") public AttributedString expressionResolve( - @ShellOption(value = "--expression", defaultValue = "hi @{bold from} expression") String expression - ) { + @ShellOption(value = "--expression", defaultValue = "hi @{bold from} expression") String expression) { AttributedStringBuilder builder = new AttributedStringBuilder(); AttributedString styledStr = themeResolver.evaluateExpression(expression); builder.append(styledStr); @@ -122,18 +120,17 @@ public AttributedString expressionResolve( @ShellMethod(key = "theme figure list", value = "List figures", group = "Styles") public AttributedString figureList() { AttributedStringBuilder builder = new AttributedStringBuilder(); - Stream.of(FigureSettings.tags()) - .forEach(tag -> { - builder.append(String.format("%-25s", tag)); - builder.append(" "); - String resolveFigureTag = themeResolver.resolveFigureTag(tag); - combinations3().stream().forEach(spec -> { - AttributedStyle style = themeResolver.resolveStyle(spec); - builder.append(" "); - builder.append(new AttributedString(resolveFigureTag, style)); - }); - builder.append("\n"); - }); + Stream.of(FigureSettings.tags()).forEach(tag -> { + builder.append(String.format("%-25s", tag)); + builder.append(" "); + String resolveFigureTag = themeResolver.resolveFigureTag(tag); + combinations3().stream().forEach(spec -> { + AttributedStyle style = themeResolver.resolveStyle(spec); + builder.append(" "); + builder.append(new AttributedString(resolveFigureTag, style)); + }); + builder.append("\n"); + }); return builder.toAttributedString(); } @@ -168,4 +165,5 @@ private List combinations3() { }); return styles; } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java b/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java index 3c7484aca..6fba6ef4d 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java @@ -72,4 +72,5 @@ protected BaseShellSession createSession(String command, boolean interactive) return session; } } + } diff --git a/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/standard/ComponentCommandsTests.java b/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/standard/ComponentCommandsTests.java index aa5bc76cc..3c8d4b53c 100644 --- a/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/standard/ComponentCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-commands/src/test/java/org/springframework/shell/samples/standard/ComponentCommandsTests.java @@ -30,10 +30,7 @@ public class ComponentCommandsTests extends AbstractSampleTests { @ParameterizedTest - @CsvSource({ - "component single,false", - "component single,true" - }) + @CsvSource({ "component single,false", "component single,true" }) void componentSingle(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); @@ -57,10 +54,7 @@ void componentSingle(String command, boolean interactive) { } @ParameterizedTest - @CsvSource({ - "component multi,false", - "component multi,true" - }) + @CsvSource({ "component multi,false", "component multi,true" }) void componentMulti(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); @@ -82,4 +76,5 @@ void componentMulti(String command, boolean interactive) { ShellAssertions.assertThat(session.screen()).containsText("Got value value1,value2"); }); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/SpringShellSample.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/SpringShellSample.java index a65b34fd8..b53a70bcc 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/SpringShellSample.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/SpringShellSample.java @@ -28,7 +28,9 @@ /** * Main entry point for the application. * - *

    Creates the application context and start the REPL.

    + *

    + * Creates the application context and start the REPL. + *

    * * @author Eric Bottard * @author Janne Valkealahti @@ -49,4 +51,5 @@ public static void main(String[] args) throws Exception { public PromptProvider myPromptProvider() { return () -> new AttributedString("my-shell:>", AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW)); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java index 1f6cb42cb..ab86f9ad0 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AliasCommands.java @@ -32,10 +32,12 @@ public String testAlias1LegacyAnnotation() { return "Hello from alias command"; } - @ShellMethod(key = { LEGACY_ANNO + "alias-2", LEGACY_ANNO + "alias1for-2", LEGACY_ANNO + "alias2for-2" }, group = GROUP) + @ShellMethod(key = { LEGACY_ANNO + "alias-2", LEGACY_ANNO + "alias1for-2", LEGACY_ANNO + "alias2for-2" }, + group = GROUP) public String testAlias2LegacyAnnotation() { return "Hello from alias command"; } + } @Command(command = BaseE2ECommands.ANNO, alias = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) @@ -55,6 +57,7 @@ public String testAlias2Annotation() { public String testAlias3Annotation() { return "Hello from alias3 command"; } + } @Component @@ -66,13 +69,13 @@ public CommandRegistration testAlias1Registration(CommandRegistration.BuilderSup .command(REG, "alias-1") .group(GROUP) .withAlias() - .command(REG, "aliasfor-1") - .and() + .command(REG, "aliasfor-1") + .and() .withTarget() - .function(ctx -> { - return "Hello from alias command"; - }) - .and() + .function(ctx -> { + return "Hello from alias command"; + }) + .and() .build(); } @@ -82,16 +85,16 @@ public CommandRegistration testAlias2Registration(CommandRegistration.BuilderSup .command(REG, "alias-2") .group(GROUP) .withAlias() - .command(REG, "alias1for-2") - .and() + .command(REG, "alias1for-2") + .and() .withAlias() - .command(REG, "alias2for-2") - .and() + .command(REG, "alias2for-2") + .and() .withTarget() - .function(ctx -> { - return "Hello from alias command"; - }) - .and() + .function(ctx -> { + return "Hello from alias command"; + }) + .and() .build(); } @@ -101,15 +104,16 @@ public CommandRegistration testAlias3Registration(CommandRegistration.BuilderSup .command(REG, "alias-3 alias-31") .group(GROUP) .withAlias() - .command(REG, "alias-32 alias-33") - .and() + .command(REG, "alias-32 alias-33") + .and() .withTarget() - .function(ctx -> { - return "Hello from alias3 command"; - }) - .and() + .function(ctx -> { + return "Hello from alias3 command"; + }) + .and() .build(); } + } } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ArityCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ArityCommands.java index d200ab5f7..ba43922a1 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ArityCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ArityCommands.java @@ -39,29 +39,23 @@ public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "arity-boolean-default-true", group = GROUP) public String testArityBooleanDefaultTrueLegacyAnnotation( - @ShellOption(value = "--overwrite", arity = 1, defaultValue = "true") Boolean overwrite - ) { + @ShellOption(value = "--overwrite", arity = 1, defaultValue = "true") Boolean overwrite) { return "Hello " + overwrite; } @ShellMethod(key = LEGACY_ANNO + "arity-string-array", group = GROUP) - public String testArityStringArrayLegacyAnnotation( - @ShellOption(value = "--arg1", arity = 3) String[] arg1 - ) { + public String testArityStringArrayLegacyAnnotation(@ShellOption(value = "--arg1", arity = 3) String[] arg1) { return "Hello " + Arrays.asList(arg1); } @ShellMethod(key = LEGACY_ANNO + "arity-float-array", group = GROUP) - public String testArityFloatArrayLegacyAnnotation( - @ShellOption(value = "--arg1", arity = 3) float[] arg1 - ) { + public String testArityFloatArrayLegacyAnnotation(@ShellOption(value = "--arg1", arity = 3) float[] arg1) { return "Hello " + stringOfFloats(arg1); } @ShellMethod(key = LEGACY_ANNO + "string-arityeone-required", group = GROUP) public String testStringArityeoneRequiredLegacyAnnotation( - @ShellOption(value = "--arg1", arity = 1) String arg1 - ) { + @ShellOption(value = "--arg1", arity = 1) String arg1) { return "Hello " + arg1; } @@ -71,35 +65,27 @@ public String testStringArityeoneRequiredLegacyAnnotation( public static class Annotation extends BaseE2ECommands { @Command(command = "arity-boolean-default-true") - public String testArityBooleanDefaultTrueAnnotation( - @Option(longNames = "overwrite", defaultValue = "true", arity = OptionArity.ZERO_OR_ONE) - Boolean overwrite - ) { - return "Hello " + overwrite; + public String testArityBooleanDefaultTrueAnnotation(@Option(longNames = "overwrite", defaultValue = "true", + arity = OptionArity.ZERO_OR_ONE) Boolean overwrite) { + return "Hello " + overwrite; } @Command(command = "arity-string-array") public String testArityStringArrayAnnotation( - @Option(longNames = "arg1", defaultValue = "true", arityMax = 3) - String[] arg1 - ) { - return "Hello " + Arrays.asList(arg1); + @Option(longNames = "arg1", defaultValue = "true", arityMax = 3) String[] arg1) { + return "Hello " + Arrays.asList(arg1); } @Command(command = "arity-float-array") public String testArityFloatArrayAnnotation( - @Option(longNames = "arg1", defaultValue = "true", arity = OptionArity.ZERO_OR_MORE) - float[] arg1 - ) { - return "Hello " + stringOfFloats(arg1); + @Option(longNames = "arg1", defaultValue = "true", arity = OptionArity.ZERO_OR_MORE) float[] arg1) { + return "Hello " + stringOfFloats(arg1); } @Command(command = "string-arityeone-required") public String testStringArityeoneRequiredAnnotation( - @Option(longNames = {"arg1"}, arity = OptionArity.EXACTLY_ONE, required = true) - String arg1 - ) { - return "Hello " + arg1; + @Option(longNames = { "arg1" }, arity = OptionArity.EXACTLY_ONE, required = true) String arg1) { + return "Hello " + arg1; } } @@ -109,102 +95,99 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testArityBooleanDefaultTrueRegistration() { - return getBuilder() - .command(REG, "arity-boolean-default-true") + return getBuilder().command(REG, "arity-boolean-default-true") .group(GROUP) .withOption() - .longNames("overwrite") - .type(Boolean.class) - .defaultValue("true") - .arity(OptionArity.ZERO_OR_ONE) - .and() + .longNames("overwrite") + .type(Boolean.class) + .defaultValue("true") + .arity(OptionArity.ZERO_OR_ONE) + .and() .withTarget() - .function(ctx -> { - Boolean overwrite = ctx.getOptionValue("overwrite"); - return "Hello " + overwrite; - }) - .and() + .function(ctx -> { + Boolean overwrite = ctx.getOptionValue("overwrite"); + return "Hello " + overwrite; + }) + .and() .build(); } @Bean public CommandRegistration testArityStringArrayRegistration() { - return getBuilder() - .command(REG, "arity-string-array") + return getBuilder().command(REG, "arity-string-array") .group(GROUP) .withOption() - .longNames("arg1") - .required() - .type(String[].class) - .arity(0, 3) - .position(0) - .and() + .longNames("arg1") + .required() + .type(String[].class) + .arity(0, 3) + .position(0) + .and() .withTarget() - .function(ctx -> { - String[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + Arrays.asList(arg1); - }) - .and() + .function(ctx -> { + String[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + Arrays.asList(arg1); + }) + .and() .build(); } @Bean public CommandRegistration testArityFloatArrayRegistration() { - return getBuilder() - .command(REG, "arity-float-array") + return getBuilder().command(REG, "arity-float-array") .group(GROUP) .withOption() - .longNames("arg1") - .type(float[].class) - .arity(0, 3) - .and() + .longNames("arg1") + .type(float[].class) + .arity(0, 3) + .and() .withTarget() - .function(ctx -> { - float[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + stringOfFloats(arg1); - }) - .and() + .function(ctx -> { + float[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + stringOfFloats(arg1); + }) + .and() .build(); } @Bean public CommandRegistration testStringArityeoneRequiredRegistration() { - return getBuilder() - .command(REG, "string-arityeone-required") + return getBuilder().command(REG, "string-arityeone-required") .group(GROUP) .withOption() - .longNames("arg1") - .type(String.class) - .required() - .arity(OptionArity.EXACTLY_ONE) - .and() + .longNames("arg1") + .type(String.class) + .required() + .arity(OptionArity.EXACTLY_ONE) + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration testArityErrorsRegistration() { - return getBuilder() - .command(REG, "arity-errors") + return getBuilder().command(REG, "arity-errors") .group(GROUP) .withOption() - .longNames("arg1") - .type(String[].class) - .required() - .arity(1, 2) - .and() + .longNames("arg1") + .type(String[].class) + .required() + .arity(1, 2) + .and() .withTarget() - .function(ctx -> { - String[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + Arrays.asList(arg1); - }) - .and() + .function(ctx -> { + String[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + Arrays.asList(arg1); + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AvailabilityCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AvailabilityCommands.java index 4228476dd..14eb23cc6 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AvailabilityCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/AvailabilityCommands.java @@ -35,8 +35,7 @@ public static class LegacyAnnotation extends BaseE2ECommands { // find from Availability @ShellMethod(key = LEGACY_ANNO + "availability-1", group = GROUP) - public String testAvailability1LegacyAnnotation( - ) { + public String testAvailability1LegacyAnnotation() { return "Hello"; } @@ -47,8 +46,7 @@ public Availability testAvailability1LegacyAnnotationAvailability() { // find from method name in @ShellMethodAvailability @ShellMethod(key = LEGACY_ANNO + "availability-2", group = GROUP) @ShellMethodAvailability("testAvailability2LegacyAnnotationAvailability2") - public String testAvailability2LegacyAnnotation( - ) { + public String testAvailability2LegacyAnnotation() { return "Hello"; } @@ -58,8 +56,7 @@ public Availability testAvailability2LegacyAnnotationAvailability2() { // find backwards from @ShellMethodAvailability command name @ShellMethod(key = LEGACY_ANNO + "availability-3", group = GROUP) - public String testAvailability3LegacyAnnotation( - ) { + public String testAvailability3LegacyAnnotation() { return "Hello"; } @@ -71,22 +68,17 @@ public Availability testAvailability3LegacyAnnotationAvailability3() { private boolean connected = false; @ShellMethod(key = LEGACY_ANNO + "availability-set", group = GROUP) - public void testAvailabilitySetLegacyAnnotation( - @ShellOption(value = "connected") boolean connected - ) { + public void testAvailabilitySetLegacyAnnotation(@ShellOption(value = "connected") boolean connected) { this.connected = connected; } @ShellMethod(key = LEGACY_ANNO + "availability-use", group = GROUP) @ShellMethodAvailability("testAvailabilityLegacyAnnotationConnected") - public void testAvailabilityUseLegacyAnnotation( - ) { + public void testAvailabilityUseLegacyAnnotation() { } public Availability testAvailabilityLegacyAnnotationConnected() { - return connected - ? Availability.available() - : Availability.unavailable("you are not connected"); + return connected ? Availability.available() : Availability.unavailable("you are not connected"); } } @@ -96,8 +88,7 @@ public static class Annotation extends BaseE2ECommands { @Command(command = "availability-1") @CommandAvailability(provider = "testAvailability1AnnotationAvailability") - public String testAvailability1Annotation( - ) { + public String testAvailability1Annotation() { return "Hello"; } @@ -109,23 +100,18 @@ public AvailabilityProvider testAvailability1AnnotationAvailability() { private boolean connected = false; @Command(command = "availability-set") - public void testAvailabilitySetAnnotation( - @Option(longNames = "connected") boolean connected - ) { + public void testAvailabilitySetAnnotation(@Option(longNames = "connected") boolean connected) { this.connected = connected; } @Command(command = "availability-use") @CommandAvailability(provider = "testAvailabilityAnnotationConnected") - public void testAvailabilityUseAnnotation( - ) { + public void testAvailabilityUseAnnotation() { } @Bean public AvailabilityProvider testAvailabilityAnnotationConnected() { - return () -> connected - ? Availability.available() - : Availability.unavailable("you are not connected"); + return () -> connected ? Availability.available() : Availability.unavailable("you are not connected"); } } @@ -135,31 +121,23 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testAvailability1Registration() { - return getBuilder() - .command(REG, "availability-1") - .group(GROUP) - .availability(() -> { - return Availability.unavailable("not available"); - }) - .withTarget() - .function(ctx -> { - return "Hello"; - }) - .and() - .build(); + return getBuilder().command(REG, "availability-1").group(GROUP).availability(() -> { + return Availability.unavailable("not available"); + }).withTarget().function(ctx -> { + return "Hello"; + }).and().build(); } @Bean public CommandRegistration testAvailability2Registration() { - return getBuilder() - .command(REG, "availability-2") + return getBuilder().command(REG, "availability-2") .group(GROUP) .availability(testAvailability2AnnotationAvailability()) .withTarget() - .function(ctx -> { - return "Hello"; - }) - .and() + .function(ctx -> { + return "Hello"; + }) + .and() .build(); } @@ -171,41 +149,38 @@ AvailabilityProvider testAvailability2AnnotationAvailability() { @Bean public CommandRegistration testAvailabilitySetRegistration() { - return getBuilder() - .command(REG, "availability-set") + return getBuilder().command(REG, "availability-set") .group(GROUP) .withOption() - .longNames("connected") - .required() - .type(boolean.class) - .and() + .longNames("connected") + .required() + .type(boolean.class) + .and() .withTarget() - .consumer(ctx -> { - boolean connected = ctx.getOptionValue("connected"); - this.connected = connected; - }) - .and() + .consumer(ctx -> { + boolean connected = ctx.getOptionValue("connected"); + this.connected = connected; + }) + .and() .build(); } @Bean public CommandRegistration testAvailabilityUseRegistration() { - return getBuilder() - .command(REG, "availability-use") + return getBuilder().command(REG, "availability-use") .group(GROUP) .availability(testAvailabilityRegistrationConnected()) .withTarget() - .consumer(ctx -> { - }) - .and() + .consumer(ctx -> { + }) + .and() .build(); } public AvailabilityProvider testAvailabilityRegistrationConnected() { - return () -> connected - ? Availability.available() - : Availability.unavailable("you are not connected"); + return () -> connected ? Availability.available() : Availability.unavailable("you are not connected"); } } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/BaseE2ECommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/BaseE2ECommands.java index 2dbd1539c..16f2280fa 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/BaseE2ECommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/BaseE2ECommands.java @@ -32,6 +32,7 @@ abstract class BaseE2ECommands { static final String GROUP = "E2E Commands"; static final String REG = "e2e reg"; static final String LEGACY_ANNO = "e2e anno "; + // TODO: anno should become anno-legacy and annox to anno static final String ANNO = "e2e annox "; @@ -63,4 +64,5 @@ static String stringOfFloats(float[] values) { .collect(Collectors.joining(",")); return String.format("[%s]", joined); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/DefaultValueCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/DefaultValueCommands.java index a3b4bc302..c4acfc85d 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/DefaultValueCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/DefaultValueCommands.java @@ -36,68 +36,52 @@ public class DefaultValueCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "default-value", group = GROUP) - public String testDefaultValue( - @ShellOption(defaultValue = "hi") String arg1 - ) { + public String testDefaultValue(@ShellOption(defaultValue = "hi") String arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "default-value-boolean1", group = GROUP) - public String testDefaultValueBoolean1( - @ShellOption(defaultValue = "false") boolean arg1 - ) { + public String testDefaultValueBoolean1(@ShellOption(defaultValue = "false") boolean arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "default-value-boolean2", group = GROUP) - public String testDefaultValueBoolean2( - @ShellOption(defaultValue = "true") boolean arg1 - ) { + public String testDefaultValueBoolean2(@ShellOption(defaultValue = "true") boolean arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "default-value-boolean3", group = GROUP) - public String testDefaultValueBoolean3( - @ShellOption boolean arg1 - ) { + public String testDefaultValueBoolean3(@ShellOption boolean arg1) { return "Hello " + arg1; } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) public static class Annotation extends BaseE2ECommands { @Command(command = "default-value") - public String testDefaultValueAnnotation( - @Option(longNames = "arg1", defaultValue = "hi") - String arg1 - ) { - return "Hello " + arg1; + public String testDefaultValueAnnotation(@Option(longNames = "arg1", defaultValue = "hi") String arg1) { + return "Hello " + arg1; } @Command(command = "default-value-boolean1") public String testDefaultValueBoolean1Annotation( - @Option(longNames = "arg1", defaultValue = "false") - boolean arg1 - ) { - return "Hello " + arg1; + @Option(longNames = "arg1", defaultValue = "false") boolean arg1) { + return "Hello " + arg1; } @Command(command = "default-value-boolean2") public String testDefaultValueBoolean2Annotation( - @Option(longNames = "arg1", defaultValue = "true") - boolean arg1 - ) { - return "Hello " + arg1; + @Option(longNames = "arg1", defaultValue = "true") boolean arg1) { + return "Hello " + arg1; } @Command(command = "default-value-boolean3") - public String testDefaultValueBoolean3Annotation( - @Option(longNames = "arg1") - boolean arg1 - ) { - return "Hello " + arg1; + public String testDefaultValueBoolean3Annotation(@Option(longNames = "arg1") boolean arg1) { + return "Hello " + arg1; } + } @Component @@ -105,78 +89,76 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testDefaultValueRegistration() { - return getBuilder() - .command(REG, "default-value") + return getBuilder().command(REG, "default-value") .group(GROUP) .withOption() - .longNames("arg1") - .defaultValue("hi") - .and() + .longNames("arg1") + .defaultValue("hi") + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration testDefaultValueBoolean1Registration() { - return getBuilder() - .command(REG, "default-value-boolean1") + return getBuilder().command(REG, "default-value-boolean1") .group(GROUP) .withOption() - .longNames("arg1") - .defaultValue("false") - .type(boolean.class) - .and() + .longNames("arg1") + .defaultValue("false") + .type(boolean.class) + .and() .withTarget() - .function(ctx -> { - boolean arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + boolean arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration testDefaultValueBoolean2Registration() { - return getBuilder() - .command(REG, "default-value-boolean2") + return getBuilder().command(REG, "default-value-boolean2") .group(GROUP) .withOption() - .longNames("arg1") - .defaultValue("true") - .type(boolean.class) - .and() + .longNames("arg1") + .defaultValue("true") + .type(boolean.class) + .and() .withTarget() - .function(ctx -> { - boolean arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + boolean arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration testDefaultValueBoolean3Registration() { - return getBuilder() - .command(REG, "default-value-boolean3") + return getBuilder().command(REG, "default-value-boolean3") .group(GROUP) .withOption() - .longNames("arg1") - .required(false) - .type(boolean.class) - .defaultValue("false") - .and() + .longNames("arg1") + .required(false) + .type(boolean.class) + .defaultValue("false") + .and() .withTarget() - .function(ctx -> { - boolean arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + boolean arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ErrorHandlingCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ErrorHandlingCommands.java index c3af77ea4..04f6ee0ff 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ErrorHandlingCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ErrorHandlingCommands.java @@ -87,6 +87,7 @@ void errorHandler3(CustomException4 e, Terminal terminal) { writer.println(String.format("Hi, handled custom exception %s", e)); writer.flush(); } + } @Component @@ -94,46 +95,47 @@ public static class Registration extends BaseE2ECommands { @Bean CommandRegistration testErrorHandlingRegistration() { - return getBuilder() - .command(REG, "error-handling") + return getBuilder().command(REG, "error-handling") .group(GROUP) .withOption() - .longNames("arg1") - .required() - .and() + .longNames("arg1") + .required() + .and() .withErrorHandling() - .resolver(new CustomExceptionResolver()) - .and() + .resolver(new CustomExceptionResolver()) + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - if ("throw1".equals(arg1)) { - throw new CustomException1(); - } - if ("throw2".equals(arg1)) { - throw new CustomException2(11); - } - if ("throw3".equals(arg1)) { - throw new RuntimeException(); - } - if ("throw4".equals(arg1)) { - throw new IllegalArgumentException(); - } - if ("throw5".equals(arg1)) { - throw new CustomException3(); - } - if ("throw6".equals(arg1)) { - throw new CustomException4(); - } - - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + if ("throw1".equals(arg1)) { + throw new CustomException1(); + } + if ("throw2".equals(arg1)) { + throw new CustomException2(11); + } + if ("throw3".equals(arg1)) { + throw new RuntimeException(); + } + if ("throw4".equals(arg1)) { + throw new IllegalArgumentException(); + } + if ("throw5".equals(arg1)) { + throw new CustomException3(); + } + if ("throw6".equals(arg1)) { + throw new CustomException4(); + } + + return "Hello " + arg1; + }) + .and() .build(); } + } private static class CustomException1 extends RuntimeException { + } private static class CustomException2 extends RuntimeException implements ExitCodeGenerator { @@ -148,12 +150,15 @@ private static class CustomException2 extends RuntimeException implements ExitCo public int getExitCode() { return code; } + } private static class CustomException3 extends RuntimeException { + } private static class CustomException4 extends RuntimeException { + } private static class CustomExceptionResolver implements CommandExceptionResolver { @@ -175,5 +180,7 @@ public CommandHandlingResult resolve(Exception e) { } return null; } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ExitCodeCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ExitCodeCommands.java index 241a23b5c..3e35092cf 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ExitCodeCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ExitCodeCommands.java @@ -28,36 +28,37 @@ public class ExitCodeCommands { @Component public static class Registration extends BaseE2ECommands { + @Bean public CommandRegistration testExitCodeRegistration() { - return getBuilder() - .command(REG, "exit-code") + return getBuilder().command(REG, "exit-code") .group(GROUP) .withOption() - .longNames("arg1") - .required() - .and() + .longNames("arg1") + .required() + .and() .withTarget() - .consumer(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - throw new MyException(arg1); - }) - .and() + .consumer(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + throw new MyException(arg1); + }) + .and() .withExitCode() - .map(MyException.class, 3) - .map(t -> { - String msg = t.getMessage(); - if (msg != null && msg.contains("ok")) { - return 0; - } - else if (msg != null && msg.contains("fun")) { - return 4; - } + .map(MyException.class, 3) + .map(t -> { + String msg = t.getMessage(); + if (msg != null && msg.contains("ok")) { return 0; - }) - .and() + } + else if (msg != null && msg.contains("fun")) { + return 4; + } + return 0; + }) + .and() .build(); } + } static class MyException extends RuntimeException { @@ -65,5 +66,7 @@ static class MyException extends RuntimeException { MyException(String msg) { super(msg); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpCommands.java index b8dd47fb1..c16add46b 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpCommands.java @@ -31,20 +31,18 @@ public class HelpCommands extends BaseE2ECommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "help-desc-1", group = GROUP) - public void helpDesc1( - @ShellOption(help = "arg1 desc", defaultValue = "hi") String arg1 - ) { + public void helpDesc1(@ShellOption(help = "arg1 desc", defaultValue = "hi") String arg1) { } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) public static class Annotation extends BaseE2ECommands { @Command(command = "help-desc-1") - public void helpDesc1( - @Option(longNames = "arg1", defaultValue = "hi", description = "arg1 desc") String arg1 - ) { + public void helpDesc1(@Option(longNames = "arg1", defaultValue = "hi", description = "arg1 desc") String arg1) { } + } @Component @@ -52,19 +50,20 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration helpDesc1() { - return getBuilder() - .command(REG, "help-desc-1") + return getBuilder().command(REG, "help-desc-1") .group(GROUP) .withOption() - .longNames("arg1") - .defaultValue("hi") - .description("arg1 desc") - .and() + .longNames("arg1") + .defaultValue("hi") + .description("arg1 desc") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); } + } } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpOptionCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpOptionCommands.java index e392d173f..f9fe55766 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpOptionCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HelpOptionCommands.java @@ -29,11 +29,10 @@ public class HelpOptionCommands extends BaseE2ECommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "help-option-default", group = GROUP) - public String testHelpOptionDefault( - @ShellOption(defaultValue = "hi") String arg1 - ) { + public String testHelpOptionDefault(@ShellOption(defaultValue = "hi") String arg1) { return "Hello " + arg1; } + } @Component @@ -41,41 +40,41 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testHelpOptionDefaultRegistration() { - return getBuilder() - .command(REG, "help-option-default") + return getBuilder().command(REG, "help-option-default") .group(GROUP) .withOption() - .longNames("arg1") - .defaultValue("hi") - .and() + .longNames("arg1") + .defaultValue("hi") + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration testHelpOptionExistsRegistration() { - return getBuilder() - .command(REG, "help-option-exists") + return getBuilder().command(REG, "help-option-exists") .group(GROUP) .withOption() - .longNames("help") - .defaultValue("hi") - .and() + .longNames("help") + .defaultValue("hi") + .and() .withHelpOptions() - .longNames("myhelp") - .and() + .longNames("myhelp") + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("help"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("help"); + return "Hello " + arg1; + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HiddenCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HiddenCommands.java index 2a48b2036..b0791c5bb 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HiddenCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/HiddenCommands.java @@ -26,10 +26,10 @@ public class HiddenCommands { public static class Annotation extends BaseE2ECommands { @Command(command = "hidden-1", hidden = true) - public String testHidden1Annotation( - ) { - return "Hello from hidden command"; + public String testHidden1Annotation() { + return "Hello from hidden command"; } + } @Component @@ -37,16 +37,11 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testHidden1Registration() { - return getBuilder() - .command(REG, "hidden-1") - .group(GROUP) - .hidden() - .withTarget() - .function(ctx -> { - return "Hello from hidden command"; - }) - .and() - .build(); + return getBuilder().command(REG, "hidden-1").group(GROUP).hidden().withTarget().function(ctx -> { + return "Hello from hidden command"; + }).and().build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/InteractiveCompletionCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/InteractiveCompletionCommands.java index bb465835c..d43efd2a2 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/InteractiveCompletionCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/InteractiveCompletionCommands.java @@ -39,10 +39,8 @@ public class InteractiveCompletionCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "interactive-completion-1", group = GROUP) - public String testInteractiveCompletion1( - @ShellOption(valueProvider = Test1ValuesProvider.class) String arg1, - @ShellOption(valueProvider = Test2ValuesProvider.class) String arg2 - ) { + public String testInteractiveCompletion1(@ShellOption(valueProvider = Test1ValuesProvider.class) String arg1, + @ShellOption(valueProvider = Test2ValuesProvider.class) String arg2) { return "Hello " + arg1; } @@ -55,6 +53,7 @@ Test1ValuesProvider test1ValuesProvider() { Test2ValuesProvider test2ValuesProvider() { return new Test2ValuesProvider(); } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) @@ -62,10 +61,11 @@ public static class Annotation extends BaseE2ECommands { @Command(command = "interactive-completion-1") public String testRequiredValueAnnotation( - @Option(longNames = "arg1", required = true) @OptionValues(provider = "test1CompletionProvider") String arg1, - @Option(longNames = "arg2", required = true) @OptionValues(provider = "test2CompletionProvider") String arg2 - ) { - return "Hello " + arg1; + @Option(longNames = "arg1", + required = true) @OptionValues(provider = "test1CompletionProvider") String arg1, + @Option(longNames = "arg2", + required = true) @OptionValues(provider = "test2CompletionProvider") String arg2) { + return "Hello " + arg1; } @Bean @@ -83,6 +83,7 @@ CompletionProvider test2CompletionProvider() { return test2ValuesProvider.complete(ctx); }; } + } @Component @@ -92,55 +93,47 @@ public static class Registration extends BaseE2ECommands { CommandRegistration testInteractiveCompletion1Registration() { Test1ValuesProvider test1ValuesProvider = new Test1ValuesProvider(); Test2ValuesProvider test2ValuesProvider = new Test2ValuesProvider(); - return getBuilder() - .command(REG, "interactive-completion-1") + return getBuilder().command(REG, "interactive-completion-1") .group(GROUP) .withOption() - .longNames("arg1") - .completion(ctx -> test1ValuesProvider.complete(ctx)) - .and() + .longNames("arg1") + .completion(ctx -> test1ValuesProvider.complete(ctx)) + .and() .withOption() - .longNames("arg2") - .completion(ctx -> test2ValuesProvider.complete(ctx)) - .and() + .longNames("arg2") + .completion(ctx -> test2ValuesProvider.complete(ctx)) + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } + } static class Test1ValuesProvider implements ValueProvider { - private final static String[] VALUES = new String[] { - "values1Complete1", - "values1Complete2" - }; + private final static String[] VALUES = new String[] { "values1Complete1", "values1Complete2" }; @Override public List complete(CompletionContext completionContext) { - return Arrays.stream(VALUES) - .map(CompletionProposal::new) - .collect(Collectors.toList()); + return Arrays.stream(VALUES).map(CompletionProposal::new).collect(Collectors.toList()); } + } static class Test2ValuesProvider implements ValueProvider { - private final static String[] VALUES = new String[] { - "values2Complete1", - "values2Complete2" - }; + private final static String[] VALUES = new String[] { "values2Complete1", "values2Complete2" }; @Override public List complete(CompletionContext completionContext) { - return Arrays.stream(VALUES) - .map(CompletionProposal::new) - .collect(Collectors.toList()); + return Arrays.stream(VALUES).map(CompletionProposal::new).collect(Collectors.toList()); } + } } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionConversionCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionConversionCommands.java index 077cc947e..0cd08c696 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionConversionCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionConversionCommands.java @@ -37,75 +37,55 @@ public class OptionConversionCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "option-conversion-integer", group = GROUP) - public String optionConversionIntegerAnnotation( - @ShellOption Integer arg1 - ) { + public String optionConversionIntegerAnnotation(@ShellOption Integer arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-conversion-custom", group = GROUP) - public String optionConversionCustomAnnotation( - @ShellOption MyPojo arg1 - ) { + public String optionConversionCustomAnnotation(@ShellOption MyPojo arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-conversion-customset", group = GROUP) - public String optionConversionCustomSetAnnotation( - @ShellOption Set arg1 - ) { + public String optionConversionCustomSetAnnotation(@ShellOption Set arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-conversion-customlist", group = GROUP) - public String optionConversionCustomListAnnotation( - @ShellOption List arg1 - ) { + public String optionConversionCustomListAnnotation(@ShellOption List arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-conversion-customarray", group = GROUP) - public String optionConversionCustomArrayAnnotation( - @ShellOption MyPojo[] arg1 - ) { + public String optionConversionCustomArrayAnnotation(@ShellOption MyPojo[] arg1) { return "Hello " + Arrays.asList(arg1); } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) public static class Annotation extends BaseE2ECommands { @Command(command = "option-conversion-integer") - public String optionConversionIntegerAnnotation( - @Option(longNames = "arg1") - Integer arg1 - ) { + public String optionConversionIntegerAnnotation(@Option(longNames = "arg1") Integer arg1) { return "Hello " + arg1; } @Command(command = "option-conversion-custom") - public String optionConversionCustomAnnotation( - @Option(longNames = "arg1") - MyPojo arg1 - ) { + public String optionConversionCustomAnnotation(@Option(longNames = "arg1") MyPojo arg1) { return "Hello " + arg1; } @Command(command = "option-conversion-customset") - public String optionConversionCustomSetAnnotation( - @Option(longNames = "arg1") - Set arg1 - ) { + public String optionConversionCustomSetAnnotation(@Option(longNames = "arg1") Set arg1) { return "Hello " + arg1; } @Command(command = "option-conversion-customarray") - public String optionConversionCustomArrayAnnotation( - @Option(longNames = "arg1") - MyPojo[] arg1 - ) { + public String optionConversionCustomArrayAnnotation(@Option(longNames = "arg1") MyPojo[] arg1) { return "Hello " + Arrays.asList(arg1); } + } @Component @@ -113,37 +93,35 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration optionConversionIntegerRegistration() { - return getBuilder() - .command(REG, "option-conversion-integer") + return getBuilder().command(REG, "option-conversion-integer") .group(GROUP) .withOption() - .longNames("arg1") - .type(Integer.class) - .and() + .longNames("arg1") + .type(Integer.class) + .and() .withTarget() - .function(ctx -> { - Integer arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + Integer arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration optionConversionCustomRegistration() { - return getBuilder() - .command(REG, "option-conversion-custom") + return getBuilder().command(REG, "option-conversion-custom") .group(GROUP) .withOption() - .longNames("arg1") - .type(MyPojo.class) - .and() + .longNames("arg1") + .type(MyPojo.class) + .and() .withTarget() - .function(ctx -> { - MyPojo arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + MyPojo arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @@ -154,35 +132,35 @@ public CommandRegistration optionConversionCustomSetRegistration() { .command(REG, "option-conversion-customset") .group(GROUP) .withOption() - .longNames("arg1") - .type(rtype) - .and() + .longNames("arg1") + .type(rtype) + .and() .withTarget() - .function(ctx -> { - Set arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + Set arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration optionConversionCustomArrayRegistration() { - return getBuilder() - .command(REG, "option-conversion-customarray") + return getBuilder().command(REG, "option-conversion-customarray") .group(GROUP) .withOption() - .longNames("arg1") - .type(MyPojo[].class) - .and() + .longNames("arg1") + .type(MyPojo[].class) + .and() .withTarget() - .function(ctx -> { - MyPojo[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + Arrays.asList(arg1); - }) - .and() + .function(ctx -> { + MyPojo[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + Arrays.asList(arg1); + }) + .and() .build(); } + } @Configuration(proxyBeanMethods = false) @@ -192,9 +170,11 @@ public static class CommonConfiguration { public Converter stringToMyPojoConverter() { return new StringToMyPojoConverter(); } + } public static class MyPojo { + private String arg; public MyPojo(String arg) { @@ -213,6 +193,7 @@ public void setArg(String arg) { public String toString() { return "MyPojo [arg=" + arg + "]"; } + } static class StringToMyPojoConverter implements Converter { @@ -221,5 +202,7 @@ static class StringToMyPojoConverter implements Converter { public MyPojo convert(String from) { return new MyPojo(from); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionNamingCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionNamingCommands.java index 3d22b49ea..602374288 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionNamingCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionNamingCommands.java @@ -30,12 +30,9 @@ public class OptionNamingCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "option-naming-1", group = GROUP) - public String testOptionNaming1Annotation( - @ShellOption("from_snake") String snake, - @ShellOption("fromCamel") String camel, - @ShellOption("from-kebab") String kebab, - @ShellOption("FromPascal") String pascal - ) { + public String testOptionNaming1Annotation(@ShellOption("from_snake") String snake, + @ShellOption("fromCamel") String camel, @ShellOption("from-kebab") String kebab, + @ShellOption("FromPascal") String pascal) { return String.format("snake='%s' camel='%s' kebab='%s' pascal='%s' ", snake, camel, kebab, pascal); } @@ -45,12 +42,9 @@ public String testOptionNaming1Annotation( public static class Annotation extends BaseE2ECommands { @Command(command = "option-naming-1") - public String testOptionNaming1Annotation( - @Option(longNames = "from_snake") String snake, - @Option(longNames = "fromCamel") String camel, - @Option(longNames = "from-kebab") String kebab, - @Option(longNames = "FromPascal") String pascal - ) { + public String testOptionNaming1Annotation(@Option(longNames = "from_snake") String snake, + @Option(longNames = "fromCamel") String camel, @Option(longNames = "from-kebab") String kebab, + @Option(longNames = "FromPascal") String pascal) { return String.format("snake='%s' camel='%s' kebab='%s' pascal='%s' ", snake, camel, kebab, pascal); } @@ -61,40 +55,41 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testOptionNaming1Registration() { - return getBuilder() - .command(REG, "option-naming-1") + return getBuilder().command(REG, "option-naming-1") .group(GROUP) .withOption() - .longNames("from_snake") - .required() - .and() + .longNames("from_snake") + .required() + .and() .withOption() - .longNames("fromCamel") - .required() - .and() + .longNames("fromCamel") + .required() + .and() .withOption() - .longNames("from-kebab") - .required() - .and() + .longNames("from-kebab") + .required() + .and() .withOption() - .longNames("FromPascal") - .required() - .and() + .longNames("FromPascal") + .required() + .and() .withOption() - .longNames("arg1") - .nameModifier(name -> "x" + name) - // .required() - .and() + .longNames("arg1") + .nameModifier(name -> "x" + name) + // .required() + .and() .withTarget() - .function(ctx -> { - String snake = ctx.getOptionValue("from_snake"); - String camel = ctx.getOptionValue("fromCamel"); - String kebab = ctx.getOptionValue("from-kebab"); - String pascal = ctx.getOptionValue("FromPascal"); - return String.format("snake='%s' camel='%s' kebab='%s' pascal='%s' ", snake, camel, kebab, pascal); - }) - .and() + .function(ctx -> { + String snake = ctx.getOptionValue("from_snake"); + String camel = ctx.getOptionValue("fromCamel"); + String kebab = ctx.getOptionValue("from-kebab"); + String pascal = ctx.getOptionValue("FromPascal"); + return String.format("snake='%s' camel='%s' kebab='%s' pascal='%s' ", snake, camel, kebab, pascal); + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionTypeCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionTypeCommands.java index fa5eecb79..1e16c80f8 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionTypeCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionTypeCommands.java @@ -39,157 +39,108 @@ public class OptionTypeCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "option-type-string", group = GROUP) - public String optionTypeStringAnnotation( - @ShellOption(help = "Desc arg1") String arg1 - ) { + public String optionTypeStringAnnotation(@ShellOption(help = "Desc arg1") String arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-type-boolean", group = GROUP) - public String optionTypeBooleanAnnotation( - @ShellOption() boolean arg1, - @ShellOption(defaultValue = "true") boolean arg2, - @ShellOption(defaultValue = "false") boolean arg3, - @ShellOption() Boolean arg4, - @ShellOption(defaultValue = "true") Boolean arg5, - @ShellOption(defaultValue = "false") Boolean arg6, - boolean arg7 - ) { + public String optionTypeBooleanAnnotation(@ShellOption() boolean arg1, + @ShellOption(defaultValue = "true") boolean arg2, @ShellOption(defaultValue = "false") boolean arg3, + @ShellOption() Boolean arg4, @ShellOption(defaultValue = "true") Boolean arg5, + @ShellOption(defaultValue = "false") Boolean arg6, boolean arg7) { return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s arg7=%s", arg1, arg2, arg3, arg4, arg5, arg6, arg7); } @ShellMethod(key = LEGACY_ANNO + "option-type-integer", group = GROUP) - public String optionTypeIntegerAnnotation( - @ShellOption int arg1, - @ShellOption Integer arg2 - ) { + public String optionTypeIntegerAnnotation(@ShellOption int arg1, @ShellOption Integer arg2) { return String.format("Hello '%s' '%s'", arg1, arg2); } @ShellMethod(key = LEGACY_ANNO + "option-type-enum", group = GROUP) - public String optionTypeEnumAnnotation( - @ShellOption(help = "Desc arg1") OptionTypeEnum arg1 - ) { + public String optionTypeEnumAnnotation(@ShellOption(help = "Desc arg1") OptionTypeEnum arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-type-string-array", group = GROUP) - public String optionTypeStringArrayAnnotation( - @ShellOption(help = "Desc arg1") String[] arg1 - ) { + public String optionTypeStringArrayAnnotation(@ShellOption(help = "Desc arg1") String[] arg1) { return "Hello " + stringOfStrings(arg1); } @ShellMethod(key = LEGACY_ANNO + "option-type-int-array", group = GROUP) - public String optionTypeIntArrayAnnotation( - @ShellOption(help = "Desc arg1") int[] arg1 - ) { + public String optionTypeIntArrayAnnotation(@ShellOption(help = "Desc arg1") int[] arg1) { return "Hello " + stringOfInts(arg1); } @ShellMethod(key = LEGACY_ANNO + "option-type-string-list", group = GROUP) - public String optionTypeStringListAnnotation( - @ShellOption(help = "Desc arg1") List arg1 - ) { + public String optionTypeStringListAnnotation(@ShellOption(help = "Desc arg1") List arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-type-string-set", group = GROUP) - public String optionTypeStringSetAnnotation( - @ShellOption(help = "Desc arg1") Set arg1 - ) { + public String optionTypeStringSetAnnotation(@ShellOption(help = "Desc arg1") Set arg1) { return "Hello " + arg1; } @ShellMethod(key = LEGACY_ANNO + "option-type-string-collection", group = GROUP) - public String optionTypeStringCollectionAnnotation( - @ShellOption(help = "Desc arg1") Collection arg1 - ) { + public String optionTypeStringCollectionAnnotation(@ShellOption(help = "Desc arg1") Collection arg1) { return "Hello " + arg1; } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) public static class Annotation extends BaseE2ECommands { @Command(command = "option-type-string") - public String optionTypeStringAnnotation( - @Option(longNames = "arg1") - String arg1 - ) { + public String optionTypeStringAnnotation(@Option(longNames = "arg1") String arg1) { return "Hello " + arg1; } @Command(command = "option-type-boolean") - public String optionTypeBooleanAnnotation( - @Option(longNames = "arg1") boolean arg1, - @Option(longNames = "arg2", defaultValue = "true") boolean arg2, - @Option(longNames = "arg3", defaultValue = "false") boolean arg3, - @Option(longNames = "arg4") Boolean arg4, - @Option(longNames = "arg5", defaultValue = "true") Boolean arg5, - @Option(longNames = "arg6", defaultValue = "false") Boolean arg6, - boolean arg7 - ) { + public String optionTypeBooleanAnnotation(@Option(longNames = "arg1") boolean arg1, + @Option(longNames = "arg2", defaultValue = "true") boolean arg2, + @Option(longNames = "arg3", defaultValue = "false") boolean arg3, + @Option(longNames = "arg4") Boolean arg4, + @Option(longNames = "arg5", defaultValue = "true") Boolean arg5, + @Option(longNames = "arg6", defaultValue = "false") Boolean arg6, boolean arg7) { return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s arg7=%s", arg1, arg2, arg3, arg4, arg5, arg6, arg7); } @Command(command = "option-type-integer") - public String optionTypeIntegerAnnotation( - @Option(longNames = "arg1") - int arg1, - @Option(longNames = "arg2") - Integer arg2 - ) { + public String optionTypeIntegerAnnotation(@Option(longNames = "arg1") int arg1, + @Option(longNames = "arg2") Integer arg2) { return String.format("Hello '%s' '%s'", arg1, arg2); } @Command(command = "option-type-enum") - public String optionTypeEnumAnnotation( - @Option(longNames = "arg1") - OptionTypeEnum arg1 - ) { + public String optionTypeEnumAnnotation(@Option(longNames = "arg1") OptionTypeEnum arg1) { return "Hello " + arg1; } @Command(command = "option-type-string-array") - public String optionTypeStringArrayAnnotation( - @Option(longNames = "arg1") - String[] arg1 - ) { + public String optionTypeStringArrayAnnotation(@Option(longNames = "arg1") String[] arg1) { return "Hello " + stringOfStrings(arg1); } @Command(command = "option-type-int-array") - public String optionTypeIntArrayAnnotation( - @Option(longNames = "arg1") - int[] arg1 - ) { + public String optionTypeIntArrayAnnotation(@Option(longNames = "arg1") int[] arg1) { return "Hello " + stringOfInts(arg1); } @Command(command = "option-type-string-list") - public String optionTypeStringListAnnotation( - @Option(longNames = "arg1") - List arg1 - ) { + public String optionTypeStringListAnnotation(@Option(longNames = "arg1") List arg1) { return "Hello " + arg1; } @Command(command = "option-type-string-set") - public String optionTypeStringSetAnnotation( - @Option(longNames = "arg1") - Set arg1 - ) { + public String optionTypeStringSetAnnotation(@Option(longNames = "arg1") Set arg1) { return "Hello " + arg1; } @Command(command = "option-type-string-collection") - public String optionTypeStringCollectionAnnotation( - @Option(longNames = "arg1") - Collection arg1 - ) { + public String optionTypeStringCollectionAnnotation(@Option(longNames = "arg1") Collection arg1) { return "Hello " + arg1; } @@ -200,235 +151,229 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration optionTypeStringRegistration() { - return getBuilder() - .command(REG, "option-type-string") + return getBuilder().command(REG, "option-type-string") .group(GROUP) .withOption() - .longNames("arg1") - .type(String.class) - .position(0) - .required() - .and() + .longNames("arg1") + .type(String.class) + .position(0) + .required() + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration optionTypeBooleanRegistration() { - return getBuilder() - .command(REG, "option-type-boolean") + return getBuilder().command(REG, "option-type-boolean") .group(GROUP) .withOption() - .longNames("arg1") - .type(boolean.class) - .and() + .longNames("arg1") + .type(boolean.class) + .and() .withOption() - .longNames("arg2") - .type(boolean.class) - .defaultValue("true") - .and() + .longNames("arg2") + .type(boolean.class) + .defaultValue("true") + .and() .withOption() - .longNames("arg3") - .type(boolean.class) - .defaultValue("false") - .and() + .longNames("arg3") + .type(boolean.class) + .defaultValue("false") + .and() .withOption() - .longNames("arg4") - .type(Boolean.class) - .and() + .longNames("arg4") + .type(Boolean.class) + .and() .withOption() - .longNames("arg5") - .type(Boolean.class) - .defaultValue("true") - .and() + .longNames("arg5") + .type(Boolean.class) + .defaultValue("true") + .and() .withOption() - .longNames("arg6") - .type(Boolean.class) - .defaultValue("false") - .and() + .longNames("arg6") + .type(Boolean.class) + .defaultValue("false") + .and() .withOption() - .longNames("arg7") - .type(boolean.class) - .and() + .longNames("arg7") + .type(boolean.class) + .and() .withTarget() - .function(ctx -> { - boolean arg1 = ctx.hasMappedOption("arg1") ? ctx.getOptionValue("arg1") : false; - boolean arg2 = ctx.getOptionValue("arg2"); - boolean arg3 = ctx.getOptionValue("arg3"); - Boolean arg4 = ctx.getOptionValue("arg4"); - Boolean arg5 = ctx.getOptionValue("arg5"); - Boolean arg6 = ctx.getOptionValue("arg6"); - boolean arg7 = ctx.hasMappedOption("arg7") ? ctx.getOptionValue("arg7") : false; - return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s arg7=%s", arg1, - arg2, arg3, arg4, arg5, arg6, arg7); - }) - .and() + .function(ctx -> { + boolean arg1 = ctx.hasMappedOption("arg1") ? ctx.getOptionValue("arg1") : false; + boolean arg2 = ctx.getOptionValue("arg2"); + boolean arg3 = ctx.getOptionValue("arg3"); + Boolean arg4 = ctx.getOptionValue("arg4"); + Boolean arg5 = ctx.getOptionValue("arg5"); + Boolean arg6 = ctx.getOptionValue("arg6"); + boolean arg7 = ctx.hasMappedOption("arg7") ? ctx.getOptionValue("arg7") : false; + return String.format("Hello arg1=%s arg2=%s arg3=%s arg4=%s arg5=%s arg6=%s arg7=%s", arg1, arg2, + arg3, arg4, arg5, arg6, arg7); + }) + .and() .build(); } @Bean public CommandRegistration optionTypeIntegerRegistration() { - return getBuilder() - .command(REG, "option-type-integer") + return getBuilder().command(REG, "option-type-integer") .group(GROUP) .withOption() - .longNames("arg1") - .type(int.class) - .required() - .and() + .longNames("arg1") + .type(int.class) + .required() + .and() .withOption() - .longNames("arg2") - .type(Integer.class) - .required() - .and() + .longNames("arg2") + .type(Integer.class) + .required() + .and() .withTarget() - .function(ctx -> { - int arg1 = ctx.getOptionValue("arg1"); - Integer arg2 = ctx.getOptionValue("arg2"); - return String.format("Hello '%s' '%s'", arg1, arg2); - }) - .and() + .function(ctx -> { + int arg1 = ctx.getOptionValue("arg1"); + Integer arg2 = ctx.getOptionValue("arg2"); + return String.format("Hello '%s' '%s'", arg1, arg2); + }) + .and() .build(); } @Bean public CommandRegistration optionTypeEnumRegistration() { - return getBuilder() - .command(REG, "option-type-enum") + return getBuilder().command(REG, "option-type-enum") .group(GROUP) .withOption() - .longNames("arg1") - .type(OptionTypeEnum.class) - .required() - .and() + .longNames("arg1") + .type(OptionTypeEnum.class) + .required() + .and() .withTarget() - .function(ctx -> { - OptionTypeEnum arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + OptionTypeEnum arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration optionTypeStringArrayRegistration() { - return getBuilder() - .command(REG, "option-type-string-array") + return getBuilder().command(REG, "option-type-string-array") .group(GROUP) .withOption() - .longNames("arg1") - .type(String[].class) - .required() - .and() + .longNames("arg1") + .type(String[].class) + .required() + .and() .withTarget() - .function(ctx -> { - String[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + stringOfStrings(arg1); - }) - .and() + .function(ctx -> { + String[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + stringOfStrings(arg1); + }) + .and() .build(); } @Bean public CommandRegistration optionTypeIntArrayRegistration() { - return getBuilder() - .command(REG, "option-type-int-array") + return getBuilder().command(REG, "option-type-int-array") .group(GROUP) .withOption() - .longNames("arg1") - .type(int[].class) - .required() - .and() + .longNames("arg1") + .type(int[].class) + .required() + .and() .withTarget() - .function(ctx -> { - int[] arg1 = ctx.getOptionValue("arg1"); - return "Hello " + stringOfInts(arg1); - }) - .and() + .function(ctx -> { + int[] arg1 = ctx.getOptionValue("arg1"); + return "Hello " + stringOfInts(arg1); + }) + .and() .build(); } @Bean public CommandRegistration optionTypeStringListRegistration() { - return getBuilder() - .command(REG, "option-type-string-list") + return getBuilder().command(REG, "option-type-string-list") .group(GROUP) .withOption() - .longNames("arg1") - .type(List.class) - .required() - .and() + .longNames("arg1") + .type(List.class) + .required() + .and() .withTarget() - .function(ctx -> { - List arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + List arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration optionTypeStringSetRegistration() { - return getBuilder() - .command(REG, "option-type-string-set") + return getBuilder().command(REG, "option-type-string-set") .group(GROUP) .withOption() - .longNames("arg1") - .type(Set.class) - .required() - .and() + .longNames("arg1") + .type(Set.class) + .required() + .and() .withTarget() - .function(ctx -> { - Set arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + Set arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration optionTypeStringCollectionRegistration() { - return getBuilder() - .command(REG, "option-type-string-collection") + return getBuilder().command(REG, "option-type-string-collection") .group(GROUP) .withOption() - .longNames("arg1") - .type(Collection.class) - .required() - .and() + .longNames("arg1") + .type(Collection.class) + .required() + .and() .withTarget() - .function(ctx -> { - Collection arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + Collection arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } @Bean public CommandRegistration optionTypeVoidRegistration() { - return getBuilder() - .command(REG, "option-type-void") + return getBuilder().command(REG, "option-type-void") .group(GROUP) .withOption() - .longNames("arg1") - .type(void.class) - .and() + .longNames("arg1") + .type(void.class) + .and() .withTarget() - .function(ctx -> { - return "Hello "; - }) - .and() + .function(ctx -> { + return "Hello "; + }) + .and() .build(); } + } public static enum OptionTypeEnum { - ONE,TWO,THREE + + ONE, TWO, THREE + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionalValueCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionalValueCommands.java index ff81f011f..8b9dbb581 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionalValueCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/OptionalValueCommands.java @@ -35,23 +35,20 @@ public class OptionalValueCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "optional-value", group = GROUP) - public String testOptionalValue( - @ShellOption(defaultValue = ShellOption.NULL) String arg1 - ) { + public String testOptionalValue(@ShellOption(defaultValue = ShellOption.NULL) String arg1) { return "Hello " + arg1; } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) public static class Annotation extends BaseE2ECommands { @Command(command = "optional-value") - public String testOptionalValueAnnotation( - @Option(longNames = "arg1") - String arg1 - ) { - return "Hello " + arg1; + public String testOptionalValueAnnotation(@Option(longNames = "arg1") String arg1) { + return "Hello " + arg1; } + } @Component @@ -59,19 +56,20 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testOptionalValueRegistration() { - return getBuilder() - .command(REG, "optional-value") + return getBuilder().command(REG, "optional-value") .group(GROUP) .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/PositionalArgumentsCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/PositionalArgumentsCommands.java index b94fe8c9e..59b338097 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/PositionalArgumentsCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/PositionalArgumentsCommands.java @@ -28,44 +28,39 @@ public class PositionalArgumentsCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "positional-args-1", group = GROUP) - public String testPositionalArgs1( - @ShellOption(arity = 1, defaultValue = ShellOption.NULL) String arg1, + public String testPositionalArgs1(@ShellOption(arity = 1, defaultValue = ShellOption.NULL) String arg1, @ShellOption(arity = 1, defaultValue = ShellOption.NULL) String arg2, - @ShellOption(arity = 1, defaultValue = ShellOption.NULL) String arg3 - ) { - return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); + @ShellOption(arity = 1, defaultValue = ShellOption.NULL) String arg3) { + return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); } @ShellMethod(key = LEGACY_ANNO + "positional-args-2", group = GROUP) - public String testPositionalArgs2( - @ShellOption(arity = 1, defaultValue = "defaultArg1") String arg1, + public String testPositionalArgs2(@ShellOption(arity = 1, defaultValue = "defaultArg1") String arg1, @ShellOption(arity = 1, defaultValue = "defaultArg2") String arg2, - @ShellOption(arity = 1, defaultValue = ShellOption.NULL) String arg3 - ) { - return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); + @ShellOption(arity = 1, defaultValue = ShellOption.NULL) String arg3) { + return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) public static class Annotation extends BaseE2ECommands { @Command(command = "positional-args-1") - public String testPositionalArgs1( - @Option(arity = OptionArity.EXACTLY_ONE) String arg1, + public String testPositionalArgs1(@Option(arity = OptionArity.EXACTLY_ONE) String arg1, @Option(arity = OptionArity.EXACTLY_ONE) String arg2, - @Option(arity = OptionArity.EXACTLY_ONE) String arg3 - ) { - return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); + @Option(arity = OptionArity.EXACTLY_ONE) String arg3) { + return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); } @Command(command = "positional-args-2") public String testPositionalArgs2( @Option(arity = OptionArity.EXACTLY_ONE, defaultValue = "defaultArg1") String arg1, @Option(arity = OptionArity.EXACTLY_ONE, defaultValue = "defaultArg2") String arg2, - @Option(arity = OptionArity.EXACTLY_ONE) String arg3 - ) { - return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); + @Option(arity = OptionArity.EXACTLY_ONE) String arg3) { + return String.format("Hi arg1='%s' arg2='%s' arg3='%s'", arg1, arg2, arg3); } + } } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/RequiredValueCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/RequiredValueCommands.java index 53f794749..1929a8325 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/RequiredValueCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/RequiredValueCommands.java @@ -35,11 +35,10 @@ public class RequiredValueCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "required-value", group = GROUP) - public String testRequiredValueAnnotation( - @ShellOption(help = "Desc arg1") String arg1 - ) { + public String testRequiredValueAnnotation(@ShellOption(help = "Desc arg1") String arg1) { return "Hello " + arg1; } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) @@ -47,11 +46,10 @@ public static class Annotation extends BaseE2ECommands { @Command(command = "required-value") public String testRequiredValueAnnotation( - @Option(longNames = "arg1", required = true, description = "Desc arg1") - String arg1 - ) { - return "Hello " + arg1; + @Option(longNames = "arg1", required = true, description = "Desc arg1") String arg1) { + return "Hello " + arg1; } + } @Component @@ -59,21 +57,22 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testRequiredValueRegistration() { - return getBuilder() - .command(REG, "required-value") + return getBuilder().command(REG, "required-value") .group(GROUP) .withOption() - .longNames("arg1") - .description("Desc arg1") - .required() - .and() + .longNames("arg1") + .description("Desc arg1") + .required() + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ShortOptionTypeCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ShortOptionTypeCommands.java index 17b869463..3fe15a621 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ShortOptionTypeCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ShortOptionTypeCommands.java @@ -30,26 +30,21 @@ public class ShortOptionTypeCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "short-option-type-string", group = GROUP) - public String shortOptionTypeStringLegacyAnnotation( - @ShellOption(value = { "--arg", "-a" }) String arg) { + public String shortOptionTypeStringLegacyAnnotation(@ShellOption(value = { "--arg", "-a" }) String arg) { return String.format("Hi '%s'", arg); } @ShellMethod(key = LEGACY_ANNO + "short-option-type-single-boolean", group = GROUP) - public String shortOptionTypeSingleBooleanLegacyAnnotation( - @ShellOption(value = "-a") boolean a) - { + public String shortOptionTypeSingleBooleanLegacyAnnotation(@ShellOption(value = "-a") boolean a) { return String.format("Hi '%s'", a); } @ShellMethod(key = LEGACY_ANNO + "short-option-type-multi-boolean", group = GROUP) - public String shortOptionTypeMultiBooleanLegacyAnnotation( - @ShellOption(value = "-a") boolean a, - @ShellOption(value = "-b") boolean b, - @ShellOption(value = "-c") boolean c) - { + public String shortOptionTypeMultiBooleanLegacyAnnotation(@ShellOption(value = "-a") boolean a, + @ShellOption(value = "-b") boolean b, @ShellOption(value = "-c") boolean c) { return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) @@ -62,18 +57,16 @@ public String shortOptionTypeStringAnnotation( } @Command(command = "short-option-type-single-boolean") - public String shortOptionTypeSingleBooleanAnnotation( - @Option(shortNames = 'a') boolean a) { + public String shortOptionTypeSingleBooleanAnnotation(@Option(shortNames = 'a') boolean a) { return String.format("Hi '%s'", a); } @Command(command = "short-option-type-multi-boolean") - public String shortOptionTypeMultiBooleanAnnotation( - @Option(shortNames = 'a') boolean a, - @Option(shortNames = 'b') boolean b, - @Option(shortNames = 'c') boolean c) { + public String shortOptionTypeMultiBooleanAnnotation(@Option(shortNames = 'a') boolean a, + @Option(shortNames = 'b') boolean b, @Option(shortNames = 'c') boolean c) { return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); } + } @Component @@ -81,71 +74,60 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration shortOptionTypeStringRegistration() { - return getBuilder() - .command(REG, "short-option-type-string") - .group(GROUP) - .withTarget() - .function(ctx -> { - String arg = ctx.hasMappedOption("arg") ? ctx.getOptionValue("arg") : null; - return String.format("Hi arg='%s'", arg); - }) - .and() - .withOption() - .longNames("arg") - .shortNames('a') - .required() - .and() - .build(); + return getBuilder().command(REG, "short-option-type-string").group(GROUP).withTarget().function(ctx -> { + String arg = ctx.hasMappedOption("arg") ? ctx.getOptionValue("arg") : null; + return String.format("Hi arg='%s'", arg); + }).and().withOption().longNames("arg").shortNames('a').required().and().build(); } @Bean public CommandRegistration shortOptionTypeSingleBooleanRegistration() { - return getBuilder() - .command(REG, "short-option-type-single-boolean") + return getBuilder().command(REG, "short-option-type-single-boolean") .group(GROUP) .withTarget() - .function(ctx -> { - Boolean a = ctx.hasMappedOption("a") ? ctx.getOptionValue("a") : null; - return String.format("Hi a='%s'", a); - }) - .and() + .function(ctx -> { + Boolean a = ctx.hasMappedOption("a") ? ctx.getOptionValue("a") : null; + return String.format("Hi a='%s'", a); + }) + .and() .withOption() - .shortNames('a') - .type(boolean.class) - .defaultValue("false") - .and() + .shortNames('a') + .type(boolean.class) + .defaultValue("false") + .and() .build(); } @Bean public CommandRegistration shortOptionTypeMultiBooleanRegistration() { - return getBuilder() - .command(REG, "short-option-type-multi-boolean") + return getBuilder().command(REG, "short-option-type-multi-boolean") .group(GROUP) .withTarget() - .function(ctx -> { - Boolean a = ctx.hasMappedOption("a") ? ctx.getOptionValue("a") : null; - Boolean b = ctx.hasMappedOption("b") ? ctx.getOptionValue("b") : null; - Boolean c = ctx.hasMappedOption("c") ? ctx.getOptionValue("c") : null; - return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); - }) - .and() + .function(ctx -> { + Boolean a = ctx.hasMappedOption("a") ? ctx.getOptionValue("a") : null; + Boolean b = ctx.hasMappedOption("b") ? ctx.getOptionValue("b") : null; + Boolean c = ctx.hasMappedOption("c") ? ctx.getOptionValue("c") : null; + return String.format("Hi a='%s' b='%s' c='%s'", a, b, c); + }) + .and() .withOption() - .shortNames('a') - .type(boolean.class) - .defaultValue("false") - .and() + .shortNames('a') + .type(boolean.class) + .defaultValue("false") + .and() .withOption() - .shortNames('b') - .type(boolean.class) - .defaultValue("false") - .and() + .shortNames('b') + .type(boolean.class) + .defaultValue("false") + .and() .withOption() - .shortNames('c') - .type(boolean.class) - .defaultValue("false") - .and() + .shortNames('c') + .type(boolean.class) + .defaultValue("false") + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/StdOutTypeCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/StdOutTypeCommands.java index 9275260c4..6680a9f4b 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/StdOutTypeCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/StdOutTypeCommands.java @@ -33,12 +33,11 @@ public static class Annotation extends BaseE2ECommands { Terminal terminal; @Command(command = "stdout") - public String testStdoutAnnotation( - CommandContext commandContext - ) { + public String testStdoutAnnotation(CommandContext commandContext) { boolean hasPty = commandContext.getShellContext().hasPty(); return String.format("hasPty='%s'", hasPty); } + } @Component @@ -46,17 +45,12 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testStdoutRegistration() { - return getBuilder() - .command(REG, "stdout") - .group(GROUP) - .withTarget() - .function(ctx -> { - boolean hasPty = ctx.getShellContext().hasPty(); - return String.format("hasPty='%s'", hasPty); - }) - .and() - .build(); + return getBuilder().command(REG, "stdout").group(GROUP).withTarget().function(ctx -> { + boolean hasPty = ctx.getShellContext().hasPty(); + return String.format("hasPty='%s'", hasPty); + }).and().build(); } + } } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/UnrecognisedOptionCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/UnrecognisedOptionCommands.java index b99155712..b84afbece 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/UnrecognisedOptionCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/UnrecognisedOptionCommands.java @@ -28,17 +28,15 @@ public class UnrecognisedOptionCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "unrecognised-option-noother", group = GROUP) - public String testUnrecognisedOptionNoOtherAnnotation( - ) { + public String testUnrecognisedOptionNoOtherAnnotation() { return "Hi"; } @ShellMethod(key = LEGACY_ANNO + "unrecognised-option-withrequired", group = GROUP) - public String testUnrecognisedOptionWithRequiredAnnotation( - @ShellOption(help = "Desc arg1") String arg1 - ) { + public String testUnrecognisedOptionWithRequiredAnnotation(@ShellOption(help = "Desc arg1") String arg1) { return "Hello " + arg1; } + } @Component @@ -46,34 +44,29 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testUnrecognisedOptionNoOtherRegistration() { - return getBuilder() - .command(REG, "unrecognised-option-noother") - .group(GROUP) - .withTarget() - .function(ctx -> { - return "Hi"; - }) - .and() - .build(); + return getBuilder().command(REG, "unrecognised-option-noother").group(GROUP).withTarget().function(ctx -> { + return "Hi"; + }).and().build(); } @Bean public CommandRegistration testUnrecognisedOptionWithRequiredRegistration() { - return getBuilder() - .command(REG, "unrecognised-option-withrequired") + return getBuilder().command(REG, "unrecognised-option-withrequired") .group(GROUP) .withOption() - .longNames("arg1") - .description("Desc arg1") - .required() - .and() + .longNames("arg1") + .description("Desc arg1") + .required() + .and() .withTarget() - .function(ctx -> { - String arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + String arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ValidatedValueCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ValidatedValueCommands.java index 81118b031..cdff8a060 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ValidatedValueCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/ValidatedValueCommands.java @@ -35,12 +35,11 @@ public class ValidatedValueCommands { public static class LegacyAnnotation extends BaseE2ECommands { @ShellMethod(key = LEGACY_ANNO + "validated-value", group = GROUP) - public String testValidatedValueAnnotation( - @ShellOption @Min(value = 1) Integer arg1, - @ShellOption @Min(value = 1) Integer arg2 - ) { + public String testValidatedValueAnnotation(@ShellOption @Min(value = 1) Integer arg1, + @ShellOption @Min(value = 1) Integer arg2) { return "Hello " + arg1; } + } @Component @@ -48,26 +47,27 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration testValidatedValueRegistration() { - return getBuilder() - .command(REG, "validated-value") + return getBuilder().command(REG, "validated-value") .group(GROUP) .withOption() - .longNames("arg1") - .type(Integer.class) - .required() - .and() + .longNames("arg1") + .type(Integer.class) + .required() + .and() .withOption() - .longNames("arg2") - .type(Integer.class) - .required() - .and() + .longNames("arg2") + .type(Integer.class) + .required() + .and() .withTarget() - .function(ctx -> { - Integer arg1 = ctx.getOptionValue("arg1"); - return "Hello " + arg1; - }) - .and() + .function(ctx -> { + Integer arg1 = ctx.getOptionValue("arg1"); + return "Hello " + arg1; + }) + .and() .build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/WriteCommands.java b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/WriteCommands.java index 93ab4eb0b..761219f71 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/WriteCommands.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/main/java/org/springframework/shell/samples/e2e/WriteCommands.java @@ -44,6 +44,7 @@ public void writeTerminalWriterAnnotation() { public void writeSystemOutAnnotation() { System.out.println("hi"); } + } @Command(command = BaseE2ECommands.ANNO, group = BaseE2ECommands.GROUP) @@ -59,6 +60,7 @@ public void writeTerminalWriter(CommandContext ctx) { public void writeSystemOut() { System.out.println("hi"); } + } @Component @@ -66,29 +68,19 @@ public static class Registration extends BaseE2ECommands { @Bean public CommandRegistration writeTerminalWriterRegistration() { - return getBuilder() - .command(REG, "write-terminalwriter") - .group(GROUP) - .withTarget() - .consumer(ctx -> { - ctx.getTerminal().writer().println("hi"); - ctx.getTerminal().writer().flush(); - }) - .and() - .build(); + return getBuilder().command(REG, "write-terminalwriter").group(GROUP).withTarget().consumer(ctx -> { + ctx.getTerminal().writer().println("hi"); + ctx.getTerminal().writer().flush(); + }).and().build(); } @Bean public CommandRegistration writeSystemOutRegistration() { - return getBuilder() - .command(REG, "write-terminalwriter") - .group(GROUP) - .withTarget() - .consumer(ctx -> { - System.out.println("hi"); - }) - .and() - .build(); + return getBuilder().command(REG, "write-terminalwriter").group(GROUP).withTarget().consumer(ctx -> { + System.out.println("hi"); + }).and().build(); } + } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java index f8ff05491..50e94a98b 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/AbstractSampleTests.java @@ -69,4 +69,5 @@ protected BaseShellSession createSession(String command, boolean interactive) return session; } } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/AliasCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/AliasCommandsTests.java index 4698b2788..22e5109c8 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/AliasCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/AliasCommandsTests.java @@ -41,4 +41,5 @@ void aliasCommandWorks(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "Hello from alias command"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ArityCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ArityCommandsTests.java index ee207a39b..a1b849b82 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ArityCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ArityCommandsTests.java @@ -56,4 +56,5 @@ void arityFloatArray(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "Hello [1.0,2.0]"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/DefaultValueCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/DefaultValueCommandsTests.java index 87f493824..119c16fd8 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/DefaultValueCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/DefaultValueCommandsTests.java @@ -56,4 +56,5 @@ void defaultValueBoolean3(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "Hello false"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2EArgumentsProvider.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2EArgumentsProvider.java index 7bc1453bf..9c22c00fb 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2EArgumentsProvider.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2EArgumentsProvider.java @@ -54,4 +54,5 @@ public Stream provideArguments(ExtensionContext context) th } return arguments.stream(); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2ESource.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2ESource.java index 5c43ca5b2..fcb99763d 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2ESource.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/E2ESource.java @@ -41,4 +41,5 @@ boolean annox() default true; boolean reg() default true; + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ErrorHandlingCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ErrorHandlingCommandsTests.java index a9900c35e..accc5e3b6 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ErrorHandlingCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/ErrorHandlingCommandsTests.java @@ -39,7 +39,8 @@ void testErrorHandling1(String command, boolean interactive) { @E2ESource(command = "error-handling --arg1 throw2", annox = false) void testErrorHandling2(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); - assertScreenContainsText(session, "org.springframework.shell.samples.e2e.ErrorHandlingCommands$CustomException2"); + assertScreenContainsText(session, + "org.springframework.shell.samples.e2e.ErrorHandlingCommands$CustomException2"); } @Disabled("trouble with spring-shell-test") @@ -68,6 +69,8 @@ void testErrorHandling5(String command, boolean interactive) { @E2ESource(command = "error-handling --arg1 throw6", annox = false) void testErrorHandling6(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); - assertScreenContainsText(session, "Hi, handled custom exception org.springframework.shell.samples.e2e.ErrorHandlingCommands$CustomException4"); + assertScreenContainsText(session, + "Hi, handled custom exception org.springframework.shell.samples.e2e.ErrorHandlingCommands$CustomException4"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HelpOptionCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HelpOptionCommandsTests.java index 8542cc429..360cde11e 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HelpOptionCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HelpOptionCommandsTests.java @@ -46,4 +46,5 @@ void testHelpOptionExists2(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "NAME"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HiddenCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HiddenCommandsTests.java index ed6e3050e..d03c0aa74 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HiddenCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/HiddenCommandsTests.java @@ -41,4 +41,5 @@ void hiddenNotVisibleInHelp(String command, boolean interactive) { BaseShellSession session = createSession("help", interactive); assertScreenNotContainsText(session, "help", "hidden-1"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionConversionCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionConversionCommandsTests.java index 2fcdd828e..dcbf320bc 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionConversionCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionConversionCommandsTests.java @@ -57,4 +57,5 @@ void optionConversionCustomArray(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "Hello [MyPojo [arg=hi]]"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionTypeCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionTypeCommandsTests.java index e27b8c3d7..4f3564334 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionTypeCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionTypeCommandsTests.java @@ -105,4 +105,5 @@ void optionTypeStringCollection(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "Hello [one, two]"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionalValueCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionalValueCommandsTests.java index 0d2f695da..c8a4143bf 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionalValueCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/OptionalValueCommandsTests.java @@ -35,4 +35,5 @@ void optionalValueResolvesToNull(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "Hello null"); } + } diff --git a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/RequiredValueCommandsTests.java b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/RequiredValueCommandsTests.java index dd2ad721d..be27e0e73 100644 --- a/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/RequiredValueCommandsTests.java +++ b/spring-shell-samples/spring-shell-sample-e2e/src/test/java/org/springframework/shell/samples/e2e/RequiredValueCommandsTests.java @@ -35,4 +35,5 @@ void shouldRequireOption(String command, boolean interactive) { BaseShellSession session = createSession(command, interactive); assertScreenContainsText(session, "Missing mandatory option"); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/AbstractShellComponent.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/AbstractShellComponent.java index f19513289..00ab6da76 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/AbstractShellComponent.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/AbstractShellComponent.java @@ -40,78 +40,79 @@ */ public abstract class AbstractShellComponent implements ApplicationContextAware, InitializingBean, ResourceLoaderAware { - private ApplicationContext applicationContext; + private ApplicationContext applicationContext; - private ResourceLoader resourceLoader; + private ResourceLoader resourceLoader; - private ObjectProvider shellProvider; + private ObjectProvider shellProvider; - private ObjectProvider terminalProvider; + private ObjectProvider terminalProvider; - private ObjectProvider commandCatalogProvider; + private ObjectProvider commandCatalogProvider; - private ObjectProvider completionResolverProvider; + private ObjectProvider completionResolverProvider; - private ObjectProvider templateExecutorProvider; + private ObjectProvider templateExecutorProvider; - private ObjectProvider themeResolverProvider; + private ObjectProvider themeResolverProvider; - private ObjectProvider viewComponentBuilderProvider; + private ObjectProvider viewComponentBuilderProvider; - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } - @Override - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } + @Override + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } - @Override - public void afterPropertiesSet() throws Exception { - shellProvider = applicationContext.getBeanProvider(Shell.class); - terminalProvider = applicationContext.getBeanProvider(Terminal.class); - commandCatalogProvider = applicationContext.getBeanProvider(CommandCatalog.class); - completionResolverProvider = applicationContext.getBeanProvider(CompletionResolver.class); - templateExecutorProvider = applicationContext.getBeanProvider(TemplateExecutor.class); - themeResolverProvider = applicationContext.getBeanProvider(ThemeResolver.class); - viewComponentBuilderProvider = applicationContext.getBeanProvider(ViewComponentBuilder.class); - } + @Override + public void afterPropertiesSet() throws Exception { + shellProvider = applicationContext.getBeanProvider(Shell.class); + terminalProvider = applicationContext.getBeanProvider(Terminal.class); + commandCatalogProvider = applicationContext.getBeanProvider(CommandCatalog.class); + completionResolverProvider = applicationContext.getBeanProvider(CompletionResolver.class); + templateExecutorProvider = applicationContext.getBeanProvider(TemplateExecutor.class); + themeResolverProvider = applicationContext.getBeanProvider(ThemeResolver.class); + viewComponentBuilderProvider = applicationContext.getBeanProvider(ViewComponentBuilder.class); + } - protected ApplicationContext getApplicationContext() { - return applicationContext; - } + protected ApplicationContext getApplicationContext() { + return applicationContext; + } - protected ResourceLoader getResourceLoader() { - return resourceLoader; - } + protected ResourceLoader getResourceLoader() { + return resourceLoader; + } - protected Shell getShell() { - return shellProvider.getObject(); - } + protected Shell getShell() { + return shellProvider.getObject(); + } - protected Terminal getTerminal() { - return terminalProvider.getObject(); - } + protected Terminal getTerminal() { + return terminalProvider.getObject(); + } - protected CommandCatalog getCommandCatalog() { - return commandCatalogProvider.getObject(); - } + protected CommandCatalog getCommandCatalog() { + return commandCatalogProvider.getObject(); + } - protected Stream getCompletionResolver() { - return completionResolverProvider.orderedStream(); - } + protected Stream getCompletionResolver() { + return completionResolverProvider.orderedStream(); + } - protected TemplateExecutor getTemplateExecutor() { - return templateExecutorProvider.getObject(); - } + protected TemplateExecutor getTemplateExecutor() { + return templateExecutorProvider.getObject(); + } - protected ThemeResolver getThemeResolver() { - return themeResolverProvider.getObject(); - } + protected ThemeResolver getThemeResolver() { + return themeResolverProvider.getObject(); + } + + protected ViewComponentBuilder getViewComponentBuilder() { + return viewComponentBuilderProvider.getObject(); + } - protected ViewComponentBuilder getViewComponentBuilder() { - return viewComponentBuilderProvider.getObject(); - } } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/CommandValueProvider.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/CommandValueProvider.java index 2c4827157..c33af4b06 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/CommandValueProvider.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/CommandValueProvider.java @@ -39,8 +39,11 @@ public CommandValueProvider(CommandCatalog commandRegistry) { @Override public List complete(CompletionContext completionContext) { - return commandRegistry.getRegistrations().keySet().stream() + return commandRegistry.getRegistrations() + .keySet() + .stream() .map(CompletionProposal::new) .collect(Collectors.toList()); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/EnumValueProvider.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/EnumValueProvider.java index 4510c5277..c7687b6d4 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/EnumValueProvider.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/EnumValueProvider.java @@ -25,7 +25,9 @@ import org.springframework.shell.command.CommandOption; /** - * A {@link ValueProvider} that knows how to complete values for {@link Enum} typed parameters. + * A {@link ValueProvider} that knows how to complete values for {@link Enum} typed + * parameters. + * * @author Eric Bottard */ public class EnumValueProvider implements ValueProvider { @@ -57,4 +59,5 @@ public List complete(CompletionContext completionContext) { } return result; } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/FileValueProvider.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/FileValueProvider.java index 3777da7b3..2f613396d 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/FileValueProvider.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/FileValueProvider.java @@ -31,8 +31,8 @@ import static java.nio.file.FileVisitOption.FOLLOW_LINKS; /** - * A {@link ValueProvider} that can populate names of local {@link File}s, either absolute or relative to the - * current working directory. + * A {@link ValueProvider} that can populate names of local {@link File}s, either absolute + * or relative to the current working directory. * * @author Eric Bottard * @author Janne Valkealahti @@ -49,15 +49,17 @@ public List complete(CompletionContext completionContext) { try { return Files .find(dir, 1, (p, a) -> p.getFileName() != null && p.getFileName().toString().startsWith(prefix), - FOLLOW_LINKS) + FOLLOW_LINKS) .map(p -> { boolean directory = Files.isDirectory(p); String value = p.toString() + (directory ? File.separatorChar : ""); return new CompletionProposal(value).complete(!directory); }) .collect(Collectors.toList()); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellCommandGroup.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellCommandGroup.java index 8b1e77461..90b8bbb0b 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellCommandGroup.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellCommandGroup.java @@ -23,27 +23,29 @@ import java.lang.annotation.Target; /** - * Used to indicate the default group of shell commands, either at the package or class level. + * Used to indicate the default group of shell commands, either at the package or class + * level. * * @author Eric Bottard */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.PACKAGE, ElementType.TYPE}) +@Target({ ElementType.PACKAGE, ElementType.TYPE }) @Documented public @interface ShellCommandGroup { /** - * The default value for the group label, which when set
      - *
    • on a class, will mean to look at the package level
    • - *
    • on a package, to go back at the class level and infer a name from the class name.
    • + * The default value for the group label, which when set + *
        + *
      • on a class, will mean to look at the package level
      • + *
      • on a package, to go back at the class level and infer a name from the class + * name.
      • *
      */ String INHERIT_AND_INFER = ""; /** - * @return - * An explicit value for the group, which will apply to all commands in the owning class or package, depending - * on where this annotation is set. + * @return An explicit value for the group, which will apply to all commands in the + * owning class or package, depending on where this annotation is set. */ String value() default INHERIT_AND_INFER; diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellComponent.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellComponent.java index 06f5b41b7..a79b1c4cf 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellComponent.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellComponent.java @@ -27,11 +27,12 @@ import org.springframework.stereotype.Component; /** - * Indicates that an annotated class may contain shell methods (themselves annotated with {@link ShellMethod}) that - * is, - * methods that may be invoked reflectively by the shell. + * Indicates that an annotated class may contain shell methods (themselves annotated with + * {@link ShellMethod}) that is, methods that may be invoked reflectively by the shell. * - *

      This annotation is a specialization of {@link Component}.

      + *

      + * This annotation is a specialization of {@link Component}. + *

      * * @author Eric Bottard * @see Component @@ -48,4 +49,5 @@ * @return the suggested component name, if any */ String value() default ""; + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethod.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethod.java index ee1db6106..9e86470cb 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethod.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethod.java @@ -31,28 +31,29 @@ * @author Florent Biville */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) @Documented @Reflective public @interface ShellMethod { /** - * The default value for {@link #group()}, meaning that the group will be inherited from the explicit value set - * on the containing element (class then package) or ultimately inferred. + * The default value for {@link #group()}, meaning that the group will be inherited + * from the explicit value set on the containing element (class then package) or + * ultimately inferred. * @see ShellCommandGroup */ String INHERITED = ""; /** - * The name(s) by which this method can be invoked via Spring Shell. If not specified, the actual method name - * will be used (turning camelCase humps into "-"). + * The name(s) by which this method can be invoked via Spring Shell. If not specified, + * the actual method name will be used (turning camelCase humps into "-"). * @return explicit command name(s) to use */ String[] key() default {}; /** - * A description for the command. Should not contain any formatting (e.g. html) characters and would typically - * start with a capital letter and end with a dot. + * A description for the command. Should not contain any formatting (e.g. html) + * characters and would typically start with a capital letter and end with a dot. * @return short description of what the command does */ String value() default ""; @@ -64,21 +65,22 @@ String prefix() default "--"; /** - * The command group which this command belongs to. The command group is used when printing a list of - * commands to group related commands. By default, group is first looked up from owning class then package, - * and if not explicitly set, is inferred from class name. + * The command group which this command belongs to. The command group is used when + * printing a list of commands to group related commands. By default, group is first + * looked up from owning class then package, and if not explicitly set, is inferred + * from class name. * @return name of the command group */ String group() default INHERITED; /** - * Defines interaction mode for a command as a hint when command should be - * available. For example presense of some commands doesn't make sense if shell - * is running as non-interactive mode and vice versa. + * Defines interaction mode for a command as a hint when command should be available. + * For example presense of some commands doesn't make sense if shell is running as + * non-interactive mode and vice versa. * * Defaults to {@link InteractionMode#ALL} - * * @return interaction mode */ InteractionMode interactionMode() default InteractionMode.ALL; + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethodAvailability.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethodAvailability.java index 2171e6118..e3a37f9f7 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethodAvailability.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellMethodAvailability.java @@ -21,28 +21,30 @@ /** * Used to customize the name of the method used to indicate availability of a command. * - * In the absence of this annotation, the dynamic availability of a command method named {@literal foo} - * is discovered via method {@literal fooAvailability}. + * In the absence of this annotation, the dynamic availability of a command method named + * {@literal foo} is discovered via method {@literal fooAvailability}. *
        - *
      • If this annotation is added to the {@literal foo} - * method, then its {@link #value()} should be the name of an availability method (in place of - * {@literal fooAvailability()}) that returns {@link org.springframework.shell.Availability}.
      • - *
      • If placed on a method that returns {@link org.springframework.shell.Availability} and takes no argument, - * then the {@link #value()} of this annotation should be the command names (or aliases) of the - * commands this availability indicator is for. The special value of {@literal "*"} (the default) matches - * all commands implemented in the current class.
      • + *
      • If this annotation is added to the {@literal foo} method, then its {@link #value()} + * should be the name of an availability method (in place of {@literal fooAvailability()}) + * that returns {@link org.springframework.shell.Availability}.
      • + *
      • If placed on a method that returns {@link org.springframework.shell.Availability} + * and takes no argument, then the {@link #value()} of this annotation should be the + * command names (or aliases) of the commands this availability indicator is for. + * The special value of {@literal "*"} (the default) matches all commands implemented in + * the current class.
      • *
      * * @author Eric Bottard */ @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) +@Target({ ElementType.METHOD }) @Documented public @interface ShellMethodAvailability { - /** - * @return the name of the availability method for this command method, or if placed on an availability method, the names of - * the commands it is for. - */ - String[] value() default "*"; + /** + * @return the name of the availability method for this command method, or if placed + * on an availability method, the names of the commands it is for. + */ + String[] value() default "*"; + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOption.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOption.java index c9c6a9343..089f6df0f 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOption.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOption.java @@ -34,13 +34,14 @@ public @interface ShellOption { /** - * Used to indicate that the default value is the value {@literal null}, which is different from the fact that - * there is no default value. + * Used to indicate that the default value is the value {@literal null}, which is + * different from the fact that there is no default value. */ String NULL = "__NULL__"; /** - * Used to indicate that there is no default value (i.e. parameter is mandatory). + * Used to indicate that there is no default value (i.e. parameter is + * mandatory). */ String NONE = "__NONE__"; @@ -50,22 +51,23 @@ int ARITY_USE_HEURISTICS = -1; /** - * The key(s) by which this parameter can be referenced - * when using named parameters. If none is specified, the actual method parameter name will be used, prefixed by the - * method {@link ShellMethod#prefix()}. + * The key(s) by which this parameter can be referenced when using named parameters. + * If none is specified, the actual method parameter name will be used, prefixed by + * the method {@link ShellMethod#prefix()}. * @return explicit key(s) to use to pass a value for this parameter */ String[] value() default {}; /** - * Return the number of input "words" this parameter consumes. Default is 1, except when parameter type is boolean, - * in which case it is 0. + * Return the number of input "words" this parameter consumes. Default is 1, except + * when parameter type is boolean, in which case it is 0. * @return the number of words to map to this parameter */ int arity() default ARITY_USE_HEURISTICS; /** - * The textual (pre-conversion) value to assign to this parameter if no value is provided by the user. + * The textual (pre-conversion) value to assign to this parameter if no value is + * provided by the user. * @return the default value for this parameter */ String defaultValue() default NONE; @@ -79,16 +81,18 @@ Class valueProvider() default NoValueProvider.class; /** - * Used to indicate to the framework that the given parameter should NOT be resolved by - * {@code StandardParameterResolver}. This is useful if several implementations of - * {@code org.springframework.shell.ParameterResolver} are present, given that the standard one can work with no - * annotation at all. - * Note that this is not used anymore! - * @return true to indicate that the {@code StandardParameterResolver} should not be used for this parameter + * Used to indicate to the framework that the given parameter should NOT be resolved + * by {@code StandardParameterResolver}. This is useful if several implementations of + * {@code org.springframework.shell.ParameterResolver} are present, given that the + * standard one can work with no annotation at all. Note that this is not used + * anymore! + * @return true to indicate that the {@code StandardParameterResolver} should not be + * used for this parameter */ boolean optOut() default false; interface NoValueProvider extends ValueProvider { } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOptionMethodArgumentResolver.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOptionMethodArgumentResolver.java index c6e513dcb..d2af83af9 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOptionMethodArgumentResolver.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ShellOptionMethodArgumentResolver.java @@ -80,5 +80,7 @@ private static final class HeaderNamedValueInfo extends NamedValueInfo { private HeaderNamedValueInfo(ShellOption annotation, List names) { super(names, false, null); } + } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java index 87c7fc546..0338657d7 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardMethodTargetRegistrar.java @@ -68,11 +68,13 @@ public class StandardMethodTargetRegistrar implements MethodTargetRegistrar { private final Logger log = LoggerFactory.getLogger(StandardMethodTargetRegistrar.class); + private ApplicationContext applicationContext; + private CommandRegistration.BuilderSupplier commandRegistrationBuilderSupplier; public StandardMethodTargetRegistrar(ApplicationContext applicationContext, - CommandRegistration.BuilderSupplier commandRegistrationBuilderSupplier) { + CommandRegistration.BuilderSupplier commandRegistrationBuilderSupplier) { this.applicationContext = applicationContext; this.commandRegistrationBuilderSupplier = commandRegistrationBuilderSupplier; } @@ -140,7 +142,8 @@ else if ("-".equals(shellMapping.prefix()) && stripped.length() == 1) { String longName = mp.getParameterName(); Class parameterType = mp.getParameterType(); if (longName != null) { - log.debug("Using mp='{}' longName='{}' parameterType='{}'", mp, longName, parameterType); + log.debug("Using mp='{}' longName='{}' parameterType='{}'", mp, longName, + parameterType); longNames.add(longName); } } @@ -180,7 +183,8 @@ else if (ClassUtils.isAssignable(Boolean.class, parameterType)) { } if (!ClassUtils.isAssignable(NoValueProvider.class, so.valueProvider())) { CompletionResolver completionResolver = ctx -> { - ValueProvider valueProviderBean = this.applicationContext.getBean(so.valueProvider()); + ValueProvider valueProviderBean = this.applicationContext + .getBean(so.valueProvider()); List complete = valueProviderBean.complete(ctx); return complete; }; @@ -217,8 +221,10 @@ else if (ClassUtils.isAssignable(Boolean.class, parameterType)) { builder.withTarget().method(bean, method); ObjectProvider terminal = this.applicationContext.getBeanProvider(Terminal.class); - // TODO: feels a bit fishy to return null terminal but for now it's mostly to pass tests as it should not fail - MethodCommandExceptionResolver resolver = new MethodCommandExceptionResolver(bean, terminal.getIfAvailable(() -> null)); + // TODO: feels a bit fishy to return null terminal but for now it's mostly + // to pass tests as it should not fail + MethodCommandExceptionResolver resolver = new MethodCommandExceptionResolver(bean, + terminal.getIfAvailable(() -> null)); builder.withErrorHandling().resolver(resolver); CommandRegistration registration = builder.build(); @@ -228,11 +234,12 @@ else if (ClassUtils.isAssignable(Boolean.class, parameterType)) { } /** - * Gets the group from the following places, in order:
        - *
      • explicit annotation at the method level
      • - *
      • explicit annotation at the class level
      • - *
      • explicit annotation at the package level
      • - *
      • implicit from the class name
      • + * Gets the group from the following places, in order: + *
          + *
        • explicit annotation at the method level
        • + *
        • explicit annotation at the class level
        • + *
        • explicit annotation at the package level
        • + *
        • implicit from the class name
        • *
        */ private String getOrInferGroup(Method method) { @@ -249,66 +256,74 @@ private String getOrInferGroup(Method method) { if (packageAnn != null && !packageAnn.value().equals(ShellCommandGroup.INHERIT_AND_INFER)) { return packageAnn.value(); } - // Shameful copy/paste from https://stackoverflow.com/questions/7593969/regex-to-split-camelcase-or-titlecase-advanced - return StringUtils.arrayToDelimitedString(clazz.getSimpleName().split("(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])"), " "); + // Shameful copy/paste from + // https://stackoverflow.com/questions/7593969/regex-to-split-camelcase-or-titlecase-advanced + return StringUtils + .arrayToDelimitedString(clazz.getSimpleName().split("(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])"), " "); } /** * Tries to locate an availability indicator (a no-arg method that returns - * {@link Availability}) for the given command method. The following are tried in order - * for method {@literal m}: + * {@link Availability}) for the given command method. The following are tried in + * order for method {@literal m}: *
          - *
        1. If {@literal m} bears the {@literal @}{@link ShellMethodAvailability} annotation, - * its value should be the method name to look up
        2. + *
        3. If {@literal m} bears the {@literal @}{@link ShellMethodAvailability} + * annotation, its value should be the method name to look up
        4. *
        5. a method named {@literal "Availability"} is looked up.
        6. - *
        7. otherwise, if some method {@literal ai} that returns {@link Availability} and takes - * no argument exists, that is annotated with {@literal @}{@link ShellMethodAvailability} - * and whose annotation value contains one of the {@literal commandKeys}, then it is - * selected
        8. + *
        9. otherwise, if some method {@literal ai} that returns {@link Availability} and + * takes no argument exists, that is annotated with + * {@literal @}{@link ShellMethodAvailability} and whose annotation value contains one + * of the {@literal commandKeys}, then it is selected
        10. *
        */ private Supplier findAvailabilityIndicator(String[] commandKeys, Object bean, Method method) { ShellMethodAvailability explicit = method.getAnnotation(ShellMethodAvailability.class); final Method indicator; if (explicit != null) { - Assert.isTrue(explicit.value().length == 1, "When set on a @" + - ShellMethod.class.getSimpleName() + " method, the value of the @" - + ShellMethodAvailability.class.getSimpleName() + - " should be a single element, the name of a method that returns " - + Availability.class.getSimpleName() + - ". Found " + Arrays.asList(explicit.value()) + " for " + method); + Assert.isTrue(explicit.value().length == 1, + "When set on a @" + ShellMethod.class.getSimpleName() + " method, the value of the @" + + ShellMethodAvailability.class.getSimpleName() + + " should be a single element, the name of a method that returns " + + Availability.class.getSimpleName() + ". Found " + Arrays.asList(explicit.value()) + + " for " + method); indicator = ReflectionUtils.findMethod(bean.getClass(), explicit.value()[0]); } // Try "Availability" else { Method implicit = ReflectionUtils.findMethod(bean.getClass(), method.getName() + "Availability"); if (implicit != null) { indicator = implicit; - } else { + } + else { Map> candidates = new HashMap<>(); ReflectionUtils.doWithMethods(bean.getClass(), candidate -> { - List matchKeys = new ArrayList<>(Arrays.asList(candidate.getAnnotation(ShellMethodAvailability.class).value())); + List matchKeys = new ArrayList<>( + Arrays.asList(candidate.getAnnotation(ShellMethodAvailability.class).value())); if (matchKeys.contains("*")) { - Assert.isTrue(matchKeys.size() == 1, "When using '*' as a wildcard for " + - ShellMethodAvailability.class.getSimpleName() + ", this can be the only value. Found " + - matchKeys + " on method " + candidate); + Assert.isTrue(matchKeys.size() == 1, + "When using '*' as a wildcard for " + ShellMethodAvailability.class.getSimpleName() + + ", this can be the only value. Found " + matchKeys + " on method " + + candidate); candidates.put(candidate, matchKeys); - } else { + } + else { matchKeys.retainAll(Arrays.asList(commandKeys)); if (!matchKeys.isEmpty()) { candidates.put(candidate, matchKeys); } } - }, m -> m.getAnnotation(ShellMethodAvailability.class) != null && m.getAnnotation(ShellMethod.class) == null); + }, m -> m.getAnnotation(ShellMethodAvailability.class) != null + && m.getAnnotation(ShellMethod.class) == null); // Make sure wildcard approach has less precedence than explicit name - Set notUsingWildcard = candidates.entrySet().stream() - .filter(e -> !e.getValue().contains("*")) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); + Set notUsingWildcard = candidates.entrySet() + .stream() + .filter(e -> !e.getValue().contains("*")) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); Assert.isTrue(notUsingWildcard.size() <= 1, - "Found several @" + ShellMethodAvailability.class.getSimpleName() + - " annotated methods that could apply for " + method + ". Offending candidates are " + "Found several @" + ShellMethodAvailability.class.getSimpleName() + + " annotated methods that could apply for " + method + ". Offending candidates are " + notUsingWildcard); if (notUsingWildcard.size() == 1) { @@ -316,7 +331,8 @@ private Supplier findAvailabilityIndicator(String[] commandKeys, O } // Wildcard was available else if (candidates.size() == 1) { indicator = candidates.keySet().iterator().next(); - } else { + } + else { indicator = null; } } @@ -333,4 +349,5 @@ else if (candidates.size() == 1) { return null; } } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardResourcesRuntimeHints.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardResourcesRuntimeHints.java index 2d1a981ef..7ec1c1d2a 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardResourcesRuntimeHints.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/StandardResourcesRuntimeHints.java @@ -29,4 +29,5 @@ class StandardResourcesRuntimeHints implements RuntimeHintsRegistrar { public void registerHints(RuntimeHints hints, ClassLoader classLoader) { hints.resources().registerPattern("org/springframework/shell/component/*.stg"); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ValueProvider.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ValueProvider.java index 64b4ef0b0..4ef98622b 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/ValueProvider.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/ValueProvider.java @@ -21,8 +21,8 @@ import org.springframework.shell.CompletionProposal; /** - * Beans implementing this interface are queried during TAB completion to gather - * possible values of a parameter. + * Beans implementing this interface are queried during TAB completion to gather possible + * values of a parameter. * * @author Eric Bottard * @author Janne Valkealahti @@ -31,9 +31,9 @@ public interface ValueProvider { /** * Complete completion proposals. - * * @param completionContext the context * @return the completion proposals */ List complete(CompletionContext completionContext); + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Clear.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Clear.java index 52bc8f474..c6b75fbb2 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Clear.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Clear.java @@ -35,15 +35,21 @@ public class Clear extends AbstractShellComponent { /** * Marker interface for beans providing {@literal clear} functionality to the shell. * - *

        To override the clear command, simply register your own bean implementing that interface - * and the standard implementation will back off.

        + *

        + * To override the clear command, simply register your own bean implementing that + * interface and the standard implementation will back off. + *

        * - *

        To disable the {@literal clear} command entirely, set the {@literal spring.shell.command.clear.enabled=false} - * property in the environment.

        + *

        + * To disable the {@literal clear} command entirely, set the + * {@literal spring.shell.command.clear.enabled=false} property in the environment. + *

        * * @author Eric Bottard */ - public interface Command {} + public interface Command { + + } public Clear() { } @@ -52,4 +58,5 @@ public Clear() { public void clear() { getTerminal().puts(InfoCmp.Capability.clear_screen); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModel.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModel.java index 79a949850..3a28d7663 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModel.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModel.java @@ -23,6 +23,7 @@ class CommandAvailabilityInfoModel { private boolean available; + private String reason; CommandAvailabilityInfoModel(boolean available, String reason) { @@ -32,7 +33,6 @@ class CommandAvailabilityInfoModel { /** * Builds {@link CommandAvailabilityInfoModel}. - * * @param available the available flag * @param reason the reason * @return a command parameter availability model @@ -48,4 +48,5 @@ public boolean getAvailable() { public String getReason() { return reason; } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandInfoModel.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandInfoModel.java index fe79a27ce..79ba93a01 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandInfoModel.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandInfoModel.java @@ -34,9 +34,13 @@ class CommandInfoModel { private String name; + private List aliases; + private String description; + private List parameters; + private CommandAvailabilityInfoModel availability; CommandInfoModel(String name, List aliases, String description, List parameters, @@ -50,29 +54,27 @@ class CommandInfoModel { /** * Builds {@link CommandInfoModel} from {@link CommandRegistration}. - * * @param name the command name * @param registration the command registration * @return the command info model */ static CommandInfoModel of(String name, CommandRegistration registration) { List options = registration.getOptions(); - List parameters = options.stream() - .map(o -> { - String type = commandOptionType(o); - List arguments = Stream.concat( - Stream.of(o.getLongNames()).map(a -> "--" + a), - Stream.of(o.getShortNames()).map(s -> "-" + s)) - .collect(Collectors.toList()); - boolean required = o.isRequired(); - String description = o.getDescription(); - String defaultValue = o.getDefaultValue(); - return CommandParameterInfoModel.of(type, arguments, required, description, defaultValue); - }) - .collect(Collectors.toList()); - - List aliases = registration.getAliases().stream().map(ca -> ca.getCommand()) + List parameters = options.stream().map(o -> { + String type = commandOptionType(o); + List arguments = Stream + .concat(Stream.of(o.getLongNames()).map(a -> "--" + a), Stream.of(o.getShortNames()).map(s -> "-" + s)) .collect(Collectors.toList()); + boolean required = o.isRequired(); + String description = o.getDescription(); + String defaultValue = o.getDefaultValue(); + return CommandParameterInfoModel.of(type, arguments, required, description, defaultValue); + }).collect(Collectors.toList()); + + List aliases = registration.getAliases() + .stream() + .map(ca -> ca.getCommand()) + .collect(Collectors.toList()); String description = registration.getDescription(); boolean available = true; @@ -128,4 +130,5 @@ public List getParameters() { public CommandAvailabilityInfoModel getAvailability() { return availability; } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandParameterInfoModel.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandParameterInfoModel.java index a35470262..7af6705e6 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandParameterInfoModel.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/CommandParameterInfoModel.java @@ -27,9 +27,13 @@ class CommandParameterInfoModel { private String type; + private List arguments; + private boolean required; + private String description; + private String defaultValue; CommandParameterInfoModel(String type, List arguments, boolean required, String description, @@ -43,7 +47,6 @@ class CommandParameterInfoModel { /** * Builds {@link CommandParameterInfoModel}. - * * @param type the type * @param arguments the arguments * @param required the required flag @@ -51,8 +54,8 @@ class CommandParameterInfoModel { * @param defaultValue the default value * @return a command parameter info model */ - static CommandParameterInfoModel of(String type, List arguments, boolean required, - String description, String defaultValue) { + static CommandParameterInfoModel of(String type, List arguments, boolean required, String description, + String defaultValue) { return new CommandParameterInfoModel(type, arguments, required, description, defaultValue); } @@ -79,4 +82,5 @@ public String getDefaultValue() { public boolean getHasDefaultValue() { return StringUtils.hasText(this.defaultValue); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Completion.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Completion.java index 5d52e7beb..c4fcae668 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Completion.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Completion.java @@ -34,9 +34,11 @@ public class Completion extends AbstractShellComponent { * Marker interface used in auto-config. */ public interface Command { + } private ResourceLoader resourceLoader; + private String rootCommand; public Completion(String rootCommand) { @@ -59,4 +61,5 @@ public String zsh() { ZshCompletions zshCompletions = new ZshCompletions(resourceLoader, getCommandCatalog()); return zshCompletions.generate(rootCommand); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupCommandInfoModel.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupCommandInfoModel.java index dd3953311..2dc8a44ba 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupCommandInfoModel.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupCommandInfoModel.java @@ -26,6 +26,7 @@ class GroupCommandInfoModel { private String group = ""; + private List commands = new ArrayList<>(); GroupCommandInfoModel(String group, List commands) { @@ -35,7 +36,6 @@ class GroupCommandInfoModel { /** * Builds {@link GroupCommandInfoModel}. - * * @param group the group * @param commands the command info models * @return a group command info model @@ -51,4 +51,5 @@ public String getGroup() { public List getCommands() { return commands; } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupsInfoModel.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupsInfoModel.java index 4357aa8cd..a29ed3293 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupsInfoModel.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/GroupsInfoModel.java @@ -27,16 +27,19 @@ import org.springframework.util.StringUtils; /** - * Model encapsulating info about command structure which is more - * friendly to show and render via templating. + * Model encapsulating info about command structure which is more friendly to show and + * render via templating. * * @author Janne Valkealahti */ class GroupsInfoModel { private boolean showGroups = true; + private final List groups; + private final List commands; + private boolean hasUnavailableCommands = false; GroupsInfoModel(boolean showGroups, List groups, List commands, @@ -49,7 +52,6 @@ class GroupsInfoModel { /** * Builds {@link GroupsInfoModel} from command registrations. - * * @param showGroups the flag showing groups * @param registrations the command registrations * @return a groups info model @@ -59,36 +61,31 @@ static GroupsInfoModel of(boolean showGroups, Map r // collect commands into groups with sorting HashSet regsWithoutAliases = new HashSet<>(registrations.values()); SortedMap> commandsByGroupAndName = regsWithoutAliases.stream() - .collect(Collectors.toMap(r -> r.getCommand(), r -> r)).entrySet().stream() + .collect(Collectors.toMap(r -> r.getCommand(), r -> r)) + .entrySet() + .stream() .collect(Collectors.groupingBy( - e -> StringUtils.hasText(e.getValue().getGroup()) ? e.getValue().getGroup() : "Default", - TreeMap::new, - Collectors.toMap(Entry::getKey, Entry::getValue) - )); - + e -> StringUtils.hasText(e.getValue().getGroup()) ? e.getValue().getGroup() : "Default", + TreeMap::new, Collectors.toMap(Entry::getKey, Entry::getValue))); // build model - List gcims = commandsByGroupAndName.entrySet().stream() - .map(e -> { - List cims = e.getValue().entrySet().stream() - .map(ee -> CommandInfoModel.of(ee.getKey(), ee.getValue())) - .collect(Collectors.toList()); - return GroupCommandInfoModel.of(e.getKey(), cims); - }) - .collect(Collectors.toList()); + List gcims = commandsByGroupAndName.entrySet().stream().map(e -> { + List cims = e.getValue() + .entrySet() + .stream() + .map(ee -> CommandInfoModel.of(ee.getKey(), ee.getValue())) + .collect(Collectors.toList()); + return GroupCommandInfoModel.of(e.getKey(), cims); + }).collect(Collectors.toList()); List commands = gcims.stream() .flatMap(gcim -> gcim.getCommands().stream()) .collect(Collectors.toList()); - boolean hasUnavailableCommands = commands.stream() - .map(c -> { - if (c.getAvailability() != null) { - return c.getAvailability().getAvailable(); - } - return true; - }) - .filter(a -> !a) - .findFirst() - .isPresent(); + boolean hasUnavailableCommands = commands.stream().map(c -> { + if (c.getAvailability() != null) { + return c.getAvailability().getAvailable(); + } + return true; + }).filter(a -> !a).findFirst().isPresent(); return new GroupsInfoModel(showGroups, gcims, commands, hasUnavailableCommands); } @@ -107,4 +104,5 @@ public List getCommands() { public boolean getHasUnavailableCommands() { return hasUnavailableCommands; } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Help.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Help.java index 67e7ff0ac..a54ec6d67 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Help.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Help.java @@ -51,8 +51,8 @@ public class Help extends AbstractShellComponent { * Marker interface for beans providing {@literal help} functionality to the shell. * *

        - * To override the help command, simply register your own bean implementing that interface - * and the standard implementation will back off. + * To override the help command, simply register your own bean implementing that + * interface and the standard implementation will back off. *

        * *

        @@ -63,37 +63,36 @@ public class Help extends AbstractShellComponent { * @author Eric Bottard */ public interface Command { + } private boolean showGroups = true; + private TemplateExecutor templateExecutor; + private String commandTemplate; - private String commandsTemplate; + private String commandsTemplate; public Help(TemplateExecutor templateExecutor) { this.templateExecutor = templateExecutor; } @ShellMethod(value = "Display help about available commands") - public AttributedString help( - @ShellOption(defaultValue = ShellOption.NULL, valueProvider = CommandValueProvider.class, value = { "-C", - "--command" }, help = "The command to obtain help for.", arity = Integer.MAX_VALUE) String[] command) - throws IOException { + public AttributedString help(@ShellOption(defaultValue = ShellOption.NULL, + valueProvider = CommandValueProvider.class, value = { "-C", "--command" }, + help = "The command to obtain help for.", arity = Integer.MAX_VALUE) String[] command) throws IOException { if (command == null) { return renderCommands(); } else { - String commandStr = Stream.of(command) - .map(c -> c.trim()) - .collect(Collectors.joining(" ")); + String commandStr = Stream.of(command).map(c -> c.trim()).collect(Collectors.joining(" ")); return renderCommand(commandStr); } } /** * Sets a location for a template rendering command help. - * * @param commandTemplate the command template location */ public void setCommandTemplate(String commandTemplate) { @@ -102,7 +101,6 @@ public void setCommandTemplate(String commandTemplate) { /** * Sets a location for a template rendering commands help. - * * @param commandsTemplate the commands template location */ public void setCommandsTemplate(String commandsTemplate) { @@ -110,9 +108,8 @@ public void setCommandsTemplate(String commandsTemplate) { } /** - * Sets if groups should be shown in a listing, defaults to true. If not enabled - * a simple list is shown without groups. - * + * Sets if groups should be shown in a listing, defaults to true. If not enabled a + * simple list is shown without groups. * @param showGroups the flag to show groups */ public void setShowGroups(boolean showGroups) { @@ -121,7 +118,7 @@ public void setShowGroups(boolean showGroups) { private AttributedString renderCommands() { Map registrations = Utils - .removeHiddenCommands(getCommandCatalog().getRegistrations()); + .removeHiddenCommands(getCommandCatalog().getRegistrations()); boolean isStg = this.commandTemplate.endsWith(".stg"); @@ -135,7 +132,7 @@ private AttributedString renderCommands() { private AttributedString renderCommand(String command) { Map registrations = Utils - .removeHiddenCommands(getCommandCatalog().getRegistrations()); + .removeHiddenCommands(getCommandCatalog().getRegistrations()); CommandRegistration registration = registrations.get(command); if (registration == null) { throw new IllegalArgumentException("Unknown command '" + command + "'"); @@ -154,8 +151,10 @@ private AttributedString renderCommand(String command) { private static String resourceAsString(Resource resource) { try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) { return FileCopyUtils.copyToString(reader); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/History.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/History.java index 77d2af4d9..3dd4a847e 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/History.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/History.java @@ -28,46 +28,56 @@ import org.springframework.shell.standard.ShellOption; /** - * A command that displays all previously run commands, optionally dumping to a file readable by {@link Script}. + * A command that displays all previously run commands, optionally dumping to a file + * readable by {@link Script}. * * @author Eric Bottard */ @ShellComponent public class History { - private final org.jline.reader.History jLineHistory; + private final org.jline.reader.History jLineHistory; - public History(org.jline.reader.History jLineHistory) { - this.jLineHistory = jLineHistory; - } + public History(org.jline.reader.History jLineHistory) { + this.jLineHistory = jLineHistory; + } - /** - * Marker interface for beans providing {@literal history} functionality to the shell. - *

        - *

        To override the history command, simply register your own bean implementing that interface - * and the standard implementation will back off.

        - *

        - *

        To disable the {@literal history} command entirely, set the {@literal spring.shell.command.history.enabled=false} - * property in the environment.

        - * - * @author Eric Bottard - */ - public interface Command { - } + /** + * Marker interface for beans providing {@literal history} functionality to the shell. + *

        + *

        + * To override the history command, simply register your own bean implementing that + * interface and the standard implementation will back off. + *

        + *

        + *

        + * To disable the {@literal history} command entirely, set the + * {@literal spring.shell.command.history.enabled=false} property in the environment. + *

        + * + * @author Eric Bottard + */ + public interface Command { + + } + + @ShellMethod(value = "Display or save the history of previously run commands") + public List history( + @ShellOption(help = "A file to save history to.", defaultValue = ShellOption.NULL) File file) + throws IOException { + if (file == null) { + List result = new ArrayList<>(jLineHistory.size()); + jLineHistory.forEach(e -> result.add(e.line())); + return result; + } + else { + try (FileWriter w = new FileWriter(file)) { + for (org.jline.reader.History.Entry entry : jLineHistory) { + w.append(entry.line()).append(System.lineSeparator()); + } + } + return Collections.singletonList(String.format("Wrote %d entries to %s", jLineHistory.size(), file)); + } + } - @ShellMethod(value = "Display or save the history of previously run commands") - public List history(@ShellOption(help = "A file to save history to.", defaultValue = ShellOption.NULL) File file) throws IOException { - if (file == null) { - List result = new ArrayList<>(jLineHistory.size()); - jLineHistory.forEach(e -> result.add(e.line())); - return result; - } else { - try (FileWriter w = new FileWriter(file)) { - for (org.jline.reader.History.Entry entry : jLineHistory) { - w.append(entry.line()).append(System.lineSeparator()); - } - } - return Collections.singletonList(String.format("Wrote %d entries to %s", jLineHistory.size(), file)); - } - } } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Quit.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Quit.java index 906a5e952..984d674cb 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Quit.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Quit.java @@ -32,18 +32,25 @@ public class Quit { /** * Marker interface for beans providing {@literal quit} functionality to the shell. * - *

        To override the quit command, simply register your own bean implementing that interface - * and the standard implementation will back off.

        + *

        + * To override the quit command, simply register your own bean implementing that + * interface and the standard implementation will back off. + *

        * - *

        To disable the {@literal quit} command entirely, set the {@literal spring.shell.command.quit.enabled=false} - * property in the environment.

        + *

        + * To disable the {@literal quit} command entirely, set the + * {@literal spring.shell.command.quit.enabled=false} property in the environment. + *

        * * @author Eric Bottard */ - public interface Command {} + public interface Command { - @ShellMethod(value = "Exit the shell.", key = {"quit", "exit"}, interactionMode = InteractionMode.INTERACTIVE) + } + + @ShellMethod(value = "Exit the shell.", key = { "quit", "exit" }, interactionMode = InteractionMode.INTERACTIVE) public void quit() { throw new ExitRequest(); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Script.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Script.java index f1308030b..07b449ac0 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Script.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Script.java @@ -35,32 +35,37 @@ @ShellComponent public class Script extends AbstractShellComponent { - private final Parser parser; + private final Parser parser; - public Script(Parser parser) { - this.parser = parser; - } + public Script(Parser parser) { + this.parser = parser; + } - /** - * Marker interface for beans providing {@literal script} functionality to the shell. - *

        - *

        To override the script command, simply register your own bean implementing that interface - * and the standard implementation will back off.

        - *

        - *

        To disable the {@literal script} command entirely, set the {@literal spring.shell.command.script.enabled=false} - * property in the environment.

        - * - * @author Eric Bottard - */ - public interface Command { - } + /** + * Marker interface for beans providing {@literal script} functionality to the shell. + *

        + *

        + * To override the script command, simply register your own bean implementing that + * interface and the standard implementation will back off. + *

        + *

        + *

        + * To disable the {@literal script} command entirely, set the + * {@literal spring.shell.command.script.enabled=false} property in the environment. + *

        + * + * @author Eric Bottard + */ + public interface Command { - @ShellMethod(value = "Read and execute commands from a file.") - public void script(File file) throws Exception { - Reader reader = new FileReader(file); - try (FileInputProvider inputProvider = new FileInputProvider(reader, parser)) { - getShell().run(inputProvider); - } - } + } + + @ShellMethod(value = "Read and execute commands from a file.") + public void script(File file) throws Exception { + Reader reader = new FileReader(file); + try (FileInputProvider inputProvider = new FileInputProvider(reader, parser)) { + getShell().run(inputProvider); + } + } } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Stacktrace.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Stacktrace.java index eff075eff..aaf983b94 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Stacktrace.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Stacktrace.java @@ -32,17 +32,25 @@ public class Stacktrace extends AbstractShellComponent { /** - * Marker interface for beans providing {@literal stacktrace} functionality to the shell. + * Marker interface for beans providing {@literal stacktrace} functionality to the + * shell. * - *

        To override the stacktrace command, simply register your own bean implementing that interface - * and the standard implementation will back off.

        + *

        + * To override the stacktrace command, simply register your own bean implementing that + * interface and the standard implementation will back off. + *

        * - *

        To disable the {@literal stacktrace} command entirely, set the {@literal spring.shell.command.stacktrace.enabled=false} - * property in the environment.

        + *

        + * To disable the {@literal stacktrace} command entirely, set the + * {@literal spring.shell.command.stacktrace.enabled=false} property in the + * environment. + *

        * * @author Eric Bottard */ - public interface Command {} + public interface Command { + + } private ObjectProvider throwableResultHandler; @@ -51,8 +59,7 @@ public Stacktrace(ObjectProvider throwableResultHandler) } @ShellMethod(key = ThrowableResultHandler.DETAILS_COMMAND_NAME, - value = "Display the full stacktrace of the last error.", - interactionMode = InteractionMode.INTERACTIVE) + value = "Display the full stacktrace of the last error.", interactionMode = InteractionMode.INTERACTIVE) public void stacktrace() { ThrowableResultHandler handler = throwableResultHandler.getIfAvailable(); if (handler != null) { @@ -61,4 +68,5 @@ public void stacktrace() { } } } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsModelsRuntimeHints.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsModelsRuntimeHints.java index 747324ccd..8ba10433f 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsModelsRuntimeHints.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsModelsRuntimeHints.java @@ -47,4 +47,5 @@ private void registerForDeclaredMethodsInvocation(ReflectionHints reflection, Cl private Iterable typeReferences(Class... classes) { return Stream.of(classes).map(TypeReference::of).collect(Collectors.toList()); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsResourcesRuntimeHints.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsResourcesRuntimeHints.java index 8818b33f1..ab24ba5b1 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsResourcesRuntimeHints.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/StandardCommandsResourcesRuntimeHints.java @@ -28,8 +28,7 @@ class StandardCommandsResourcesRuntimeHints implements RuntimeHintsRegistrar { @Override public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) { - hints.resources() - .registerPattern("template/*.st") - .registerPattern("template/*.stg"); + hints.resources().registerPattern("template/*.st").registerPattern("template/*.stg"); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Version.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Version.java index 6ec83ff9d..071689e65 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Version.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/commands/Version.java @@ -47,20 +47,33 @@ public class Version extends AbstractShellComponent { * Marker interface used in auto-config. */ public interface Command { + } private BuildProperties buildProperties; + private GitProperties gitProperties; + private TemplateExecutor templateExecutor; + private String template; + private boolean showBuildGroup; + private boolean showBuildArtifact; + private boolean showBuildName; + private boolean showBuildVersion; + private boolean showBuildTime; + private boolean showGitBranch; + private boolean showGitCommitId; + private boolean showGitShortCommitId; + private boolean showGitCommitTime; public Version(TemplateExecutor templateExecutor) { @@ -177,8 +190,10 @@ public void setShowGitCommitTime(boolean showGitCommitTime) { private static String resourceAsString(Resource resource) { try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) { return FileCopyUtils.copyToString(reader); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/AbstractCompletions.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/AbstractCompletions.java index a3e03ad78..37d249f8e 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/AbstractCompletions.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/AbstractCompletions.java @@ -44,14 +44,15 @@ import org.springframework.util.MultiValueMap; /** - * Base class for completion script commands providing functionality for - * resource handling and templating with {@code antrl stringtemplate}. + * Base class for completion script commands providing functionality for resource handling + * and templating with {@code antrl stringtemplate}. * * @author Janne Valkealahti */ public abstract class AbstractCompletions { private final ResourceLoader resourceLoader; + private final CommandCatalog commandCatalog; public AbstractCompletions(ResourceLoader resourceLoader, CommandCatalog commandCatalog) { @@ -64,88 +65,85 @@ protected Builder builder() { } /** - * Generates a model for a recursive command model starting from root - * level going down with all sub commands with options. Essentially providing - * all needed to build completions structure. + * Generates a model for a recursive command model starting from root level going down + * with all sub commands with options. Essentially providing all needed to build + * completions structure. */ protected CommandModel generateCommandModel() { Collection commandsByName = Utils.removeHiddenCommands(commandCatalog.getRegistrations()) - .values(); + .values(); HashMap commands = new HashMap<>(); HashSet topCommands = new HashSet<>(); - commandsByName.stream() - .forEach(registration -> { - String key = registration.getCommand(); - String[] splitKeys = key.split(" "); - String commandKey = ""; - for (int i = 0; i < splitKeys.length; i++) { - DefaultCommandModelCommand parent = null; - String main = splitKeys[i]; - if (i > 0) { - parent = commands.get(commandKey); - commandKey = commandKey + " " + splitKeys[i]; - } - else { - commandKey = splitKeys[i]; - } - String desc = i + 1 < splitKeys.length ? null : registration.getDescription(); - DefaultCommandModelCommand command = commands.computeIfAbsent(commandKey, - (fullCommand) -> new DefaultCommandModelCommand(fullCommand, main, desc)); - - // TODO long vs short - List options = registration.getOptions().stream() - .flatMap(co -> Arrays.stream(co.getLongNames())) - .map(lo -> CommandModelOption.of("--", lo)) - .collect(Collectors.toList()); - - if (i == splitKeys.length - 1) { - command.addOptions(options); - } - if (parent != null) { - parent.addCommand(command); - } - if (i == 0) { - topCommands.add(command); - } + commandsByName.stream().forEach(registration -> { + String key = registration.getCommand(); + String[] splitKeys = key.split(" "); + String commandKey = ""; + for (int i = 0; i < splitKeys.length; i++) { + DefaultCommandModelCommand parent = null; + String main = splitKeys[i]; + if (i > 0) { + parent = commands.get(commandKey); + commandKey = commandKey + " " + splitKeys[i]; } - }); + else { + commandKey = splitKeys[i]; + } + String desc = i + 1 < splitKeys.length ? null : registration.getDescription(); + DefaultCommandModelCommand command = commands.computeIfAbsent(commandKey, + (fullCommand) -> new DefaultCommandModelCommand(fullCommand, main, desc)); + + // TODO long vs short + List options = registration.getOptions() + .stream() + .flatMap(co -> Arrays.stream(co.getLongNames())) + .map(lo -> CommandModelOption.of("--", lo)) + .collect(Collectors.toList()); + + if (i == splitKeys.length - 1) { + command.addOptions(options); + } + if (parent != null) { + parent.addCommand(command); + } + if (i == 0) { + topCommands.add(command); + } + } + }); return new DefaultCommandModel(new ArrayList<>(topCommands)); } /** - * Interface for a command model structure. Is also used as entry model - * for ST4 templates which is a reason it has utility methods for easier usage - * of a templates. + * Interface for a command model structure. Is also used as entry model for ST4 + * templates which is a reason it has utility methods for easier usage of a templates. */ interface CommandModel { /** * Gets root level commands where sub-commands can be found. - * * @return root level commands */ List getCommands(); /** * Gets all commands as a flattened structure. - * * @return all commands */ List getAllCommands(); /** * Gets root commands. - * * @return root commands */ List getRootCommands(); + } /** - * Interface for a command in a model. Also contains methods which makes it - * easier to work with ST4 templates. + * Interface for a command in a model. Also contains methods which makes it easier to + * work with ST4 templates. */ - interface CommandModelCommand { + interface CommandModelCommand { /** * Gets a description of a command. @@ -161,53 +159,50 @@ interface CommandModelCommand { /** * Gets options known to this command - * * @return known options */ List getOptions(); /** * Gets command flags. - * * @return command flags */ List getFlags(); /** * Gets sub commands. - * * @return sub commands */ List getSubCommands(); /** * Gets command parts. Essentially full command split into parts. - * * @return command parts */ List getCommandParts(); /** * Gets a main command - * * @return the main command */ String getMainCommand(); /** * Gets a last command part. - * * @return the last command part */ String getLastCommandPart(); + } interface CommandModelOption { + String option(); static CommandModelOption of(String prefix, String name) { return new DefaultCommandModelOption(String.format("%s%s", prefix, name)); } + } class DefaultCommandModel implements CommandModel { @@ -225,29 +220,30 @@ public List getCommands() { @Override public List getAllCommands() { - return getCommands().stream() - .flatMap(c -> flatten(c)) - .collect(Collectors.toList()); + return getCommands().stream().flatMap(c -> flatten(c)).collect(Collectors.toList()); } @Override public List getRootCommands() { - return getCommands().stream() - .map(c -> c.getLastCommandPart()) - .collect(Collectors.toList()); + return getCommands().stream().map(c -> c.getLastCommandPart()).collect(Collectors.toList()); } private Stream flatten(CommandModelCommand command) { return Stream.concat(Stream.of(command), command.getCommands().stream().flatMap(c -> flatten(c))); } + } class DefaultCommandModelCommand implements CommandModelCommand { private String fullCommand; + private String mainCommand; + private String description; + private List commands = new ArrayList<>(); + private List options = new ArrayList<>(); DefaultCommandModelCommand(String fullCommand, String mainCommand, String description) { @@ -279,16 +275,12 @@ public String getMainCommand() { @Override public List getSubCommands() { - return this.commands.stream() - .map(c -> c.getMainCommand()) - .collect(Collectors.toList()); + return this.commands.stream().map(c -> c.getMainCommand()).collect(Collectors.toList()); } @Override public List getFlags() { - return this.options.stream() - .map(o -> o.option()) - .collect(Collectors.toList()); + return this.options.stream().map(o -> o.option()).collect(Collectors.toList()); } @Override @@ -340,7 +332,8 @@ public boolean equals(Object obj) { if (other.fullCommand != null) { return false; } - } else if (!fullCommand.equals(other.fullCommand)) { + } + else if (!fullCommand.equals(other.fullCommand)) { return false; } return true; @@ -349,6 +342,7 @@ public boolean equals(Object obj) { private AbstractCompletions getEnclosingInstance() { return AbstractCompletions.this; } + } static class DefaultCommandModelOption implements CommandModelOption { @@ -363,12 +357,14 @@ public DefaultCommandModelOption(String option) { public String option() { return option; } + } private static String resourceAsString(Resource resource) { try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) { return FileCopyUtils.copyToString(reader); - } catch (IOException e) { + } + catch (IOException e) { throw new UncheckedIOException(e); } } @@ -376,15 +372,21 @@ private static String resourceAsString(Resource resource) { interface Builder { Builder attribute(String name, Object value); + Builder group(String resource); + Builder appendGroup(String instance); + String build(); + } class DefaultBuilder implements Builder { private final MultiValueMap defaultAttributes = new LinkedMultiValueMap<>(); + private final List> operations = new ArrayList<>(); + private String groupResource; @Override @@ -427,5 +429,7 @@ public String build() { }); return buf.toString(); } + } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/BashCompletions.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/BashCompletions.java index 291bbf481..3987785cb 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/BashCompletions.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/BashCompletions.java @@ -31,11 +31,11 @@ public BashCompletions(ResourceLoader resourceLoader, CommandCatalog commandCata public String generate(String rootCommand) { CommandModel model = generateCommandModel(); - return builder() - .attribute("name", rootCommand) - .attribute("model", model) - .group("classpath:completion/bash.stg") - .appendGroup("main") - .build(); + return builder().attribute("name", rootCommand) + .attribute("model", model) + .group("classpath:completion/bash.stg") + .appendGroup("main") + .build(); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/StandardCompletionModelsRuntimeHints.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/StandardCompletionModelsRuntimeHints.java index 28bc9238b..a641a845e 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/StandardCompletionModelsRuntimeHints.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/StandardCompletionModelsRuntimeHints.java @@ -47,4 +47,5 @@ private void registerForDeclaredMethodsInvocation(ReflectionHints reflection, Cl private Iterable typeReferences(Class... classes) { return Stream.of(classes).map(TypeReference::of).collect(Collectors.toList()); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/ZshCompletions.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/ZshCompletions.java index 0e37399a6..e5ac31d43 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/ZshCompletions.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/completion/ZshCompletions.java @@ -31,11 +31,11 @@ public ZshCompletions(ResourceLoader resourceLoader, CommandCatalog commandCatal public String generate(String rootCommand) { CommandModel model = generateCommandModel(); - return builder() - .attribute("name", rootCommand) - .attribute("model", model) - .group("classpath:completion/zsh.stg") - .appendGroup("main") - .build(); + return builder().attribute("name", rootCommand) + .attribute("model", model) + .group("classpath:completion/zsh.stg") + .appendGroup("main") + .build(); } + } diff --git a/spring-shell-standard/src/main/java/org/springframework/shell/standard/package-info.java b/spring-shell-standard/src/main/java/org/springframework/shell/standard/package-info.java index 1a891cc9a..76b301482 100644 --- a/spring-shell-standard/src/main/java/org/springframework/shell/standard/package-info.java +++ b/spring-shell-standard/src/main/java/org/springframework/shell/standard/package-info.java @@ -15,7 +15,8 @@ */ /** - * Contains infrastructure for describing commands with the "new" preferred Spring Shell programming model. + * Contains infrastructure for describing commands with the "new" preferred Spring Shell + * programming model. * * @author Eric Bottard */ diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/CommandValueProviderTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/CommandValueProviderTests.java index 4d2de9e12..edce2e126 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/CommandValueProviderTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/CommandValueProviderTests.java @@ -62,7 +62,7 @@ public void testValues() { when(catalog.getRegistrations()).thenReturn(registrations); List proposals = valueProvider.complete(completionContext); - assertThat(proposals).extracting("value", String.class) - .contains("me", "meow", "yourself"); + assertThat(proposals).extracting("value", String.class).contains("me", "meow", "yourself"); } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java index d6fb4fef7..387126caf 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/StandardMethodTargetRegistrarTests.java @@ -44,9 +44,13 @@ public class StandardMethodTargetRegistrarTests { private StandardMethodTargetRegistrar registrar; + private AnnotationConfigApplicationContext applicationContext; + private CommandCatalog catalog; + private DefaultShellContext shellContext; + private CommandRegistration.BuilderSupplier builder = () -> CommandRegistration.builder(); @BeforeEach @@ -93,10 +97,11 @@ public String sayHello(String what) { return "hello " + what; } - @ShellMethod(value = "method with alias", key = {"hi", "alias"}) + @ShellMethod(value = "method with alias", key = { "hi", "alias" }) public String greet(String what) { return "hi " + what; } + } @Test @@ -119,6 +124,7 @@ public static class Sample2 { public String sayHello(@ShellOption String what) { return "hello " + what; } + } @Test @@ -139,9 +145,10 @@ public void testOptionOptionalWithAnnotation() { public static class Sample3 { @ShellMethod("some command") - public String sayHello(@ShellOption( defaultValue = ShellOption.NULL) String what) { + public String sayHello(@ShellOption(defaultValue = ShellOption.NULL) String what) { return "hello " + what; } + } @Test @@ -170,7 +177,8 @@ public void testAvailabilityIndicators() { assertThat(registrations.get("bonjour").getAvailability().isAvailable()).isTrue(); sample.available = false; assertThat(registrations.get("bonjour").getAvailability().isAvailable()).isFalse(); - assertThat(registrations.get("bonjour").getAvailability().getReason()).isEqualTo("availabilityForSeveralCommands"); + assertThat(registrations.get("bonjour").getAvailability().getReason()) + .isEqualTo("availabilityForSeveralCommands"); sample.available = true; } @@ -183,26 +191,27 @@ public static class SampleWithAvailability { public void sayHello() { } + public Availability sayHelloAvailability() { return available ? Availability.available() : Availability.unavailable("sayHelloAvailability"); } - @ShellMethodAvailability("customAvailabilityMethod") @ShellMethod("some method with an explicit availability indicator") public void hi() { } + public Availability customAvailabilityMethod() { return available ? Availability.available() : Availability.unavailable("customAvailabilityMethod"); } - @ShellMethod(value = "some method with an explicit availability indicator", key = {"bonjour", "salut"}) + @ShellMethod(value = "some method with an explicit availability indicator", key = { "bonjour", "salut" }) public void bonjour() { } - @ShellMethodAvailability({"salut", "other"}) + @ShellMethodAvailability({ "salut", "other" }) public Availability availabilityForSeveralCommands() { return available ? Availability.available() : Availability.unavailable("availabilityForSeveralCommands"); } @@ -216,6 +225,7 @@ public void wild() { private Availability availabilityFromWildcard() { return available ? Availability.available() : Availability.unavailable("availabilityFromWildcard"); } + } @Test @@ -226,18 +236,20 @@ public void testAvailabilityIndicatorErrorMultipleExplicit() { assertThatThrownBy(() -> { registrar.register(catalog); }).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("When set on a @ShellMethod method, the value of the @ShellMethodAvailability should be a single element") - .hasMessageContaining("Found [one, two]") - .hasMessageContaining("wrong()"); + .hasMessageContaining( + "When set on a @ShellMethod method, the value of the @ShellMethodAvailability should be a single element") + .hasMessageContaining("Found [one, two]") + .hasMessageContaining("wrong()"); } @ShellComponent public static class WrongAvailabilityIndicatorOnShellMethod { - @ShellMethodAvailability({"one", "two"}) + @ShellMethodAvailability({ "one", "two" }) @ShellMethod("foo") public void wrong() { } + } @Test @@ -248,14 +260,15 @@ public void testAvailabilityIndicatorWildcardNotAlone() { assertThatThrownBy(() -> { registrar.register(catalog); }).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("When using '*' as a wildcard for ShellMethodAvailability, this can be the only value. Found [one, *]") - .hasMessageContaining("availability()"); + .hasMessageContaining( + "When using '*' as a wildcard for ShellMethodAvailability, this can be the only value. Found [one, *]") + .hasMessageContaining("availability()"); } @ShellComponent public static class WrongAvailabilityIndicatorWildcardNotAlone { - @ShellMethodAvailability({"one", "*"}) + @ShellMethodAvailability({ "one", "*" }) public Availability availability() { return Availability.available(); } @@ -264,6 +277,7 @@ public Availability availability() { public void wrong() { } + } @Test @@ -274,21 +288,21 @@ public void testAvailabilityIndicatorAmbiguous() { assertThatThrownBy(() -> { registrar.register(catalog); }).isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("Found several @ShellMethodAvailability") - .hasMessageContaining("wrong()") - .hasMessageContaining("availability()") - .hasMessageContaining("otherAvailability()"); + .hasMessageContaining("Found several @ShellMethodAvailability") + .hasMessageContaining("wrong()") + .hasMessageContaining("availability()") + .hasMessageContaining("otherAvailability()"); } @ShellComponent public static class WrongAvailabilityIndicatorAmbiguous { - @ShellMethodAvailability({"one", "wrong"}) + @ShellMethodAvailability({ "one", "wrong" }) public Availability availability() { return Availability.available(); } - @ShellMethodAvailability({"bar", "wrong"}) + @ShellMethodAvailability({ "bar", "wrong" }) public Availability otherAvailability() { return Availability.available(); } @@ -297,12 +311,13 @@ public Availability otherAvailability() { public void wrong() { } + } @Test public void testGrouping() { - applicationContext = new AnnotationConfigApplicationContext(GroupOneCommands.class, - GroupTwoCommands.class, GroupThreeCommands.class); + applicationContext = new AnnotationConfigApplicationContext(GroupOneCommands.class, GroupTwoCommands.class, + GroupThreeCommands.class); registrar = new StandardMethodTargetRegistrar(applicationContext, builder); registrar.register(catalog); @@ -334,10 +349,10 @@ public void testGrouping() { @Test public void testInteractionModeInteractive() { - shellContext.setInteractionMode(InteractionMode.INTERACTIVE); + shellContext.setInteractionMode(InteractionMode.INTERACTIVE); applicationContext = new AnnotationConfigApplicationContext(InteractionModeCommands.class); registrar = new StandardMethodTargetRegistrar(applicationContext, builder); - registrar.register(catalog); + registrar.register(catalog); assertThat(catalog.getRegistrations().get("foo1")).isNotNull(); assertThat(catalog.getRegistrations().get("foo2")).isNull(); @@ -346,10 +361,10 @@ public void testInteractionModeInteractive() { @Test public void testInteractionModeNonInteractive() { - shellContext.setInteractionMode(InteractionMode.NONINTERACTIVE); + shellContext.setInteractionMode(InteractionMode.NONINTERACTIVE); applicationContext = new AnnotationConfigApplicationContext(InteractionModeCommands.class); registrar = new StandardMethodTargetRegistrar(applicationContext, builder); - registrar.register(catalog); + registrar.register(catalog); assertThat(catalog.getRegistrations().get("foo1")).isNull(); assertThat(catalog.getRegistrations().get("foo2")).isNotNull(); @@ -370,14 +385,15 @@ public void foo2() { @ShellMethod(value = "foo3") public void foo3() { } + } @Test public void testOptionUseDefaultValue() { - shellContext.setInteractionMode(InteractionMode.NONINTERACTIVE); + shellContext.setInteractionMode(InteractionMode.NONINTERACTIVE); applicationContext = new AnnotationConfigApplicationContext(DefaultValuesCommands.class); registrar = new StandardMethodTargetRegistrar(applicationContext, builder); - registrar.register(catalog); + registrar.register(catalog); assertThat(catalog.getRegistrations().get("foo1")).isNotNull(); assertThat(catalog.getRegistrations().get("foo1").getOptions()).hasSize(1); @@ -406,6 +422,7 @@ public void foo2(@ShellOption(defaultValue = ShellOption.NONE) String arg1) { @ShellMethod(value = "foo") public void foo3(@ShellOption(defaultValue = ShellOption.NULL) String arg1) { } + } @Test @@ -461,6 +478,7 @@ public void foo3(@ShellOption boolean arg1) { @ShellMethod(value = "foo4") public void foo4(boolean arg1) { } + } @Test @@ -481,6 +499,7 @@ public static class OptionWithoutHyphenRegisterFromDefaultPrefix { @ShellMethod(value = "foo1") public void foo1(@ShellOption("xxx") boolean arg1) { } + } @Test @@ -501,6 +520,7 @@ public static class OptionWithoutHyphenRegisterFromChangedPrefix { @ShellMethod(value = "foo1", prefix = "-") public void foo1(@ShellOption("x") boolean arg1) { } + } @Test @@ -524,9 +544,11 @@ public static class OptionWithCustomType { @ShellMethod(value = "foo1", prefix = "-") public void foo1(@ShellOption Set arg1) { } + } public static class Pojo { } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModelTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModelTests.java index 0620f4e39..0853c1db5 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModelTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandAvailabilityInfoModelTests.java @@ -31,4 +31,5 @@ void hasDefaults() { assertThat(caim.getAvailable()).isFalse(); assertThat(caim.getReason()).isEqualTo("fakereason"); } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandInfoModelTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandInfoModelTests.java index 85fbff92d..eebadeeda 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandInfoModelTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/CommandInfoModelTests.java @@ -25,33 +25,21 @@ public class CommandInfoModelTests { @Test void hasGivenName() { - CommandRegistration r1 = CommandRegistration.builder() - .command("main1") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + CommandRegistration r1 = CommandRegistration.builder().command("main1").withTarget().consumer(ctx -> { + }).and().build(); CommandInfoModel cim = CommandInfoModel.of("main1", r1); assertThat(cim.getName()).isEqualTo("main1"); } @Test void hasGivenNames() { - CommandRegistration r1 = CommandRegistration.builder() - .command("main1") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + CommandRegistration r1 = CommandRegistration.builder().command("main1").withTarget().consumer(ctx -> { + }).and().build(); CommandInfoModel cim = CommandInfoModel.of("main1", r1); assertThat(cim.getNames()).containsExactly("main1"); - r1 = CommandRegistration.builder() - .command("main1 sub1") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + r1 = CommandRegistration.builder().command("main1 sub1").withTarget().consumer(ctx -> { + }).and().build(); cim = CommandInfoModel.of("main1 sub1", r1); assertThat(cim.getNames()).containsExactly("main1", "sub1"); @@ -63,8 +51,9 @@ void hasGivenDescription() { .command("main1") .description("desc1") .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); CommandInfoModel cim = CommandInfoModel.of("main1", r1); assertThat(cim.getDescription()).isEqualTo("desc1"); @@ -72,24 +61,16 @@ void hasGivenDescription() { @Test void hasNoParameters() { - CommandRegistration r1 = CommandRegistration.builder() - .command("main1") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + CommandRegistration r1 = CommandRegistration.builder().command("main1").withTarget().consumer(ctx -> { + }).and().build(); CommandInfoModel cim = CommandInfoModel.of("main1", r1); assertThat(cim.getParameters()).isEmpty(); } @Test void hasExpectedDefaultAvailability() { - CommandRegistration r1 = CommandRegistration.builder() - .command("main1") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + CommandRegistration r1 = CommandRegistration.builder().command("main1").withTarget().consumer(ctx -> { + }).and().build(); CommandInfoModel cim = CommandInfoModel.of("main1", r1); assertThat(cim.getAvailability()).isNotNull(); assertThat(cim.getAvailability().getAvailable()).isTrue(); @@ -98,12 +79,8 @@ void hasExpectedDefaultAvailability() { @Test void hasNoAliases() { - CommandRegistration r1 = CommandRegistration.builder() - .command("main1") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + CommandRegistration r1 = CommandRegistration.builder().command("main1").withTarget().consumer(ctx -> { + }).and().build(); CommandInfoModel cim = CommandInfoModel.of("main1", r1); assertThat(cim.getAliases()).isEmpty(); } @@ -113,11 +90,12 @@ void hasAliases() { CommandRegistration r1 = CommandRegistration.builder() .command("main1") .withAlias() - .command("alias1") - .and() + .command("alias1") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); CommandInfoModel cim = CommandInfoModel.of("main1", r1); assertThat(cim.getAliases()).containsExactly("alias1"); @@ -128,12 +106,13 @@ void voidTypeUsesEmptyStringAsName() { CommandRegistration r1 = CommandRegistration.builder() .command("main1") .withOption() - .longNames("arg1") - .type(void.class) - .and() + .longNames("arg1") + .type(void.class) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); CommandInfoModel cim1 = CommandInfoModel.of("main1", r1); assertThat(cim1.getParameters()).hasSize(1); @@ -143,16 +122,18 @@ void voidTypeUsesEmptyStringAsName() { CommandRegistration r2 = CommandRegistration.builder() .command("main1") .withOption() - .longNames("arg1") - .type(Void.class) - .and() + .longNames("arg1") + .type(Void.class) + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); CommandInfoModel cim2 = CommandInfoModel.of("main1", r2); assertThat(cim2.getParameters()).hasSize(1); assertThat(cim2.getParameters().get(0).getArguments()).containsExactly("--arg1"); assertThat(cim2.getParameters().get(0).getType()).isEmpty(); } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/GroupsInfoModelTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/GroupsInfoModelTests.java index 95a21e145..45458cbc8 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/GroupsInfoModelTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/GroupsInfoModelTests.java @@ -43,18 +43,10 @@ void showGroupsIsSet() { @Test void simpleCommandsAreSeparated() { - CommandRegistration r1 = CommandRegistration.builder() - .command("main1") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); - CommandRegistration r2 = CommandRegistration.builder() - .command("main2") - .withTarget() - .consumer(ctx -> {}) - .and() - .build(); + CommandRegistration r1 = CommandRegistration.builder().command("main1").withTarget().consumer(ctx -> { + }).and().build(); + CommandRegistration r2 = CommandRegistration.builder().command("main2").withTarget().consumer(ctx -> { + }).and().build(); this.commandCatalog.register(r1, r2); GroupsInfoModel gim = buildGIM(); @@ -67,11 +59,12 @@ void aliasNotAddedToTopModel() { CommandRegistration r1 = CommandRegistration.builder() .command("main1") .withAlias() - .command("alias1") - .and() + .command("alias1") + .and() .withTarget() - .consumer(ctx -> {}) - .and() + .consumer(ctx -> { + }) + .and() .build(); this.commandCatalog.register(r1); GroupsInfoModel gim = buildGIM(); @@ -86,4 +79,5 @@ private GroupsInfoModel buildGIM(boolean showGroups) { private GroupsInfoModel buildGIM() { return buildGIM(true); } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/HelpTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/HelpTests.java index 563b6f33c..abb350237 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/HelpTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/commands/HelpTests.java @@ -58,7 +58,9 @@ public class HelpTests { private static Locale previousLocale; + private String testName; + private CommandsPojo commandsPojo = new CommandsPojo(); @Autowired @@ -96,29 +98,29 @@ public void testCommandHelp() throws Exception { .command("first-command") .description("A rather extensive description of some command.") .withTarget() - .method(commandsPojo, "firstCommand") - .and() + .method(commandsPojo, "firstCommand") + .and() .withOption() - .shortNames('r') - .description("Whether to delete recursively") - .type(boolean.class) - .and() + .shortNames('r') + .description("Whether to delete recursively") + .type(boolean.class) + .and() .withOption() - .shortNames('f') - .description("Do not ask for confirmation. YOLO") - .type(boolean.class) - .and() + .shortNames('f') + .description("Do not ask for confirmation. YOLO") + .type(boolean.class) + .and() .withOption() - .shortNames('n') - .description("The answer to everything") - .defaultValue("42") - .type(int.class) - .and() + .shortNames('n') + .description("The answer to everything") + .defaultValue("42") + .type(int.class) + .and() .withOption() - .shortNames('o') - .description("Some other parameters") - .type(float[].class) - .and() + .shortNames('o') + .description("Some other parameters") + .type(float[].class) + .and() .build(); commandCatalog.register(registration); String help = this.help.help(new String[] { "first-command" }).toString(); @@ -155,7 +157,9 @@ private String removeNewLines(String str) { } private String sample() throws IOException { - InputStream is = new ClassPathResource(HelpTests.class.getSimpleName() + "-" + testName + ".txt", HelpTests.class).getInputStream(); + InputStream is = new ClassPathResource(HelpTests.class.getSimpleName() + "-" + testName + ".txt", + HelpTests.class) + .getInputStream(); return removeNewLines(FileCopyUtils.copyToString(new InputStreamReader(is, "UTF-8"))); } @@ -164,14 +168,14 @@ private void registerCommandListCommands() throws Exception { .command("first-command") .description("A rather extensive description of some command.") .withAlias() - .command("1st-command") - .and() + .command("1st-command") + .and() .withTarget() - .method(commandsPojo, "firstCommand") - .and() + .method(commandsPojo, "firstCommand") + .and() .withOption() - .shortNames('r') - .and() + .shortNames('r') + .and() .build(); commandCatalog.register(registration1); @@ -179,11 +183,11 @@ private void registerCommandListCommands() throws Exception { .command("second-command") .description("The second command. This one is known under several aliases as well.") .withAlias() - .command("yet-another-command") - .and() + .command("yet-another-command") + .and() .withTarget() - .method(commandsPojo, "secondCommand") - .and() + .method(commandsPojo, "secondCommand") + .and() .build(); commandCatalog.register(registration2); @@ -191,8 +195,8 @@ private void registerCommandListCommands() throws Exception { .command("third-command") .description("The last command.") .withTarget() - .method(commandsPojo, "thirdCommand") - .and() + .method(commandsPojo, "thirdCommand") + .and() .build(); commandCatalog.register(registration3); @@ -201,8 +205,8 @@ private void registerCommandListCommands() throws Exception { .description("The first command in a separate group.") .group("Example Group") .withTarget() - .method(commandsPojo, "firstCommandInGroup") - .and() + .method(commandsPojo, "firstCommandInGroup") + .and() .build(); commandCatalog.register(registration4); @@ -211,8 +215,8 @@ private void registerCommandListCommands() throws Exception { .description("The second command in a separate group.") .group("Example Group") .withTarget() - .method(commandsPojo, "secondCommandInGroup") - .and() + .method(commandsPojo, "secondCommandInGroup") + .and() .build(); commandCatalog.register(registration5); } @@ -236,6 +240,7 @@ public Help help() { help.setCommandsTemplate("classpath:template/help-commands-default.stg"); return help; } + } @ShellComponent @@ -246,13 +251,13 @@ public void firstCommand( // Single key and arity = 0. Help displayed on same line @ShellOption(help = "Whether to delete recursively", arity = 0, value = "-r") boolean r, // Multiple keys and arity 0. Help displayed on next line - @ShellOption(help = "Do not ask for confirmation. YOLO", arity = 0, value = {"-f", "--force"}) boolean force, + @ShellOption(help = "Do not ask for confirmation. YOLO", arity = 0, + value = { "-f", "--force" }) boolean force, // Single key, arity >= 1. Help displayed on next line. Optional // Also, bears bean validation annotation @ShellOption(help = "The answer to everything", defaultValue = "42", value = "-n") @Max(5) int n, - // Single key, arity > 1. - @ShellOption(help = "Some other parameters", arity = 3, value = "-o") float[] o - ) { + // Single key, arity > 1. + @ShellOption(help = "Some other parameters", arity = 3, value = "-o") float[] o) { } @ShellMethod @@ -270,5 +275,7 @@ public void firstCommandInGroup() { @ShellMethod public void secondCommandInGroup() { } + } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/AbstractCompletionsTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/AbstractCompletionsTests.java index 77286a8f3..8a4f5b909 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/AbstractCompletionsTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/AbstractCompletionsTests.java @@ -34,85 +34,85 @@ public class AbstractCompletionsTests { private final CommandRegistration r1 = CommandRegistration.builder() .command("test1") .withTarget() - .method(commands, "test1") - .and() + .method(commands, "test1") + .and() .withOption() - .longNames("param1") - .and() + .longNames("param1") + .and() .build(); private final CommandRegistration r2 = CommandRegistration.builder() .command("test2") .withTarget() - .method(commands, "test2") - .and() + .method(commands, "test2") + .and() .build(); private final CommandRegistration r3 = CommandRegistration.builder() .command("test3") .withTarget() - .method(commands, "test3") - .and() + .method(commands, "test3") + .and() .build(); private final CommandRegistration r3_4 = CommandRegistration.builder() .command("test3", "test4") .withTarget() - .method(commands, "test4") - .and() + .method(commands, "test4") + .and() .withOption() - .longNames("param4") - .and() + .longNames("param4") + .and() .build(); private final CommandRegistration r3_5 = CommandRegistration.builder() .command("test3", "test5") .withTarget() - .method(commands, "test4") - .and() + .method(commands, "test4") + .and() .withOption() - .longNames("param4") - .and() + .longNames("param4") + .and() .build(); private final CommandRegistration r3_4_5 = CommandRegistration.builder() .command("test3", "test4", "test5") .withTarget() - .method(commands, "test4") - .and() + .method(commands, "test4") + .and() .withOption() - .longNames("param4") - .and() + .longNames("param4") + .and() .build(); private final CommandRegistration r3_4_6 = CommandRegistration.builder() .command("test3", "test4", "test6") .withTarget() - .method(commands, "test4") - .and() + .method(commands, "test4") + .and() .withOption() - .longNames("param4") - .and() + .longNames("param4") + .and() .build(); private final CommandRegistration r3_5_5 = CommandRegistration.builder() .command("test3", "test5", "test5") .withTarget() - .method(commands, "test4") - .and() + .method(commands, "test4") + .and() .withOption() - .longNames("param4") - .and() + .longNames("param4") + .and() .build(); private final CommandRegistration r3_5_6 = CommandRegistration.builder() .command("test3", "test5", "test6") .withTarget() - .method(commands, "test4") - .and() + .method(commands, "test4") + .and() .withOption() - .longNames("param4") - .and() + .longNames("param4") + .and() .build(); @Test @@ -127,38 +127,27 @@ public void deepL3Commands() { TestCompletions completions = new TestCompletions(resourceLoader, commandCatalog); CommandModel commandModel = completions.testCommandModel(); - assertThat(commandModel.getCommands()).satisfiesExactlyInAnyOrder( - c3 -> { - assertThat(c3.getMainCommand()).isEqualTo("test3"); - assertThat(c3.getOptions()).hasSize(0); - assertThat(c3.getSubCommands()).hasSize(2); - assertThat(c3.getCommands()).hasSize(2); - assertThat(c3.getCommands()).satisfiesExactlyInAnyOrder( - c34 -> { - assertThat(c34.getMainCommand()).isEqualTo("test4"); - assertThat(c34.getCommands()).satisfiesExactlyInAnyOrder( - c345 -> { - assertThat(c345.getMainCommand()).isEqualTo("test5"); - }, - c346 -> { - assertThat(c346.getMainCommand()).isEqualTo("test6"); - } - ); - }, - c35 -> { - assertThat(c35.getMainCommand()).isEqualTo("test5"); - assertThat(c35.getCommands()).satisfiesExactlyInAnyOrder( - c355 -> { - assertThat(c355.getMainCommand()).isEqualTo("test5"); - }, - c356 -> { - assertThat(c356.getMainCommand()).isEqualTo("test6"); - } - ); - } - ); - } - ); + assertThat(commandModel.getCommands()).satisfiesExactlyInAnyOrder(c3 -> { + assertThat(c3.getMainCommand()).isEqualTo("test3"); + assertThat(c3.getOptions()).hasSize(0); + assertThat(c3.getSubCommands()).hasSize(2); + assertThat(c3.getCommands()).hasSize(2); + assertThat(c3.getCommands()).satisfiesExactlyInAnyOrder(c34 -> { + assertThat(c34.getMainCommand()).isEqualTo("test4"); + assertThat(c34.getCommands()).satisfiesExactlyInAnyOrder(c345 -> { + assertThat(c345.getMainCommand()).isEqualTo("test5"); + }, c346 -> { + assertThat(c346.getMainCommand()).isEqualTo("test6"); + }); + }, c35 -> { + assertThat(c35.getMainCommand()).isEqualTo("test5"); + assertThat(c35.getCommands()).satisfiesExactlyInAnyOrder(c355 -> { + assertThat(c355.getMainCommand()).isEqualTo("test5"); + }, c356 -> { + assertThat(c356.getMainCommand()).isEqualTo("test6"); + }); + }); + }); } @Test @@ -171,34 +160,25 @@ public void deepL2Commands() { TestCompletions completions = new TestCompletions(resourceLoader, commandCatalog); CommandModel commandModel = completions.testCommandModel(); - assertThat(commandModel.getCommands()).satisfiesExactlyInAnyOrder( - c3 -> { - assertThat(c3.getMainCommand()).isEqualTo("test3"); - assertThat(c3.getOptions()).hasSize(0); - assertThat(c3.getSubCommands()).hasSize(2); - assertThat(c3.getCommands()).hasSize(2); - assertThat(c3.getCommands()).satisfiesExactlyInAnyOrder( - c34 -> { - assertThat(c34.getMainCommand()).isEqualTo("test4"); - assertThat(c34.getOptions()).hasSize(1); - assertThat(c34.getOptions()).satisfiesExactly( - o -> { - assertThat(o.option()).isEqualTo("--param4"); - } - ); - }, - c35 -> { - assertThat(c35.getMainCommand()).isEqualTo("test5"); - assertThat(c35.getOptions()).hasSize(1); - assertThat(c35.getOptions()).satisfiesExactly( - o -> { - assertThat(o.option()).isEqualTo("--param4"); - } - ); - } - ); - } - ); + assertThat(commandModel.getCommands()).satisfiesExactlyInAnyOrder(c3 -> { + assertThat(c3.getMainCommand()).isEqualTo("test3"); + assertThat(c3.getOptions()).hasSize(0); + assertThat(c3.getSubCommands()).hasSize(2); + assertThat(c3.getCommands()).hasSize(2); + assertThat(c3.getCommands()).satisfiesExactlyInAnyOrder(c34 -> { + assertThat(c34.getMainCommand()).isEqualTo("test4"); + assertThat(c34.getOptions()).hasSize(1); + assertThat(c34.getOptions()).satisfiesExactly(o -> { + assertThat(o.option()).isEqualTo("--param4"); + }); + }, c35 -> { + assertThat(c35.getMainCommand()).isEqualTo("test5"); + assertThat(c35.getOptions()).hasSize(1); + assertThat(c35.getOptions()).satisfiesExactly(o -> { + assertThat(o.option()).isEqualTo("--param4"); + }); + }); + }); } @Test @@ -213,40 +193,30 @@ public void testBasicModelGeneration() { TestCompletions completions = new TestCompletions(resourceLoader, commandCatalog); CommandModel commandModel = completions.testCommandModel(); - assertThat(commandModel.getCommands()).satisfiesExactlyInAnyOrder( - c1 -> { - assertThat(c1.getMainCommand()).isEqualTo("test1"); - assertThat(c1.getSubCommands()).hasSize(0); - assertThat(c1.getOptions()).hasSize(1); - assertThat(c1.getOptions()).satisfiesExactly( - o -> { - assertThat(o.option()).isEqualTo("--param1"); - } - ); - }, - c2 -> { - assertThat(c2.getMainCommand()).isEqualTo("test2"); - assertThat(c2.getSubCommands()).hasSize(0); - assertThat(c2.getOptions()).hasSize(0); - }, - c3 -> { - assertThat(c3.getMainCommand()).isEqualTo("test3"); - assertThat(c3.getOptions()).hasSize(0); - assertThat(c3.getSubCommands()).hasSize(1); - assertThat(c3.getCommands()).hasSize(1); - assertThat(c3.getCommands()).satisfiesExactly( - c34 -> { - assertThat(c34.getMainCommand()).isEqualTo("test4"); - assertThat(c34.getOptions()).hasSize(1); - assertThat(c34.getOptions()).satisfiesExactly( - o -> { - assertThat(o.option()).isEqualTo("--param4"); - } - ); - } - ); - } - ); + assertThat(commandModel.getCommands()).satisfiesExactlyInAnyOrder(c1 -> { + assertThat(c1.getMainCommand()).isEqualTo("test1"); + assertThat(c1.getSubCommands()).hasSize(0); + assertThat(c1.getOptions()).hasSize(1); + assertThat(c1.getOptions()).satisfiesExactly(o -> { + assertThat(o.option()).isEqualTo("--param1"); + }); + }, c2 -> { + assertThat(c2.getMainCommand()).isEqualTo("test2"); + assertThat(c2.getSubCommands()).hasSize(0); + assertThat(c2.getOptions()).hasSize(0); + }, c3 -> { + assertThat(c3.getMainCommand()).isEqualTo("test3"); + assertThat(c3.getOptions()).hasSize(0); + assertThat(c3.getSubCommands()).hasSize(1); + assertThat(c3.getCommands()).hasSize(1); + assertThat(c3.getCommands()).satisfiesExactly(c34 -> { + assertThat(c34.getMainCommand()).isEqualTo("test4"); + assertThat(c34.getOptions()).hasSize(1); + assertThat(c34.getOptions()).satisfiesExactly(o -> { + assertThat(o.option()).isEqualTo("--param4"); + }); + }); + }); } @Test @@ -256,10 +226,10 @@ public void testBuilder() { TestCompletions completions = new TestCompletions(resourceLoader, commandCatalog); String result = completions.testBuilder() - .attribute("x", "command") - .group("classpath:completion/test.stg") - .appendGroup("a") - .build(); + .attribute("x", "command") + .group("classpath:completion/test.stg") + .appendGroup("a") + .build(); assertThat(result).contains("foocommand"); } @@ -276,6 +246,7 @@ CommandModel testCommandModel() { Builder testBuilder() { return super.builder(); } + } private static class TestCommands { @@ -295,5 +266,7 @@ void test3() { @ShellMethod void test4(@ShellOption String param4) { } + } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/BashCompletionsTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/BashCompletionsTests.java index af374b092..d0fb8832e 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/BashCompletionsTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/BashCompletionsTests.java @@ -84,11 +84,11 @@ private void registerFromMethod(CommandCatalog commandCatalog) { CommandRegistration registration = CommandRegistration.builder() .command("testmethod1") .withTarget() - .method(pojo1, "method1") - .and() + .method(pojo1, "method1") + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); commandCatalog.register(registration); } @@ -101,17 +101,20 @@ private void registerFromFunction(CommandCatalog commandCatalog, String command) CommandRegistration registration = CommandRegistration.builder() .command(command) .withTarget() - .function(function) - .and() + .function(function) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); commandCatalog.register(registration); } protected static class Pojo1 { - void method1() {} + void method1() { + } + } + } diff --git a/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/ZshCompletionsTests.java b/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/ZshCompletionsTests.java index 21091f067..948196c23 100644 --- a/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/ZshCompletionsTests.java +++ b/spring-shell-standard/src/test/java/org/springframework/shell/standard/completion/ZshCompletionsTests.java @@ -84,11 +84,11 @@ private void registerFromMethod(CommandCatalog commandCatalog) { .command("testmethod1") .description("desc") .withTarget() - .method(pojo1, "method1") - .and() + .method(pojo1, "method1") + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); commandCatalog.register(registration); } @@ -101,17 +101,20 @@ private void registerFromFunction(CommandCatalog commandCatalog, String command) CommandRegistration registration = CommandRegistration.builder() .command(command) .withTarget() - .function(function) - .and() + .function(function) + .and() .withOption() - .longNames("arg1") - .and() + .longNames("arg1") + .and() .build(); commandCatalog.register(registration); } protected static class Pojo1 { - void method1() {} + void method1() { + } + } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/TerminalSizeAware.java b/spring-shell-table/src/main/java/org/springframework/shell/TerminalSizeAware.java index 7d8735525..ae3536d80 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/TerminalSizeAware.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/TerminalSizeAware.java @@ -17,14 +17,18 @@ package org.springframework.shell; /** - * To be implemented by command result objects that can adapt to the terminal size when they are being rendered. + * To be implemented by command result objects that can adapt to the terminal size when + * they are being rendered. * - *

        An object which does not implement this interface will simply be rendered by invoking its {@link Object#toString()} - * method.

        + *

        + * An object which does not implement this interface will simply be rendered by invoking + * its {@link Object#toString()} method. + *

        * * @author Eric Bottard */ public interface TerminalSizeAware { CharSequence render(int terminalWidth); + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/AbsoluteWidthSizeConstraints.java b/spring-shell-table/src/main/java/org/springframework/shell/table/AbsoluteWidthSizeConstraints.java index 99ea47000..cf58092aa 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/AbsoluteWidthSizeConstraints.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/AbsoluteWidthSizeConstraints.java @@ -29,9 +29,9 @@ public AbsoluteWidthSizeConstraints(int width) { this.width = width; } - @Override public Extent width(String[] raw, int previous, int tableWidth) { return new Extent(width, width); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/Aligner.java b/spring-shell-table/src/main/java/org/springframework/shell/table/Aligner.java index fcb1b4321..e1e838660 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/Aligner.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/Aligner.java @@ -24,18 +24,18 @@ public interface Aligner { /** - * Perform text alignment, returning a String array that MUST contain {@code cellHeight} - * lines, each of which MUST be {@code cellWidth} chars in length. + * Perform text alignment, returning a String array that MUST contain + * {@code cellHeight} lines, each of which MUST be {@code cellWidth} chars in length. * *

        - * Input array is guaranteed to contain lines that have length equal to {@code cellWidth}. - * There is no guarantee on the input number of lines though. + * Input array is guaranteed to contain lines that have length equal to + * {@code cellWidth}. There is no guarantee on the input number of lines though. *

        - * * @param text the text to align * @param cellWidth the width of of the table cell * @param cellHeight the height of the table cell * @return the aligned text, in a {@code cellHeight} element array */ String[] align(String[] text, int cellWidth, int cellHeight); + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/ArrayTableModel.java b/spring-shell-table/src/main/java/org/springframework/shell/table/ArrayTableModel.java index 16ae2e3de..f096b967b 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/ArrayTableModel.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/ArrayTableModel.java @@ -46,4 +46,5 @@ public int getColumnCount() { public Object getValue(int row, int column) { return data[row][column]; } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/AutoSizeConstraints.java b/spring-shell-table/src/main/java/org/springframework/shell/table/AutoSizeConstraints.java index e48ba5b9b..4eca09630 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/AutoSizeConstraints.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/AutoSizeConstraints.java @@ -17,8 +17,8 @@ package org.springframework.shell.table; /** - * A SizeConstraints implementation that splits lines at space boundaries - * and returns an extent with minimal and maximal width requirements. + * A SizeConstraints implementation that splits lines at space boundaries and returns an + * extent with minimal and maximal width requirements. * * @author Eric Bottard */ @@ -37,4 +37,5 @@ public Extent width(String[] raw, int tableWidth, int nbColumns) { } return new Extent(min, max); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/BeanListTableModel.java b/spring-shell-table/src/main/java/org/springframework/shell/table/BeanListTableModel.java index db1d15d2e..d3418cdf7 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/BeanListTableModel.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/BeanListTableModel.java @@ -29,8 +29,10 @@ /** * A table model that is backed by a list of beans. * - *

        One can control which properties are exposed (and their order). There is also - * a convenience constructor for adding a special header row.

        + *

        + * One can control which properties are exposed (and their order). There is also a + * convenience constructor for adding a special header row. + *

        * * @author Eric Bottard */ @@ -96,4 +98,5 @@ public Object getValue(int row, int column) { return data.get(rowToUse).getPropertyValue(propertyName); } } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/BorderSpecification.java b/spring-shell-table/src/main/java/org/springframework/shell/table/BorderSpecification.java index 19f8d2fec..940d3ead6 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/BorderSpecification.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/BorderSpecification.java @@ -23,8 +23,8 @@ import org.springframework.util.StringUtils; /** - * This represents a directive to set some borders on cells of a table. - * Multiple specifications can be combined on a single table. + * This represents a directive to set some borders on cells of a table. Multiple + * specifications can be combined on a single table. * * @author Eric Bottard */ @@ -57,9 +57,10 @@ public class BorderSpecification { private final BorderStyle style; /** - * Specifications are created by {@link Table#addBorder(int, int, int, int, int, BorderStyle)}. + * Specifications are created by + * {@link Table#addBorder(int, int, int, int, int, BorderStyle)}. */ - /*default*/ BorderSpecification(int row1, int column1, int row2, int column2, int match, BorderStyle style) { + /* default */ BorderSpecification(int row1, int column1, int row2, int column2, int match, BorderStyle style) { this.row1 = row1; this.row2 = row2; this.column1 = column1; @@ -71,7 +72,7 @@ public class BorderSpecification { /** * Does this specification result in the need to paint a vertical bar at row,column? */ - /*default*/ char verticals(int row, int column) { + /* default */ char verticals(int row, int column) { boolean result = (match & LEFT) == LEFT && column == column1; result |= (match & INNER_VERTICAL) == INNER_VERTICAL && column > column1 && column < column2; result |= (match & RIGHT) == RIGHT && column == column2; @@ -82,9 +83,10 @@ public class BorderSpecification { } /** - * Does this specification result in the need to paint an horizontal bar at row,column? + * Does this specification result in the need to paint an horizontal bar at + * row,column? */ - /*default*/ char horizontals(int row, int column) { + /* default */ char horizontals(int row, int column) { boolean result = (match & TOP) == TOP && row == row1; result |= (match & INNER_HORIZONTAL) == INNER_HORIZONTAL && row > row1 && row < row2; result |= (match & BOTTOM) == BOTTOM && row == row2; @@ -96,19 +98,21 @@ public class BorderSpecification { @Override public String toString() { - return String.format("%s[(%d, %d)->(%d, %d), %s, %s]", getClass().getSimpleName(), row1, column1, row2, column2, style, matchConstants()); + return String.format("%s[(%d, %d)->(%d, %d), %s, %s]", getClass().getSimpleName(), row1, column1, row2, column2, + style, matchConstants()); } private String matchConstants() { try { - for (String field : new String[] {"NONE", "INNER", "FULL", "OUTLINE"}) { + for (String field : new String[] { "NONE", "INNER", "FULL", "OUTLINE" }) { int value = ReflectionUtils.findField(getClass(), field).getInt(null); - if (match == value) { + if (match == value) { return field; } } List constants = new ArrayList(); - for (String field : new String[] {"TOP", "BOTTOM", "LEFT", "RIGHT", "INNER_HORIZONTAL", "INNER_VERTICAL"}) { + for (String field : new String[] { "TOP", "BOTTOM", "LEFT", "RIGHT", "INNER_HORIZONTAL", + "INNER_VERTICAL" }) { int value = ReflectionUtils.findField(getClass(), field).getInt(null); if ((match & value) == value) { constants.add(field); @@ -120,4 +124,5 @@ private String matchConstants() { throw new RuntimeException(e); } } + } \ No newline at end of file diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/BorderStyle.java b/spring-shell-table/src/main/java/org/springframework/shell/table/BorderStyle.java index 5e29c36be..8db6ce204 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/BorderStyle.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/BorderStyle.java @@ -21,19 +21,21 @@ /** * Provides support for different styles of borders, using simple or fancy ascii art. * - * @see https://en.wikipedia.org/wiki/Box-drawing_character - * + * @see https://en.wikipedia.org/wiki/Box-drawing_character * @author Eric Bottard */ public enum BorderStyle { /** - * A simplistic style, using characters that ought to always be available in all systems (pipe and minus). + * A simplistic style, using characters that ought to always be available in all + * systems (pipe and minus). */ oldschool('|', '-'), /** - * A border style that uses dedicated light box drawing characters from the unicode set. + * A border style that uses dedicated light box drawing characters from the unicode + * set. */ fancy_light('│', '─'), @@ -43,7 +45,8 @@ public enum BorderStyle { fancy_heavy('┃', '━'), /** - * A border style that uses dedicated double-light box drawing characters from the unicode set. + * A border style that uses dedicated double-light box drawing characters from the + * unicode set. */ fancy_double('║', '═'), @@ -53,32 +56,38 @@ public enum BorderStyle { air(' ', ' '), /** - * A border style that uses dedicated double dash light box drawing characters from the unicode set. + * A border style that uses dedicated double dash light box drawing characters from + * the unicode set. */ fancy_light_double_dash('╎', '╌'), /** - * A border style that uses dedicated double dash light box drawing characters from the unicode set. + * A border style that uses dedicated double dash light box drawing characters from + * the unicode set. */ fancy_light_triple_dash('┆', '┄'), /** - * A border style that uses dedicated double dash light box drawing characters from the unicode set. + * A border style that uses dedicated double dash light box drawing characters from + * the unicode set. */ fancy_light_quadruple_dash('┊', '┈'), /** - * A border style that uses dedicated double dash heavy box drawing characters from the unicode set. + * A border style that uses dedicated double dash heavy box drawing characters from + * the unicode set. */ fancy_heavy_double_dash('╏', '╍'), /** - * A border style that uses dedicated double dash heavy box drawing characters from the unicode set. + * A border style that uses dedicated double dash heavy box drawing characters from + * the unicode set. */ fancy_heavy_triple_dash('┇', '┅'), /** - * A border style that uses dedicated double dash heavy box drawing characters from the unicode set. + * A border style that uses dedicated double dash heavy box drawing characters from + * the unicode set. */ fancy_heavy_quadruple_dash('┋', '┉'), @@ -165,7 +174,6 @@ public char horizontalGlyph() { registerSameCorners(fancy_heavy_triple_dash, fancy_heavy); registerSameCorners(fancy_heavy_quadruple_dash, fancy_heavy); - // Air-style glyphs are easy to combine with others. Register some combinations registerMixedWithAirCombinations(oldschool.vertical, oldschool.horizontal); registerMixedWithAirCombinations(fancy_light.vertical, fancy_light.horizontal); @@ -199,7 +207,8 @@ private static void registerMixedWithAirCombinations(char vertical, char horizon } /** - * Register corner glyphs for a given set, not taking care of mixed style intersections. + * Register corner glyphs for a given set, not taking care of mixed style + * intersections. */ private static void registerCorners(String list) { char horizontal = list.charAt(0); diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatcher.java b/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatcher.java index 7f83acf49..e1bbde45d 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatcher.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatcher.java @@ -19,7 +19,9 @@ /** * This is used to specify where some components of a Table may be applied. * - *

        Some commonly used matchers can be created via {@link CellMatchers}.

        + *

        + * Some commonly used matchers can be created via {@link CellMatchers}. + *

        * * @author Eric Bottard */ @@ -32,4 +34,5 @@ public interface CellMatcher { * @param model the data model of the table */ public boolean matches(int row, int column, TableModel model); + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatchers.java b/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatchers.java index 0a56303a6..2088fdc6c 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatchers.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/CellMatchers.java @@ -60,8 +60,9 @@ public boolean matches(int row, int column, TableModel model) { /** * @param theRow the row to select - * @param col the column to select - * @return a matcher that applies to exactly one cell of the table, identified by its row and colum. + * @param col the column to select + * @return a matcher that applies to exactly one cell of the table, identified by its + * row and colum. */ public static CellMatcher at(final int theRow, final int col) { return new CellMatcher() { @@ -90,4 +91,5 @@ public boolean matches(int row, int column, TableModel model) { } }; } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/DebugAligner.java b/spring-shell-table/src/main/java/org/springframework/shell/table/DebugAligner.java index 703ba3afc..385e2f72e 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/DebugAligner.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/DebugAligner.java @@ -39,9 +39,10 @@ public String[] align(String[] text, int cellWidth, int cellHeight) { Assert.isTrue(result.length == cellHeight, String.format("%s had the wrong number of lines (%d), expected %d", Arrays.asList(result), result.length, cellHeight)); for (String s : result) { - Assert.isTrue(s.length() == cellWidth, String.format("'%s' had wrong length (%d), expected %d", s, s.length(), - cellWidth)); + Assert.isTrue(s.length() == cellWidth, + String.format("'%s' had wrong length (%d), expected %d", s, s.length(), cellWidth)); } return result; } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/DebugTextWrapper.java b/spring-shell-table/src/main/java/org/springframework/shell/table/DebugTextWrapper.java index 97d8e3620..a5782cbc5 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/DebugTextWrapper.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/DebugTextWrapper.java @@ -19,7 +19,8 @@ import org.springframework.util.Assert; /** - * A TextWrapper that delegates to another but makes sure that the contract is not violated. + * A TextWrapper that delegates to another but makes sure that the contract is not + * violated. * * @author Eric Bottard */ @@ -35,8 +36,10 @@ public DebugTextWrapper(TextWrapper delegate) { public String[] wrap(String[] original, int columnWidth) { String[] result = delegate.wrap(original, columnWidth); for (String s : result) { - Assert.isTrue(s.length() == columnWidth, String.format("'%s' has the wrong length (%d), expected %d", s, s.length(), columnWidth)); + Assert.isTrue(s.length() == columnWidth, + String.format("'%s' has the wrong length (%d), expected %d", s, s.length(), columnWidth)); } return result; } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/DefaultFormatter.java b/spring-shell-table/src/main/java/org/springframework/shell/table/DefaultFormatter.java index 5fc3f7c87..a5f174b75 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/DefaultFormatter.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/DefaultFormatter.java @@ -24,7 +24,7 @@ public class DefaultFormatter implements Formatter { public String[] format(Object value) { - return value == null ? new String[] {""} : value.toString().split("\n"); + return value == null ? new String[] { "" } : value.toString().split("\n"); } } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/DelimiterTextWrapper.java b/spring-shell-table/src/main/java/org/springframework/shell/table/DelimiterTextWrapper.java index df8747b79..c4469e1dc 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/DelimiterTextWrapper.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/DelimiterTextWrapper.java @@ -20,7 +20,8 @@ import java.util.List; /** - * A Text wrapper that wraps at "word" boundaries. The default delimiter is the space character. + * A Text wrapper that wraps at "word" boundaries. The default delimiter is the space + * character. * * @author Eric Bottard */ @@ -47,9 +48,11 @@ public String[] wrap(String[] original, int columnWidth) { line = line.substring(split == -1 ? columnWidth : split + 1); } if (columnWidth > 0) { - result.add(String.format("%-" + columnWidth + "s", line)); // right pad if necessary + result.add(String.format("%-" + columnWidth + "s", line)); // right pad if + // necessary } } return result.toArray(new String[result.size()]); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/Formatter.java b/spring-shell-table/src/main/java/org/springframework/shell/table/Formatter.java index f92d06d36..b542a7cb6 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/Formatter.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/Formatter.java @@ -19,13 +19,16 @@ /** * A Formatter is responsible for the initial rendering of a value to lines of text. * - *

        Note that this representation is likely to be altered later in the pipeline, for the + *

        + * Note that this representation is likely to be altered later in the pipeline, for the * purpose of text wrapping and aligning. The role of a formatter is merely to give the - * raw text representation (e.g. format numbers).

        + * raw text representation (e.g. format numbers). + *

        * * @author Eric Bottard */ public interface Formatter { public String[] format(Object value); + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueHorizontalAligner.java b/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueHorizontalAligner.java index 484032842..7db30ee53 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueHorizontalAligner.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueHorizontalAligner.java @@ -17,10 +17,13 @@ package org.springframework.shell.table; /** - * A text alignment strategy that aligns text horizontally so that all instances of some special character(s) - * line up perfectly in a column. + * A text alignment strategy that aligns text horizontally so that all instances of some + * special character(s) line up perfectly in a column. * - *

        Typically used to render numbers which may or may not have a decimal point, or series of key-value pairs

        + *

        + * Typically used to render numbers which may or may not have a decimal point, or series + * of key-value pairs + *

        * * @author Eric Bottard */ @@ -69,4 +72,5 @@ private String pad(int left, int right, String original) { } return sb.toString(); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueSizeConstraints.java b/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueSizeConstraints.java index 2d4a450a7..065487e0f 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueSizeConstraints.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueSizeConstraints.java @@ -17,8 +17,8 @@ package org.springframework.shell.table; /** - * A SizeConstraints implementation that is tailored to rendering a series - * of {@literal key = value} pairs. Computes extents so that equal signs (or any other + * A SizeConstraints implementation that is tailored to rendering a series of + * {@literal key = value} pairs. Computes extents so that equal signs (or any other * configurable delimiter) line up vertically. * * @author Eric Bottard @@ -52,7 +52,7 @@ private static String rightTrim(String raw) { public Extent width(String[] raw, int tableWidth, int nbColumns) { // We need to make sure we take care of the case where we have - // k = long-value + // k = long-value // long-key = v // as the real maximal extent is size(long-key) + size( = ) + size(long-value) @@ -66,7 +66,8 @@ public Extent width(String[] raw, int tableWidth, int nbColumns) { int offset = lineToConsider.indexOf(delimiter); if (offset != -1) { - // Compute minimal case (line can be split, decide where to put the delimiter) + // Compute minimal case (line can be split, decide where to put the + // delimiter) String minimalLeftPart = lineToConsider.substring(0, offset).trim(); String minimalRightPart = lineToConsider.substring(offset + delimiter.length()).trim(); int left = minimalLeftPart.length(); @@ -89,4 +90,5 @@ public Extent width(String[] raw, int tableWidth, int nbColumns) { return new Extent(min, maxLeft + delimiter.length() + maxRight); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueTextWrapper.java b/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueTextWrapper.java index 4b10c9b5d..05c9b1b16 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueTextWrapper.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/KeyValueTextWrapper.java @@ -20,8 +20,8 @@ import java.util.List; /** - * A TextWrapper implementation tailored for key-value rendering (working in concert - * with {@link KeyValueSizeConstraints}, {@link KeyValueHorizontalAligner}), that tries its + * A TextWrapper implementation tailored for key-value rendering (working in concert with + * {@link KeyValueSizeConstraints}, {@link KeyValueHorizontalAligner}), that tries its * best to vertically align some delimiter character (default '='). */ public class KeyValueTextWrapper implements TextWrapper { @@ -66,4 +66,5 @@ private String rightPad(String raw, int width) { } return result.toString(); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/MapFormatter.java b/spring-shell-table/src/main/java/org/springframework/shell/table/MapFormatter.java index da018feff..4aa577fa8 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/MapFormatter.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/MapFormatter.java @@ -41,4 +41,5 @@ public String[] format(Object value) { } return result; } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/NoWrapSizeConstraints.java b/spring-shell-table/src/main/java/org/springframework/shell/table/NoWrapSizeConstraints.java index 6545997f1..3fce21611 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/NoWrapSizeConstraints.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/NoWrapSizeConstraints.java @@ -31,4 +31,5 @@ public Extent width(String[] raw, int tableWidth, int nbColumns) { } return new Extent(max, max); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/SizeConstraints.java b/spring-shell-table/src/main/java/org/springframework/shell/table/SizeConstraints.java index 87070e951..8db3f974b 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/SizeConstraints.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/SizeConstraints.java @@ -27,7 +27,8 @@ public interface SizeConstraints { /** * @return the minimum and maximum width of the cell, given its raw content. - * @param raw the raw String representation of the cell contents (may be reformatted later, eg wrapped) + * @param raw the raw String representation of the cell contents (may be reformatted + * later, eg wrapped) * @param tableWidth the whole available width for the table * @param nbColumns the number of columns in the table */ @@ -50,5 +51,7 @@ public Extent(int min, int max) { this.min = min; this.max = max; } + } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/Table.java b/spring-shell-table/src/main/java/org/springframework/shell/table/Table.java index 7e3f09b8d..164ee8977 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/Table.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/Table.java @@ -27,25 +27,30 @@ /** * This is the central API for table rendering. A Table object is constructed with a given - * TableModel, which holds raw table contents. Its rendering logic is then altered by applying - * various customizations, in a fashion very similar to what is used e.g. in a spreadsheet - * program:
          - *
        1. {@link #formatters formatters} know how to derive character data out of raw data. For - * example, numbers are - * formatted according to a Locale, or Maps are emitted as a series of {@literal key=value} lines
        2. - *
        3. {@link #sizeConstraints size constraints} are then applied, which decide how - * much column real estate to allocate to cells
        4. - *
        5. {@link #wrappers text wrapping policies} are applied once the column sizes - * are known
        6. - *
        7. finally, {@link #aligners alignment} strategies actually render - * text as a series of space-padded strings that draw nicely on screen.
        8. + * TableModel, which holds raw table contents. Its rendering logic is then altered by + * applying various customizations, in a fashion very similar to what is used e.g. + * in a spreadsheet program: + *
            + *
          1. {@link #formatters formatters} know how to derive character data out of raw data. + * For example, numbers are formatted according to a Locale, or Maps are emitted as a + * series of {@literal key=value} lines
          2. + *
          3. {@link #sizeConstraints size constraints} are then applied, which decide how much + * column real estate to allocate to cells
          4. + *
          5. {@link #wrappers text wrapping policies} are applied once the column sizes are + * known
          6. + *
          7. finally, {@link #aligners alignment} strategies actually render text as a series of + * space-padded strings that draw nicely on screen.
          8. *
          - * All those customizations are applied selectively on the Table cells thanks to a {@link CellMatcher}: One can - * decide to right pad column number 3, or to format in a certain way all instances of {@literal java.util.Map}. + * All those customizations are applied selectively on the Table cells thanks to a + * {@link CellMatcher}: One can decide to right pad column number 3, or to format in a + * certain way all instances of {@literal java.util.Map}. + * + *

          + * Of course, all of those customizations often work hand in hand, and not all + * combinations make sense: one needs to anticipate the fact that text will be split using + * the ' ' (space) character to properly calculate column sizes. + *

          * - *

          Of course, all of those customizations often work hand in hand, and not all combinations make sense: - * one needs to anticipate the fact that text will be split using the ' ' (space) character to properly - * calculate column sizes.

          * @author Eric Bottard */ public class Table implements TerminalSizeAware { @@ -67,18 +72,16 @@ public class Table implements TerminalSizeAware { private List borderSpecifications = new ArrayList(); /** - * Construct a new Table with the given model and customizers. - * The passed in LinkedHashMap should be in reverse-insertion order (i.e. the first CellMatcher - * found in iteration order will "win"). + * Construct a new Table with the given model and customizers. The passed in + * LinkedHashMap should be in reverse-insertion order (i.e. the first + * CellMatcher found in iteration order will "win"). * * @see TableBuilder#build() */ - /*package*/ Table(TableModel model, - LinkedHashMap formatters, - LinkedHashMap sizeConstraints, - LinkedHashMap wrappers, - LinkedHashMap aligners, - List borderSpecifications) { + /* package */ Table(TableModel model, LinkedHashMap formatters, + LinkedHashMap sizeConstraints, + LinkedHashMap wrappers, LinkedHashMap aligners, + List borderSpecifications) { this.model = model; this.formatters = formatters; this.sizeConstraints = sizeConstraints; @@ -114,7 +117,8 @@ public String render(int totalAvailableWidth) { String[] lines = getFormatter(row, column).format(value); subLines[row][column] = lines; - SizeConstraints.Extent extent = getSizeConstraints(row, column).width(lines, widthAvailableForContents, columns); + SizeConstraints.Extent extent = getSizeConstraints(row, column).width(lines, widthAvailableForContents, + columns); minCellWidths[column] = Math.max(minCellWidths[column], extent.min); maxCellWidths[column] = Math.max(maxCellWidths[column], extent.max); @@ -122,7 +126,6 @@ public String render(int totalAvailableWidth) { } } - cellWidths = computeColumnWidths(widthAvailableForContents, minCellWidths, maxCellWidths); // Now that widths are known, apply wrapping & render for (int row = 0; row < rows; row++) { @@ -133,13 +136,13 @@ public String render(int totalAvailableWidth) { for (int column = 0; column < columns; column++) { for (Map.Entry kv : aligners.entrySet()) { if (kv.getKey().matches(row, column, model)) { - subLines[row][column] = kv.getValue().align(subLines[row][column], cellWidths[column], cellHeights[row]); + subLines[row][column] = kv.getValue() + .align(subLines[row][column], cellWidths[column], cellHeights[row]); } } } } - for (int row = 0; row < rows; row++) { // TOP CELL BORDER @@ -229,7 +232,7 @@ private SizeConstraints getSizeConstraints(int row, int column) { private Formatter getFormatter(int row, int column) { for (Map.Entry kv : formatters.entrySet()) { if (kv.getKey().matches(row, column, model)) { - return kv.getValue(); + return kv.getValue(); } } throw new AssertionError("Can't be reached thanks to the whole-table default"); @@ -238,8 +241,11 @@ private Formatter getFormatter(int row, int column) { /** * An instance of this class knows where to paint border glyphs. * - *

          In all instance arrays, 'row' and 'column' are actually indices in-between - * table rows and columns. Hence, sizes are larger by one.

          + *

          + * In all instance arrays, 'row' and 'column' are actually indices in-between table + * rows and columns. Hence, sizes are larger by one. + *

          + * * @author Eric Bottard */ private class Borders { @@ -356,6 +362,7 @@ public int getNumberOfVerticalBorders() { } return result; } + } } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/TableBuilder.java b/spring-shell-table/src/main/java/org/springframework/shell/table/TableBuilder.java index 80560be6a..e665fe427 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/TableBuilder.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/TableBuilder.java @@ -31,6 +31,7 @@ /** * A builder class to incrementally configure a Table. + * * @author Eric Bottard */ public class TableBuilder { @@ -52,15 +53,15 @@ public class TableBuilder { private final int columns; /** - * Construct a table with the given model. The table will use the following - * strategies for all cells, unless overridden:
            + * Construct a table with the given model. The table will use the following strategies + * for all cells, unless overridden: + *
              *
            • {@link DefaultFormatter default formatting} using {@literal toString()}
            • - *
            • {@link AutoSizeConstraints sizing strategy} trying to use the maximum space, resorting to splitting lines on - * spaces
            • + *
            • {@link AutoSizeConstraints sizing strategy} trying to use the maximum space, + * resorting to splitting lines on spaces
            • *
            • {@link DelimiterTextWrapper wrapping text} on space characters
            • *
            • {@link SimpleHorizontalAligner left aligning} text.
            • *
            - * * @param model the data model of the table to construct */ @@ -78,9 +79,12 @@ public TableBuilder(TableModel model) { private TableBuilder addBorder(int top, int left, int bottom, int right, int match, BorderStyle style) { Assert.isTrue(top >= 0 && top < rows, "top row must be positive and less than total number of rows"); - Assert.isTrue(left >= 0 && left < columns, "left column must be positive and less than total number of columns"); - Assert.isTrue(bottom > top && bottom <= rows, "bottom row must be greater than top and less than total number of rows"); - Assert.isTrue(right >= left && right <= columns, "right column must be greater than left and less than total number of columns"); + Assert.isTrue(left >= 0 && left < columns, + "left column must be positive and less than total number of columns"); + Assert.isTrue(bottom > top && bottom <= rows, + "bottom row must be greater than top and less than total number of rows"); + Assert.isTrue(right >= left && right <= columns, + "right column must be greater than left and less than total number of columns"); Assert.notNull(style, "style cannot be null"); borderSpecifications.add(new BorderSpecification(top, left, bottom, right, match, style)); return this; @@ -95,11 +99,7 @@ public CellMatcherStub on(CellMatcher matcher) { } public Table build() { - return new Table(model, - reverse(formatters), - reverse(sizeConstraints), - reverse(wrappers), - aligners, + return new Table(model, reverse(formatters), reverse(sizeConstraints), reverse(wrappers), aligners, borderSpecifications); } @@ -131,7 +131,6 @@ public TableBuilder addHeaderBorder(BorderStyle style) { /** * Set a border around each and every cell of the table. - * * @param style the style to apply * @return this, for method chaining */ @@ -141,9 +140,8 @@ public TableBuilder addFullBorder(BorderStyle style) { } /** - * Set a border on the outline of the whole table, around the first row and draw vertical lines - * around each column. - * + * Set a border on the outline of the whole table, around the first row and draw + * vertical lines around each column. * @param style the style to apply * @return this, for method chaining */ @@ -154,8 +152,8 @@ public TableBuilder addHeaderAndVerticalsBorders(BorderStyle style) { } /** - * Set a border on the inner verticals and horizontals of the table, but not on the outline. - * + * Set a border on the inner verticals and horizontals of the table, but not on the + * outline. * @param style the style to apply * @return this, for method chaining */ @@ -213,6 +211,7 @@ public TableBuilder and() { public Table build() { return TableBuilder.this.build(); } + } public class BorderStub { @@ -235,6 +234,7 @@ public TopLeft fromTopLeft() { } public class TopLeft { + private final int row; private final int column; @@ -245,13 +245,17 @@ private TopLeft(int row, int column) { } public TableBuilder toRowColumn(int row, int column) { - TableBuilder.this.addBorder(TopLeft.this.row, TopLeft.this.column, row, column, BorderStub.this.match, BorderStub.this.style); + TableBuilder.this.addBorder(TopLeft.this.row, TopLeft.this.column, row, column, BorderStub.this.match, + BorderStub.this.style); return TableBuilder.this; } public TableBuilder toBottomRight() { return toRowColumn(model.getRowCount(), model.getColumnCount()); } + } + } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/TableModel.java b/spring-shell-table/src/main/java/org/springframework/shell/table/TableModel.java index 7128a6a83..90ed6acca 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/TableModel.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/TableModel.java @@ -24,19 +24,20 @@ public abstract class TableModel { /** - * @return the number of rows that can be queried. - * Values between 0 and {@code rowCount-1} inclusive are valid values. + * @return the number of rows that can be queried. Values between 0 and + * {@code rowCount-1} inclusive are valid values. */ public abstract int getRowCount(); /** - * @return the number of columns that can be queried. - * Values between 0 and {@code columnCount-1} inclusive are valid values. + * @return the number of columns that can be queried. Values between 0 and + * {@code columnCount-1} inclusive are valid values. */ public abstract int getColumnCount(); /** - * @return the data value to be displayed at a given row and column, which may be null. + * @return the data value to be displayed at a given row and column, which may be + * null. * @param row the row that is being queried * @param column the column that is being queried */ @@ -63,4 +64,5 @@ public Object getValue(int row, int column) { } }; } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/TableModelBuilder.java b/spring-shell-table/src/main/java/org/springframework/shell/table/TableModelBuilder.java index 9a7a84a37..6bc7c224d 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/TableModelBuilder.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/TableModelBuilder.java @@ -80,4 +80,5 @@ public Object getValue(int row, int column) { }; } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/Tables.java b/spring-shell-table/src/main/java/org/springframework/shell/table/Tables.java index 8d4968634..8138f19a6 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/Tables.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/Tables.java @@ -26,17 +26,19 @@ public class Tables { /** - * Install all the necessary formatters, aligners, etc for key-value rendering of Maps. - * + * Install all the necessary formatters, aligners, etc for key-value rendering of + * Maps. * @param builder the builder to configure * @param delimiter the delimiter to apply between keys and values * @return buider for method chaining */ public static TableBuilder configureKeyValueRendering(TableBuilder builder, String delimiter) { return builder.on(CellMatchers.ofType(Map.class)) - .addFormatter(new MapFormatter(delimiter)) - .addAligner(new KeyValueHorizontalAligner(delimiter.trim())) - .addSizer(new KeyValueSizeConstraints(delimiter)) - .addWrapper(new KeyValueTextWrapper(delimiter)).and(); + .addFormatter(new MapFormatter(delimiter)) + .addAligner(new KeyValueHorizontalAligner(delimiter.trim())) + .addSizer(new KeyValueSizeConstraints(delimiter)) + .addWrapper(new KeyValueTextWrapper(delimiter)) + .and(); } + } diff --git a/spring-shell-table/src/main/java/org/springframework/shell/table/TextWrapper.java b/spring-shell-table/src/main/java/org/springframework/shell/table/TextWrapper.java index 50111f838..5f0c0639d 100644 --- a/spring-shell-table/src/main/java/org/springframework/shell/table/TextWrapper.java +++ b/spring-shell-table/src/main/java/org/springframework/shell/table/TextWrapper.java @@ -24,12 +24,13 @@ public interface TextWrapper { /** - * @return a list of lines where each line length MUST be equal to {@code columnWidth} (padding with spaces if - * appropriate). There is no constraint on the number of lines returned however (typically, will be greater than - * the input number if wrapping occurred). - * + * @return a list of lines where each line length MUST be equal to {@code columnWidth} + * (padding with spaces if appropriate). There is no constraint on the number of lines + * returned however (typically, will be greater than the input number if wrapping + * occurred). * @param original the text in its original form * @param columnWidth the width to conform to */ String[] wrap(String[] original, int columnWidth); + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/AbstractTestWithSample.java b/spring-shell-table/src/test/java/org/springframework/shell/table/AbstractTestWithSample.java index 6592b9c1e..e8607b4bf 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/AbstractTestWithSample.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/AbstractTestWithSample.java @@ -27,8 +27,8 @@ import org.springframework.util.FileCopyUtils; /** - * Base class that allows reading a sample result rendering of a table, based on the actual - * class and method name of the test. + * Base class that allows reading a sample result rendering of a table, based on the + * actual class and method name of the test. * * @author Eric Bottard */ @@ -42,8 +42,7 @@ public void setup(TestInfo testInfo) { } protected String sample() throws IOException { - String sampleName = String.format("%s-%s.txt", - this.getClass().getSimpleName(), testName); + String sampleName = String.format("%s-%s.txt", this.getClass().getSimpleName(), testName); InputStream stream = TableTest.class.getResourceAsStream(sampleName); Assert.notNull(stream, "Can't find expected rendering result at " + sampleName); return FileCopyUtils.copyToString(new InputStreamReader(stream, "UTF-8")).replace("&", ""); @@ -62,4 +61,5 @@ protected TableModel generate(int rows, int columns) { } return new ArrayTableModel(data); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/ArrayTableModelTest.java b/spring-shell-table/src/test/java/org/springframework/shell/table/ArrayTableModelTest.java index f4cd976e0..a39c51772 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/ArrayTableModelTest.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/ArrayTableModelTest.java @@ -30,7 +30,7 @@ public class ArrayTableModelTest { @Test public void testValid() { - TableModel model = new ArrayTableModel(new String[][] {{"a", "b"}, {"c", "d"}}); + TableModel model = new ArrayTableModel(new String[][] { { "a", "b" }, { "c", "d" } }); assertThat(model.getColumnCount()).isEqualTo(2); assertThat(model.getRowCount()).isEqualTo(2); assertThat(model.getValue(0, 1)).isEqualTo("b"); @@ -46,7 +46,8 @@ public void testEmpty() { @Test public void testInvalidDimensions() { assertThatThrownBy(() -> { - new ArrayTableModel(new String[][] {{"a", "b"}, {"c", "d", "e"}}); + new ArrayTableModel(new String[][] { { "a", "b" }, { "c", "d", "e" } }); }).isInstanceOf(IllegalArgumentException.class); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/BeanListTableModelTest.java b/spring-shell-table/src/test/java/org/springframework/shell/table/BeanListTableModelTest.java index 6cc979312..44c018798 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/BeanListTableModelTest.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/BeanListTableModelTest.java @@ -25,7 +25,6 @@ import static org.assertj.core.api.Assertions.assertThat; - /** * Test for BeanListTableModel. * @@ -76,6 +75,7 @@ private List data() { } public static class Person { + private int age; private String firstName; @@ -99,5 +99,7 @@ public String getFirstName() { public String getLastName() { return lastName; } + } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/BorderFactoryTest.java b/spring-shell-table/src/test/java/org/springframework/shell/table/BorderFactoryTest.java index b80aa674b..5685dd8b6 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/BorderFactoryTest.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/BorderFactoryTest.java @@ -23,7 +23,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.shell.table.BorderStyle.fancy_double; - /** * Tests for convenience borders factory. * @@ -62,4 +61,5 @@ public void testHeaderAndVerticalsBorder() throws IOException { String result = table.render(80); assertThat(result).isEqualTo(sample()); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/BorderStyleTests.java b/spring-shell-table/src/test/java/org/springframework/shell/table/BorderStyleTests.java index cc93e48b6..67e15dec9 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/BorderStyleTests.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/BorderStyleTests.java @@ -22,7 +22,6 @@ import static org.assertj.core.api.Assertions.assertThat; - /** * Tests for BorderStyle rendering and combinations. * @@ -62,75 +61,78 @@ public void testAir() throws IOException { @Test public void testMixedOldSchoolWithAir() throws IOException { - Table table = new TableBuilder(generate(2, 2)) - .addFullBorder(BorderStyle.air) - .addOutlineBorder(BorderStyle.oldschool) - .build(); + Table table = new TableBuilder(generate(2, 2)).addFullBorder(BorderStyle.air) + .addOutlineBorder(BorderStyle.oldschool) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } @Test public void testMixedFancyLightAndHeavy() throws IOException { - Table table = new TableBuilder(generate(2, 2)) - .addFullBorder(BorderStyle.fancy_heavy) - .addOutlineBorder(BorderStyle.fancy_light) - .build(); + Table table = new TableBuilder(generate(2, 2)).addFullBorder(BorderStyle.fancy_heavy) + .addOutlineBorder(BorderStyle.fancy_light) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } @Test public void testMixedFancyHeavyAndLight() throws IOException { - Table table = new TableBuilder(generate(2, 2)) - .addFullBorder(BorderStyle.fancy_light) - .addOutlineBorder(BorderStyle.fancy_heavy) - .build(); + Table table = new TableBuilder(generate(2, 2)).addFullBorder(BorderStyle.fancy_light) + .addOutlineBorder(BorderStyle.fancy_heavy) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } @Test public void testMixedDoubleAndSingle() throws IOException { - Table table = new TableBuilder(generate(2, 2)) - .addFullBorder(BorderStyle.fancy_light) - .addOutlineBorder(BorderStyle.fancy_double) - .build(); + Table table = new TableBuilder(generate(2, 2)).addFullBorder(BorderStyle.fancy_light) + .addOutlineBorder(BorderStyle.fancy_double) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } @Test public void testMixedSingleAndDouble() throws IOException { - Table table = new TableBuilder(generate(2, 2)) - .addFullBorder(BorderStyle.fancy_double) - .addOutlineBorder(BorderStyle.fancy_light) - .build(); + Table table = new TableBuilder(generate(2, 2)).addFullBorder(BorderStyle.fancy_double) + .addOutlineBorder(BorderStyle.fancy_light) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } @Test public void testMixedLightInternalAndHeavy() throws IOException { - Table table = new TableBuilder(generate(3, 3)) - .addFullBorder(BorderStyle.fancy_heavy) - .paintBorder(BorderStyle.fancy_light, BorderSpecification.OUTLINE).fromRowColumn(1, 1).toRowColumn(2, 2) - .build(); + Table table = new TableBuilder(generate(3, 3)).addFullBorder(BorderStyle.fancy_heavy) + .paintBorder(BorderStyle.fancy_light, BorderSpecification.OUTLINE) + .fromRowColumn(1, 1) + .toRowColumn(2, 2) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } @Test public void testMixedHeavyInternalAndLight() throws IOException { - Table table = new TableBuilder(generate(3, 3)) - .addFullBorder(BorderStyle.fancy_light) - .paintBorder(BorderStyle.fancy_heavy, BorderSpecification.OUTLINE).fromRowColumn(1, 1).toRowColumn(2, 2) - .build(); + Table table = new TableBuilder(generate(3, 3)).addFullBorder(BorderStyle.fancy_light) + .paintBorder(BorderStyle.fancy_heavy, BorderSpecification.OUTLINE) + .fromRowColumn(1, 1) + .toRowColumn(2, 2) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } @Test public void testHeavyOutlineAndHeader_LightVerticals_AirHorizontals() throws IOException { - Table table = new TableBuilder(generate(4, 4)) - .addOutlineBorder(BorderStyle.fancy_heavy) - .paintBorder(BorderStyle.fancy_light, BorderSpecification.INNER_VERTICAL).fromTopLeft().toBottomRight() - .paintBorder(BorderStyle.air, BorderSpecification.INNER_HORIZONTAL).fromTopLeft().toBottomRight() - .paintBorder(BorderStyle.fancy_heavy, BorderSpecification.OUTLINE).fromTopLeft().toRowColumn(1, 4) - .build(); + Table table = new TableBuilder(generate(4, 4)).addOutlineBorder(BorderStyle.fancy_heavy) + .paintBorder(BorderStyle.fancy_light, BorderSpecification.INNER_VERTICAL) + .fromTopLeft() + .toBottomRight() + .paintBorder(BorderStyle.air, BorderSpecification.INNER_HORIZONTAL) + .fromTopLeft() + .toBottomRight() + .paintBorder(BorderStyle.fancy_heavy, BorderSpecification.OUTLINE) + .fromTopLeft() + .toRowColumn(1, 4) + .build(); assertThat(table.render(10)).isEqualTo(sample()); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/DelimiterTextWrapperTest.java b/spring-shell-table/src/test/java/org/springframework/shell/table/DelimiterTextWrapperTest.java index e0cf049b8..721a18a1a 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/DelimiterTextWrapperTest.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/DelimiterTextWrapperTest.java @@ -31,15 +31,16 @@ public class DelimiterTextWrapperTest { @Test public void testNoWordSplit() { - String[] text = new String[] {"the quick brown fox jumps over the lazy dog."}; + String[] text = new String[] { "the quick brown fox jumps over the lazy dog." }; assertThat(wrapper.wrap(text, 10)).containsExactly("the quick ", "brown fox ", "jumps over", "the lazy ", "dog. "); } @Test public void testWordSplit() { - String[] text = new String[] {"the quick brown fox jumps over the lazy dog."}; + String[] text = new String[] { "the quick brown fox jumps over the lazy dog." }; assertThat(wrapper.wrap(text, 4)).containsExactly("the ", "quic", "k ", "brow", "n ", "fox ", "jump", "s ", "over", "the ", "lazy", "dog."); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/KeyValueRenderingTests.java b/spring-shell-table/src/test/java/org/springframework/shell/table/KeyValueRenderingTests.java index 0a8ec2405..0c062a90a 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/KeyValueRenderingTests.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/KeyValueRenderingTests.java @@ -37,9 +37,8 @@ public void testRenderConstrained() throws IOException { values.put("a", "b"); values.put("long-key", "c"); values.put("d", "long-value"); - TableModel model = new ArrayTableModel(new Object[][] {{"Thing", "Properties"}, {"Something", values}}); - TableBuilder tableBuilder = new TableBuilder(model) - .addHeaderAndVerticalsBorders(BorderStyle.fancy_light); + TableModel model = new ArrayTableModel(new Object[][] { { "Thing", "Properties" }, { "Something", values } }); + TableBuilder tableBuilder = new TableBuilder(model).addHeaderAndVerticalsBorders(BorderStyle.fancy_light); Tables.configureKeyValueRendering(tableBuilder, " = "); Table table = tableBuilder.build(); String result = table.render(10); @@ -52,12 +51,12 @@ public void testRenderUnconstrained() throws IOException { values.put("a", "b"); values.put("long-key", "c"); values.put("d", "long-value"); - TableModel model = new ArrayTableModel(new Object[][] {{"Thing", "Properties"}, {"Something", values}}); - TableBuilder tableBuilder = new TableBuilder(model) - .addHeaderAndVerticalsBorders(BorderStyle.fancy_light); + TableModel model = new ArrayTableModel(new Object[][] { { "Thing", "Properties" }, { "Something", values } }); + TableBuilder tableBuilder = new TableBuilder(model).addHeaderAndVerticalsBorders(BorderStyle.fancy_light); Tables.configureKeyValueRendering(tableBuilder, " = "); Table table = tableBuilder.build(); String result = table.render(80); assertThat(result).isEqualTo(sample()); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelBuilderTests.java b/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelBuilderTests.java index 3dbae0648..d9c580dca 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelBuilderTests.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelBuilderTests.java @@ -70,17 +70,12 @@ public void testAddingLessValues() { @Test public void simpleBuild() { TableModelBuilder builder = new TableModelBuilder(); - builder - .addRow() - .addValue(7).addValue(2) - .addRow() - .addValue(3).addValue(5.5) - .addRow() - .addValue(1).addValue(4); + builder.addRow().addValue(7).addValue(2).addRow().addValue(3).addValue(5.5).addRow().addValue(1).addValue(4); TableModel model = builder.build(); assertThat(model.getColumnCount()).isEqualTo(2); assertThat(model.getRowCount()).isEqualTo(3); assertThat(model.getValue(1, 1)).isEqualTo(5.5); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelTest.java b/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelTest.java index db3cf918f..1bf40d97f 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelTest.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/TableModelTest.java @@ -29,10 +29,11 @@ public class TableModelTest { @Test public void testTranspose() { - TableModel model = new ArrayTableModel(new String[][] {{"a", "b", "c"}, {"d", "e", "f"}}); + TableModel model = new ArrayTableModel(new String[][] { { "a", "b", "c" }, { "d", "e", "f" } }); assertThat(model.transpose().getColumnCount()).isEqualTo(2); assertThat(model.transpose().getRowCount()).isEqualTo(3); assertThat(model.transpose().getValue(2, 1)).isEqualTo("f"); } + } diff --git a/spring-shell-table/src/test/java/org/springframework/shell/table/TableTest.java b/spring-shell-table/src/test/java/org/springframework/shell/table/TableTest.java index e39816687..10b1ae80e 100644 --- a/spring-shell-table/src/test/java/org/springframework/shell/table/TableTest.java +++ b/spring-shell-table/src/test/java/org/springframework/shell/table/TableTest.java @@ -24,7 +24,6 @@ import java.io.IOException; - /** * Tests for Table rendering. * @@ -50,7 +49,7 @@ public void testPreformattedModel() { @Test public void testExpandingColumns() throws IOException { - TableModel model = new ArrayTableModel(new String[][] {{"a", "b"}, {"ccc", "d"}}); + TableModel model = new ArrayTableModel(new String[][] { { "a", "b" }, { "ccc", "d" } }); Table table = new TableBuilder(model).build(); String result = table.render(80); assertThat(result).isEqualTo(sample()); @@ -58,7 +57,7 @@ public void testExpandingColumns() throws IOException { @Test public void testRightAlignment() throws IOException { - TableModel model = new ArrayTableModel(new String[][] {{"a\na\na", "bbb"}, {"ccc", "d"}}); + TableModel model = new ArrayTableModel(new String[][] { { "a\na\na", "bbb" }, { "ccc", "d" } }); Table table = new TableBuilder(model).on(CellMatchers.column(1)).addAligner(right).build(); String result = table.render(80); assertThat(result).isEqualTo(sample()); @@ -66,7 +65,7 @@ public void testRightAlignment() throws IOException { @Test public void testVerticalAlignment() throws IOException { - TableModel model = new ArrayTableModel(new String[][] {{"a\na\na", "bbb"}, {"ccc", "d"}}); + TableModel model = new ArrayTableModel(new String[][] { { "a\na\na", "bbb" }, { "ccc", "d" } }); Table table = new TableBuilder(model).on(CellMatchers.row(0)).addAligner(middle).build(); String result = table.render(80); assertThat(result).isEqualTo(sample()); @@ -74,7 +73,7 @@ public void testVerticalAlignment() throws IOException { @Test public void testAutoWrapping() throws IOException { - TableModel model = new ArrayTableModel(new String[][] {{"this is a long line", "bbb"}, {"ccc", "d"}}); + TableModel model = new ArrayTableModel(new String[][] { { "this is a long line", "bbb" }, { "ccc", "d" } }); Table table = new TableBuilder(model).build(); String result = table.render(10); assertThat(result).isEqualTo(sample()); @@ -82,7 +81,7 @@ public void testAutoWrapping() throws IOException { @Test public void testOverflow() throws IOException { - TableModel model = new ArrayTableModel(new String[][] {{"this is a long line", "bbb"}, {"ccc", "d"}}); + TableModel model = new ArrayTableModel(new String[][] { { "this is a long line", "bbb" }, { "ccc", "d" } }); Table table = new TableBuilder(model).build(); String result = table.render(3); assertThat(result).isEqualTo(sample()); @@ -90,8 +89,9 @@ public void testOverflow() throws IOException { @Test public void testEmptyCellsVerticalAligner() throws IOException { - TableModel model = new ArrayTableModel(new String[][] {{"a", "b"}, {null, null}}); + TableModel model = new ArrayTableModel(new String[][] { { "a", "b" }, { null, null } }); Table table = new TableBuilder(model).on(CellMatchers.table()).addAligner(SimpleVerticalAligner.middle).build(); table.render(3); } + } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShell.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShell.java index bf86c5aa9..ae2afa9a5 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShell.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShell.java @@ -38,4 +38,5 @@ @Inherited @ImportAutoConfiguration public @interface AutoConfigureShell { + } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShellTestClient.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShellTestClient.java index c4a174fb0..4aa06e6ca 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShellTestClient.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/AutoConfigureShellTestClient.java @@ -36,4 +36,5 @@ @Inherited @ImportAutoConfiguration public @interface AutoConfigureShellTestClient { + } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellAutoConfiguration.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellAutoConfiguration.java index f01bd8e91..bc044ee80 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellAutoConfiguration.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellAutoConfiguration.java @@ -40,10 +40,7 @@ public class ShellAutoConfiguration { @Bean TerminalCustomizer terminalStreamsTerminalCustomizer(TerminalStreams terminalStreams) { return builder -> { - builder.streams(terminalStreams.input, terminalStreams.output) - .jansi(false) - .jna(false) - .jni(false); + builder.streams(terminalStreams.input, terminalStreams.output).jansi(false).jna(false).jni(false); }; } @@ -65,9 +62,13 @@ TerminalSession terminalSession(TtyConnector ttyConnector, SpringShellTestProper } public static class TerminalStreams { + PipedInputStream input; + PipedOutputStream output; + InputStreamReader myReader; + OutputStreamWriter myWriter; public TerminalStreams() { @@ -76,16 +77,20 @@ public TerminalStreams() { try { myReader = new InputStreamReader(new PipedInputStream(this.output)); myWriter = new OutputStreamWriter(new PipedOutputStream(this.input)); - } catch (IOException e) { + } + catch (IOException e) { } } + } private static class TestTtyConnector implements TtyConnector { private final static Logger log = LoggerFactory.getLogger(TestTtyConnector.class); + InputStreamReader myReader; + OutputStreamWriter myWriter; TestTtyConnector(InputStreamReader myReader, OutputStreamWriter myWriter) { @@ -145,6 +150,7 @@ public boolean ready() throws IOException { log.trace("ready2 {}", ready); return ready; } + } } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTest.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTest.java index 260a1003b..e7b1bab83 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTest.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTest.java @@ -37,8 +37,8 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; /** - * Annotation that can be used for a Shell test that focuses - * only on Shell components. + * Annotation that can be used for a Shell test that focuses only on + * Shell components. * * @author Janne Valkealahti */ @@ -58,14 +58,12 @@ /** * Properties in form {@literal key=value} that should be added to the Spring * {@link Environment} before the test runs. - * * @return the properties to add */ String[] properties() default {}; /** * Set emulated terminal width. - * * @return emulated terminal width */ @PropertyMapping(value = "spring.shell.test.terminal-width", skip = SkipPropertyMapping.ON_DEFAULT_VALUE) @@ -73,7 +71,6 @@ /** * Set emulated terminal height. - * * @return emulated terminal height */ @PropertyMapping(value = "spring.shell.test.terminal-height", skip = SkipPropertyMapping.ON_DEFAULT_VALUE) @@ -92,7 +89,6 @@ /** * A set of include filters which can be used to add otherwise filtered beans to the * application context. - * * @return include filters to apply */ Filter[] includeFilters() default {}; @@ -100,16 +96,15 @@ /** * A set of exclude filters which can be used to filter beans that would otherwise be * added to the application context. - * * @return exclude filters to apply */ Filter[] excludeFilters() default {}; /** * Auto-configuration exclusions that should be applied for this test. - * * @return auto-configuration exclusions to apply */ @AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude") Class[] excludeAutoConfiguration() default {}; + } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestClientAutoConfiguration.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestClientAutoConfiguration.java index 64f9dcb44..887e67b2f 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestClientAutoConfiguration.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestClientAutoConfiguration.java @@ -27,7 +27,6 @@ import org.springframework.shell.test.jediterm.terminal.ui.TerminalSession; /** - * * @author Janne Valkealahti */ @AutoConfiguration @@ -39,4 +38,5 @@ ShellTestClient shellTestClient(TerminalSession widget, Shell shell, PromptProvi LineReader lineReader, Terminal terminal) { return ShellTestClient.builder(widget, shell, promptProvider, lineReader, terminal).build(); } + } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestContextBootstrapper.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestContextBootstrapper.java index 948053a69..4c7ba5745 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestContextBootstrapper.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTestContextBootstrapper.java @@ -29,7 +29,10 @@ public class ShellTestContextBootstrapper extends SpringBootTestContextBootstrap @Override protected String[] getProperties(Class testClass) { - return MergedAnnotations.from(testClass, SearchStrategy.INHERITED_ANNOTATIONS).get(ShellTest.class) - .getValue("properties", String[].class).orElse(null); + return MergedAnnotations.from(testClass, SearchStrategy.INHERITED_ANNOTATIONS) + .get(ShellTest.class) + .getValue("properties", String[].class) + .orElse(null); } + } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTypeExcludeFilter.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTypeExcludeFilter.java index 5cbbd4fe9..2e531d5f3 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTypeExcludeFilter.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/ShellTypeExcludeFilter.java @@ -46,4 +46,5 @@ public class ShellTypeExcludeFilter extends StandardAnnotationCustomizableTypeEx protected Set> getDefaultIncludes() { return DEFAULT_INCLUDES; } + } diff --git a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/SpringShellTestProperties.java b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/SpringShellTestProperties.java index 97c7bfa9f..12d25784c 100644 --- a/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/SpringShellTestProperties.java +++ b/spring-shell-test-autoconfigure/src/main/java/org/springframework/shell/test/autoconfigure/SpringShellTestProperties.java @@ -50,4 +50,5 @@ public int getTerminalHeight() { public void setTerminalHeight(int terminalHeight) { this.terminalHeight = terminalHeight; } + } diff --git a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestIntegrationTests.java b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestIntegrationTests.java index d17aa5026..3d918a9a2 100644 --- a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestIntegrationTests.java +++ b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestIntegrationTests.java @@ -94,11 +94,10 @@ void testNonInteractive() throws Exception { Condition helpCondition = new Condition<>(line -> line.contains("AVAILABLE COMMANDS"), "Help has expected output"); - Condition helpHelpCondition = new Condition<>(line -> line.contains("help - Display help about available commands"), - "Help help has expected output"); + Condition helpHelpCondition = new Condition<>( + line -> line.contains("help - Display help about available commands"), "Help help has expected output"); - Condition emptyCondition = new Condition<>(line -> line.trim().length() == 0, - "Have only whitespace"); + Condition emptyCondition = new Condition<>(line -> line.trim().length() == 0, "Have only whitespace"); NonInteractiveShellSession session = client.nonInterative("help").run(); @@ -130,8 +129,7 @@ void testNonInteractive() throws Exception { @Test void testNonInteractive2() throws Exception { - Condition helloCondition = new Condition<>(line -> line.contains("hello"), - "Hello has expected output"); + Condition helloCondition = new Condition<>(line -> line.contains("hello"), "Hello has expected output"); NonInteractiveShellSession session = client.nonInterative("hello").run(); @@ -140,4 +138,5 @@ void testNonInteractive2() throws Exception { assertThat(lines).areExactly(1, helloCondition); }); } + } diff --git a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestPropertiesIntegrationTests.java b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestPropertiesIntegrationTests.java index daece6446..8c826f0da 100644 --- a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestPropertiesIntegrationTests.java +++ b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestPropertiesIntegrationTests.java @@ -52,4 +52,5 @@ void dimensionsSet() { assertThat(session.getTerminal().getTerminalWidth()).isEqualTo(81); assertThat(session.getTerminal().getTerminalHeight()).isEqualTo(25); } + } diff --git a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestTerminalDimensionsIntegrationTests.java b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestTerminalDimensionsIntegrationTests.java index 8c19a7627..645b021c8 100644 --- a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestTerminalDimensionsIntegrationTests.java +++ b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/ShellTestTerminalDimensionsIntegrationTests.java @@ -36,4 +36,5 @@ void dimensionsSet() { assertThat(session.getTerminal().getTerminalWidth()).isEqualTo(81); assertThat(session.getTerminal().getTerminalHeight()).isEqualTo(25); } + } diff --git a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/SpringShellTestPropertiesTests.java b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/SpringShellTestPropertiesTests.java index ee1137281..ce201a33f 100644 --- a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/SpringShellTestPropertiesTests.java +++ b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/SpringShellTestPropertiesTests.java @@ -28,29 +28,28 @@ class SpringShellTestPropertiesTests { @Test public void defaultNoPropertiesSet() { - this.contextRunner - .withUserConfiguration(Config1.class) - .run((context) -> { - SpringShellTestProperties properties = context.getBean(SpringShellTestProperties.class); - assertThat(properties.getTerminalWidth()).isEqualTo(80); - assertThat(properties.getTerminalHeight()).isEqualTo(24); - }); + this.contextRunner.withUserConfiguration(Config1.class).run((context) -> { + SpringShellTestProperties properties = context.getBean(SpringShellTestProperties.class); + assertThat(properties.getTerminalWidth()).isEqualTo(80); + assertThat(properties.getTerminalHeight()).isEqualTo(24); + }); } @Test public void setProperties() { - this.contextRunner - .withPropertyValues("spring.shell.test.terminal-width=81") - .withPropertyValues("spring.shell.test.terminal-height=25") - .withUserConfiguration(Config1.class) - .run((context) -> { - SpringShellTestProperties properties = context.getBean(SpringShellTestProperties.class); - assertThat(properties.getTerminalWidth()).isEqualTo(81); - assertThat(properties.getTerminalHeight()).isEqualTo(25); - }); + this.contextRunner.withPropertyValues("spring.shell.test.terminal-width=81") + .withPropertyValues("spring.shell.test.terminal-height=25") + .withUserConfiguration(Config1.class) + .run((context) -> { + SpringShellTestProperties properties = context.getBean(SpringShellTestProperties.class); + assertThat(properties.getTerminalWidth()).isEqualTo(81); + assertThat(properties.getTerminalHeight()).isEqualTo(25); + }); } @EnableConfigurationProperties({ SpringShellTestProperties.class }) private static class Config1 { + } + } diff --git a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/ExampleShellApplication.java b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/ExampleShellApplication.java index e512c92c7..b227932ed 100644 --- a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/ExampleShellApplication.java +++ b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/ExampleShellApplication.java @@ -26,4 +26,5 @@ */ @SpringBootApplication public class ExampleShellApplication { + } diff --git a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/HelloCommand.java b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/HelloCommand.java index c68212779..254617c3a 100644 --- a/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/HelloCommand.java +++ b/spring-shell-test-autoconfigure/src/test/java/org/springframework/shell/test/autoconfigure/app/HelloCommand.java @@ -25,4 +25,5 @@ public class HelloCommand { public String hello() { return "hello"; } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellAssertions.java b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellAssertions.java index fe4c0532d..7a0e75312 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellAssertions.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellAssertions.java @@ -27,16 +27,16 @@ public class ShellAssertions { /** * Instance of a assert factory for {@link ShellScreen}. */ - public static final InstanceOfAssertFactory SHELLSCREEN = new InstanceOfAssertFactory<>(ShellScreen.class, - ShellAssertions::assertThat); + public static final InstanceOfAssertFactory SHELLSCREEN = new InstanceOfAssertFactory<>( + ShellScreen.class, ShellAssertions::assertThat); /** * Creates an instance of {@link ShellScreenAssert}. - * * @param actual the actual value * @return the created assertion object */ public static ShellScreenAssert assertThat(ShellScreen actual) { return new ShellScreenAssert(actual); } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreen.java b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreen.java index baddd6863..1625e52fe 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreen.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreen.java @@ -26,14 +26,12 @@ public interface ShellScreen { /** * Gets a visible lines in a screen. - * * @return visible lines in a screen */ - List lines(); + List lines(); /** * Get {@code ShellScreen} out of lines. - * * @param lines the lines * @return instance of shell screen */ @@ -43,16 +41,17 @@ static ShellScreen of(List lines) { class DefaultShellScreen implements ShellScreen { - List lines; + List lines; - DefaultShellScreen(List lines) { - this.lines = lines; - } + DefaultShellScreen(List lines) { + this.lines = lines; + } - @Override - public List lines() { - return lines; - } - } + @Override + public List lines() { + return lines; + } + + } } \ No newline at end of file diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreenAssert.java b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreenAssert.java index 8be3e9b61..281fb7d60 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreenAssert.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellScreenAssert.java @@ -33,7 +33,6 @@ public ShellScreenAssert(ShellScreen actual) { /** * Verifies that text if found from a screen. - * * @param text the text to look for * @return this assertion object */ @@ -47,4 +46,5 @@ public ShellScreenAssert containsText(String text) { } return this; } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellTestClient.java b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellTestClient.java index 2ffcd9b43..f39920aaf 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellTestClient.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellTestClient.java @@ -37,9 +37,9 @@ import org.springframework.shell.test.jediterm.terminal.ui.TerminalSession; /** - * Client for terminal session which can be used as a programmatic way - * to interact with a shell application. In a typical test it is required - * to write into a shell and read what is visible in a shell. + * Client for terminal session which can be used as a programmatic way to interact with a + * shell application. In a typical test it is required to write into a shell and read what + * is visible in a shell. * * @author Janne Valkealahti */ @@ -47,14 +47,12 @@ public interface ShellTestClient extends Closeable { /** * Run interactive shell session. - * * @return session for chaining */ InteractiveShellSession interactive(); /** * Run non-interactive command session. - * * @param args the command arguments * @return session for chaining */ @@ -62,14 +60,12 @@ public interface ShellTestClient extends Closeable { /** * Read the screen. - * * @return the screen */ ShellScreen screen(); /** * Get an instance of a builder. - * * @param terminalSession the terminal session * @param shell the shell * @param promptProvider the prompt provider @@ -89,31 +85,28 @@ interface Builder { /** * Build a shell client. - * * @return a shell client */ ShellTestClient build(); + } - interface BaseShellSession> { + interface BaseShellSession> { /** * Get a write sequencer. - * * @return a write sequencer */ ShellWriteSequence writeSequence(); /** * Read the screen. - * * @return the screen */ ShellScreen screen(); /** * Write plain text into a shell. - * * @param text the text * @return client for chaining */ @@ -121,26 +114,32 @@ interface BaseShellSession> { /** * Run a session. - * * @return client for chaining */ T run(); boolean isComplete(); + } interface InteractiveShellSession extends BaseShellSession { + } interface NonInteractiveShellSession extends BaseShellSession { + } static class DefaultBuilder implements Builder { private TerminalSession terminalSession; + private Shell shell; + private PromptProvider promptProvider; + private LineReader lineReader; + private Terminal terminal; DefaultBuilder(TerminalSession terminalSession, Shell shell, PromptProvider promptProvider, @@ -156,17 +155,25 @@ static class DefaultBuilder implements Builder { public ShellTestClient build() { return new DefaultShellClient(terminalSession, shell, promptProvider, lineReader, terminal); } + } static class DefaultShellClient implements ShellTestClient { private final static Logger log = LoggerFactory.getLogger(DefaultShellClient.class); + private TerminalSession terminalSession; + private Shell shell; + private PromptProvider promptProvider; + private LineReader lineReader; + private Thread runnerThread; + private Terminal terminal; + private final BlockingQueue blockingQueue = new LinkedBlockingDeque<>(10); DefaultShellClient(TerminalSession terminalSession, Shell shell, PromptProvider promptProvider, @@ -185,7 +192,8 @@ public InteractiveShellSession interactive() { runnerThread = new Thread(new ShellRunnerTask(this.blockingQueue)); runnerThread.start(); } - return new DefaultInteractiveShellSession(shell, promptProvider, lineReader, blockingQueue, terminalSession, terminal); + return new DefaultInteractiveShellSession(shell, promptProvider, lineReader, blockingQueue, terminalSession, + terminal); } @Override @@ -212,16 +220,23 @@ public void close() throws IOException { runnerThread = null; terminalSession.close(); } + } static class DefaultInteractiveShellSession implements InteractiveShellSession { private Shell shell; + private PromptProvider promptProvider; + private LineReader lineReader; + private BlockingQueue blockingQueue; + private TerminalSession terminalSession; + private Terminal terminal; + private final AtomicInteger state = new AtomicInteger(-2); public DefaultInteractiveShellSession(Shell shell, PromptProvider promptProvider, LineReader lineReader, @@ -252,7 +267,8 @@ public ShellScreen screen() { @Override public InteractiveShellSession run() { - ShellRunner runner = new InteractiveShellRunner(lineReader, promptProvider, shell, new DefaultShellContext()); + ShellRunner runner = new InteractiveShellRunner(lineReader, promptProvider, shell, + new DefaultShellContext()); ApplicationArguments appArgs = new DefaultApplicationArguments(); this.blockingQueue.add(new ShellRunnerTaskData(runner, appArgs, state)); return this; @@ -262,15 +278,21 @@ public InteractiveShellSession run() { public boolean isComplete() { return state.get() >= 0; } + } static class DefaultNonInteractiveShellSession implements NonInteractiveShellSession { private Shell shell; + private String[] args; + private BlockingQueue blockingQueue; + private TerminalSession terminalSession; + private Terminal terminal; + private final AtomicInteger state = new AtomicInteger(-2); public DefaultNonInteractiveShellSession(Shell shell, String[] args, @@ -310,17 +332,16 @@ public NonInteractiveShellSession run() { public boolean isComplete() { return state.get() >= 0; } + } - static record ShellRunnerTaskData( - ShellRunner runner, - ApplicationArguments args, - AtomicInteger state - ) {} + static record ShellRunnerTaskData(ShellRunner runner, ApplicationArguments args, AtomicInteger state) { + } static class ShellRunnerTask implements Runnable { private final static Logger log = LoggerFactory.getLogger(ShellRunnerTask.class); + private BlockingQueue blockingQueue; ShellRunnerTask(BlockingQueue blockingQueue) { @@ -348,15 +369,19 @@ public void run() { } data.state().set(0); log.trace("Running done {}", data.runner()); - } catch (Exception e) { + } + catch (Exception e) { data.state().set(1); log.trace("ShellRunnerThread ex", e); } } - } catch (InterruptedException e) { + } + catch (InterruptedException e) { Thread.currentThread().interrupt(); } log.trace("ShellRunnerTask end"); } + } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellWriteSequence.java b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellWriteSequence.java index 9f85624cb..f10f55da3 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/ShellWriteSequence.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/ShellWriteSequence.java @@ -28,21 +28,18 @@ public interface ShellWriteSequence { /** * Sequence terminal clear screen. - * * @return a sequence for chaining */ ShellWriteSequence clearScreen(); /** * Sequence terminal carriage return. - * * @return a sequence for chaining */ ShellWriteSequence carriageReturn(); /** * Sequence from command with expected {@code carriage return}. - * * @param command the command * @return a sequence for chaining */ @@ -50,7 +47,6 @@ public interface ShellWriteSequence { /** * Sequence terminal carriage return. Alias for {@link #carriageReturn} - * * @return a sequence for chaining * @see #carriageReturn() */ @@ -58,7 +54,6 @@ public interface ShellWriteSequence { /** * Sequence text. - * * @param text the text * @return a sequence for chaining */ @@ -66,56 +61,48 @@ public interface ShellWriteSequence { /** * Sequence terminal key down. - * * @return a sequence for chaining */ ShellWriteSequence keyDown(); /** * Sequence terminal key left. - * * @return a sequence for chaining */ ShellWriteSequence keyLeft(); /** * Sequence terminal key right. - * * @return a sequence for chaining */ ShellWriteSequence keyRight(); /** * Sequence terminal key up. - * * @return a sequence for chaining */ ShellWriteSequence keyUp(); /** * Sequence terminal space. - * * @return a sequence for chaining */ ShellWriteSequence space(); /** * Sequence terminal ctrl. - * * @return a sequence for chaining */ ShellWriteSequence ctrl(char c); /** * Build the result. - * * @return the result */ String build(); /** * Get a new instance of a {@code ShellWriteSequence}. - * * @param terminal the terminal * @return instance of a write sequence */ @@ -126,6 +113,7 @@ static ShellWriteSequence of(Terminal terminal) { static class DefaultShellWriteSequence implements ShellWriteSequence { private final Terminal terminal; + private StringBuilder buf = new StringBuilder(); DefaultShellWriteSequence(Terminal terminal) { @@ -202,5 +190,7 @@ public ShellWriteSequence space() { public String build() { return buf.toString(); } + } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/ArrayTerminalDataStream.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/ArrayTerminalDataStream.java index 68ba61000..fc1db2190 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/ArrayTerminalDataStream.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/ArrayTerminalDataStream.java @@ -27,7 +27,9 @@ public class ArrayTerminalDataStream implements TerminalDataStream { protected char[] buf; + protected int offset; + protected int length; public ArrayTerminalDataStream(char[] buf, int offset, int length) { @@ -93,4 +95,5 @@ public void pushBackBuffer(final char[] bytes, final int length) throws EOF { public boolean isEmpty() { return this.length == 0; } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/CursorShape.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/CursorShape.java index 66dacac45..c19a063e3 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/CursorShape.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/CursorShape.java @@ -21,10 +21,7 @@ * @author jediterm authors */ public enum CursorShape { - BLINK_BLOCK, - STEADY_BLOCK, - BLINK_UNDERLINE, - STEADY_UNDERLINE, - BLINK_VERTICAL_BAR, - STEADY_VERTICAL_BAR + + BLINK_BLOCK, STEADY_BLOCK, BLINK_UNDERLINE, STEADY_UNDERLINE, BLINK_VERTICAL_BAR, STEADY_VERTICAL_BAR + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/DataStreamIteratingEmulator.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/DataStreamIteratingEmulator.java index 3f57d6ca4..befb8daee 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/DataStreamIteratingEmulator.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/DataStreamIteratingEmulator.java @@ -25,6 +25,7 @@ public abstract class DataStreamIteratingEmulator implements Emulator { protected final TerminalDataStream myDataStream; + protected final Terminal myTerminal; private boolean myEof = false; @@ -56,4 +57,5 @@ public void next() throws IOException { } protected abstract void processChar(char ch, Terminal terminal) throws IOException; + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/RequestOrigin.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/RequestOrigin.java index b5f0f6135..9e17b1563 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/RequestOrigin.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/RequestOrigin.java @@ -18,12 +18,11 @@ */ package org.springframework.shell.test.jediterm.terminal; - /** - * * @author jediterm authors */ -public enum RequestOrigin{ - User, - Remote +public enum RequestOrigin { + + User, Remote + } \ No newline at end of file diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumer.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumer.java index 493bf682a..4b22ab7f0 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumer.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumer.java @@ -18,19 +18,20 @@ import org.springframework.shell.test.jediterm.terminal.model.CharBuffer; /** - * General interface that obtains styled range of characters at coordinates (x, y) when the screen starts at startRow + * General interface that obtains styled range of characters at coordinates (x, + * y) when the screen starts at startRow * * @author jediterm authors */ public interface StyledTextConsumer { + /** - * * @param x indicates starting column of the characters * @param y indicates row of the characters * @param style style of characters * @param characters text characters - * @param startRow number of the first row. - * It can be different for different buffers, e.g. backBuffer starts from 0, textBuffer and scrollBuffer from -count + * @param startRow number of the first row. It can be different for different buffers, + * e.g. backBuffer starts from 0, textBuffer and scrollBuffer from -count */ void consume(int x, int y, TextStyle style, CharBuffer characters, int startRow); diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumerAdapter.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumerAdapter.java index d8fda825f..5f1e7cd22 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumerAdapter.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/StyledTextConsumerAdapter.java @@ -18,7 +18,6 @@ import org.springframework.shell.test.jediterm.terminal.model.CharBuffer; /** - * * @author jediterm authors */ public class StyledTextConsumerAdapter implements StyledTextConsumer { diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/Terminal.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/Terminal.java index 0257c2608..8594f83b5 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/Terminal.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/Terminal.java @@ -21,11 +21,14 @@ import org.springframework.shell.test.jediterm.terminal.model.StyleState; /** - * Executes terminal commands interpreted by {@link org.springframework.shell.test.jediterm.terminal.emulator.Emulator}, receives text + * Executes terminal commands interpreted by + * {@link org.springframework.shell.test.jediterm.terminal.emulator.Emulator}, receives + * text * * @author jediterm authors */ public interface Terminal { + void resize(int width, int height, RequestOrigin origin); void resize(int width, int height, RequestOrigin origin, CompletableFuture promptUpdated); @@ -167,4 +170,5 @@ public interface Terminal { // TerminalColor getWindowForeground(); // TerminalColor getWindowBackground(); + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalCopyPasteHandler.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalCopyPasteHandler.java index ed8593423..e7ff89e49 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalCopyPasteHandler.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalCopyPasteHandler.java @@ -16,11 +16,12 @@ package org.springframework.shell.test.jediterm.terminal; /** - * * @author jediterm authors */ public interface TerminalCopyPasteHandler { + void setContents(String text, boolean useSystemSelectionClipboardIfAvailable); String getContents(boolean useSystemSelectionClipboardIfAvailable); + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDataStream.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDataStream.java index ad1e27d4b..e04c2e841 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDataStream.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDataStream.java @@ -18,10 +18,10 @@ import java.io.IOException; /** - * Represents data communication interface for terminal. - * It allows to {@link #getChar()} by one and {@link #pushChar(char)} back as well as requesting a chunk of plain ASCII - * characters ({@link #readNonControlCharacters(int)} - for faster processing from buffer in the size {@literal <=maxChars}). - * + * Represents data communication interface for terminal. It allows to {@link #getChar()} + * by one and {@link #pushChar(char)} back as well as requesting a chunk of plain ASCII + * characters ({@link #readNonControlCharacters(int)} - for faster processing from buffer + * in the size {@literal <=maxChars}). * * @author jediterm authors */ @@ -38,8 +38,11 @@ public interface TerminalDataStream { boolean isEmpty(); class EOF extends IOException { + public EOF() { super("EOF: There is no more data or connection is lost"); } + } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDisplay.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDisplay.java index ccf8cb55f..674c52350 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDisplay.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalDisplay.java @@ -16,7 +16,6 @@ package org.springframework.shell.test.jediterm.terminal; /** - * * @author jediterm authors */ public interface TerminalDisplay { @@ -35,13 +34,15 @@ public interface TerminalDisplay { boolean ambiguousCharsAreDoubleWidth(); - default void setBracketedPasteMode(boolean enabled) {} + default void setBracketedPasteMode(boolean enabled) { + } // default TerminalColor getWindowForeground() { - // return null; + // return null; // } // default TerminalColor getWindowBackground() { - // return null; + // return null; // } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalMode.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalMode.java index 8987ac12b..9b5f54221 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalMode.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalMode.java @@ -15,28 +15,26 @@ */ package org.springframework.shell.test.jediterm.terminal; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * * @author jediterm authors */ public enum TerminalMode { - Null, - CursorKey { + + Null, CursorKey { @Override public void setEnabled(Terminal terminal, boolean enabled) { terminal.setApplicationArrowKeys(enabled); } }, - ANSI, - WideColumn { + ANSI, WideColumn { @Override public void setEnabled(Terminal terminal, boolean enabled) { // Skip resizing as it would require to resize parent container. - // Other terminal emulators (iTerm2, Terminal.app, GNOME Terminal) ignore it too. + // Other terminal emulators (iTerm2, Terminal.app, GNOME Terminal) ignore it + // too. terminal.clearScreen(); terminal.resetScrollRegions(); } @@ -53,9 +51,7 @@ public void setEnabled(Terminal terminal, boolean enabled) { terminal.useAlternateBuffer(enabled); } }, - SmoothScroll, - ReverseVideo, - OriginMode { + SmoothScroll, ReverseVideo, OriginMode { @Override public void setEnabled(Terminal terminal, boolean enabled) { } @@ -63,12 +59,10 @@ public void setEnabled(Terminal terminal, boolean enabled) { AutoWrap { @Override public void setEnabled(Terminal terminal, boolean enabled) { - //we do nothing just switching the mode + // we do nothing just switching the mode } }, - AutoRepeatKeys, - Interlace, - Keypad { + AutoRepeatKeys, Interlace, Keypad { @Override public void setEnabled(Terminal terminal, boolean enabled) { terminal.setApplicationKeypad(enabled); @@ -91,27 +85,25 @@ public void setEnabled(Terminal terminal, boolean enabled) { terminal.setBlinkingCursor(enabled); } }, - AllowWideColumn, - ReverseWrapAround, - AutoNewLine { + AllowWideColumn, ReverseWrapAround, AutoNewLine { @Override public void setEnabled(Terminal terminal, boolean enabled) { terminal.setAutoNewLine(enabled); } }, - KeyboardAction, - InsertMode, - SendReceive, - EightBitInput, //Interpret "meta" key, sets eighth bit. (enables the eightBitInput resource). - // http://www.leonerd.org.uk/hacks/hints/xterm-8bit.html + KeyboardAction, InsertMode, SendReceive, EightBitInput, // Interpret "meta" key, sets + // eighth bit. (enables the + // eightBitInput resource). + // http://www.leonerd.org.uk/hacks/hints/xterm-8bit.html - AltSendsEscape //See section Alt and Meta Keys in http://invisible-island.net/xterm/ctlseqs/ctlseqs.html - { - @Override - public void setEnabled(Terminal terminal, boolean enabled) { - terminal.setAltSendsEscape(enabled); - } - }, + AltSendsEscape // See section Alt and Meta Keys in + // http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + { + @Override + public void setEnabled(Terminal terminal, boolean enabled) { + terminal.setAltSendsEscape(enabled); + } + }, // https://cirw.in/blog/bracketed-paste // http://www.xfree86.org/current/ctlseqs.html#Bracketed%20Paste%20Mode @@ -120,12 +112,12 @@ public void setEnabled(Terminal terminal, boolean enabled) { public void setEnabled(Terminal terminal, boolean enabled) { terminal.setBracketedPasteMode(enabled); } - } - ; + }; private static final Logger LOG = LoggerFactory.getLogger(TerminalMode.class); public void setEnabled(Terminal terminal, boolean enabled) { LOG.warn("Mode " + name() + " is not implemented, setting to " + enabled); } + } \ No newline at end of file diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalOutputStream.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalOutputStream.java index 78606e418..420861cf6 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalOutputStream.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalOutputStream.java @@ -16,11 +16,12 @@ package org.springframework.shell.test.jediterm.terminal; /** - * Sends a response from the terminal emulator. + * Sends a response from the terminal emulator. * * @author jediterm authors */ public interface TerminalOutputStream { + /** * @deprecated use {@link #sendBytes(byte[], boolean)} instead */ @@ -38,7 +39,9 @@ public interface TerminalOutputStream { default void sendBytes(byte[] response, boolean userInput) { sendBytes(response); } + default void sendString(String string, boolean userInput) { sendString(string); } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalStarter.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalStarter.java index a44e3f804..c6bb45dc6 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalStarter.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TerminalStarter.java @@ -29,7 +29,6 @@ import org.springframework.shell.test.jediterm.terminal.emulator.Emulator; import org.springframework.shell.test.jediterm.terminal.emulator.JediEmulator; - /** * Runs terminal emulator. Manages threads to send response. * @@ -83,7 +82,7 @@ public void start() { } // public byte[] getCode(final int key, final int modifiers) { - // return myTerminal.getCodeForKey(key, modifiers); + // return myTerminal.getCodeForKey(key, modifiers); // } public void postResize(int width, int height, RequestOrigin origin) { @@ -99,7 +98,7 @@ public void postResize(int width, int height, RequestOrigin origin) { */ public static void resize(Emulator emulator, Terminal terminal, TtyConnector ttyConnector, int width, int height, RequestOrigin origin, BiConsumer taskScheduler) { - CompletableFuture promptUpdated = ((JediEmulator)emulator).getPromptUpdatedAfterResizeFuture(taskScheduler); + CompletableFuture promptUpdated = ((JediEmulator) emulator).getPromptUpdatedAfterResizeFuture(taskScheduler); terminal.resize(width, height, origin, promptUpdated); ttyConnector.resize(width, height); } @@ -152,4 +151,5 @@ public void close() { } }); } + } diff --git a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TextStyle.java b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TextStyle.java index f114316b9..e4b2b12cf 100644 --- a/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TextStyle.java +++ b/spring-shell-test/src/main/java/org/springframework/shell/test/jediterm/terminal/TextStyle.java @@ -21,10 +21,10 @@ import java.util.WeakHashMap; /** - * * @author jediterm authors */ public class TextStyle { + private static final EnumSet