Skip to content

Commit

Permalink
Groovy: customizable colors
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Jun 26, 2020
1 parent 458ec40 commit 8e979e1
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 27 deletions.
4 changes: 4 additions & 0 deletions builtins/src/main/java/org/jline/builtins/Styles.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public static StyleResolver prntStyle() {
return style(PRNT_COLORS, DEFAULT_PRNT_COLORS);
}

public static boolean isAnsiStylePattern(String style) {
return style.matches(ANSI_STYLE_PATTERN);
}

private static StyleResolver style(String name, String defStyle) {
String style = consoleOption(name);
if (style == null) {
Expand Down
5 changes: 3 additions & 2 deletions groovy/src/main/java/org/jline/script/GroovyCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

public class GroovyCommand extends AbstractCommandRegistry implements CommandRegistry {
public enum Command {INSPECT, CONSOLE, GRAB}
private static final String DEFAULT_NANORC_VALUE = "classpath:/org/jline/groovy/gron.nanorc";
private GroovyEngine engine;
private Printer printer;
private final Map<Command,CmdDesc> commandDescs = new HashMap<>();
Expand Down Expand Up @@ -116,7 +117,7 @@ public Object grab(CommandInput input) {
options.put(Printer.SKIP_DEFAULT_OPTIONS, true);
options.put(Printer.MAX_DEPTH, 1);
options.put(Printer.INDENTION, 4);
options.put(Printer.VALUE_STYLE, "classpath:/org/jline/groovy/gron.nanorc");
options.put(Printer.VALUE_STYLE, engine.groovyOption(GroovyEngine.NANORC_VALUE, DEFAULT_NANORC_VALUE));
printer.println(options, resp);
} else {
int artifactId = 0;
Expand Down Expand Up @@ -204,7 +205,7 @@ public Object inspect(CommandInput input) {
out = inspector.metaMethods();
} else if (option.equals("-i") || option.equals("--info")) {
out = inspector.properties();
options.put(Printer.VALUE_STYLE, "classpath:/org/jline/groovy/gron.nanorc");
options.put(Printer.VALUE_STYLE, engine.groovyOption(GroovyEngine.NANORC_VALUE, DEFAULT_NANORC_VALUE));
} else if (consoleUi && (option.equals("-g") || option.equals("--gui"))) {
ObjectBrowser.inspect(obj);
} else {
Expand Down
64 changes: 39 additions & 25 deletions groovy/src/main/java/org/jline/script/GroovyEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
import org.codehaus.groovy.syntax.SyntaxException;
import org.jline.builtins.Nano.SyntaxHighlighter;
import org.jline.builtins.Styles;
import org.jline.console.CmdDesc;
import org.jline.console.CmdLine;
import org.jline.console.ScriptEngine;
Expand All @@ -37,9 +39,9 @@
import org.jline.reader.impl.completer.NullCompleter;
import org.jline.reader.impl.completer.StringsCompleter;
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStyle;
import org.jline.utils.Log;
import org.jline.utils.OSUtils;
import org.jline.utils.StyleResolver;

import groovy.lang.Binding;
import groovy.lang.Closure;
Expand All @@ -56,6 +58,9 @@
public class GroovyEngine implements ScriptEngine {
public enum Format {JSON, GROOVY, NONE};
public static final String CANONICAL_NAMES = "canonicalNames";
public static final String NANORC_SYNTAX = "nanorcSyntax";
public static final String NANORC_VALUE = "nanorcValue";
public static final String GROOVY_COLORS = "groovyColors";

private static final String VAR_GROOVY_OPTIONS = "GROOVY_OPTIONS";
private static final String REGEX_SYSTEM_VAR = "[A-Z]+[A-Z_]*";
Expand Down Expand Up @@ -367,7 +372,7 @@ private Map<String,Object> groovyOptions() {
}

@SuppressWarnings("unchecked")
private <T>T groovyOption(String option, T defval) {
protected <T>T groovyOption(String option, T defval) {
T out = defval;
try {
out = (T) groovyOptions().getOrDefault(option, defval);
Expand Down Expand Up @@ -787,19 +792,27 @@ private static class Inspector {
static final Pattern PATTERN_FOR = Pattern.compile("^for\\s*\\((.*?);.*");
static final Pattern PATTERN_FUNCTION_BODY = Pattern.compile("^\\s*\\(([a-zA-Z0-9_ ,]*)\\)\\s*\\{(.*)?\\}(|\n)$"
, Pattern.DOTALL);
static final String DEFAULT_NANORC_SYNTAX = "classpath:/org/jline/groovy/java.nanorc";
static final String DEFAULT_GROOVY_COLORS = "ti=1;34:me=31";

private GroovyShell shell;
protected Binding sharedData = new Binding();
private Map<String,String> imports = new HashMap<>();
private Map<String,Class<?>> nameClass = new HashMap<>();
PrintStream nullstream;
boolean canonicalNames = false;
String[] equationLines;
int cuttedSize;
private PrintStream nullstream;
private boolean canonicalNames = false;
private String[] equationLines;
private int cuttedSize;
private String nanorcSyntax;
private String groovyColors;

public Inspector(GroovyEngine groovyEngine) {
this.imports = groovyEngine.imports;
this.nameClass = groovyEngine.nameClass;
this.canonicalNames = groovyEngine.groovyOption(CANONICAL_NAMES, canonicalNames);
this.nanorcSyntax = groovyEngine.groovyOption(NANORC_SYNTAX, DEFAULT_NANORC_SYNTAX);
String gc = groovyEngine.groovyOption(GROOVY_COLORS, null);
groovyColors = gc != null && Styles.isAnsiStylePattern(gc) ? gc : DEFAULT_GROOVY_COLORS;
for (Map.Entry<String, Object> entry : groovyEngine.find().entrySet()) {
Object obj = groovyEngine.getObjectCloner().clone(entry.getValue());
sharedData.setVariable(entry.getKey(), obj);
Expand Down Expand Up @@ -962,7 +975,7 @@ private CmdDesc methodDescription(CmdLine line) throws Exception {
}
List<AttributedString> mainDesc = new ArrayList<>();
if (clazz != null) {
SyntaxHighlighter java = SyntaxHighlighter.build("classpath:/org/jline/groovy/java.nanorc");
SyntaxHighlighter java = SyntaxHighlighter.build(nanorcSyntax);
mainDesc.add(java.highlight(clazz.toString()));
if (constructor) {
for (Constructor<?> m : clazz.getConstructors()) {
Expand Down Expand Up @@ -1097,20 +1110,13 @@ private CmdDesc checkSyntax(CmdLine line) {
if (o instanceof SyntaxErrorMessage) {
SyntaxErrorMessage sem = (SyntaxErrorMessage)o;
out.setErrorIndex(errorIndex(e.getMessage(), sem.getCause()));
} else {
mainDesc.add(new AttributedString("Error: " + o.getClass().getCanonicalName()
, AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW)));
}
}
} }
}
if (e.getErrorCollector().getWarnings() != null) {
for (Object o: e.getErrorCollector().getWarnings()) {
if (o instanceof SyntaxErrorMessage) {
SyntaxErrorMessage sem = (SyntaxErrorMessage)o;
out.setErrorIndex(errorIndex(e.getMessage(), sem.getCause()));
} else {
mainDesc.add(new AttributedString("Warning: " + o.getClass().getCanonicalName()
, AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW)));
}
}
}
Expand All @@ -1123,40 +1129,41 @@ private CmdDesc checkSyntax(CmdLine line) {
return out;
}

private static List<AttributedString> doExceptionMessage(Exception exception) {
private List<AttributedString> doExceptionMessage(Exception exception) {
List<AttributedString> out = new ArrayList<>();
SyntaxHighlighter java = SyntaxHighlighter.build(nanorcSyntax);
StyleResolver resolver = style(groovyColors);
Pattern header = Pattern.compile("^[a-zA-Z() ]{3,}:(\\s+|$)");
out.add(new AttributedString(exception.getClass().getCanonicalName(), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)));
out.add(java.highlight(exception.getClass().getCanonicalName()));
if (exception.getMessage() != null) {
for (String s: exception.getMessage().split("\\r?\\n")) {
if (s.length() > 80) {
boolean doHeader = true;
int start = 0;
for (int i = 80; i < s.length(); i++) {
if ((s.charAt(i) == ' ' && i - start > 80 ) || i - start > 100) {
AttributedString as = new AttributedString(s.substring(start, i), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
AttributedString as = new AttributedString(s.substring(start, i), resolver.resolve(".me"));
if (doHeader) {
as = as.styleMatches(header, AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE));
as = as.styleMatches(header, resolver.resolve(".ti"));
doHeader = false;
}
out.add(as);
start = i;
if (s.length() - start < 80) {
out.add(new AttributedString(s.substring(start), AttributedStyle.DEFAULT.foreground(AttributedStyle.RED)));
out.add(new AttributedString(s.substring(start), resolver.resolve(".me")));
break;
}
}
}
if (doHeader) {
AttributedString as = new AttributedString(s, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
as = as.styleMatches(header, AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE));
AttributedString as = new AttributedString(s, resolver.resolve(".me"));
as = as.styleMatches(header, resolver.resolve(".ti"));
out.add(as);
}
} else {
AttributedString as = new AttributedString(s, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
as = as.styleMatches(header, AttributedStyle.DEFAULT.foreground(AttributedStyle.BLUE));
AttributedString as = new AttributedString(s, resolver.resolve(".me"));
as = as.styleMatches(header, resolver.resolve(".ti"));
out.add(as);

}
}
}
Expand Down Expand Up @@ -1186,6 +1193,13 @@ private int errorIndex(String message, SyntaxException se) {
return out;
}

private static StyleResolver style(String style) {
Map<String, String> colors = Arrays.stream(style.split(":"))
.collect(Collectors.toMap(s -> s.substring(0, s.indexOf('=')),
s -> s.substring(s.indexOf('=') + 1)));
return new StyleResolver(colors::get);
}

}

private static class ObjectCloner implements Cloner {
Expand Down

0 comments on commit 8e979e1

Please sign in to comment.