package main; import static com.googlecode.lanterna.terminal.IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter; import static java.text.MessageFormat.format; import static terminal.LispTerminal.END_OF_SEGMENT; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.PrintStream; import java.util.function.Function; import com.googlecode.lanterna.terminal.DefaultTerminalFactory; import com.googlecode.lanterna.terminal.IOSafeTerminal; import com.googlecode.lanterna.terminal.Terminal; import interpreter.LispInterpreter; import interpreter.LispInterpreterBuilder; import interpreter.LispInterpreterBuilderImpl; import stream.UncheckedIOException; import terminal.LispTerminal; import terminal.TerminalConfiguration; public class LispMain { public static final String GREETING = "Transcendental Lisp - Version {0}"; 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 final String[] LANGUAGE_FILE_NAMES = new String[] { "functions.lisp", "dlambda.lisp" }; 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 PrintStream output; private LispTerminal lispTerminal; private TerminalConfiguration configuration; public LispMain() { this.builder = LispInterpreterBuilderImpl.getInstance(); } public LispMain(LispInterpreterBuilder builder, TerminalConfiguration configuration) { this.builder = builder; this.configuration = configuration; } public void runInteractive() { initializeTerminal(); printGreeting(); lispTerminal.start(); buildInteractiveInterpreter().interpret(); shutdownTerminal(); } private void initializeTerminal() { createTerminalConfiguration(); inputReader = configuration.getInputReader(); output = new PrintStream(configuration.getOutputWriter()); lispTerminal = new LispTerminal(configuration); } private void createTerminalConfiguration() { if (configuration == null) { configuration = new TerminalConfiguration(); configuration.setInputPair(new PipedOutputStream(), new PipedInputStream()); configuration.setOutputPair(new PipedOutputStream(), new PipedInputStream()); configuration.setTerminal(createIOSafeTerminal()); } } private IOSafeTerminal createIOSafeTerminal() { return createRuntimeExceptionConvertingAdapter(createDefaultTerminal()); } private Terminal createDefaultTerminal() { try { return new DefaultTerminalFactory().createTerminal(); } catch (IOException e) { throw new UncheckedIOException(e); } } private void printGreeting() { output.println(format(GREETING, getVersion())); output.println(); } private String getVersion() { return getClass().getPackage().getImplementationVersion(); } private LispInterpreter buildInteractiveInterpreter() { builder.setInput(inputReader, "terminal"); builder.setOutput(output); builder.setErrorOutput(output); builder.setTerminationFunction(this::shutdownTerminal); builder.setErrorTerminationFunction(this::shutdownTerminal); builder.setLanguageFileNames(LANGUAGE_FILE_NAMES); 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.setLanguageFileNames(LANGUAGE_FILE_NAMES); builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN)); builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW)); builder.setErrorOutputDecorator(makeColorDecorator(ANSI_RED)); builder.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE)); return builder.build(); } }