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 stream.UncheckedIOException; import terminal.*; public class LispMain { private static final String GREETING = "Transcendental Lisp - Version 1.0.1"; public static final String ANSI_RESET = "\u001B[0m"; public static final String ANSI_RED = "\u001B[31m"; public static final String ANSI_GREEN = "\u001B[32m"; public static final String ANSI_YELLOW = "\u001B[33m"; public 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(); } }