diff --git a/src/environment/RuntimeEnvironment.java b/src/environment/RuntimeEnvironment.java index de0030f..eec0f9f 100644 --- a/src/environment/RuntimeEnvironment.java +++ b/src/environment/RuntimeEnvironment.java @@ -1,6 +1,7 @@ package environment; import java.io.*; +import java.util.function.Function; import error.ErrorManager; @@ -16,6 +17,12 @@ public class RuntimeEnvironment { private InputStream input; private PrintStream output; private PrintStream errorOutput; + + private Function outputDecorator; + private Function valueOutputDecorator; + private Function warningOutputDecorator; + private Function errorOutputDecorator; + private Function criticalOutputDecorator; private Runnable terminationFunction; private Runnable errorTerminationFunction; private ErrorManager errorManager; @@ -50,6 +57,26 @@ public class RuntimeEnvironment { this.errorManager = errorManager; } + public void setOutputDecorator(Function outputDecorator) { + this.outputDecorator = outputDecorator; + } + + public void setValueOutputDecorator(Function valueOutputDecorator) { + this.valueOutputDecorator = valueOutputDecorator; + } + + public void setWarningOutputDecorator(Function warningOutputDecorator) { + this.warningOutputDecorator = warningOutputDecorator; + } + + public void setErrorOutputDecorator(Function errorOutputDecorator) { + this.errorOutputDecorator = errorOutputDecorator; + } + + public void setCriticalOutputDecorator(Function criticalOutputDecorator) { + this.criticalOutputDecorator = criticalOutputDecorator; + } + public String getInputName() { return inputName; } @@ -78,4 +105,24 @@ public class RuntimeEnvironment { return errorManager; } + public String decorateOutput(String output) { + return outputDecorator.apply(output); + } + + public String decorateValueOutput(String valueOutput) { + return valueOutputDecorator.apply(valueOutput); + } + + public String decorateWarningOutput(String warningOutput) { + return warningOutputDecorator.apply(warningOutput); + } + + public String decorateErrorOutput(String errorOutput) { + return errorOutputDecorator.apply(errorOutput); + } + + public String decorateCriticalOutput(String criticalOutput) { + return criticalOutputDecorator.apply(criticalOutput); + } + } diff --git a/src/error/ErrorManager.java b/src/error/ErrorManager.java index 55497d9..4788665 100644 --- a/src/error/ErrorManager.java +++ b/src/error/ErrorManager.java @@ -12,11 +12,6 @@ import environment.RuntimeEnvironment; */ public class ErrorManager { - private static final String ANSI_RESET = "\u001B[0m"; - private static final String ANSI_RED = "\u001B[31m"; - private static final String ANSI_PURPLE = "\u001B[35m"; - private static final String ANSI_YELLOW = "\u001B[33m"; - private RuntimeEnvironment environment; public ErrorManager() { @@ -44,10 +39,10 @@ public class ErrorManager { private String formatMessage(LispException lispException) { Severity severity = lispException.getSeverity(); - String color = severity.getMessageColor(); String prefix = severity.toDisplayString(); + String message = MessageFormat.format("{0}: {1}", prefix, lispException.getMessage()); - return MessageFormat.format("{0}{1}: {2}{3}", color, prefix, lispException.getMessage(), ANSI_RESET); + return severity.decorate(message, environment); } private boolean isCritical(LispException lispException) { @@ -57,8 +52,8 @@ public class ErrorManager { public static enum Severity { WARNING { - public String getMessageColor() { - return ANSI_YELLOW; + public String decorate(String warningOutput, RuntimeEnvironment environment) { + return environment.decorateWarningOutput(warningOutput); } public String toDisplayString() { @@ -67,8 +62,8 @@ public class ErrorManager { }, ERROR { - public String getMessageColor() { - return ANSI_RED; + public String decorate(String errorOutput, RuntimeEnvironment environment) { + return environment.decorateErrorOutput(errorOutput); } public String toDisplayString() { @@ -77,8 +72,8 @@ public class ErrorManager { }, CRITICAL { - public String getMessageColor() { - return ANSI_PURPLE; + public String decorate(String criticalOutput, RuntimeEnvironment environment) { + return environment.decorateCriticalOutput(criticalOutput); } public String toDisplayString() { @@ -86,7 +81,7 @@ public class ErrorManager { } }; - public abstract String getMessageColor(); + public abstract String decorate(String output, RuntimeEnvironment environment); public abstract String toDisplayString(); } diff --git a/src/interpreter/LispInterpreter.java b/src/interpreter/LispInterpreter.java index 40724cc..f3f0121 100644 --- a/src/interpreter/LispInterpreter.java +++ b/src/interpreter/LispInterpreter.java @@ -1,7 +1,5 @@ package interpreter; -import java.text.MessageFormat; - import environment.RuntimeEnvironment; import error.*; import function.builtin.EVAL; @@ -10,9 +8,6 @@ import sexpression.SExpression; public class LispInterpreter { - public static final String ANSI_RESET = "\u001B[0m"; - public static final String ANSI_GREEN = "\u001B[32m"; - protected RuntimeEnvironment environment; protected ErrorManager errorManager; private LispParser parser; @@ -47,7 +42,7 @@ public class LispInterpreter { private void printValueOfNextSExpressionWithException() { SExpression sExpression = parser.getNextSExpression(); - String result = MessageFormat.format("{0}{1}{2}", ANSI_GREEN, EVAL.eval(sExpression), ANSI_RESET); + String result = environment.decorateValueOutput(String.valueOf(EVAL.eval(sExpression))); erasePrompt(); environment.getOutput().println(result); diff --git a/src/interpreter/LispInterpreterBuilder.java b/src/interpreter/LispInterpreterBuilder.java index 98c5b6b..cad2659 100644 --- a/src/interpreter/LispInterpreterBuilder.java +++ b/src/interpreter/LispInterpreterBuilder.java @@ -1,6 +1,7 @@ package interpreter; import java.io.*; +import java.util.function.Function; public interface LispInterpreterBuilder { @@ -18,6 +19,16 @@ public interface LispInterpreterBuilder { void useFile(String fileName); + void setOutputDecorator(Function outputDecorator); + + void setValueOutputDecorator(Function valueOutputDecorator); + + void setWarningOutputDecorator(Function warningOutputDecorator); + + void setErrorOutputDecorator(Function errorOutputDecorator); + + void setCriticalOutputDecorator(Function criticalOutputDecorator); + LispInterpreter build(); } diff --git a/src/interpreter/LispInterpreterBuilderImpl.java b/src/interpreter/LispInterpreterBuilderImpl.java index cc8842b..8cf7e17 100644 --- a/src/interpreter/LispInterpreterBuilderImpl.java +++ b/src/interpreter/LispInterpreterBuilderImpl.java @@ -1,6 +1,7 @@ package interpreter; import java.io.*; +import java.util.function.Function; import environment.RuntimeEnvironment; import error.*; @@ -19,6 +20,11 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { private PrintStream errorOutputStream; private Runnable terminationFunction; private Runnable errorTerminationFunction; + private Function outputDecorator; + private Function valueOutputDecorator; + private Function warningOutputDecorator; + private Function errorOutputDecorator; + private Function criticalOutputDecorator; private RuntimeEnvironment environment; private boolean isInteractive; private boolean isBuilt; @@ -28,6 +34,11 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { this.inputName = ""; this.isInteractive = true; this.isBuilt = false; + this.outputDecorator = s -> s; + this.valueOutputDecorator = s -> s; + this.warningOutputDecorator = s -> s; + this.errorOutputDecorator = s -> s; + this.criticalOutputDecorator = s -> s; } @Override @@ -67,6 +78,33 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { this.isInteractive = false; } + @Override + public void setOutputDecorator(Function decorator) { + this.outputDecorator = decorator; + } + + @Override + public void setValueOutputDecorator(Function decorator) { + this.valueOutputDecorator = decorator; + } + + @Override + public void setWarningOutputDecorator(Function decorator) { + this.warningOutputDecorator = decorator; + + } + + @Override + public void setErrorOutputDecorator(Function decorator) { + this.errorOutputDecorator = decorator; + + } + + @Override + public void setCriticalOutputDecorator(Function decorator) { + this.criticalOutputDecorator = decorator; + } + @Override public LispInterpreter build() { if (!isBuilt) @@ -91,6 +129,11 @@ public class LispInterpreterBuilderImpl implements LispInterpreterBuilder { environment.setTerminationFunction(terminationFunction); environment.setErrorTerminationFunction(errorTerminationFunction); environment.setErrorManager(errorManager); + environment.setOutputDecorator(outputDecorator); + environment.setValueOutputDecorator(valueOutputDecorator); + environment.setWarningOutputDecorator(warningOutputDecorator); + environment.setErrorOutputDecorator(errorOutputDecorator); + environment.setCriticalOutputDecorator(criticalOutputDecorator); configureInput(errorManager); } diff --git a/src/main/LispMain.java b/src/main/LispMain.java index a91e510..21d03f0 100644 --- a/src/main/LispMain.java +++ b/src/main/LispMain.java @@ -1,9 +1,17 @@ package main; +import java.util.function.Function; + import interpreter.*; public class LispMain { + 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"; + private LispMain() {} public static void main(String[] args) { @@ -13,11 +21,15 @@ public class LispMain { private static LispInterpreter buildInterpreter(String[] args) { LispInterpreterBuilder builder = LispInterpreterBuilderImpl.getInstance(); + configureInput(args, builder); builder.setOutput(System.out); builder.setErrorOutput(System.err); builder.setTerminationFunction(() -> System.exit(0)); builder.setErrorTerminationFunction(() -> System.exit(1)); - configureInput(args, builder); + builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN)); + builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW)); + builder.setErrorOutputDecorator(makeColorDecorator(ANSI_RED)); + builder.setCriticalOutputDecorator(makeColorDecorator(ANSI_PURPLE)); return builder.build(); } @@ -31,4 +43,14 @@ public class LispMain { } } + private static Function makeColorDecorator(String color) { + return new Function() { + + @Override + public String apply(String s) { + return color + s + ANSI_RESET; + } + }; + } + } diff --git a/test/error/ErrorManagerTester.java b/test/error/ErrorManagerTester.java index 36929f3..5fa5519 100644 --- a/test/error/ErrorManagerTester.java +++ b/test/error/ErrorManagerTester.java @@ -29,6 +29,9 @@ public class ErrorManagerTester { environment.setErrorTerminationFunction(() -> indicatorSet.add(TERMINATED)); environment.setErrorOutput(new PrintStream(errorOutputStream)); environment.setOutput(new PrintStream(outputStream)); + environment.setWarningOutputDecorator(s -> s); + environment.setErrorOutputDecorator(s -> s); + environment.setCriticalOutputDecorator(s -> s); return new ErrorManager(); } diff --git a/test/function/builtin/LOADTester.java b/test/function/builtin/LOADTester.java index 4dfff24..cb4b6dc 100644 --- a/test/function/builtin/LOADTester.java +++ b/test/function/builtin/LOADTester.java @@ -45,6 +45,9 @@ public class LOADTester { environment.setOutput(new PrintStream(outputStream)); environment.setErrorOutput(new PrintStream(errorOutputStream)); environment.setErrorManager(new ErrorManager()); + environment.setOutputDecorator(s -> s); + environment.setWarningOutputDecorator(s -> s); + environment.setErrorOutputDecorator(s -> s); } @Test diff --git a/test/function/builtin/special/DEFUNTester.java b/test/function/builtin/special/DEFUNTester.java index c3fae13..257ce08 100644 --- a/test/function/builtin/special/DEFUNTester.java +++ b/test/function/builtin/special/DEFUNTester.java @@ -31,6 +31,7 @@ public class DEFUNTester { environment.setOutput(new PrintStream(outputStream)); environment.setErrorManager(new ErrorManager()); + environment.setWarningOutputDecorator(s -> s); FunctionTable.reset(); }