Convert terminal to kotlin
This commit is contained in:
parent
ae48d9c2ca
commit
3ec8e72a17
2
pom.xml
2
pom.xml
|
@ -211,7 +211,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.stefanbirkner</groupId>
|
||||
<artifactId>system-rules</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<version>1.18.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -5,7 +5,7 @@ import com.googlecode.lanterna.terminal.IOSafeTerminalAdapter.createRuntimeExcep
|
|||
import interpreter.LispInterpreter
|
||||
import interpreter.LispInterpreterBuilder
|
||||
import terminal.LispTerminal
|
||||
import terminal.LispTerminal.END_OF_SEGMENT
|
||||
import terminal.LispTerminal.Companion.END_OF_SEGMENT
|
||||
import terminal.TerminalConfiguration
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
|
|
|
@ -1,460 +0,0 @@
|
|||
package terminal;
|
||||
|
||||
import com.googlecode.lanterna.TerminalPosition;
|
||||
import com.googlecode.lanterna.TerminalSize;
|
||||
import com.googlecode.lanterna.input.KeyStroke;
|
||||
import com.googlecode.lanterna.input.KeyType;
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal;
|
||||
import stream.SafeInputStream;
|
||||
import stream.SafeOutputStream;
|
||||
import util.Characters;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static com.googlecode.lanterna.input.KeyType.ArrowDown;
|
||||
import static com.googlecode.lanterna.input.KeyType.ArrowLeft;
|
||||
import static com.googlecode.lanterna.input.KeyType.ArrowRight;
|
||||
import static com.googlecode.lanterna.input.KeyType.ArrowUp;
|
||||
import static com.googlecode.lanterna.input.KeyType.Backspace;
|
||||
import static com.googlecode.lanterna.input.KeyType.Character;
|
||||
import static com.googlecode.lanterna.input.KeyType.Delete;
|
||||
import static com.googlecode.lanterna.input.KeyType.Enter;
|
||||
import static terminal.ControlSequenceHandler.isEscape;
|
||||
|
||||
public class LispTerminal {
|
||||
|
||||
public static final char END_OF_SEGMENT = Characters.UNICODE_NULL;
|
||||
|
||||
private IOSafeTerminal terminal;
|
||||
private SafeOutputStream inputWriter;
|
||||
private SafeInputStream outputReader;
|
||||
private ControlSequenceHandler controlSequenceHandler;
|
||||
private TerminalHistory history;
|
||||
private ExecutorService executorService;
|
||||
private TerminalSize terminalSize;
|
||||
private String inputLine;
|
||||
private String outputSegment;
|
||||
private boolean isStopped;
|
||||
private int originColumn;
|
||||
private int originRow;
|
||||
|
||||
public LispTerminal(TerminalConfiguration configuration) {
|
||||
this.terminal = configuration.getTerminal();
|
||||
this.inputWriter = new SafeOutputStream(configuration.getInputWriter());
|
||||
this.outputReader = new SafeInputStream(configuration.getOutputReader());
|
||||
this.controlSequenceHandler = new ControlSequenceHandler();
|
||||
this.history = new TerminalHistory();
|
||||
this.executorService = Executors.newFixedThreadPool(2);
|
||||
this.terminalSize = terminal.getTerminalSize();
|
||||
this.inputLine = "";
|
||||
this.outputSegment = "";
|
||||
this.isStopped = false;
|
||||
|
||||
setOriginToCurrentPosition();
|
||||
terminal.addResizeListener((t, newSize) -> resize());
|
||||
}
|
||||
|
||||
private synchronized void setOriginToCurrentPosition() {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
originColumn = cursorPosition.getColumn();
|
||||
originRow = cursorPosition.getRow();
|
||||
}
|
||||
|
||||
private synchronized void resize() {
|
||||
terminalSize = terminal.getTerminalSize();
|
||||
terminal.clearScreen();
|
||||
terminal.setCursorPosition(0, 0);
|
||||
redisplayInput();
|
||||
}
|
||||
|
||||
private synchronized void redisplayInput() {
|
||||
setOriginToCurrentPosition();
|
||||
putStringToTerminal(inputLine);
|
||||
moveCursorToEndOfInput();
|
||||
}
|
||||
|
||||
private synchronized void putStringToTerminal(String characters) {
|
||||
for (char c : characters.toCharArray())
|
||||
terminal.putCharacter(c);
|
||||
}
|
||||
|
||||
private synchronized void moveCursorToEndOfInput() {
|
||||
terminal.setCursorPosition(getLeadingEdge());
|
||||
}
|
||||
|
||||
private synchronized TerminalPosition getLeadingEdge() {
|
||||
int inputLength = inputLine.length();
|
||||
int totalColumns = terminalSize.getColumns();
|
||||
int rowDifference = inputLength / totalColumns;
|
||||
int columnDifference = inputLength % totalColumns;
|
||||
|
||||
return new TerminalPosition(originColumn + columnDifference, originRow + rowDifference);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
executorService.execute(this::readInput);
|
||||
executorService.execute(this::writeOutput);
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
private void readInput() {
|
||||
while (!isStopped)
|
||||
processNextKey();
|
||||
}
|
||||
|
||||
private void processNextKey() {
|
||||
KeyStroke keyStroke = terminal.pollInput();
|
||||
|
||||
if (keyStroke != null)
|
||||
handleKey(keyStroke);
|
||||
else
|
||||
takeNap();
|
||||
}
|
||||
|
||||
private synchronized void handleKey(KeyStroke keyStroke) {
|
||||
doKey(keyStroke);
|
||||
terminal.flush();
|
||||
}
|
||||
|
||||
private synchronized void doKey(KeyStroke keyStroke) {
|
||||
if (keyStroke.isCtrlDown())
|
||||
doControlKey(keyStroke);
|
||||
else
|
||||
doNormalKey(keyStroke);
|
||||
}
|
||||
|
||||
private synchronized void doControlKey(KeyStroke keyStroke) {
|
||||
KeyType keyType = keyStroke.getKeyType();
|
||||
|
||||
if (keyType == Character)
|
||||
doControlCharacter(keyStroke);
|
||||
}
|
||||
|
||||
private synchronized void doControlCharacter(KeyStroke keyStroke) {
|
||||
if (keyStroke.getCharacter() == 'd')
|
||||
doControlD();
|
||||
}
|
||||
|
||||
private synchronized void doControlD() {
|
||||
doEnter();
|
||||
stop();
|
||||
}
|
||||
|
||||
private synchronized void doNormalKey(KeyStroke keyStroke) {
|
||||
KeyType keyType = keyStroke.getKeyType();
|
||||
|
||||
if (keyType == Enter)
|
||||
doEnter();
|
||||
else if (keyType == ArrowUp)
|
||||
doUpArrow();
|
||||
else if (keyType == ArrowDown)
|
||||
doDownArrow();
|
||||
else if (keyType == ArrowLeft)
|
||||
doLeftArrow();
|
||||
else if (keyType == ArrowRight)
|
||||
doRightArrow();
|
||||
else if (keyType == Backspace)
|
||||
doBackspace();
|
||||
else if (keyType == Delete)
|
||||
doDelete();
|
||||
else if (keyType == Character)
|
||||
doCharacter(keyStroke.getCharacter());
|
||||
}
|
||||
|
||||
private synchronized void doEnter() {
|
||||
moveCursorToEndOfInput();
|
||||
history.addLine(inputLine);
|
||||
terminal.putCharacter('\n');
|
||||
writeInputLine();
|
||||
setOriginToCurrentPosition();
|
||||
}
|
||||
|
||||
private synchronized void writeInputLine() {
|
||||
inputLine += "\n";
|
||||
inputWriter.write(inputLine.getBytes());
|
||||
inputWriter.flush();
|
||||
inputLine = "";
|
||||
}
|
||||
|
||||
private synchronized void doUpArrow() {
|
||||
if (!history.isBeginning())
|
||||
replaceInputWithPreviousLine();
|
||||
}
|
||||
|
||||
private synchronized void replaceInputWithPreviousLine() {
|
||||
history.updateCurrentLine(inputLine);
|
||||
clearInput();
|
||||
displayPreviousInputLine();
|
||||
}
|
||||
|
||||
private synchronized void clearInput() {
|
||||
terminal.setCursorPosition(originColumn, originRow);
|
||||
putStringToTerminal(inputLine.replaceAll(".{1}", " "));
|
||||
terminal.setCursorPosition(originColumn, originRow);
|
||||
}
|
||||
|
||||
private synchronized void displayPreviousInputLine() {
|
||||
inputLine = history.getPreviousLine();
|
||||
char[] inputCharacters = inputLine.toCharArray();
|
||||
|
||||
for (int i = 0; i < inputCharacters.length; i++)
|
||||
displayCharacter(inputCharacters[i], i);
|
||||
}
|
||||
|
||||
private synchronized void displayCharacter(char character, int offsetFromOrigin) {
|
||||
if (isLastColumn(offsetFromOrigin)) {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
terminal.putCharacter(character);
|
||||
moveCursorToNextRow(cursorPosition);
|
||||
} else
|
||||
terminal.putCharacter(character);
|
||||
}
|
||||
|
||||
private synchronized boolean isLastColumn(int offsetFromOrigin) {
|
||||
int totalColumns = terminalSize.getColumns();
|
||||
|
||||
return (originColumn + offsetFromOrigin) % totalColumns == totalColumns - 1;
|
||||
}
|
||||
|
||||
private synchronized void doDownArrow() {
|
||||
if (!history.isEnd())
|
||||
replaceInputWithNextLine();
|
||||
}
|
||||
|
||||
private synchronized void replaceInputWithNextLine() {
|
||||
history.updateCurrentLine(inputLine);
|
||||
clearInput();
|
||||
displayNextInputLine();
|
||||
}
|
||||
|
||||
private synchronized void displayNextInputLine() {
|
||||
inputLine = history.getNextLine();
|
||||
putStringToTerminal(inputLine);
|
||||
}
|
||||
|
||||
private synchronized void doLeftArrow() {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
|
||||
if (isPossibleToMoveLeft(cursorPosition))
|
||||
moveCursorLeft(cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized boolean isPossibleToMoveLeft(TerminalPosition cursorPosition) {
|
||||
return getDistanceFromOrigin(cursorPosition) > 0;
|
||||
}
|
||||
|
||||
private synchronized int getDistanceFromOrigin(TerminalPosition cursorPosition) {
|
||||
int columnDifference = cursorPosition.getColumn() - originColumn;
|
||||
int rowDifference = cursorPosition.getRow() - originRow;
|
||||
int totalColumns = terminalSize.getColumns();
|
||||
|
||||
return columnDifference + (totalColumns * rowDifference);
|
||||
}
|
||||
|
||||
private synchronized void moveCursorLeft(TerminalPosition cursorPosition) {
|
||||
TerminalPosition newPosition = cursorPosition.withRelativeColumn(-1);
|
||||
|
||||
if (isAtStartOfRow(cursorPosition))
|
||||
newPosition = cursorPosition.withColumn(terminalSize.getColumns()).withRelativeRow(-1);
|
||||
|
||||
terminal.setCursorPosition(newPosition);
|
||||
}
|
||||
|
||||
private synchronized boolean isAtStartOfRow(TerminalPosition cursorPosition) {
|
||||
return cursorPosition.getColumn() == 0;
|
||||
}
|
||||
|
||||
private synchronized void doRightArrow() {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
|
||||
if (isPossibleToMoveRight(cursorPosition))
|
||||
moveCursorRight(cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized boolean isPossibleToMoveRight(TerminalPosition cursorPosition) {
|
||||
return getDistanceFromOrigin(cursorPosition) < inputLine.length();
|
||||
}
|
||||
|
||||
private synchronized void moveCursorRight(TerminalPosition cursorPosition) {
|
||||
if (isEndOfRow(cursorPosition))
|
||||
moveCursorToNextRow(cursorPosition);
|
||||
else
|
||||
terminal.setCursorPosition(cursorPosition.withRelativeColumn(1));
|
||||
}
|
||||
|
||||
private synchronized boolean isEndOfRow(TerminalPosition cursorPosition) {
|
||||
return cursorPosition.getColumn() >= terminalSize.getColumns() - 1;
|
||||
}
|
||||
|
||||
private synchronized void moveCursorToNextRow(TerminalPosition cursorPosition) {
|
||||
if (isEndOfBuffer(cursorPosition))
|
||||
createNewRowForCursor(cursorPosition);
|
||||
else
|
||||
terminal.setCursorPosition(cursorPosition.withColumn(0).withRelativeRow(1));
|
||||
}
|
||||
|
||||
private synchronized boolean isEndOfBuffer(TerminalPosition cursorPosition) {
|
||||
return cursorPosition.getRow() == terminalSize.getRows() - 1;
|
||||
}
|
||||
|
||||
private synchronized void createNewRowForCursor(TerminalPosition cursorPosition) {
|
||||
terminal.setCursorPosition(cursorPosition);
|
||||
terminal.putCharacter('\n');
|
||||
terminal.setCursorPosition(cursorPosition.withColumn(0));
|
||||
--originRow;
|
||||
}
|
||||
|
||||
private synchronized void doBackspace() {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
|
||||
if (isPossibleToMoveLeft(cursorPosition))
|
||||
deletePreviousCharacter(cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized void deletePreviousCharacter(TerminalPosition cursorPosition) {
|
||||
int distanceFromOrigin = getDistanceFromOrigin(cursorPosition);
|
||||
String remaining = inputLine.substring(distanceFromOrigin, inputLine.length());
|
||||
inputLine = inputLine.substring(0, distanceFromOrigin - 1) + remaining;
|
||||
moveCursorLeft(cursorPosition);
|
||||
putStringToTerminal(remaining + " ");
|
||||
moveCursorLeft(cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized void doDelete() {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
|
||||
if (isPossibleToMoveRight(cursorPosition))
|
||||
deleteCharacterAtPosition(cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized void deleteCharacterAtPosition(TerminalPosition cursorPosition) {
|
||||
int distanceFromOrigin = getDistanceFromOrigin(cursorPosition);
|
||||
String remaining = inputLine.substring(distanceFromOrigin + 1, inputLine.length());
|
||||
inputLine = inputLine.substring(0, distanceFromOrigin) + remaining;
|
||||
putStringToTerminal(remaining + " ");
|
||||
terminal.setCursorPosition(cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized void doCharacter(Character character) {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
|
||||
if (!isBufferFilled())
|
||||
if (isPossibleToMoveRight(cursorPosition))
|
||||
insertCharacter(character, cursorPosition);
|
||||
else
|
||||
appendCharacter(character, cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized boolean isBufferFilled() {
|
||||
int row = getLeadingEdge().getRow();
|
||||
int column = getLeadingEdge().getColumn();
|
||||
|
||||
return (row == terminalSize.getRows() - 1) && (column >= terminalSize.getColumns() - 1) && (originRow <= 0);
|
||||
}
|
||||
|
||||
private synchronized void insertCharacter(Character character, TerminalPosition cursorPosition) {
|
||||
cursorPosition = shiftPositionIfNewRowAdded(cursorPosition);
|
||||
terminal.setCursorPosition(cursorPosition);
|
||||
int distanceFromOrigin = getDistanceFromOrigin(cursorPosition);
|
||||
String remaining = character + inputLine.substring(distanceFromOrigin, inputLine.length());
|
||||
inputLine = inputLine.substring(0, distanceFromOrigin) + remaining;
|
||||
putStringToTerminal(remaining);
|
||||
moveCursorRight(cursorPosition);
|
||||
}
|
||||
|
||||
private synchronized TerminalPosition shiftPositionIfNewRowAdded(TerminalPosition cursorPosition) {
|
||||
int oldOriginRow = originRow;
|
||||
moveCursorRight(getLeadingEdge());
|
||||
|
||||
return isNewRowAdded(oldOriginRow) ? adjustCursorPosition(cursorPosition) : cursorPosition;
|
||||
}
|
||||
|
||||
private synchronized boolean isNewRowAdded(int oldOriginRow) {
|
||||
return originRow != oldOriginRow;
|
||||
}
|
||||
|
||||
private synchronized TerminalPosition adjustCursorPosition(TerminalPosition cursorPosition) {
|
||||
terminal.setCursorPosition(new TerminalPosition(originColumn, originRow));
|
||||
putStringToTerminal(inputLine);
|
||||
|
||||
return cursorPosition.withRelativeRow(-1);
|
||||
}
|
||||
|
||||
private synchronized void appendCharacter(Character character, TerminalPosition cursorPosition) {
|
||||
terminal.putCharacter(character);
|
||||
inputLine += character;
|
||||
moveCursorRight(cursorPosition);
|
||||
}
|
||||
|
||||
private void takeNap() {
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOutput() {
|
||||
for (int c = outputReader.read(); c != Characters.EOF; c = outputReader.read())
|
||||
processOutput((char) c);
|
||||
|
||||
terminal.flush();
|
||||
terminal.close();
|
||||
}
|
||||
|
||||
private synchronized void processOutput(char c) {
|
||||
if (isEndOfSegment(c))
|
||||
writeSegment();
|
||||
else
|
||||
outputSegment += c;
|
||||
}
|
||||
|
||||
private synchronized boolean isEndOfSegment(char c) {
|
||||
return c == END_OF_SEGMENT;
|
||||
}
|
||||
|
||||
private synchronized void writeSegment() {
|
||||
printSegmentCharacters();
|
||||
outputSegment = "";
|
||||
redisplayInput();
|
||||
terminal.flush();
|
||||
}
|
||||
|
||||
private synchronized void printSegmentCharacters() {
|
||||
moveCursorToEndOfInput();
|
||||
putOutputToTerminal();
|
||||
moveCursorToNextRowIfNecessary();
|
||||
}
|
||||
|
||||
private synchronized void putOutputToTerminal() {
|
||||
SafeInputStream input = convertOutputToStream();
|
||||
|
||||
for (int c = input.read(); c != Characters.EOF; c = input.read())
|
||||
if (isEscape((char) c))
|
||||
applyControlSequence(input);
|
||||
else
|
||||
terminal.putCharacter((char) c);
|
||||
}
|
||||
|
||||
private synchronized SafeInputStream convertOutputToStream() {
|
||||
return new SafeInputStream(new ByteArrayInputStream(outputSegment.getBytes()));
|
||||
}
|
||||
|
||||
private synchronized void applyControlSequence(SafeInputStream input) {
|
||||
ControlSequence controlSequence = controlSequenceHandler.parse(input);
|
||||
controlSequence.applyTo(terminal);
|
||||
}
|
||||
|
||||
private synchronized void moveCursorToNextRowIfNecessary() {
|
||||
TerminalPosition cursorPosition = terminal.getCursorPosition();
|
||||
|
||||
if (isEndOfRow(cursorPosition))
|
||||
moveCursorToNextRow(cursorPosition);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
isStopped = true;
|
||||
inputWriter.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,494 @@
|
|||
package terminal
|
||||
|
||||
import com.googlecode.lanterna.TerminalPosition
|
||||
import com.googlecode.lanterna.input.KeyStroke
|
||||
import com.googlecode.lanterna.input.KeyType.ArrowDown
|
||||
import com.googlecode.lanterna.input.KeyType.ArrowLeft
|
||||
import com.googlecode.lanterna.input.KeyType.ArrowRight
|
||||
import com.googlecode.lanterna.input.KeyType.ArrowUp
|
||||
import com.googlecode.lanterna.input.KeyType.Backspace
|
||||
import com.googlecode.lanterna.input.KeyType.Character
|
||||
import com.googlecode.lanterna.input.KeyType.Delete
|
||||
import com.googlecode.lanterna.input.KeyType.Enter
|
||||
import stream.SafeInputStream
|
||||
import stream.SafeOutputStream
|
||||
import terminal.ControlSequenceHandler.Companion.isEscape
|
||||
import util.Characters
|
||||
import util.Characters.EOF
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class LispTerminal(configuration: TerminalConfiguration) {
|
||||
|
||||
private val terminal = configuration.terminal!!
|
||||
private val inputWriter = SafeOutputStream(configuration.inputWriter)
|
||||
private val outputReader = SafeInputStream(configuration.outputReader)
|
||||
private val controlSequenceHandler = ControlSequenceHandler()
|
||||
private val history = TerminalHistory()
|
||||
private val executorService = Executors.newFixedThreadPool(2)
|
||||
private var terminalSize = terminal.terminalSize
|
||||
private var inputLine = ""
|
||||
private var outputSegment = ""
|
||||
private var isStopped = false
|
||||
private var originColumn = 0
|
||||
private var originRow = 0
|
||||
|
||||
private val leadingEdge: TerminalPosition
|
||||
@Synchronized get() {
|
||||
val inputLength = inputLine.length
|
||||
val totalColumns = terminalSize.columns
|
||||
val rowDifference = inputLength / totalColumns
|
||||
val columnDifference = inputLength % totalColumns
|
||||
|
||||
return TerminalPosition(originColumn + columnDifference, originRow + rowDifference)
|
||||
}
|
||||
|
||||
private val isBufferFilled: Boolean
|
||||
@Synchronized get() {
|
||||
val row = leadingEdge.row
|
||||
val column = leadingEdge.column
|
||||
|
||||
return row == terminalSize.rows - 1
|
||||
&& column >= terminalSize.columns - 1
|
||||
&& originRow <= 0
|
||||
}
|
||||
|
||||
init {
|
||||
setOriginToCurrentPosition()
|
||||
terminal.addResizeListener { _, _ -> resize() }
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun setOriginToCurrentPosition() {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
originColumn = cursorPosition.column
|
||||
originRow = cursorPosition.row
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun resize() {
|
||||
terminalSize = terminal.terminalSize
|
||||
terminal.clearScreen()
|
||||
terminal.setCursorPosition(0, 0)
|
||||
redisplayInput()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun redisplayInput() {
|
||||
setOriginToCurrentPosition()
|
||||
putStringToTerminal(inputLine)
|
||||
moveCursorToEndOfInput()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun putStringToTerminal(characters: String) {
|
||||
for (c in characters.toCharArray())
|
||||
terminal.putCharacter(c)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun moveCursorToEndOfInput() {
|
||||
terminal.cursorPosition = leadingEdge
|
||||
}
|
||||
|
||||
fun start() {
|
||||
executorService.execute { this.readInput() }
|
||||
executorService.execute { this.writeOutput() }
|
||||
executorService.shutdown()
|
||||
}
|
||||
|
||||
private fun readInput() {
|
||||
while (!isStopped)
|
||||
processNextKey()
|
||||
}
|
||||
|
||||
private fun processNextKey() {
|
||||
val keyStroke = terminal.pollInput()
|
||||
|
||||
if (keyStroke != null)
|
||||
handleKey(keyStroke)
|
||||
else
|
||||
takeNap()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun handleKey(keyStroke: KeyStroke) {
|
||||
doKey(keyStroke)
|
||||
terminal.flush()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doKey(keyStroke: KeyStroke) {
|
||||
if (keyStroke.isCtrlDown)
|
||||
doControlKey(keyStroke)
|
||||
else
|
||||
doNormalKey(keyStroke)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doControlKey(keyStroke: KeyStroke) {
|
||||
if (keyStroke.keyType == Character)
|
||||
doControlCharacter(keyStroke)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doControlCharacter(keyStroke: KeyStroke) {
|
||||
if (keyStroke.character == 'd')
|
||||
doControlD()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doControlD() {
|
||||
doEnter()
|
||||
stop()
|
||||
}
|
||||
|
||||
@Suppress("NON_EXHAUSTIVE_WHEN")
|
||||
@Synchronized
|
||||
private fun doNormalKey(keyStroke: KeyStroke) {
|
||||
when (keyStroke.keyType) {
|
||||
Enter -> doEnter()
|
||||
ArrowUp -> doUpArrow()
|
||||
ArrowDown -> doDownArrow()
|
||||
ArrowLeft -> doLeftArrow()
|
||||
ArrowRight -> doRightArrow()
|
||||
Backspace -> doBackspace()
|
||||
Delete -> doDelete()
|
||||
Character -> doCharacter(keyStroke.character!!)
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doEnter() {
|
||||
moveCursorToEndOfInput()
|
||||
history.addLine(inputLine)
|
||||
terminal.putCharacter('\n')
|
||||
writeInputLine()
|
||||
setOriginToCurrentPosition()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun writeInputLine() {
|
||||
inputLine += "\n"
|
||||
inputWriter.write(inputLine.toByteArray())
|
||||
inputWriter.flush()
|
||||
inputLine = ""
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doUpArrow() {
|
||||
if (!history.isBeginning())
|
||||
replaceInputWithPreviousLine()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun replaceInputWithPreviousLine() {
|
||||
history.updateCurrentLine(inputLine)
|
||||
clearInput()
|
||||
displayPreviousInputLine()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun clearInput() {
|
||||
terminal.setCursorPosition(originColumn, originRow)
|
||||
putStringToTerminal(inputLine.replace(".".toRegex(), " "))
|
||||
terminal.setCursorPosition(originColumn, originRow)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun displayPreviousInputLine() {
|
||||
inputLine = history.getPreviousLine()
|
||||
val inputCharacters = inputLine.toCharArray()
|
||||
|
||||
for (i in inputCharacters.indices)
|
||||
displayCharacter(inputCharacters[i], i)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun displayCharacter(character: Char, offsetFromOrigin: Int) {
|
||||
if (isLastColumn(offsetFromOrigin)) {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
terminal.putCharacter(character)
|
||||
moveCursorToNextRow(cursorPosition)
|
||||
} else
|
||||
terminal.putCharacter(character)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun isLastColumn(offsetFromOrigin: Int): Boolean {
|
||||
val totalColumns = terminalSize.columns
|
||||
|
||||
return (originColumn + offsetFromOrigin) % totalColumns == totalColumns - 1
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doDownArrow() {
|
||||
if (!history.isEnd())
|
||||
replaceInputWithNextLine()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun replaceInputWithNextLine() {
|
||||
history.updateCurrentLine(inputLine)
|
||||
clearInput()
|
||||
displayNextInputLine()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun displayNextInputLine() {
|
||||
inputLine = history.getNextLine()
|
||||
putStringToTerminal(inputLine)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doLeftArrow() {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
|
||||
if (isPossibleToMoveLeft(cursorPosition))
|
||||
moveCursorLeft(cursorPosition)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun isPossibleToMoveLeft(cursorPosition: TerminalPosition): Boolean {
|
||||
return getDistanceFromOrigin(cursorPosition) > 0
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun getDistanceFromOrigin(cursorPosition: TerminalPosition): Int {
|
||||
val columnDifference = cursorPosition.column - originColumn
|
||||
val rowDifference = cursorPosition.row - originRow
|
||||
val totalColumns = terminalSize.columns
|
||||
|
||||
return columnDifference + totalColumns * rowDifference
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun moveCursorLeft(cursorPosition: TerminalPosition) {
|
||||
var newPosition = cursorPosition.withRelativeColumn(-1)
|
||||
|
||||
if (isAtStartOfRow(cursorPosition))
|
||||
newPosition = cursorPosition.withColumn(terminalSize.columns).withRelativeRow(-1)
|
||||
|
||||
terminal.cursorPosition = newPosition
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun isAtStartOfRow(cursorPosition: TerminalPosition): Boolean {
|
||||
return cursorPosition.column == 0
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doRightArrow() {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
|
||||
if (isPossibleToMoveRight(cursorPosition))
|
||||
moveCursorRight(cursorPosition)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun isPossibleToMoveRight(cursorPosition: TerminalPosition): Boolean {
|
||||
return getDistanceFromOrigin(cursorPosition) < inputLine.length
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun moveCursorRight(cursorPosition: TerminalPosition) {
|
||||
if (isEndOfRow(cursorPosition))
|
||||
moveCursorToNextRow(cursorPosition)
|
||||
else
|
||||
terminal.cursorPosition = cursorPosition.withRelativeColumn(1)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun isEndOfRow(cursorPosition: TerminalPosition): Boolean {
|
||||
return cursorPosition.column >= terminalSize.columns - 1
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun moveCursorToNextRow(cursorPosition: TerminalPosition) {
|
||||
if (isEndOfBuffer(cursorPosition))
|
||||
createNewRowForCursor(cursorPosition)
|
||||
else
|
||||
terminal.cursorPosition = cursorPosition.withColumn(0).withRelativeRow(1)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun isEndOfBuffer(cursorPosition: TerminalPosition): Boolean {
|
||||
return cursorPosition.row == terminalSize.rows - 1
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun createNewRowForCursor(cursorPosition: TerminalPosition) {
|
||||
terminal.cursorPosition = cursorPosition
|
||||
terminal.putCharacter('\n')
|
||||
terminal.cursorPosition = cursorPosition.withColumn(0)
|
||||
--originRow
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doBackspace() {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
|
||||
if (isPossibleToMoveLeft(cursorPosition))
|
||||
deletePreviousCharacter(cursorPosition)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun deletePreviousCharacter(cursorPosition: TerminalPosition) {
|
||||
val distanceFromOrigin = getDistanceFromOrigin(cursorPosition)
|
||||
val remaining = inputLine.substring(distanceFromOrigin, inputLine.length)
|
||||
inputLine = inputLine.substring(0, distanceFromOrigin - 1) + remaining
|
||||
moveCursorLeft(cursorPosition)
|
||||
putStringToTerminal("$remaining ")
|
||||
moveCursorLeft(cursorPosition)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doDelete() {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
|
||||
if (isPossibleToMoveRight(cursorPosition))
|
||||
deleteCharacterAtPosition(cursorPosition)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun deleteCharacterAtPosition(cursorPosition: TerminalPosition) {
|
||||
val distanceFromOrigin = getDistanceFromOrigin(cursorPosition)
|
||||
val remaining = inputLine.substring(distanceFromOrigin + 1, inputLine.length)
|
||||
inputLine = inputLine.substring(0, distanceFromOrigin) + remaining
|
||||
putStringToTerminal("$remaining ")
|
||||
terminal.cursorPosition = cursorPosition
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun doCharacter(character: Char) {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
|
||||
if (!isBufferFilled)
|
||||
if (isPossibleToMoveRight(cursorPosition))
|
||||
insertCharacter(character, cursorPosition)
|
||||
else
|
||||
appendCharacter(character, cursorPosition)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun insertCharacter(character: Char, cursorPosition: TerminalPosition) {
|
||||
val shiftedPosition = shiftPositionIfNewRowAdded(cursorPosition)
|
||||
terminal.cursorPosition = shiftedPosition
|
||||
|
||||
val distanceFromOrigin = getDistanceFromOrigin(shiftedPosition)
|
||||
val remaining = character + inputLine.substring(distanceFromOrigin, inputLine.length)
|
||||
inputLine = inputLine.substring(0, distanceFromOrigin) + remaining
|
||||
putStringToTerminal(remaining)
|
||||
moveCursorRight(shiftedPosition)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun shiftPositionIfNewRowAdded(cursorPosition: TerminalPosition): TerminalPosition {
|
||||
val oldOriginRow = originRow
|
||||
moveCursorRight(leadingEdge)
|
||||
|
||||
return if (isNewRowAdded(oldOriginRow)) adjustCursorPosition(cursorPosition) else cursorPosition
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun isNewRowAdded(oldOriginRow: Int): Boolean {
|
||||
return originRow != oldOriginRow
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun adjustCursorPosition(cursorPosition: TerminalPosition): TerminalPosition {
|
||||
terminal.cursorPosition = TerminalPosition(originColumn, originRow)
|
||||
putStringToTerminal(inputLine)
|
||||
|
||||
return cursorPosition.withRelativeRow(-1)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun appendCharacter(character: Char, cursorPosition: TerminalPosition) {
|
||||
terminal.putCharacter(character)
|
||||
inputLine += character
|
||||
moveCursorRight(cursorPosition)
|
||||
}
|
||||
|
||||
private fun takeNap() {
|
||||
Thread.sleep(1)
|
||||
}
|
||||
|
||||
private fun writeOutput() {
|
||||
var c = outputReader.read()
|
||||
|
||||
while (c != EOF) {
|
||||
processOutput(c.toChar())
|
||||
c = outputReader.read()
|
||||
}
|
||||
|
||||
terminal.flush()
|
||||
terminal.close()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun processOutput(c: Char) {
|
||||
if (c == END_OF_SEGMENT)
|
||||
writeSegment()
|
||||
else
|
||||
outputSegment += c
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun writeSegment() {
|
||||
printSegmentCharacters()
|
||||
outputSegment = ""
|
||||
redisplayInput()
|
||||
terminal.flush()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun printSegmentCharacters() {
|
||||
moveCursorToEndOfInput()
|
||||
putOutputToTerminal()
|
||||
moveCursorToNextRowIfNecessary()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun putOutputToTerminal() {
|
||||
val input = convertOutputToStream()
|
||||
var c = input.read()
|
||||
|
||||
while (c != EOF) {
|
||||
if (isEscape(c.toChar()))
|
||||
applyControlSequence(input)
|
||||
else
|
||||
terminal.putCharacter(c.toChar())
|
||||
|
||||
c = input.read()
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun convertOutputToStream(): SafeInputStream {
|
||||
return SafeInputStream(ByteArrayInputStream(outputSegment.toByteArray()))
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun applyControlSequence(input: SafeInputStream) {
|
||||
val controlSequence = controlSequenceHandler.parse(input)
|
||||
controlSequence.applyTo(terminal)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun moveCursorToNextRowIfNecessary() {
|
||||
val cursorPosition = terminal.cursorPosition
|
||||
|
||||
if (isEndOfRow(cursorPosition))
|
||||
moveCursorToNextRow(cursorPosition)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
isStopped = true
|
||||
inputWriter.close()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val END_OF_SEGMENT = Characters.UNICODE_NULL
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ import org.junit.Test
|
|||
import org.junit.contrib.java.lang.system.ExpectedSystemExit
|
||||
import org.junit.contrib.java.lang.system.SystemErrRule
|
||||
import org.junit.contrib.java.lang.system.SystemOutRule
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import terminal.TerminalConfiguration
|
||||
import terminal.VirtualTerminalInteractor
|
||||
import testutil.SymbolAndFunctionCleaner
|
||||
|
@ -21,6 +23,7 @@ import java.io.PipedOutputStream
|
|||
import java.text.MessageFormat.format
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class MainTest : SymbolAndFunctionCleaner() {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -8,9 +8,12 @@ import org.assertj.core.api.Assertions.assertThat
|
|||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class ErrorManagerTest {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -7,6 +7,8 @@ import function.ArgumentValidator.TooManyArgumentsException
|
|||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import sexpression.Cons
|
||||
import sexpression.LispString
|
||||
import sexpression.Nil
|
||||
|
@ -15,6 +17,7 @@ import sexpression.Symbol
|
|||
import sexpression.Symbol.Companion.T
|
||||
import testutil.TestUtilities.assertIsErrorWithMessage
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class ArgumentValidatorTest {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -2,9 +2,12 @@ package function
|
|||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispFunctionTest {
|
||||
|
||||
@Test
|
||||
|
|
|
@ -2,9 +2,12 @@ package function
|
|||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import sexpression.Cons
|
||||
import sexpression.Nil
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispSpecialFunctionTest {
|
||||
|
||||
@Test
|
||||
|
|
|
@ -6,6 +6,8 @@ import function.UserDefinedFunction.IllegalKeywordRestPositionException
|
|||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import sexpression.Cons
|
||||
import sexpression.LispNumber
|
||||
import sexpression.Nil
|
||||
|
@ -13,6 +15,7 @@ import sexpression.Symbol
|
|||
import testutil.TestUtilities.assertIsErrorWithMessage
|
||||
import testutil.TestUtilities.assertSExpressionsMatch
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class UserDefinedFunctionTest {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -6,10 +6,13 @@ import org.assertj.core.api.Assertions.assertThat
|
|||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import testutil.TestUtilities.createInputStreamFromString
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispInterpreterTest {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -2,8 +2,11 @@ package recursion
|
|||
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import recursion.TailCalls.done
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class TailCallTest {
|
||||
|
||||
@Test
|
||||
|
|
|
@ -4,11 +4,14 @@ import error.Severity.CRITICAL
|
|||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import scanner.LispInputStream.MaximumUnreadsExceededException
|
||||
import stream.LispIOException
|
||||
import testutil.TestUtilities.createIOExceptionThrowingInputStream
|
||||
import testutil.TestUtilities.createInputStreamFromString
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispCommentRemovingInputStreamTest {
|
||||
|
||||
private fun getLispCommentRemovingInputStreamResult(inputString: String) =
|
||||
|
|
|
@ -3,8 +3,11 @@ package scanner
|
|||
import file.FilePosition
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import testutil.TestUtilities.createInputStreamFromString
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispScannerLineColumnTest {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -2,8 +2,11 @@ package scanner
|
|||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import testutil.TestUtilities.createInputStreamFromString
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispScannerTextTest {
|
||||
|
||||
private fun assertTokenTextMatches(input: String, expectedText: Array<String>) {
|
||||
|
|
|
@ -4,6 +4,8 @@ import org.assertj.core.api.Assertions.assertThat
|
|||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import scanner.LispScanner.UnterminatedStringException
|
||||
import testutil.TestUtilities.assertIsErrorWithMessage
|
||||
import testutil.TestUtilities.createInputStreamFromString
|
||||
|
@ -20,6 +22,7 @@ import token.RightParenthesis
|
|||
import token.Token
|
||||
import token.TokenFactory.BadCharacterException
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispScannerTypeTest {
|
||||
|
||||
private val expectedTypes = mutableListOf<Class<out Token>>()
|
||||
|
|
|
@ -4,6 +4,8 @@ import function.UserDefinedFunction
|
|||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import sexpression.LispNumber.InvalidNumberException
|
||||
import testutil.TestUtilities.assertIsErrorWithMessage
|
||||
import testutil.TestUtilities.assertSExpressionsMatch
|
||||
|
@ -11,6 +13,7 @@ import testutil.TestUtilities.makeList
|
|||
import java.math.BigInteger
|
||||
import java.util.Locale
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class SExpressionTest {
|
||||
|
||||
private fun assertSExpressionMatchesString(expected: String, sExpression: SExpression) {
|
||||
|
|
|
@ -4,10 +4,13 @@ import org.assertj.core.api.Assertions.assertThat
|
|||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import testutil.TestUtilities.createIOExceptionThrowingInputStream
|
||||
import testutil.TestUtilities.createInputStreamFromString
|
||||
import util.Characters.EOF
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class SafeInputStreamTest {
|
||||
|
||||
private lateinit var safe: SafeInputStream
|
||||
|
|
|
@ -4,9 +4,12 @@ import org.assertj.core.api.Assertions.assertThat
|
|||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import testutil.TestUtilities.createIOExceptionThrowingOutputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class SafeOutputStreamTest {
|
||||
|
||||
private lateinit var safe: SafeOutputStream
|
||||
|
|
|
@ -3,6 +3,8 @@ package terminal
|
|||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import stream.SafeInputStream
|
||||
import terminal.ControlSequence.NullControlSequence
|
||||
import terminal.ControlSequenceHandler.Companion.isEscape
|
||||
|
@ -14,6 +16,7 @@ import terminal.SelectGraphicRendition.YELLOW
|
|||
import testutil.TestUtilities
|
||||
import util.Characters.EOF
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class ControlSequenceHandlerTest {
|
||||
|
||||
private lateinit var handler: ControlSequenceHandler
|
||||
|
|
|
@ -6,6 +6,8 @@ import com.googlecode.lanterna.terminal.virtual.VirtualTerminal
|
|||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import terminal.ControlSequence.NullControlSequence
|
||||
import terminal.SelectGraphicRendition.GREEN
|
||||
import terminal.SelectGraphicRendition.PURPLE
|
||||
|
@ -14,6 +16,7 @@ import terminal.SelectGraphicRendition.RESET
|
|||
import terminal.SelectGraphicRendition.YELLOW
|
||||
import java.util.HashSet
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class ControlSequenceTest {
|
||||
|
||||
private lateinit var indicatorSet: MutableSet<String>
|
||||
|
|
|
@ -11,8 +11,11 @@ import com.googlecode.lanterna.input.KeyType.Escape
|
|||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import terminal.LispTerminal.END_OF_SEGMENT
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import terminal.LispTerminal.Companion.END_OF_SEGMENT
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class LispTerminalTest {
|
||||
|
||||
private lateinit var terminal: VirtualTerminalInteractor
|
||||
|
|
|
@ -3,11 +3,14 @@ package terminal
|
|||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import stream.LispIOException
|
||||
import java.io.IOException
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class TerminalConfigurationTest {
|
||||
|
||||
private lateinit var configuration: TerminalConfiguration
|
||||
|
|
|
@ -4,6 +4,10 @@ import org.assertj.core.api.Assertions.assertThat
|
|||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
class TerminalHistoryTest {
|
||||
|
||||
private lateinit var history: TerminalHistory
|
||||
|
|
|
@ -8,7 +8,7 @@ import com.googlecode.lanterna.terminal.virtual.DefaultVirtualTerminal
|
|||
import com.googlecode.lanterna.terminal.virtual.VirtualTerminal
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Assert.fail
|
||||
import terminal.LispTerminal.END_OF_SEGMENT
|
||||
import terminal.LispTerminal.Companion.END_OF_SEGMENT
|
||||
import java.io.IOException
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
|
|
Loading…
Reference in New Issue