Mercurial > hg > release > thermostat-2.0
changeset 2497:25b96e8c3259
Add "clear"/"cls" keyword to clear screen in shell
Reviewed-by: jerboaa
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-October/021220.html
author | Andrew Azores <aazores@redhat.com> |
---|---|
date | Wed, 26 Oct 2016 13:04:00 -0400 |
parents | 50b5d89f6e25 |
children | d488ec8f49fd |
files | launcher/src/main/java/com/redhat/thermostat/launcher/internal/ShellCommand.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java |
diffstat | 2 files changed, 90 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/ShellCommand.java Wed Oct 26 17:22:43 2016 +0200 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/ShellCommand.java Wed Oct 26 13:04:00 2016 -0400 @@ -76,6 +76,7 @@ private static final Translate<LocaleResources> t = LocaleResources.createLocalizer(); private static final List<String> exitKeywords = Arrays.asList("exit", "quit", "q" ); + private static final List<String> clearKeywords = Arrays.asList("clear", "cls"); private HistoryProvider historyProvider; private Version version; @@ -137,7 +138,10 @@ String userGuideUrl = new ApplicationInfo().getUserGuide(); String userGuideMessage = t.localize(LocaleResources.COMMAND_SHELL_USER_GUIDE, userGuideUrl).getContents(); ctx.getConsole().getOutput().println(userGuideMessage); - shellMainLoop(ctx, history, term); + + ConsoleReader reader = createConsoleReader(ctx, term); + setupConsoleReader(reader, history); + shellMainLoop(ctx.getConsole(), reader); } catch (IOException ex) { throw new CommandException(t.localize(LocaleResources.COMMAND_SHELL_IO_EXCEPTION), ex); } finally { @@ -152,16 +156,7 @@ } } - private void closeTerminal(Terminal term) { - try { - term.restore(); - } catch (Exception e) { - logger.log(Level.WARNING, "Error restoring terminal state.", e); - } - } - - private void shellMainLoop(CommandContext ctx, History history, Terminal term) throws IOException, CommandException { - ConsoleReader reader = new ConsoleReader(ctx.getConsole().getInput(), ctx.getConsole().getOutput(), term); + private void setupConsoleReader(ConsoleReader reader, History history) throws IOException { reader.setHandleUserInterrupt(true); reader.setPrompt(shellPrompt.getPrompt()); if (completerServiceRegistry != null) { @@ -174,8 +169,24 @@ CandidateListCompletionHandler completionHandler = new CandidateListCompletionHandler(); completionHandler.setPrintSpaceAfterFullCompletion(false); reader.setCompletionHandler(completionHandler); + } + + // package-private for testing + ConsoleReader createConsoleReader(CommandContext ctx, Terminal terminal) throws IOException { + return new ConsoleReader(ctx.getConsole().getInput(), ctx.getConsole().getOutput(), terminal); + } + + private void closeTerminal(Terminal term) { try { - while (handleConsoleInput(reader, ctx.getConsole(), shellPrompt.getPrompt())) { /* no-op; the loop conditional performs the action */ } + term.restore(); + } catch (Exception e) { + logger.log(Level.WARNING, "Error restoring terminal state.", e); + } + } + + private void shellMainLoop(Console console, ConsoleReader reader) throws IOException, CommandException { + try { + while (handleConsoleInput(console, reader, shellPrompt.getPrompt())) { /* no-op; the loop conditional performs the action */ } } finally { reader.shutdown(); } @@ -184,7 +195,7 @@ /** * @return true if the shell should continue accepting more input or false if the shell should quit */ - private boolean handleConsoleInput(ConsoleReader reader, Console console, String prompt) throws IOException, CommandException { + private boolean handleConsoleInput(Console console, ConsoleReader reader, String prompt) throws IOException, CommandException { String line; try { line = reader.readLine(prompt); @@ -200,6 +211,9 @@ return true; } else if (exitKeywords.contains(line)) { return false; + } else if (clearKeywords.contains(line)) { + reader.clearScreen(); + return true; } else { launchCommand(line); return true;
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java Wed Oct 26 17:22:43 2016 +0200 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java Wed Oct 26 13:04:00 2016 -0400 @@ -39,10 +39,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.io.IOException; @@ -51,6 +53,7 @@ import java.util.Collection; import java.util.EnumSet; +import jline.Terminal; import jline.console.ConsoleReader; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; @@ -270,6 +273,66 @@ } @Test + public void testClearKeywordClearsScreen() throws CommandException, IOException { + final ConsoleReader reader = mock(ConsoleReader.class); + when(reader.readLine()).thenReturn("clear").thenReturn("quit"); + when(reader.readLine(anyString())).thenReturn("clear").thenReturn("quit"); + cmd = new ShellCommand(bundleContext, version, historyProvider, config, prefs) { + @Override + ConsoleReader createConsoleReader(CommandContext ctx, Terminal terminal) throws IOException { + return reader; + } + }; + cmd.setTabCompletion(tabCompletion); + setupCommandInfoSource(); + + ServiceReference ref = mock(ServiceReference.class); + when(bundleContext.getServiceReference(Launcher.class.getName())).thenReturn(ref); + + Launcher launcher = mock(Launcher.class); + when(bundleContext.getService(ref)).thenReturn(launcher); + + TestCommandContextFactory ctxFactory = new TestCommandContextFactory(bundleContext); + + Arguments args = new SimpleArguments(); + CommandContext ctx = ctxFactory.createContext(args); + cmd.run(ctx); + verify(reader).clearScreen(); + // "clear" is a shell keyword, not a real command, so it should not have been passed through to the Launcher + verifyZeroInteractions(launcher); + } + + @Test + public void testClsKeywordClearsScreen() throws CommandException, IOException { + final ConsoleReader reader = mock(ConsoleReader.class); + when(reader.readLine()).thenReturn("clear").thenReturn("quit"); + when(reader.readLine(anyString())).thenReturn("clear").thenReturn("quit"); + cmd = new ShellCommand(bundleContext, version, historyProvider, config, prefs) { + @Override + ConsoleReader createConsoleReader(CommandContext ctx, Terminal terminal) throws IOException { + return reader; + } + }; + cmd.setTabCompletion(tabCompletion); + setupCommandInfoSource(); + + ServiceReference ref = mock(ServiceReference.class); + when(bundleContext.getServiceReference(Launcher.class.getName())).thenReturn(ref); + + Launcher launcher = mock(Launcher.class); + when(bundleContext.getService(ref)).thenReturn(launcher); + + TestCommandContextFactory ctxFactory = new TestCommandContextFactory(bundleContext); + + Arguments args = new SimpleArguments(); + CommandContext ctx = ctxFactory.createContext(args); + cmd.run(ctx); + verify(reader).clearScreen(); + // "cls" is a shell keyword, not a real command, so it should not have been passed through to the Launcher + verifyZeroInteractions(launcher); + } + + @Test public void testNoInputTabCompletes() throws CommandException { ServiceReference ref = mock(ServiceReference.class); when(bundleContext.getServiceReference(Launcher.class.getName())).thenReturn(ref);