package main; 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; import terminal.SafeStream.SafePipedOutputStream; import terminal.SafeStream.UncheckedIOException; 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[] args) throws IOException { LispMain lispMain = new LispMain(); if (args.length == 0) lispMain.runInteractive(); else lispMain.runWithFile(args[0]); } private PipedInputStream inputReader; private PipedOutputStream inputWriter; private PipedInputStream outputReader; private PipedOutputStream outputWriter; private PrintStream outputStream; private SafePipedOutputStream safeOutputWriter; private LispTerminal lispTerminal; private void runInteractive() { initializeTerminalAndStreams(); printGreeting(); lispTerminal.start(); buildInteractiveInterpreter().interpret(); outputStream.close(); } private void initializeTerminalAndStreams() { try { initalizeTerminalAndStreamsWithException(); } catch (IOException e) { throw new UncheckedIOException(e); } } private void initalizeTerminalAndStreamsWithException() throws IOException { inputReader = new PipedInputStream(); inputWriter = new PipedOutputStream(inputReader); outputReader = new PipedInputStream(); outputWriter = new PipedOutputStream(outputReader); outputStream = new PrintStream(outputWriter); safeOutputWriter = new SafePipedOutputStream(outputWriter); lispTerminal = new LispTerminal(createIOSafeTerminal(), inputWriter, outputReader); } private IOSafeTerminal createIOSafeTerminal() throws IOException { Terminal defaultTerminal = new DefaultTerminalFactory().createTerminal(); return IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter(defaultTerminal); } private void printGreeting() { outputStream.println(GREETING); outputStream.println(); } private LispInterpreter buildInteractiveInterpreter() { LispInterpreterBuilder builder = LispInterpreterBuilderImpl.getInstance(); builder.setInput(inputReader, "terminal"); builder.setOutput(outputStream); builder.setErrorOutput(outputStream); builder.setTerminationFunction(this::shutdown); builder.setErrorTerminationFunction(this::shutdown); builder.setPromptDecorator(makeSegmentDecorator(ANSI_GREEN)); builder.setValueOutputDecorator(s -> s); builder.setWarningOutputDecorator(s -> s); builder.setErrorOutputDecorator(s -> s); builder.setCriticalOutputDecorator(s -> s); return builder.build(); } private void shutdown() { outputStream.println(); outputStream.println(END_OF_SEGMENT); lispTerminal.stop(); safeOutputWriter.close(); } private static Function makeSegmentDecorator(String color) { return new Function() { @Override public String apply(String s) { return s + END_OF_SEGMENT; } }; } private void runWithFile(String fileName) { buildFileInterpreter(fileName).interpret(); } private LispInterpreter buildFileInterpreter(String fileName) { LispInterpreterBuilder builder = LispInterpreterBuilderImpl.getInstance(); 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(); } private static Function makeColorDecorator(String color) { return new Function() { @Override public String apply(String s) { return color + s + ANSI_RESET; } }; } }