Start converting terminal classes to kotlin
This commit is contained in:
parent
516603a948
commit
e76aefa3d1
|
@ -1,6 +1,5 @@
|
|||
package recursion
|
||||
|
||||
@FunctionalInterface
|
||||
interface TailCall<T> {
|
||||
|
||||
fun isComplete() = false
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
package terminal;
|
||||
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal;
|
||||
|
||||
public interface ControlSequence {
|
||||
|
||||
default String getCode() {
|
||||
return "";
|
||||
}
|
||||
|
||||
default void applyTo(IOSafeTerminal terminal) {}
|
||||
|
||||
public static class NullControlSequence implements ControlSequence {}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package terminal
|
||||
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal
|
||||
|
||||
interface ControlSequence {
|
||||
|
||||
val code
|
||||
get() = ""
|
||||
|
||||
fun applyTo(terminal: IOSafeTerminal) {}
|
||||
|
||||
class NullControlSequence : ControlSequence
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package terminal;
|
||||
|
||||
import stream.SafeInputStream;
|
||||
import util.Characters;
|
||||
|
||||
import static java.lang.Character.isDigit;
|
||||
|
||||
class ControlSequenceHandler {
|
||||
|
||||
public static final boolean isEscape(char c) {
|
||||
return c == Characters.UNICODE_ESCAPE;
|
||||
}
|
||||
|
||||
private ControlSequenceLookup controlSequenceLookup;
|
||||
private SafeInputStream input;
|
||||
private String code;
|
||||
private int currentCharacter;
|
||||
|
||||
public ControlSequenceHandler() {
|
||||
this.controlSequenceLookup = new ControlSequenceLookup();
|
||||
}
|
||||
|
||||
public ControlSequence parse(SafeInputStream inputStream) {
|
||||
input = inputStream;
|
||||
code = "";
|
||||
|
||||
readCharacter();
|
||||
if (isExpectedFirstCharacter())
|
||||
readCode();
|
||||
|
||||
return controlSequenceLookup.get((char) currentCharacter, code);
|
||||
}
|
||||
|
||||
private void readCharacter() {
|
||||
currentCharacter = input.read();
|
||||
}
|
||||
|
||||
private boolean isExpectedFirstCharacter() {
|
||||
return isCharacter() && isLeftBracket();
|
||||
}
|
||||
|
||||
private boolean isCharacter() {
|
||||
return currentCharacter != Characters.EOF;
|
||||
}
|
||||
|
||||
private boolean isLeftBracket() {
|
||||
return (char) currentCharacter == Characters.LEFT_SQUARE_BRACKET;
|
||||
}
|
||||
|
||||
private void readCode() {
|
||||
for (readCharacter(); isPartOfCode(); readCharacter())
|
||||
code += (char) currentCharacter;
|
||||
}
|
||||
|
||||
private boolean isPartOfCode() {
|
||||
return isCharacter() && isDigit((char) currentCharacter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package terminal
|
||||
|
||||
import stream.SafeInputStream
|
||||
import util.Characters.EOF
|
||||
import util.Characters.LEFT_SQUARE_BRACKET
|
||||
import util.Characters.UNICODE_ESCAPE
|
||||
import java.lang.Character.isDigit
|
||||
|
||||
class ControlSequenceHandler {
|
||||
|
||||
private val controlSequenceLookup: ControlSequenceLookup = ControlSequenceLookup()
|
||||
private var currentCharacter: Int = 0
|
||||
private lateinit var input: SafeInputStream
|
||||
private lateinit var code: String
|
||||
|
||||
private fun isExpectedFirstCharacter() = isCharacter() && isLeftBracket()
|
||||
private fun isCharacter() = currentCharacter != EOF
|
||||
private fun isLeftBracket() = currentCharacter.toChar() == LEFT_SQUARE_BRACKET
|
||||
private fun isPartOfCode() = isCharacter() && isDigit(currentCharacter.toChar())
|
||||
|
||||
fun parse(inputStream: SafeInputStream): ControlSequence {
|
||||
input = inputStream
|
||||
code = ""
|
||||
|
||||
readCharacter()
|
||||
|
||||
if (isExpectedFirstCharacter())
|
||||
readCode()
|
||||
|
||||
return controlSequenceLookup[currentCharacter.toChar(), code]
|
||||
}
|
||||
|
||||
private fun readCharacter() {
|
||||
currentCharacter = input.read()
|
||||
}
|
||||
|
||||
private fun readCode() {
|
||||
readCharacter()
|
||||
|
||||
while (isPartOfCode()) {
|
||||
code += currentCharacter.toChar()
|
||||
readCharacter()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun isEscape(c: Char): Boolean {
|
||||
return c == UNICODE_ESCAPE
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package terminal;
|
||||
|
||||
import terminal.ControlSequence.NullControlSequence;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static terminal.SelectGraphicRendition.SGR_COMMAND;
|
||||
|
||||
public class ControlSequenceLookup {
|
||||
|
||||
private Map<Character, Map<String, ControlSequence>> commands;
|
||||
|
||||
public ControlSequenceLookup() {
|
||||
this.commands = new HashMap<>();
|
||||
|
||||
initializeCommands();
|
||||
}
|
||||
|
||||
private void initializeCommands() {
|
||||
Map<String, ControlSequence> sgrCodes = new HashMap<>();
|
||||
|
||||
for (SelectGraphicRendition sgr : SelectGraphicRendition.values())
|
||||
sgrCodes.put(sgr.getCode(), sgr);
|
||||
|
||||
commands.put(SGR_COMMAND, sgrCodes);
|
||||
}
|
||||
|
||||
public ControlSequence get(char command, String code) {
|
||||
Map<String, ControlSequence> codes = commands.getOrDefault(command, new HashMap<>());
|
||||
|
||||
return codes.getOrDefault(code, new NullControlSequence());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package terminal
|
||||
|
||||
import terminal.ControlSequence.NullControlSequence
|
||||
import terminal.SelectGraphicRendition.Companion.SGR_COMMAND
|
||||
|
||||
class ControlSequenceLookup {
|
||||
|
||||
private val commands = mapOf(SGR_COMMAND to SelectGraphicRendition.values().associateBy({ it.code }, { it }))
|
||||
|
||||
operator fun get(command: Char, code: String): ControlSequence {
|
||||
val codes = commands.getOrDefault(command, emptyMap())
|
||||
|
||||
return codes.getOrDefault(code, NullControlSequence())
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package terminal;
|
||||
|
||||
import com.googlecode.lanterna.TextColor;
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal;
|
||||
|
||||
public enum SelectGraphicRendition implements ControlSequence {
|
||||
|
||||
RESET {
|
||||
@Override
|
||||
public String getCode() {
|
||||
return "0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(IOSafeTerminal terminal) {
|
||||
terminal.resetColorAndSGR();
|
||||
}
|
||||
},
|
||||
|
||||
RED {
|
||||
@Override
|
||||
public String getCode() {
|
||||
return "31";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(IOSafeTerminal terminal) {
|
||||
terminal.setForegroundColor(TextColor.ANSI.RED);
|
||||
}
|
||||
},
|
||||
|
||||
GREEN {
|
||||
@Override
|
||||
public String getCode() {
|
||||
return "32";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(IOSafeTerminal terminal) {
|
||||
terminal.setForegroundColor(TextColor.ANSI.GREEN);
|
||||
}
|
||||
},
|
||||
|
||||
YELLOW {
|
||||
@Override
|
||||
public String getCode() {
|
||||
return "33";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(IOSafeTerminal terminal) {
|
||||
terminal.setForegroundColor(TextColor.ANSI.YELLOW);
|
||||
}
|
||||
},
|
||||
|
||||
PURPLE {
|
||||
@Override
|
||||
public String getCode() {
|
||||
return "35";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(IOSafeTerminal terminal) {
|
||||
terminal.setForegroundColor(TextColor.ANSI.MAGENTA);
|
||||
}
|
||||
};
|
||||
|
||||
public static final char SGR_COMMAND = 'm';
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package terminal
|
||||
|
||||
import com.googlecode.lanterna.TextColor.ANSI
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal
|
||||
|
||||
enum class SelectGraphicRendition : ControlSequence {
|
||||
|
||||
RESET {
|
||||
override val code = "0"
|
||||
|
||||
override fun applyTo(terminal: IOSafeTerminal) {
|
||||
terminal.resetColorAndSGR()
|
||||
}
|
||||
},
|
||||
|
||||
RED {
|
||||
override val code = "31"
|
||||
|
||||
override fun applyTo(terminal: IOSafeTerminal) {
|
||||
terminal.setForegroundColor(ANSI.RED)
|
||||
}
|
||||
},
|
||||
|
||||
GREEN {
|
||||
override val code = "32"
|
||||
|
||||
override fun applyTo(terminal: IOSafeTerminal) {
|
||||
terminal.setForegroundColor(ANSI.GREEN)
|
||||
}
|
||||
},
|
||||
|
||||
YELLOW {
|
||||
override val code = "33"
|
||||
|
||||
override fun applyTo(terminal: IOSafeTerminal) {
|
||||
terminal.setForegroundColor(ANSI.YELLOW)
|
||||
}
|
||||
},
|
||||
|
||||
PURPLE {
|
||||
override val code = "35"
|
||||
|
||||
override fun applyTo(terminal: IOSafeTerminal) {
|
||||
terminal.setForegroundColor(ANSI.MAGENTA)
|
||||
}
|
||||
};
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
val SGR_COMMAND = 'm'
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package terminal;
|
||||
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal;
|
||||
import stream.LispIOException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
|
||||
public class TerminalConfiguration {
|
||||
|
||||
private PipedOutputStream inputWriter;
|
||||
private PipedInputStream inputReader;
|
||||
private PipedOutputStream outputWriter;
|
||||
private PipedInputStream outputReader;
|
||||
private IOSafeTerminal terminal;
|
||||
|
||||
public void setInputPair(PipedOutputStream inputWriter, PipedInputStream inputReader) {
|
||||
this.inputWriter = inputWriter;
|
||||
this.inputReader = inputReader;
|
||||
connectInputPair();
|
||||
}
|
||||
|
||||
private void connectInputPair() {
|
||||
try {
|
||||
inputWriter.connect(inputReader);
|
||||
} catch (IOException e) {
|
||||
throw new LispIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOutputPair(PipedOutputStream outputWriter, PipedInputStream outputReader) {
|
||||
this.outputWriter = outputWriter;
|
||||
this.outputReader = outputReader;
|
||||
connectOutputPair();
|
||||
}
|
||||
|
||||
private void connectOutputPair() {
|
||||
try {
|
||||
outputWriter.connect(outputReader);
|
||||
} catch (IOException e) {
|
||||
throw new LispIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTerminal(IOSafeTerminal terminal) {
|
||||
this.terminal = terminal;
|
||||
}
|
||||
|
||||
public PipedOutputStream getInputWriter() {
|
||||
return inputWriter;
|
||||
}
|
||||
|
||||
public PipedInputStream getInputReader() {
|
||||
return inputReader;
|
||||
}
|
||||
|
||||
public PipedOutputStream getOutputWriter() {
|
||||
return outputWriter;
|
||||
}
|
||||
|
||||
public PipedInputStream getOutputReader() {
|
||||
return outputReader;
|
||||
}
|
||||
|
||||
public IOSafeTerminal getTerminal() {
|
||||
return terminal;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package terminal
|
||||
|
||||
import com.googlecode.lanterna.terminal.IOSafeTerminal
|
||||
import stream.LispIOException
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
|
||||
class TerminalConfiguration {
|
||||
|
||||
var inputWriter: PipedOutputStream? = null
|
||||
private set
|
||||
lateinit var inputReader: PipedInputStream
|
||||
private set
|
||||
var outputWriter: PipedOutputStream? = null
|
||||
private set
|
||||
var outputReader: PipedInputStream? = null
|
||||
private set
|
||||
var terminal: IOSafeTerminal? = null
|
||||
|
||||
fun setInputPair(inputWriter: PipedOutputStream, inputReader: PipedInputStream) {
|
||||
this.inputWriter = inputWriter
|
||||
this.inputReader = inputReader
|
||||
connectInputPair()
|
||||
}
|
||||
|
||||
private fun connectInputPair() {
|
||||
try {
|
||||
inputWriter!!.connect(inputReader!!)
|
||||
} catch (e: IOException) {
|
||||
throw LispIOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun setOutputPair(outputWriter: PipedOutputStream, outputReader: PipedInputStream) {
|
||||
this.outputWriter = outputWriter
|
||||
this.outputReader = outputReader
|
||||
connectOutputPair()
|
||||
}
|
||||
|
||||
private fun connectOutputPair() {
|
||||
try {
|
||||
outputWriter!!.connect(outputReader!!)
|
||||
} catch (e: IOException) {
|
||||
throw LispIOException(e)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package terminal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TerminalHistory {
|
||||
|
||||
private List<String> history;
|
||||
private int lineIndex;
|
||||
|
||||
public TerminalHistory() {
|
||||
this.history = new ArrayList<>();
|
||||
this.history.add("");
|
||||
this.lineIndex = 0;
|
||||
}
|
||||
|
||||
public void addLine(String line) {
|
||||
history.set(lastIndex(), line);
|
||||
history.add("");
|
||||
lineIndex = lastIndex();
|
||||
}
|
||||
|
||||
private int lastIndex() {
|
||||
return history.size() - 1;
|
||||
}
|
||||
|
||||
public void updateCurrentLine(String line) {
|
||||
history.set(lineIndex, line);
|
||||
}
|
||||
|
||||
public String getPreviousLine() {
|
||||
if (isBeginning())
|
||||
return history.get(lineIndex);
|
||||
|
||||
return history.get(--lineIndex);
|
||||
}
|
||||
|
||||
public boolean isBeginning() {
|
||||
return lineIndex == 0;
|
||||
}
|
||||
|
||||
public String getNextLine() {
|
||||
if (isEnd())
|
||||
return history.get(lineIndex);
|
||||
|
||||
return history.get(++lineIndex);
|
||||
}
|
||||
|
||||
public boolean isEnd() {
|
||||
return lineIndex == lastIndex();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package terminal
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class TerminalHistory {
|
||||
|
||||
private val history: MutableList<String>
|
||||
private var lineIndex: Int = 0
|
||||
|
||||
val previousLine: String
|
||||
get() = if (isBeginning) history[lineIndex] else history[--lineIndex]
|
||||
|
||||
val isBeginning: Boolean
|
||||
get() = lineIndex == 0
|
||||
|
||||
val nextLine: String
|
||||
get() = if (isEnd) history[lineIndex] else history[++lineIndex]
|
||||
|
||||
val isEnd: Boolean
|
||||
get() = lineIndex == lastIndex()
|
||||
|
||||
init {
|
||||
this.history = ArrayList()
|
||||
this.history.add("")
|
||||
this.lineIndex = 0
|
||||
}
|
||||
|
||||
fun addLine(line: String) {
|
||||
history[lastIndex()] = line
|
||||
history.add("")
|
||||
lineIndex = lastIndex()
|
||||
}
|
||||
|
||||
private fun lastIndex(): Int {
|
||||
return history.size - 1
|
||||
}
|
||||
|
||||
fun updateCurrentLine(line: String) {
|
||||
history[lineIndex] = line
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue