Skip to content

Commit

Permalink
GroovyEngine & DefaultPrinter: add syntaxHighlighter cache
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Dec 18, 2021
1 parent e9cbb19 commit 652d7a1
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 25 deletions.
5 changes: 5 additions & 0 deletions console/src/main/java/org/jline/console/Printer.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,9 @@ default Exception prntCommand(CommandInput input) {
return null;
}

/**
* Clear printer syntax highlighter cache
*/
boolean refresh();

}
17 changes: 17 additions & 0 deletions console/src/main/java/org/jline/console/impl/DefaultPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class DefaultPrinter extends JlineCommandRegistry implements Printer {
protected static final int PRNT_MAX_DEPTH = 1;
protected static final int PRNT_INDENTION = 4;
private static final int NANORC_MAX_STRING_LENGTH = 400;
private static final int HIGHLIGHTER_CACHE_SIZE = 5;

private Map<Class<?>, Function<Object, Map<String,Object>>> objectToMap = new HashMap<>();
private Map<Class<?>, Function<Object, String>> objectToString = new HashMap<>();
Expand All @@ -55,6 +56,12 @@ public class DefaultPrinter extends JlineCommandRegistry implements Printer {
private final ScriptEngine engine;
private final ConfigurationPath configPath;
private StyleResolver prntStyle;
private final LinkedHashMap<String, SyntaxHighlighter> highlighters = new LinkedHashMap<String,
SyntaxHighlighter>(HIGHLIGHTER_CACHE_SIZE + 1, .75F, false) {
protected boolean removeEldestEntry(Map.Entry<String, SyntaxHighlighter> eldest) {
return size() > HIGHLIGHTER_CACHE_SIZE;
}
};

public DefaultPrinter(ConfigurationPath configPath) {
this(null, configPath);
Expand All @@ -81,6 +88,12 @@ public void println(Map<String, Object> optionsIn, Object object) {
internalPrintln(options, object);
}

@Override
public boolean refresh() {
highlighters.clear();
return true;
}

public String[] appendUsage(String[] customUsage) {
final String[] usage = {
"prnt - print object",
Expand Down Expand Up @@ -385,8 +398,11 @@ private SyntaxHighlighter valueHighlighter(String style) {
SyntaxHighlighter out;
if (style == null || style.isEmpty()) {
out = null;
} else if (highlighters.containsKey(style)) {
out = highlighters.get(style);
} else if (style.matches("[a-z]+:.*")) {
out = SyntaxHighlighter.build(style);
highlighters.put(style, out);
} else {
Path nanorc = configPath != null ? configPath.getConfig(DEFAULT_NANORC_FILE) : null;
if (engine != null && engine.hasVariable(VAR_NANORC)) {
Expand All @@ -396,6 +412,7 @@ private SyntaxHighlighter valueHighlighter(String style) {
nanorc = Paths.get("/etc/nanorc");
}
out = SyntaxHighlighter.build(nanorc, style);
highlighters.put(style, out);
}
return out;
}
Expand Down
57 changes: 32 additions & 25 deletions groovy/src/main/java/org/jline/script/GroovyEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public enum Format {JSON, GROOVY, NONE}
public static final String SYNTHETIC_METHODS_COMPLETION = "syntheticMethodsCompletion";

private static final String VAR_GROOVY_OPTIONS = "GROOVY_OPTIONS";
private static final String DEFAULT_NANORC_SYNTAX = "classpath:/org/jline/groovy/java.nanorc";
private static final String REGEX_SYSTEM_VAR = "[A-Z]+[A-Z_]*";
private static final String REGEX_VAR = "[a-zA-Z_]+[a-zA-Z0-9_]*";
private static final Pattern PATTERN_FUNCTION_DEF = Pattern.compile(
Expand Down Expand Up @@ -100,6 +101,8 @@ public enum Format {JSON, GROOVY, NONE}
private final Map<String,Class<?>> nameClass;
private Cloner objectCloner = new ObjectCloner();
protected final EngineClassLoader classLoader;
private SyntaxHighlighter syntaxHighlighter;
private String syntaxHighlighterStyle;

public interface Cloner {
Object clone(Object obj);
Expand Down Expand Up @@ -530,6 +533,28 @@ protected static <T>T groovyOption(Map<String,Object> options, String option, T
return out;
}

public boolean refresh() {
syntaxHighlighter = null;
return true;
}

protected SyntaxHighlighter getSyntaxHighlighter() {
String syntax = groovyOption(NANORC_SYNTAX, DEFAULT_NANORC_SYNTAX);
if (syntaxHighlighter == null || syntax == null || !syntax.equals(syntaxHighlighterStyle)) {
String nanorcString = (String) get(VAR_NANORC);
Path nanorc = nanorcString != null ? Paths.get(nanorcString) : null;
if (syntax == null) {
syntaxHighlighter = SyntaxHighlighter.build("");
} else if (syntax.contains(":") || nanorc == null) {
syntaxHighlighter = SyntaxHighlighter.build(syntax);
} else {
syntaxHighlighter = SyntaxHighlighter.build(nanorc, syntax);
}
syntaxHighlighterStyle = syntax;
}
return syntaxHighlighter;
}

private Completer compileCompleter() {
List<Completer> completers = new ArrayList<>();
completers.add(new ArgumentCompleter(new StringsCompleter("def"), new StringsCompleter(methods::keySet)
Expand Down Expand Up @@ -1320,7 +1345,6 @@ private static class Inspector {
static final Pattern PATTERN_FUNCTION = Pattern.compile("\\s*def\\s+\\w+\\s*\\((.*?)\\).*");
static final Pattern PATTERN_CLOSURE = Pattern.compile(".*\\{(.*?)->.*");
static final Pattern PATTERN_TYPE_VAR = Pattern.compile("(\\w+)\\s+(\\w+)");
static final String DEFAULT_NANORC_SYNTAX = "classpath:/org/jline/groovy/java.nanorc";
static final String DEFAULT_GROOVY_COLORS = "ti=1;34:me=31";

private final GroovyShell shell;
Expand All @@ -1336,21 +1360,20 @@ private static class Inspector {
private final AccessRules access;
private String[] equationLines;
private int cuttedSize;
private final String nanorcSyntax;
private final String groovyColors;
private Object involvedObject = null;
private final Path nanorc;
private final SyntaxHighlighter syntaxHighlighter;

public Inspector(GroovyEngine groovyEngine) {
this.imports = groovyEngine.imports;
this.nameClass = groovyEngine.nameClass;
this.canonicalNames = groovyEngine.groovyOption(CANONICAL_NAMES, false);
this.nanorcSyntax = groovyEngine.groovyOption(NANORC_SYNTAX, DEFAULT_NANORC_SYNTAX);
this.noSyntaxCheck = groovyEngine.groovyOption(NO_SYNTAX_CHECK, false);
this.restrictedCompletion = groovyEngine.groovyOption(RESTRICTED_COMPLETION, false);
this.metaMethodsCompletion = groovyEngine.groovyOption(META_METHODS_COMPLETION, false);
this.syntheticCompletion = groovyEngine.groovyOption(SYNTHETIC_METHODS_COMPLETION, false);
this.access = new AccessRules(groovyEngine.groovyOptions());
this.syntaxHighlighter = groovyEngine.getSyntaxHighlighter();
String gc = groovyEngine.groovyOption(GROOVY_COLORS, null);
groovyColors = gc != null && Styles.isStylePattern(gc) ? gc : DEFAULT_GROOVY_COLORS;
groovyEngine.getObjectCloner().markCache();
Expand All @@ -1374,8 +1397,6 @@ public Inspector(GroovyEngine groovyEngine) {
sharedData.setVariable(entry.getKey(), execute("{" + m.group(1) + "->" + m.group(2) + "}"));
}
}
String nanorcString = (String)groovyEngine.get(VAR_NANORC);
nanorc = nanorcString != null ? Paths.get(nanorcString) : null;
}

public Object getInvolvedObject() {
Expand Down Expand Up @@ -1603,18 +1624,6 @@ private String accessModifier(int modifier, boolean all) {
return out;
}

private SyntaxHighlighter buildHighlighter(String syntax) {
SyntaxHighlighter out;
if (syntax == null) {
out = SyntaxHighlighter.build("");
} else if (syntax.contains(":") || nanorc == null) {
out = SyntaxHighlighter.build(syntax);
} else {
out = SyntaxHighlighter.build(nanorc, syntax);
}
return out;
}

private CmdDesc methodDescription(CmdLine line) {
CmdDesc out = new CmdDesc();
List<String> args = line.getArgs();
Expand Down Expand Up @@ -1647,8 +1656,7 @@ && new Brackets(args.get(args.size() - 1)).openRound()) {
}
List<AttributedString> mainDesc = new ArrayList<>();
if (clazz != null) {
SyntaxHighlighter java = buildHighlighter(nanorcSyntax);
mainDesc.add(java.highlight(clazz.toString()));
mainDesc.add(syntaxHighlighter.highlight(clazz.toString()));
if (constructor) {
for (Constructor<?> m : access.allConstructors ? clazz.getDeclaredConstructors()
: clazz.getConstructors()) {
Expand Down Expand Up @@ -1680,7 +1688,7 @@ && new Brackets(args.get(args.size() - 1)).openRound()) {
sb.append(canonicalNames ? e.getCanonicalName() : e.getSimpleName());
first = false;
}
mainDesc.add(java.highlight(trimMethodDescription(sb)));
mainDesc.add(syntaxHighlighter.highlight(trimMethodDescription(sb)));
}
} else {
List<String> addedMethods = new ArrayList<>();
Expand All @@ -1707,7 +1715,7 @@ && new Brackets(args.get(args.size() - 1)).openRound()) {
sb.append(")");
if (!addedMethods.contains(sb.toString())) {
addedMethods.add(sb.toString());
mainDesc.add(java.highlight(trimMethodDescription(sb)));
mainDesc.add(syntaxHighlighter.highlight(trimMethodDescription(sb)));
}
}
}
Expand Down Expand Up @@ -1748,7 +1756,7 @@ && new Brackets(args.get(args.size() - 1)).openRound()) {
}
if (!addedMethods.contains(sb.toString())) {
addedMethods.add(sb.toString());
mainDesc.add(java.highlight(trimMethodDescription(sb)));
mainDesc.add(syntaxHighlighter.highlight(trimMethodDescription(sb)));
}
}
}
Expand Down Expand Up @@ -1855,10 +1863,9 @@ private CmdDesc checkSyntax(CmdLine line) {

private List<AttributedString> doExceptionMessage(Exception exception) {
List<AttributedString> out = new ArrayList<>();
SyntaxHighlighter java = buildHighlighter(nanorcSyntax);
StyleResolver resolver = Styles.style(groovyColors);
Pattern header = Pattern.compile("^[a-zA-Z() ]{3,}:(\\s+|$)");
out.add(java.highlight(exception.getClass().getCanonicalName()));
out.add(syntaxHighlighter.highlight(exception.getClass().getCanonicalName()));
if (exception.getMessage() != null) {
for (String s: exception.getMessage().split("\\r?\\n")) {
if (s.trim().length() == 0) {
Expand Down

0 comments on commit 652d7a1

Please sign in to comment.