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);