From 058e937c3ef6261033e36eed5be12fc91474458c Mon Sep 17 00:00:00 2001 From: Mike Cifelli Date: Tue, 21 Mar 2017 15:03:16 -0400 Subject: [PATCH] Refactor main interpreter code Fixed several minor issues Only print the last value when interpreting a file Resolves #4 --- src/environment/RuntimeEnvironment.java | 12 +- src/interpreter/FileLispInterpreter.java | 24 +++- .../InteractiveLispInterpreter.java | 22 ++-- src/interpreter/LispInterpreter.java | 27 ++-- src/interpreter/LispInterpreterBuilder.java | 10 +- .../LispInterpreterBuilderImpl.java | 10 +- src/main/LispMain.java | 60 +++++---- src/terminal/LispTerminal.java | 18 ++- test/environment/RuntimeEnvironmentTest.java | 12 +- test/function/builtin/LOADTest.java | 1 - test/terminal/LispTerminalTest.java | 124 +++++++++++------- 11 files changed, 187 insertions(+), 133 deletions(-) diff --git a/src/environment/RuntimeEnvironment.java b/src/environment/RuntimeEnvironment.java index 8e03352..7b96dde 100644 --- a/src/environment/RuntimeEnvironment.java +++ b/src/environment/RuntimeEnvironment.java @@ -21,7 +21,7 @@ public class RuntimeEnvironment { private String path; private Runnable terminationFunction; private Runnable errorTerminationFunction; - private Function outputDecorator; + private Function promptDecorator; private Function valueOutputDecorator; private Function warningOutputDecorator; private Function errorOutputDecorator; @@ -40,7 +40,7 @@ public class RuntimeEnvironment { path = null; terminationFunction = null; errorTerminationFunction = null; - outputDecorator = null; + promptDecorator = null; valueOutputDecorator = null; warningOutputDecorator = null; errorOutputDecorator = null; @@ -79,8 +79,8 @@ public class RuntimeEnvironment { this.errorTerminationFunction = errorTerminationFunction; } - public void setOutputDecorator(Function outputDecorator) { - this.outputDecorator = outputDecorator; + public void setPromptDecorator(Function promptDecorator) { + this.promptDecorator = promptDecorator; } public void setValueOutputDecorator(Function valueOutputDecorator) { @@ -131,8 +131,8 @@ public class RuntimeEnvironment { errorTerminationFunction.run(); } - public String decorateOutput(String output) { - return outputDecorator.apply(output); + public String decoratePrompt(String prompt) { + return promptDecorator.apply(prompt); } public String decorateValueOutput(String valueOutput) { diff --git a/src/interpreter/FileLispInterpreter.java b/src/interpreter/FileLispInterpreter.java index b83e081..f5c0288 100644 --- a/src/interpreter/FileLispInterpreter.java +++ b/src/interpreter/FileLispInterpreter.java @@ -1,11 +1,29 @@ package interpreter; +import sexpression.SExpression; + public class FileLispInterpreter extends LispInterpreter { + private SExpression lastSExpression; + + public FileLispInterpreter() { + this.lastSExpression = null; + } + @Override - protected void afterInterpreting() { - environment.getOutput().println(); - environment.getOutput().close(); + protected SExpression evaluateNextSExpression() { + return this.lastSExpression = super.evaluateNextSExpression(); + } + + @Override + protected void printSExpression(SExpression sExpression) {} + + @Override + protected void applyFinishingTouches() { + if (lastSExpression != null) + super.printSExpression(lastSExpression); + + super.applyFinishingTouches(); } } diff --git a/src/interpreter/InteractiveLispInterpreter.java b/src/interpreter/InteractiveLispInterpreter.java index 2204714..0fda432 100644 --- a/src/interpreter/InteractiveLispInterpreter.java +++ b/src/interpreter/InteractiveLispInterpreter.java @@ -1,34 +1,28 @@ package interpreter; +import sexpression.SExpression; + public class InteractiveLispInterpreter extends LispInterpreter { - private static final String GREETING = "Transcendental Lisp - Version 1.0.0"; private static final String PROMPT = "~ "; - @Override - protected void beforeInterpreting() { - environment.getOutput().println(GREETING); - environment.getOutput().println(); - environment.getOutput().flush(); - } - @Override protected void prompt() { - environment.getOutput().print(environment.decorateOutput(PROMPT)); + environment.getOutput().print(environment.decoratePrompt(PROMPT)); environment.getOutput().flush(); } @Override - protected void printValueOfNextSExpression() { + protected void printSExpression(SExpression sExpression) { environment.getOutput().println(); - super.printValueOfNextSExpression(); + super.printSExpression(sExpression); } @Override - protected void afterInterpreting() { + protected void applyFinishingTouches() { environment.getOutput().println(); - environment.getOutput().println(); - environment.getOutput().close(); + environment.getOutput().println(environment.decoratePrompt("")); + environment.getOutput().flush(); } } diff --git a/src/interpreter/LispInterpreter.java b/src/interpreter/LispInterpreter.java index d8dfaa2..d06cf8f 100644 --- a/src/interpreter/LispInterpreter.java +++ b/src/interpreter/LispInterpreter.java @@ -18,39 +18,44 @@ public class LispInterpreter { public void interpret() { createParser(); - beforeInterpreting(); for (prompt(); !parser.isEof(); prompt()) - printValueOfNextSExpression(); + evaluateAndPrintNextSExpression(); - afterInterpreting(); + applyFinishingTouches(); } private void createParser() { parser = new LispParser(environment.getInput(), environment.getInputName()); } - protected void beforeInterpreting() {} - protected void prompt() {} - protected void printValueOfNextSExpression() { + private void evaluateAndPrintNextSExpression() { try { - printValueOfNextSExpressionWithException(); + evaluateAndPrintNextSExpressionWithException(); } catch (LispException e) { environment.getErrorManager().handle(e); } } - private void printValueOfNextSExpressionWithException() { - SExpression sExpression = parser.getNextSExpression(); - String result = environment.decorateValueOutput(String.valueOf(eval(sExpression))); + private void evaluateAndPrintNextSExpressionWithException() { + printSExpression(evaluateNextSExpression()); + } + protected SExpression evaluateNextSExpression() { + SExpression sExpression = parser.getNextSExpression(); + + return eval(sExpression); + } + + protected void printSExpression(SExpression sExpression) { + String result = environment.decorateValueOutput(String.valueOf(sExpression)); environment.getOutput().println(result); environment.getOutput().flush(); } - protected void afterInterpreting() { + protected void applyFinishingTouches() { environment.getOutput().println(); environment.getOutput().flush(); } diff --git a/src/interpreter/LispInterpreterBuilder.java b/src/interpreter/LispInterpreterBuilder.java index e37f819..f74effd 100644 --- a/src/interpreter/LispInterpreterBuilder.java +++ b/src/interpreter/LispInterpreterBuilder.java @@ -19,15 +19,15 @@ public interface LispInterpreterBuilder { void useFile(String fileName); - void setOutputDecorator(Function outputDecorator); + void setPromptDecorator(Function decorator); - void setValueOutputDecorator(Function valueOutputDecorator); + void setValueOutputDecorator(Function decorator); - void setWarningOutputDecorator(Function warningOutputDecorator); + void setWarningOutputDecorator(Function decorator); - void setErrorOutputDecorator(Function errorOutputDecorator); + void setErrorOutputDecorator(Function decorator); - void setCriticalOutputDecorator(Function criticalOutputDecorator); + void setCriticalOutputDecorator(Function decorator); LispInterpreter build(); diff --git a/src/interpreter/LispInterpreterBuilderImpl.java b/src/interpreter/LispInterpreterBuilderImpl.java index 645010a..0f9d01d 100644 --- a/src/interpreter/LispInterpreterBuilderImpl.java +++ b/src/interpreter/LispInterpreterBuilderImpl.java @@ -22,7 +22,7 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { private PrintStream errorOutputStream; private Runnable terminationFunction; private Runnable errorTerminationFunction; - private Function outputDecorator; + private Function promptDecorator; private Function valueOutputDecorator; private Function warningOutputDecorator; private Function errorOutputDecorator; @@ -38,7 +38,7 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { this.isInteractive = true; this.isFileBased = false; this.isBuilt = false; - this.outputDecorator = s -> s; + this.promptDecorator = s -> s; this.valueOutputDecorator = s -> s; this.warningOutputDecorator = s -> s; this.errorOutputDecorator = s -> s; @@ -85,8 +85,8 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { } @Override - public void setOutputDecorator(Function decorator) { - this.outputDecorator = decorator; + public void setPromptDecorator(Function decorator) { + this.promptDecorator = decorator; } @Override @@ -135,7 +135,7 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { environment.setErrorManager(errorManager); environment.setTerminationFunction(terminationFunction); environment.setErrorTerminationFunction(errorTerminationFunction); - environment.setOutputDecorator(outputDecorator); + environment.setPromptDecorator(promptDecorator); environment.setValueOutputDecorator(valueOutputDecorator); environment.setWarningOutputDecorator(warningOutputDecorator); environment.setErrorOutputDecorator(errorOutputDecorator); diff --git a/src/main/LispMain.java b/src/main/LispMain.java index d3abc77..4ea277a 100644 --- a/src/main/LispMain.java +++ b/src/main/LispMain.java @@ -14,6 +14,7 @@ import terminal.SafeStream.UncheckedIOException; public class LispMain { + private static final String GREETING = "Transcendental Lisp - Version 1.0.1"; private static final String ANSI_RESET = "\u001B[0m"; private static final String ANSI_RED = "\u001B[31m"; private static final String ANSI_GREEN = "\u001B[32m"; @@ -33,30 +34,55 @@ public class LispMain { private PipedOutputStream inputWriter; private PipedInputStream outputReader; private PipedOutputStream outputWriter; + private PrintStream outputStream; private SafePipedOutputStream safeOutputWriter; private LispTerminal lispTerminal; + private void runInteractive() { + initializeTerminalAndStreams(); + printGreeting(); + lispTerminal.start(); + buildInteractiveInterpreter().interpret(); + outputStream.close(); + } + + private void initializeTerminalAndStreams() { + try { + initalizeTerminalAndStreamsWithException(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void initalizeTerminalAndStreamsWithException() throws IOException { + inputReader = new PipedInputStream(); + inputWriter = new PipedOutputStream(inputReader); + outputReader = new PipedInputStream(); + outputWriter = new PipedOutputStream(outputReader); + outputStream = new PrintStream(outputWriter); + safeOutputWriter = new SafePipedOutputStream(outputWriter); + lispTerminal = new LispTerminal(createIOSafeTerminal(), inputWriter, outputReader); + } + private IOSafeTerminal createIOSafeTerminal() throws IOException { Terminal defaultTerminal = new DefaultTerminalFactory().createTerminal(); return IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter(defaultTerminal); } - private void runInteractive() { - initializeTerminal(); - lispTerminal.start(); - buildInteractiveInterpreter().interpret(); + private void printGreeting() { + outputStream.println(GREETING); + outputStream.println(); } private LispInterpreter buildInteractiveInterpreter() { LispInterpreterBuilder builder = LispInterpreterBuilderImpl.getInstance(); - PrintStream outputStream = new PrintStream(outputWriter); builder.setInput(inputReader, "terminal"); builder.setOutput(outputStream); builder.setErrorOutput(outputStream); builder.setTerminationFunction(this::shutdown); builder.setErrorTerminationFunction(this::shutdown); - builder.setOutputDecorator(makeInteractiveDecorator(ANSI_GREEN)); + builder.setPromptDecorator(makeSegmentDecorator(ANSI_GREEN)); builder.setValueOutputDecorator(s -> s); builder.setWarningOutputDecorator(s -> s); builder.setErrorOutputDecorator(s -> s); @@ -66,11 +92,13 @@ public class LispMain { } private void shutdown() { + outputStream.println(); + outputStream.println(END_OF_SEGMENT); lispTerminal.stop(); safeOutputWriter.close(); } - private static Function makeInteractiveDecorator(String color) { + private static Function makeSegmentDecorator(String color) { return new Function() { @Override @@ -80,23 +108,6 @@ public class LispMain { }; } - private void initializeTerminal() { - try { - initalizeTerminalWithException(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private void initalizeTerminalWithException() throws IOException { - inputReader = new PipedInputStream(); - inputWriter = new PipedOutputStream(inputReader); - outputReader = new PipedInputStream(); - outputWriter = new PipedOutputStream(outputReader); - safeOutputWriter = new SafePipedOutputStream(outputWriter); - lispTerminal = new LispTerminal(createIOSafeTerminal(), inputWriter, outputReader); - } - private void runWithFile(String fileName) { buildFileInterpreter(fileName).interpret(); } @@ -108,7 +119,6 @@ public class LispMain { builder.setErrorOutput(System.err); builder.setTerminationFunction(() -> System.exit(0)); builder.setErrorTerminationFunction(() -> System.exit(1)); - builder.setOutputDecorator(makeColorDecorator(ANSI_GREEN)); builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN)); builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW)); builder.setErrorOutputDecorator(makeColorDecorator(ANSI_RED)); diff --git a/src/terminal/LispTerminal.java b/src/terminal/LispTerminal.java index e3a2b93..fbee282 100644 --- a/src/terminal/LispTerminal.java +++ b/src/terminal/LispTerminal.java @@ -100,17 +100,23 @@ public class LispTerminal { private KeyStroke getKeyStroke() { KeyStroke keyStroke = null; + // issue #299 try { keyStroke = terminal.pollInput(); - } catch (IllegalStateException e) { // issue #299 - moveCursorToEndOfInput(); - terminal.putCharacter('\n'); - stop(); + } catch (IllegalStateException e) { + doControlC(); } return keyStroke; } + private void doControlC() { + moveCursorToEndOfInput(); + terminal.putCharacter('\n'); + updateOrigin(); + stop(); + } + private synchronized void handleKey(KeyStroke keyStroke) { doKey(keyStroke); terminal.flush(); @@ -324,9 +330,7 @@ public class LispTerminal { private void takeNap() { try { Thread.sleep(1); - } catch (InterruptedException e) { - isStopped = true; - } + } catch (InterruptedException ignored) {} } private void writeOutput() { diff --git a/test/environment/RuntimeEnvironmentTest.java b/test/environment/RuntimeEnvironmentTest.java index 6628e3b..95572ea 100644 --- a/test/environment/RuntimeEnvironmentTest.java +++ b/test/environment/RuntimeEnvironmentTest.java @@ -91,10 +91,10 @@ public class RuntimeEnvironmentTest { } @Test - public void assignOutputDecorator() { - environment.setOutputDecorator(s -> "[" + s + "]"); + public void assignPromptDecorator() { + environment.setPromptDecorator(s -> "[" + s + "]"); - assertEquals("[test]", environment.decorateOutput("test")); + assertEquals("[test]", environment.decoratePrompt("test")); } @Test @@ -135,7 +135,7 @@ public class RuntimeEnvironmentTest { environment.setPath("testpath/"); environment.setTerminationFunction(() -> indicatorSet.add(TERMINATED_SUCCESSFULLY)); environment.setErrorTerminationFunction(() -> indicatorSet.add(TERMINATED_EXCEPTIONALLY)); - environment.setOutputDecorator(s -> "[" + s + "]"); + environment.setPromptDecorator(s -> "[" + s + "]"); environment.setValueOutputDecorator(s -> "(" + s + ")"); environment.setWarningOutputDecorator(s -> "|" + s + "|"); environment.setErrorOutputDecorator(s -> "{" + s + "}"); @@ -160,8 +160,8 @@ public class RuntimeEnvironmentTest { } catch (NullPointerException e) {} try { - environment.decorateOutput(""); - fail("decorateOutput"); + environment.decoratePrompt(""); + fail("decoratePrompt"); } catch (NullPointerException e) {} try { diff --git a/test/function/builtin/LOADTest.java b/test/function/builtin/LOADTest.java index e82fd32..585528c 100644 --- a/test/function/builtin/LOADTest.java +++ b/test/function/builtin/LOADTest.java @@ -47,7 +47,6 @@ public class LOADTest { environment.setErrorOutput(new PrintStream(errorOutputStream)); environment.setErrorManager(new ErrorManager()); environment.setPath(""); - environment.setOutputDecorator(s -> s); environment.setWarningOutputDecorator(s -> s); environment.setErrorOutputDecorator(s -> s); } diff --git a/test/terminal/LispTerminalTest.java b/test/terminal/LispTerminalTest.java index 8f3b91b..fddd166 100644 --- a/test/terminal/LispTerminalTest.java +++ b/test/terminal/LispTerminalTest.java @@ -1,5 +1,6 @@ package terminal; +import static com.googlecode.lanterna.input.KeyType.*; import static org.junit.Assert.*; import static terminal.LispTerminal.END_OF_SEGMENT; @@ -146,7 +147,7 @@ public class LispTerminalTest { @Test public void leftArrowDoesNotMovePastOrigin() { - pressKey(KeyType.ArrowLeft); + pressKey(ArrowLeft); assertCursorPosition(0, 0); } @@ -154,13 +155,13 @@ public class LispTerminalTest { public void leftArrowWorksAfterEnteringCharacters() { enterCharacters("abc"); assertCursorPosition(3, 0); - pressKey(KeyType.ArrowLeft); + pressKey(ArrowLeft); assertCursorPosition(2, 0); - pressKey(KeyType.ArrowLeft); + pressKey(ArrowLeft); assertCursorPosition(1, 0); - pressKey(KeyType.ArrowLeft); + pressKey(ArrowLeft); assertCursorPosition(0, 0); - pressKey(KeyType.ArrowLeft); + pressKey(ArrowLeft); assertCursorPosition(0, 0); } @@ -169,13 +170,13 @@ public class LispTerminalTest { setColumns(5); enterCharacters("123451"); assertCursorPosition(1, 1); - pressKeyTimes(KeyType.ArrowLeft, 2); + pressKeyTimes(ArrowLeft, 2); assertCursorPosition(4, 0); } @Test public void rightArrowDoesNotMovePastEndOfInput() { - pressKey(KeyType.ArrowRight); + pressKey(ArrowRight); assertCursorPosition(0, 0); } @@ -183,11 +184,11 @@ public class LispTerminalTest { public void rightArrowWorksAfterMovingLeft() { enterCharacters("12"); assertCursorPosition(2, 0); - pressKey(KeyType.ArrowLeft); + pressKey(ArrowLeft); assertCursorPosition(1, 0); - pressKey(KeyType.ArrowRight); + pressKey(ArrowRight); assertCursorPosition(2, 0); - pressKey(KeyType.ArrowRight); + pressKey(ArrowRight); assertCursorPosition(2, 0); } @@ -196,9 +197,9 @@ public class LispTerminalTest { setColumns(5); enterCharacters("123451"); assertCursorPosition(1, 1); - pressKeyTimes(KeyType.ArrowLeft, 3); + pressKeyTimes(ArrowLeft, 3); assertCursorPosition(3, 0); - pressKeyTimes(KeyType.ArrowRight, 3); + pressKeyTimes(ArrowRight, 3); assertCursorPosition(1, 1); } @@ -212,7 +213,7 @@ public class LispTerminalTest { @Test public void characterIsInserted() { enterCharacters("abcd"); - pressKeyTimes(KeyType.ArrowLeft, 2); + pressKeyTimes(ArrowLeft, 2); enterCharacter('x'); assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c', 'd' } }); } @@ -221,21 +222,21 @@ public class LispTerminalTest { public void characterIsInserted_PushesInputToNextRow() { setColumns(4); enterCharacters("abcd"); - pressKeyTimes(KeyType.ArrowLeft, 2); + pressKeyTimes(ArrowLeft, 2); enterCharacter('x'); assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c' }, { 'd', ' ', ' ', ' ' } }); } @Test public void backspaceDoesNothingAtOrigin() { - pressKey(KeyType.Backspace); + pressKey(Backspace); assertCursorPosition(0, 0); } @Test public void backspaceWorksAfterInput() { enterCharacters("12345"); - pressKeyTimes(KeyType.Backspace, 2); + pressKeyTimes(Backspace, 2); assertCursorPosition(3, 0); assertCharacterPositions(new char[][] { { '1', '2', '3', ' ', ' ', ' ' } }); } @@ -244,7 +245,7 @@ public class LispTerminalTest { public void backspaceWorksAcrossRow() { setColumns(4); enterCharacters("1234567"); - pressKeyTimes(KeyType.Backspace, 5); + pressKeyTimes(Backspace, 5); assertCursorPosition(2, 0); assertCharacterPositions(new char[][] { { '1', '2', ' ', ' ' }, { ' ', ' ', ' ', ' ' } }); } @@ -252,22 +253,22 @@ public class LispTerminalTest { @Test public void backspaceWorksInMiddleOfInput() { enterCharacters("12345"); - pressKeyTimes(KeyType.ArrowLeft, 2); - pressKey(KeyType.Backspace); + pressKeyTimes(ArrowLeft, 2); + pressKey(Backspace); assertCursorPosition(2, 0); assertCharacterPositions(new char[][] { { '1', '2', '4', '5' } }); } @Test public void deleteDoesNothingAtOrigin() { - pressKey(KeyType.Delete); + pressKey(Delete); assertCursorPosition(0, 0); } @Test public void deleteDoesNothingAtEndOfInput() { enterCharacters("del"); - pressKey(KeyType.Delete); + pressKey(Delete); assertCursorPosition(3, 0); assertCharacterPositions(new char[][] { { 'd', 'e', 'l' } }); } @@ -275,8 +276,8 @@ public class LispTerminalTest { @Test public void deleteWorksAtStartOfInput() { enterCharacters("del"); - pressKeyTimes(KeyType.ArrowLeft, 3); - pressKeyTimes(KeyType.Delete, 3); + pressKeyTimes(ArrowLeft, 3); + pressKeyTimes(Delete, 3); assertCursorPosition(0, 0); assertCharacterPositions(new char[][] { { ' ', ' ', ' ' } }); } @@ -285,56 +286,56 @@ public class LispTerminalTest { public void deleteWorksAcrossRow() { setColumns(4); enterCharacters("delete"); - pressKeyTimes(KeyType.ArrowLeft, 5); - pressKey(KeyType.Delete); + pressKeyTimes(ArrowLeft, 5); + pressKey(Delete); assertCursorPosition(1, 0); assertCharacterPositions(new char[][] { { 'd', 'l', 'e', 't' }, { 'e', ' ' } }); } @Test public void enterMovesToNextLine() { - pressKey(KeyType.Enter); + pressKey(Enter); assertCursorPosition(0, 1); } @Test public void enterWritesLineToPipedStream() { enterCharacters("enter"); - pressKey(KeyType.Enter); + pressKey(Enter); assertInputWritten("enter\n"); } @Test public void enterPressedInMiddleOfInput_WritesEntireLineToPipedStream() { enterCharacters("enter"); - pressKeyTimes(KeyType.ArrowLeft, 2); - pressKey(KeyType.Enter); + pressKeyTimes(ArrowLeft, 2); + pressKey(Enter); assertInputWritten("enter\n"); } @Test public void enterAfterInsertedText_WritesLineToPipedStream() { enterCharacters("enter"); - pressKeyTimes(KeyType.ArrowLeft, 2); + pressKeyTimes(ArrowLeft, 2); enterCharacters("||"); - pressKey(KeyType.Enter); + pressKey(Enter); assertInputWritten("ent||er\n"); } @Test public void enterAfterBackspace_WritesLineToPipedStream() { enterCharacters("enter"); - pressKeyTimes(KeyType.Backspace, 2); - pressKey(KeyType.Enter); + pressKeyTimes(Backspace, 2); + pressKey(Enter); assertInputWritten("ent\n"); } @Test public void enterAfterDelete_WritesLineToPipedStream() { enterCharacters("enter"); - pressKeyTimes(KeyType.ArrowLeft, 2); - pressKeyTimes(KeyType.Delete, 2); - pressKey(KeyType.Enter); + pressKeyTimes(ArrowLeft, 2); + pressKeyTimes(Delete, 2); + pressKey(Enter); assertInputWritten("ent\n"); } @@ -349,7 +350,7 @@ public class LispTerminalTest { @Test public void controlDWorksInMiddleOfInput() { enterCharacters("control-d"); - pressKeyTimes(KeyType.ArrowLeft, 2); + pressKeyTimes(ArrowLeft, 2); enterControlCharacter('d'); assertInputStreamClosed(); assertInputWritten("control-d\n"); @@ -357,7 +358,7 @@ public class LispTerminalTest { @Test public void escapeDoesNothing() { - pressKey(KeyType.Escape); + pressKey(Escape); assertCursorPosition(0, 0); assertInputWritten(""); } @@ -371,7 +372,7 @@ public class LispTerminalTest { @Test public void controlEnterDoesNothing() { - pressControlKey(KeyType.Enter); + pressControlKey(Enter); assertCursorPosition(0, 0); assertInputWritten(""); } @@ -403,9 +404,9 @@ public class LispTerminalTest { public void insertingTextPushesInputPastEndOfBuffer() { setColumns(3); setRows(4); - pressKey(KeyType.Enter); + pressKey(Enter); enterCharacters("00011122"); - pressKeyTimes(KeyType.ArrowLeft, 4); + pressKeyTimes(ArrowLeft, 4); assertCursorPosition(1, 2); enterCharacters("zz"); assertCursorPosition(0, 2); @@ -418,7 +419,7 @@ public class LispTerminalTest { setColumns(3); setRows(3); enterCharacters("00011122"); - pressKeyTimes(KeyType.ArrowLeft, 4); + pressKeyTimes(ArrowLeft, 4); assertCursorPosition(1, 1); enterCharacters("zz"); assertCursorPosition(1, 1); @@ -454,7 +455,7 @@ public class LispTerminalTest { public void printedOutputDoesNotOverwriteInput() { setColumns(3); enterCharacters("01201201"); - pressKeyTimes(KeyType.ArrowLeft, 5); + pressKeyTimes(ArrowLeft, 5); produceOutput("out"); assertCursorPosition(0, 4); assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', 'o' }, @@ -465,8 +466,8 @@ public class LispTerminalTest { public void printedOutputDoesNotOverwriteInput_AfterEnter() { setColumns(3); enterCharacters("01201201"); - pressKeyTimes(KeyType.ArrowLeft, 5); - pressKey(KeyType.Enter); + pressKeyTimes(ArrowLeft, 5); + pressKey(Enter); produceOutput("out"); assertCursorPosition(0, 4); assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', ' ' }, @@ -476,12 +477,35 @@ public class LispTerminalTest { @Test public void resizeIsHandledGracefully() { enterCharacters("resize"); - pressKey(KeyType.Enter); + pressKey(Enter); enterCharacters("test"); - setColumns(10); - assertCursorPosition(4, 0); - assertCharacterPositions(new char[][] { { 't', 'e', 's', 't', ' ', ' ', ' ', ' ', ' ', ' ' }, - { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } }); + setColumns(3); + assertCursorPosition(1, 1); + assertCharacterPositions(new char[][] { { 't', 'e', 's' }, { 't', ' ', ' ' } }); } + @Test + public void backspaceWorksAfterResize() { + enterCharacters("resize"); + pressKey(Enter); + enterCharacters("test"); + setColumns(3); + pressKeyTimes(Backspace, 20); + assertCursorPosition(0, 0); + assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } }); + } + + @Test + public void deleteWorksAfterResize() { + enterCharacters("resize"); + pressKey(Enter); + enterCharacters("test"); + setColumns(3); + pressKeyTimes(ArrowLeft, 20); + pressKeyTimes(Delete, 20); + pressKeyTimes(ArrowRight, 20); + assertCursorPosition(0, 0); + assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } }); + } + }