From 9f88c03cf3eb47770fb9775f740c1ee66726c5c7 Mon Sep 17 00:00:00 2001 From: Eric Bottard Date: Wed, 30 Aug 2017 16:54:36 +0200 Subject: [PATCH] Add ability to run commands and exit --- .../java/org/springframework/shell/Shell.java | 9 ++--- .../shell/SpringShellAutoConfiguration.java | 12 ++---- .../jline/JLineShellAutoConfiguration.java | 40 ++++++++++++++----- .../AttributedCharSequenceResultHandler.java | 1 + .../result/CommandNotFoundResultHandler.java | 1 + .../TerminalSizeAwareResultHandler.java | 1 + .../shell/result/ThrowableResultHandler.java | 1 + .../org/springframework/shell/ShellTest.java | 10 ++--- .../shell/samples/SpringShellSample.java | 1 + .../shell/standard/commands/Script.java | 6 +-- 10 files changed, 49 insertions(+), 33 deletions(-) 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 2d83003a..b53f4a1a 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 @@ -49,8 +49,6 @@ import org.springframework.util.ReflectionUtils; */ public class Shell implements CommandRegistry { - private final InputProvider inputProvider; - private final ResultHandler resultHandler; @Autowired @@ -65,8 +63,7 @@ public class Shell implements CommandRegistry { */ protected static final Object UNRESOLVED = new Object(); - public Shell(InputProvider inputProvider, ResultHandler resultHandler) { - this.inputProvider = inputProvider; + public Shell(ResultHandler resultHandler) { this.resultHandler = resultHandler; } @@ -94,9 +91,9 @@ public class Shell implements CommandRegistry { /** * 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. + * {@link ResultHandler} causes the process to exit or there is no input. */ - public void run() throws IOException { + public void run(InputProvider inputProvider) throws IOException { while (true) { Input input; try { diff --git a/spring-shell-core/src/main/java/org/springframework/shell/SpringShellAutoConfiguration.java b/spring-shell-core/src/main/java/org/springframework/shell/SpringShellAutoConfiguration.java index 7673fa3a..9d221d92 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/SpringShellAutoConfiguration.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/SpringShellAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.shell; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -40,14 +41,9 @@ public class SpringShellAutoConfiguration { } @Bean - @ConditionalOnMissingBean(ApplicationRunner.class) - public ApplicationRunner applicationRunner(Shell shell) { - return new ApplicationRunner() { - @Override - public void run(ApplicationArguments args) throws Exception { - shell.run(); - } - }; + public Shell shell(@Qualifier("main") ResultHandler resultHandler) { + return new Shell(resultHandler); } + } diff --git a/spring-shell-core/src/main/java/org/springframework/shell/jline/JLineShellAutoConfiguration.java b/spring-shell-core/src/main/java/org/springframework/shell/jline/JLineShellAutoConfiguration.java index 3c47dcd5..e6d867c9 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/jline/JLineShellAutoConfiguration.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/jline/JLineShellAutoConfiguration.java @@ -16,7 +16,7 @@ package org.springframework.shell.jline; -import java.io.IOException; +import java.io.*; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; @@ -35,6 +35,8 @@ import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationListener; @@ -61,16 +63,15 @@ import org.springframework.shell.Shell; @Configuration class JLineShellAutoConfiguration { - @Autowired - @Qualifier("main") - private ResultHandler resultHandler; - @Autowired private PromptProvider promptProvider; @Autowired private History history; + @Autowired + private Shell shell; + @Bean public Terminal terminal() { try { @@ -82,10 +83,31 @@ class JLineShellAutoConfiguration { } @Bean - public Shell shell() { - return new Shell(new JLineInputProvider(lineReader(), promptProvider), resultHandler); + @ConditionalOnMissingBean(ApplicationRunner.class) + public ApplicationRunner applicationRunner(Parser parser) { + return new ApplicationRunner() { + @Override + public void run(ApplicationArguments args) throws Exception { + List scriptsToRun = args.getNonOptionArgs().stream() + .filter(s -> s.startsWith("@")) + .map(s -> new File(s.substring(1))) + .collect(Collectors.toList()); + + if (scriptsToRun.isEmpty()) { + InputProvider inputProvider = new JLineInputProvider(lineReader(), promptProvider); + shell.run(inputProvider); + } else { + for (File file : scriptsToRun) { + try (Reader reader = new FileReader(file); FileInputProvider inputProvider = new FileInputProvider(reader, parser)) { + shell.run(inputProvider); + } + } + } + } + }; } + @Bean @ConditionalOnMissingBean(PromptProvider.class) public PromptProvider promptProvider() { @@ -127,7 +149,7 @@ class JLineShellAutoConfiguration { */ @PostConstruct public void lateInit() { - completer().setShell(shell()); + completer().setShell(shell); } @Bean @@ -151,7 +173,7 @@ class JLineShellAutoConfiguration { public AttributedString highlight(LineReader reader, String buffer) { int l = 0; String best = null; - for (String command : shell().listCommands().keySet()) { + for (String command : shell.listCommands().keySet()) { if (buffer.startsWith(command) && command.length() > l) { l = command.length(); best = command; 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 a7ec18e6..fafc7e29 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 @@ -32,5 +32,6 @@ public class AttributedCharSequenceResultHandler extends TerminalAwareResultHand @Override public void handleResult(AttributedCharSequence result) { terminal.writer().println(result.toAnsi(terminal)); + terminal.writer().flush(); } } 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 17ae3fbe..a5109aef 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 @@ -37,6 +37,7 @@ public class CommandNotFoundResultHandler extends TerminalAwareResultHandler imp public void handleResult(CommandNotFound result) { terminal.writer().println(new AttributedString(result.getMessage(), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)).toAnsi()); + terminal.writer().flush(); } } 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 8fa9679a..b3e361e0 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 @@ -31,5 +31,6 @@ public class TerminalSizeAwareResultHandler extends TerminalAwareResultHandler i public void handleResult(TerminalSizeAware result) { CharSequence toPrint = result.render(terminal.getWidth()); terminal.writer().println(toPrint); + terminal.writer().flush(); } } 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 d3644e5d..0966adef 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 @@ -58,6 +58,7 @@ public class ThrowableResultHandler extends TerminalAwareResultHandler implement .toAnsi() ); } + terminal.writer().flush(); } /** diff --git a/spring-shell-core/src/test/java/org/springframework/shell/ShellTest.java b/spring-shell-core/src/test/java/org/springframework/shell/ShellTest.java index 3c91e33d..933af916 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/ShellTest.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/ShellTest.java @@ -82,7 +82,7 @@ public class ShellTest { shell.methodTargets = Collections.singletonMap("hello world", MethodTarget.of("helloWorld", this, "Say hello")); try { - shell.run(); + shell.run(inputProvider); fail("Exit expected"); } catch (Exit expected) { @@ -100,7 +100,7 @@ public class ShellTest { shell.methodTargets = Collections.singletonMap("bonjour", MethodTarget.of("helloWorld", this, "Say hello")); try { - shell.run(); + shell.run(inputProvider); fail("Exit expected"); } catch (Exit expected) { @@ -119,7 +119,7 @@ public class ShellTest { shell.methodTargets = Collections.singletonMap("hello world", MethodTarget.of("helloWorld", this, "Say hello")); try { - shell.run(); + shell.run(inputProvider); fail("Exit expected"); } catch (Exit expected) { @@ -138,7 +138,7 @@ public class ShellTest { shell.methodTargets = Collections.singletonMap("fail", MethodTarget.of("failing", this, "Will throw an exception")); try { - shell.run(); + shell.run(inputProvider); fail("Exit expected"); } catch (Exit expected) { @@ -154,7 +154,7 @@ public class ShellTest { when(parameterResolver.supports(any())).thenReturn(true); when(inputProvider.readInput()).thenReturn(() -> "// This is a comment", (Input) null); - shell.run(); + shell.run(inputProvider); } diff --git a/spring-shell-samples/src/main/java/org/springframework/shell/samples/SpringShellSample.java b/spring-shell-samples/src/main/java/org/springframework/shell/samples/SpringShellSample.java index 4ae09724..4cea9ce0 100644 --- a/spring-shell-samples/src/main/java/org/springframework/shell/samples/SpringShellSample.java +++ b/spring-shell-samples/src/main/java/org/springframework/shell/samples/SpringShellSample.java @@ -16,6 +16,7 @@ package org.springframework.shell.samples; +import org.jline.terminal.Terminal; import org.jline.utils.AttributedString; import org.jline.utils.AttributedStyle; diff --git a/spring-shell-standard-commands/src/main/java/org/springframework/shell/standard/commands/Script.java b/spring-shell-standard-commands/src/main/java/org/springframework/shell/standard/commands/Script.java index 2414a655..c1d439cb 100644 --- a/spring-shell-standard-commands/src/main/java/org/springframework/shell/standard/commands/Script.java +++ b/spring-shell-standard-commands/src/main/java/org/springframework/shell/standard/commands/Script.java @@ -47,11 +47,7 @@ public class Script { public void script(File file) throws IOException { Reader reader = new FileReader(file); try (FileInputProvider inputProvider = new FileInputProvider(reader, parser)) { - Input input = inputProvider.readInput(); - while (input != null) { - shell.evaluate(input); - input = inputProvider.readInput(); - } + shell.run(inputProvider); } }