Fix output interfering with input

Refactored some code
This commit is contained in:
Mike Cifelli 2017-03-22 15:26:00 -04:00
parent 228b4b1793
commit 79fb8b633b
5 changed files with 60 additions and 21 deletions

View File

@ -8,10 +8,8 @@ import stream.SafeInputStream;
class ControlSequenceHandler { class ControlSequenceHandler {
private static final char ESCAPE = '\u001B';
public static final boolean isEscape(char c) { public static final boolean isEscape(char c) {
return c == ESCAPE; return c == UNICODE_ESCAPE;
} }
private SafeInputStream input; private SafeInputStream input;

View File

@ -8,21 +8,21 @@ import terminal.ControlSequence.NullControlSequence;
public class ControlSequenceLookup { public class ControlSequenceLookup {
private static Map<Character, Map<String, ControlSequence>> controlSequenceMap = new HashMap<>(); private static Map<Character, Map<String, ControlSequence>> commands = new HashMap<>();
static { static {
Map<String, ControlSequence> selectGraphicRenditionMap = new HashMap<>(); Map<String, ControlSequence> sgrCodes = new HashMap<>();
for (SelectGraphicRendition sgr : SelectGraphicRendition.values()) for (SelectGraphicRendition sgr : SelectGraphicRendition.values())
selectGraphicRenditionMap.put(sgr.getCode(), sgr); sgrCodes.put(sgr.getCode(), sgr);
controlSequenceMap.put(SGR_COMMAND, selectGraphicRenditionMap); commands.put(SGR_COMMAND, sgrCodes);
} }
public static ControlSequence lookupControlSequence(char command, String code) { public static ControlSequence lookupControlSequence(char command, String code) {
Map<String, ControlSequence> commandMap = controlSequenceMap.getOrDefault(command, new HashMap<>()); Map<String, ControlSequence> codes = commands.getOrDefault(command, new HashMap<>());
return commandMap.getOrDefault(code, new NullControlSequence()); return codes.getOrDefault(code, new NullControlSequence());
} }
} }

View File

@ -3,6 +3,7 @@ package terminal;
import static com.googlecode.lanterna.input.KeyType.*; import static com.googlecode.lanterna.input.KeyType.*;
import static terminal.ControlSequenceHandler.isEscape; import static terminal.ControlSequenceHandler.isEscape;
import static util.Characters.EOF; import static util.Characters.EOF;
import static util.Characters.UNICODE_NULL;
import java.io.*; import java.io.*;
import java.util.concurrent.*; import java.util.concurrent.*;
@ -15,7 +16,7 @@ import stream.*;
public class LispTerminal { public class LispTerminal {
public static final char END_OF_SEGMENT = 'x'; public static final char END_OF_SEGMENT = UNICODE_NULL;
private IOSafeTerminal terminal; private IOSafeTerminal terminal;
private SafeOutputStream inputWriter; private SafeOutputStream inputWriter;
@ -54,6 +55,10 @@ public class LispTerminal {
terminalSize = terminal.getTerminalSize(); terminalSize = terminal.getTerminalSize();
terminal.clearScreen(); terminal.clearScreen();
terminal.setCursorPosition(0, 0); terminal.setCursorPosition(0, 0);
redisplayInput();
}
private synchronized void redisplayInput() {
setOriginToCurrentPosition(); setOriginToCurrentPosition();
putStringToTerminal(inputLine); putStringToTerminal(inputLine);
moveCursorToEndOfInput(); moveCursorToEndOfInput();
@ -358,14 +363,14 @@ public class LispTerminal {
printSegmentCharacters(); printSegmentCharacters();
terminal.setCursorVisible(true); terminal.setCursorVisible(true);
outputSegment = ""; outputSegment = "";
setOriginToCurrentPosition(); redisplayInput();
terminal.flush();
} }
private synchronized void printSegmentCharacters() { private synchronized void printSegmentCharacters() {
moveCursorToEndOfInput(); moveCursorToEndOfInput();
putOutputToTerminal(); putOutputToTerminal();
moveCursorToNextRowIfNecessary(); moveCursorToNextRowIfNecessary();
terminal.flush();
} }
private synchronized void putOutputToTerminal() { private synchronized void putOutputToTerminal() {

View File

@ -24,6 +24,8 @@ public final class Characters {
public static final char RIGHT_SQUARE_BRACKET = ']'; public static final char RIGHT_SQUARE_BRACKET = ']';
public static final char SEMICOLON = ';'; public static final char SEMICOLON = ';';
public static final char SINGLE_QUOTE = '\''; public static final char SINGLE_QUOTE = '\'';
public static final char UNICODE_ESCAPE = '\u001B';
public static final char UNICODE_NULL = '\u0000';
public static final Set<Character> illegalIdentifierCharacters = new HashSet<>(); public static final Set<Character> illegalIdentifierCharacters = new HashSet<>();

View File

@ -452,18 +452,52 @@ public class LispTerminalTest {
} }
@Test @Test
public void printedOutputDoesNotOverwriteInput() { public void outputDoesNotOverwriteInput_AndRedisplaysInput() {
setColumns(3); setColumns(3);
enterCharacters("01201201"); enterCharacters("0123");
pressKeyTimes(ArrowLeft, 5); pressKeyTimes(ArrowLeft, 3);
produceOutput("out"); produceOutput("out");
assertCursorPosition(0, 4); assertCursorPosition(2, 3);
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', 'o' }, assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', 'o', 'u' }, { 't', '0', '1' },
{ 'u', 't', ' ' } }); { '2', '3', ' ' }, { ' ', ' ', ' ' } });
} }
@Test @Test
public void printedOutputDoesNotOverwriteInput_AfterEnter() { public void outputEndsOnSecondToLastColumn_MovesToNewRow() {
setColumns(3);
enterCharacters("01234");
pressKeyTimes(ArrowLeft, 3);
produceOutput("out");
assertCursorPosition(2, 4);
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', 'o' }, { 'u', 't', ' ' },
{ '0', '1', '2' }, { '3', '4', ' ' } });
}
@Test
public void outputEndsOnLastColumn_MovesToNewRow() {
setColumns(3);
enterCharacters("012345");
pressKeyTimes(ArrowLeft, 3);
produceOutput("out");
assertCursorPosition(0, 5);
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', '5' }, { 'o', 'u', 't' },
{ '0', '1', '2' }, { '3', '4', '5' }, { ' ', ' ', ' ' } });
}
@Test
public void outputRedisplaysInputAtEndOfBuffer() {
setColumns(3);
setRows(4);
enterCharacters("01234");
pressKeyTimes(ArrowLeft, 3);
produceOutput("out");
assertCursorPosition(2, 3);
assertCharacterPositions(new char[][] { { '3', '4', 'o' }, { 'u', 't', ' ' }, { '0', '1', '2' },
{ '3', '4', ' ' } });
}
@Test
public void outputDoesNotOverwriteInput_AfterEnter() {
setColumns(3); setColumns(3);
enterCharacters("01201201"); enterCharacters("01201201");
pressKeyTimes(ArrowLeft, 5); pressKeyTimes(ArrowLeft, 5);
@ -471,7 +505,7 @@ public class LispTerminalTest {
produceOutput("out"); produceOutput("out");
assertCursorPosition(0, 4); assertCursorPosition(0, 4);
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', ' ' }, assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', ' ' },
{ 'o', 'u', 't' } }); { 'o', 'u', 't' }, { ' ', ' ', ' ' } });
} }
@Test @Test
@ -509,7 +543,7 @@ public class LispTerminalTest {
} }
@Test @Test
public void controlSequenceIsNotPrinted() { public void controlSequencesAreNotPrinted() {
produceOutput("\u001B[32mcontrol\u001B[0mseq"); produceOutput("\u001B[32mcontrol\u001B[0mseq");
assertCharacterPositions(new char[][] { { 'c', 'o', 'n', 't', 'r', 'o', 'l', 's', 'e', 'q' } }); assertCharacterPositions(new char[][] { { 'c', 'o', 'n', 't', 'r', 'o', 'l', 's', 'e', 'q' } });
} }