diff --git a/src/main/kotlin/recursion/TailCall.kt b/src/main/kotlin/recursion/TailCall.kt index 97bde28..4442cfe 100644 --- a/src/main/kotlin/recursion/TailCall.kt +++ b/src/main/kotlin/recursion/TailCall.kt @@ -1,6 +1,5 @@ package recursion -@FunctionalInterface interface TailCall { fun isComplete() = false diff --git a/src/main/kotlin/terminal/ControlSequence.java b/src/main/kotlin/terminal/ControlSequence.java deleted file mode 100644 index 231aa3d..0000000 --- a/src/main/kotlin/terminal/ControlSequence.java +++ /dev/null @@ -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 {} -} \ No newline at end of file diff --git a/src/main/kotlin/terminal/ControlSequence.kt b/src/main/kotlin/terminal/ControlSequence.kt new file mode 100644 index 0000000..14bc200 --- /dev/null +++ b/src/main/kotlin/terminal/ControlSequence.kt @@ -0,0 +1,13 @@ +package terminal + +import com.googlecode.lanterna.terminal.IOSafeTerminal + +interface ControlSequence { + + val code + get() = "" + + fun applyTo(terminal: IOSafeTerminal) {} + + class NullControlSequence : ControlSequence +} \ No newline at end of file diff --git a/src/main/kotlin/terminal/ControlSequenceHandler.java b/src/main/kotlin/terminal/ControlSequenceHandler.java deleted file mode 100644 index 4f072a8..0000000 --- a/src/main/kotlin/terminal/ControlSequenceHandler.java +++ /dev/null @@ -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); - } -} diff --git a/src/main/kotlin/terminal/ControlSequenceHandler.kt b/src/main/kotlin/terminal/ControlSequenceHandler.kt new file mode 100644 index 0000000..c87c1d1 --- /dev/null +++ b/src/main/kotlin/terminal/ControlSequenceHandler.kt @@ -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 + } + } +} diff --git a/src/main/kotlin/terminal/ControlSequenceLookup.java b/src/main/kotlin/terminal/ControlSequenceLookup.java deleted file mode 100644 index 2cec30a..0000000 --- a/src/main/kotlin/terminal/ControlSequenceLookup.java +++ /dev/null @@ -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> commands; - - public ControlSequenceLookup() { - this.commands = new HashMap<>(); - - initializeCommands(); - } - - private void initializeCommands() { - Map 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 codes = commands.getOrDefault(command, new HashMap<>()); - - return codes.getOrDefault(code, new NullControlSequence()); - } -} \ No newline at end of file diff --git a/src/main/kotlin/terminal/ControlSequenceLookup.kt b/src/main/kotlin/terminal/ControlSequenceLookup.kt new file mode 100644 index 0000000..f669f28 --- /dev/null +++ b/src/main/kotlin/terminal/ControlSequenceLookup.kt @@ -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()) + } +} \ No newline at end of file diff --git a/src/main/kotlin/terminal/SelectGraphicRendition.java b/src/main/kotlin/terminal/SelectGraphicRendition.java deleted file mode 100644 index 9b4d9b5..0000000 --- a/src/main/kotlin/terminal/SelectGraphicRendition.java +++ /dev/null @@ -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'; - -} \ No newline at end of file diff --git a/src/main/kotlin/terminal/SelectGraphicRendition.kt b/src/main/kotlin/terminal/SelectGraphicRendition.kt new file mode 100644 index 0000000..0edcae7 --- /dev/null +++ b/src/main/kotlin/terminal/SelectGraphicRendition.kt @@ -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' + } +} \ No newline at end of file diff --git a/src/main/kotlin/terminal/TerminalConfiguration.java b/src/main/kotlin/terminal/TerminalConfiguration.java deleted file mode 100644 index b7512db..0000000 --- a/src/main/kotlin/terminal/TerminalConfiguration.java +++ /dev/null @@ -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; - } -} \ No newline at end of file diff --git a/src/main/kotlin/terminal/TerminalConfiguration.kt b/src/main/kotlin/terminal/TerminalConfiguration.kt new file mode 100644 index 0000000..b43a22e --- /dev/null +++ b/src/main/kotlin/terminal/TerminalConfiguration.kt @@ -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) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/terminal/TerminalHistory.java b/src/main/kotlin/terminal/TerminalHistory.java deleted file mode 100644 index 63fb0ca..0000000 --- a/src/main/kotlin/terminal/TerminalHistory.java +++ /dev/null @@ -1,52 +0,0 @@ -package terminal; - -import java.util.ArrayList; -import java.util.List; - -public class TerminalHistory { - - private List 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(); - } -} diff --git a/src/main/kotlin/terminal/TerminalHistory.kt b/src/main/kotlin/terminal/TerminalHistory.kt new file mode 100644 index 0000000..f721d78 --- /dev/null +++ b/src/main/kotlin/terminal/TerminalHistory.kt @@ -0,0 +1,41 @@ +package terminal + +import java.util.ArrayList + +class TerminalHistory { + + private val history: MutableList + 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 + } +}