package main; import static com.googlecode.lanterna.terminal.IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter; import static terminal.LispTerminal.END_OF_SEGMENT; import java.io.*; import java.util.function.Function; import com.googlecode.lanterna.terminal.*; import interpreter.*; import terminal.LispTerminal; public class LispMain { private static final String GREETING = "Transcendental Lisp - Version 1.0.1"; private static final String ANSI_RESET = "\u001B[0m"; private static final String ANSI_RED = "\u001B[31m"; private static final String ANSI_GREEN = "\u001B[32m"; private static final String ANSI_YELLOW = "\u001B[33m"; private static final String ANSI_PURPLE = "\u001B[35m"; public static void main(String[] arguments) { LispMain lispMain = new LispMain(); if (arguments.length == 0) lispMain.runInteractive(); else lispMain.runWithFile(arguments[0]); } private LispInterpreterBuilder builder; private PipedInputStream inputReader; private PipedOutputStream outputWriter; private PrintStream output; private LispTerminal lispTerminal; public LispMain() { this.builder = LispInterpreterBuilderImpl.getInstance(); TerminalConfiguration terminalConfiguration = new TerminalConfiguration(); terminalConfiguration.setInputWriter(new PipedOutputStream()); terminalConfiguration.setOutputReader(new PipedInputStream()); terminalConfiguration.setTerminal(createIOSafeTerminal()); initializeTerminal(terminalConfiguration); } private IOSafeTerminal createIOSafeTerminal() { return createRuntimeExceptionConvertingAdapter(createDefaultTerminal()); } private Terminal createDefaultTerminal() { try { return new DefaultTerminalFactory().createTerminal(); } catch (IOException e) { throw new UncheckedIOException(e); } } public LispMain(LispInterpreterBuilder builder, TerminalConfiguration configuration) { this.builder = builder; initializeTerminal(configuration); } private void initializeTerminal(TerminalConfiguration configuration) { try { initalizeTerminalWithException(configuration); } catch (IOException e) { throw new UncheckedIOException(e); } } private void initalizeTerminalWithException(TerminalConfiguration configuration) throws IOException { PipedOutputStream inputWriter = configuration.getInputWriter(); PipedInputStream outputReader = configuration.getOutputReader(); inputReader = new PipedInputStream(inputWriter); outputWriter = new PipedOutputStream(outputReader); output = new PrintStream(outputWriter); lispTerminal = new LispTerminal(configuration.getTerminal(), inputWriter, outputReader); } public void runInteractive() { printGreeting(); lispTerminal.start(); buildInteractiveInterpreter().interpret(); shutdownTerminal(); } private void printGreeting() { output.println(GREETING); output.println(); } private LispInterpreter buildInteractiveInterpreter() { builder.setInput(inputReader, "terminal"); builder.setOutput(output); builder.setErrorOutput(output); builder.setTerminationFunction(this::shutdownTerminal); builder.setErrorTerminationFunction(this::shutdownTerminal); builder.setPromptDecorator(s -> s + END_OF_SEGMENT); builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN)); builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW)); builder.setErrorOutputDecorator(makeColorDecorator(ANSI_RED)); builder.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE)); return builder.build(); } private void shutdownTerminal() { output.print(END_OF_SEGMENT); lispTerminal.stop(); output.close(); } private Function makeColorDecorator(String color) { return new Function() { @Override public String apply(String s) { return color + s + ANSI_RESET; } }; } public void runWithFile(String fileName) { buildFileInterpreter(fileName).interpret(); } private LispInterpreter buildFileInterpreter(String fileName) { builder.useFile(fileName); builder.setOutput(System.out); builder.setErrorOutput(System.err); builder.setTerminationFunction(() -> System.exit(0)); builder.setErrorTerminationFunction(() -> System.exit(1)); builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN)); builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW)); builder.setErrorOutputDecorator(makeColorDecorator(ANSI_RED)); builder.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE)); return builder.build(); } public class TerminalConfiguration { private PipedOutputStream inputWriter; private PipedInputStream outputReader; private IOSafeTerminal terminal; public PipedOutputStream getInputWriter() { return inputWriter; } public void setInputWriter(PipedOutputStream inputWriter) { this.inputWriter = inputWriter; } public PipedInputStream getOutputReader() { return outputReader; } public void setOutputReader(PipedInputStream outputReader) { this.outputReader = outputReader; } public IOSafeTerminal getTerminal() { return terminal; } public void setTerminal(IOSafeTerminal terminal) { this.terminal = terminal; } } }