parent
228b4b1793
commit
79fb8b633b
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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() {
|
||||||
|
|
|
@ -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<>();
|
||||||
|
|
||||||
|
|
|
@ -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' } });
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue