Improve syntax highlighting internals
This commit is contained in:
@ -288,7 +288,7 @@ public class DesignerWindowPresenter {
|
||||
}
|
||||
});
|
||||
|
||||
view.getXpathExpressionArea().setSyntaxHighlightingEnabled(XPathSyntaxHighlighter.INSTANCE);
|
||||
view.getXpathExpressionArea().setSyntaxHighlightingEnabled(new XPathSyntaxHighlighter());
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,22 +20,22 @@ import net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.XmlS
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public enum AvailableSyntaxHighlighters {
|
||||
JAVA("java", JavaSyntaxHighlighter.INSTANCE),
|
||||
APEX("apex", ApexSyntaxHighlighter.INSTANCE),
|
||||
XML("xml", XmlSyntaxHighlighter.INSTANCE),
|
||||
XSL("xsl", XmlSyntaxHighlighter.INSTANCE),
|
||||
WSDL("wsdl", XmlSyntaxHighlighter.INSTANCE),
|
||||
POM("pom", XmlSyntaxHighlighter.INSTANCE),
|
||||
XPATH("xpath", XPathSyntaxHighlighter.INSTANCE);
|
||||
JAVA("java", new JavaSyntaxHighlighter()),
|
||||
APEX("apex", new ApexSyntaxHighlighter()),
|
||||
XML("xml", new XmlSyntaxHighlighter()),
|
||||
XSL("xsl", new XmlSyntaxHighlighter()),
|
||||
WSDL("wsdl", new XmlSyntaxHighlighter()),
|
||||
POM("pom", new XmlSyntaxHighlighter()),
|
||||
XPATH("xpath", new XPathSyntaxHighlighter());
|
||||
|
||||
|
||||
private final String language;
|
||||
private final SyntaxHighlighter computer;
|
||||
private final SyntaxHighlighter engine;
|
||||
|
||||
|
||||
AvailableSyntaxHighlighters(String languageTerseName, SyntaxHighlighter computer) {
|
||||
AvailableSyntaxHighlighters(String languageTerseName, SyntaxHighlighter engine) {
|
||||
this.language = languageTerseName;
|
||||
this.computer = computer;
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ public enum AvailableSyntaxHighlighters {
|
||||
.filter(e -> e.language.equals(language.getTerseName()))
|
||||
.findFirst();
|
||||
if (found.isPresent()) {
|
||||
return found.get().computer;
|
||||
return found.get().engine;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -18,24 +18,31 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SpanBound;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SyntaxHighlighter;
|
||||
|
||||
import javafx.concurrent.Task;
|
||||
|
||||
/**
|
||||
* Language specific engine for syntax highlighting.
|
||||
* Language-specific engine for syntax highlighting. The highlighter assigns classes to
|
||||
*
|
||||
* @author Clément Fournier
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
|
||||
private final Pattern pattern;
|
||||
private final Map<String, String> namesToCssClass;
|
||||
private final RegexHighlightGrammar grammar;
|
||||
private final String languageName;
|
||||
|
||||
|
||||
protected SimpleRegexSyntaxHighlighter(String languageName, Pattern pattern, Map<String, String> namesToCssClass) {
|
||||
this.pattern = pattern;
|
||||
this.namesToCssClass = namesToCssClass;
|
||||
/**
|
||||
* Creates a highlighter given a name for the language and a "regex grammar".
|
||||
*
|
||||
* @param languageName The language name
|
||||
* @param grammar The grammar
|
||||
*/
|
||||
protected SimpleRegexSyntaxHighlighter(String languageName, final RegexHighlightGrammar grammar) {
|
||||
this.grammar = grammar;
|
||||
this.languageName = languageName;
|
||||
}
|
||||
|
||||
@ -57,12 +64,12 @@ public class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
|
||||
private List<SpanBound> computeHighlighting(String text) {
|
||||
List<SpanBound> updated = new ArrayList<>();
|
||||
Matcher matcher = pattern.matcher(text);
|
||||
Matcher matcher = grammar.getPattern().matcher(text);
|
||||
int lastKwEnd = 0;
|
||||
|
||||
try {
|
||||
while (matcher.find()) {
|
||||
String styleClass = getCssClassOfLastGroup(matcher);
|
||||
String styleClass = grammar.getCssClassOfLastGroup(matcher);
|
||||
updated.add(new SpanBound(lastKwEnd, Collections.singleton(languageName), true));
|
||||
updated.add(new SpanBound(matcher.start(), Collections.emptySet(), false));
|
||||
updated.add(new SpanBound(matcher.start(), new HashSet<>(Arrays.asList(languageName, styleClass)), true));
|
||||
@ -76,37 +83,32 @@ public class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
}
|
||||
|
||||
|
||||
private String getCssClassOfLastGroup(Matcher matcher) {
|
||||
for (Entry<String, String> groupToClass : namesToCssClass.entrySet()) {
|
||||
if (matcher.group(groupToClass.getKey()) != null) {
|
||||
return groupToClass.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final String getLanguageTerseName() {
|
||||
return languageName;
|
||||
}
|
||||
|
||||
|
||||
public static RegexHighlighterBuilder builder(String languageName, String cssClass, String pattern) {
|
||||
return new RegexHighlighterBuilder(languageName, cssClass, pattern);
|
||||
/**
|
||||
* Gets a builder to make a grammar to build a highlighter.
|
||||
*
|
||||
* @param cssClass The css class of the first pattern
|
||||
* @param pattern The first pattern
|
||||
*
|
||||
* @return A builder
|
||||
*/
|
||||
protected static RegexHighlightGrammarBuilder grammarBuilder(String cssClass, String pattern) {
|
||||
return new RegexHighlightGrammarBuilder(cssClass, pattern);
|
||||
}
|
||||
|
||||
|
||||
public static class RegexHighlighterBuilder {
|
||||
protected static class RegexHighlightGrammarBuilder {
|
||||
|
||||
private final String language;
|
||||
private Map<String, String> regexToClasses = new LinkedHashMap<>();
|
||||
|
||||
|
||||
RegexHighlighterBuilder(String languageName, String cssClass, String regex) {
|
||||
RegexHighlightGrammarBuilder(String cssClass, String regex) {
|
||||
or(cssClass, regex);
|
||||
language = languageName;
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +120,7 @@ public class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
*
|
||||
* @return The same builder
|
||||
*/
|
||||
public RegexHighlighterBuilder or(String cssClass, String regex) {
|
||||
public RegexHighlightGrammarBuilder or(String cssClass, String regex) {
|
||||
regexToClasses.put(regex, cssClass);
|
||||
return this;
|
||||
}
|
||||
@ -135,7 +137,6 @@ public class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
|
||||
|
||||
private String getRegexString() {
|
||||
|
||||
return String.join("|",
|
||||
regexToClasses.entrySet()
|
||||
.stream()
|
||||
@ -144,24 +145,27 @@ public class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
}
|
||||
|
||||
|
||||
public SyntaxHighlighter create() {
|
||||
return new SimpleRegexSyntaxHighlighter(language,
|
||||
Pattern.compile(getRegexString()),
|
||||
getGroupNamesToCssClasses());
|
||||
/**
|
||||
* Builds the grammar.
|
||||
*
|
||||
* @return A new grammar
|
||||
*/
|
||||
public RegexHighlightGrammar create() {
|
||||
return new RegexHighlightGrammar(Pattern.compile(getRegexString()),
|
||||
getGroupNamesToCssClasses());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the syntax highlighter.
|
||||
* Builds the grammar.
|
||||
*
|
||||
* @param flags Regex compilation flags
|
||||
*
|
||||
* @return A new highlighter
|
||||
* @return A new grammar
|
||||
*/
|
||||
public SyntaxHighlighter create(int flags) {
|
||||
return new SimpleRegexSyntaxHighlighter(language,
|
||||
Pattern.compile(getRegexString(), flags),
|
||||
getGroupNamesToCssClasses());
|
||||
public RegexHighlightGrammar create(int flags) {
|
||||
return new RegexHighlightGrammar(Pattern.compile(getRegexString(), flags),
|
||||
getGroupNamesToCssClasses());
|
||||
}
|
||||
|
||||
|
||||
@ -176,4 +180,48 @@ public class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the tokens of the language that should be colored with a regular expression.
|
||||
*/
|
||||
protected static class RegexHighlightGrammar {
|
||||
|
||||
private final Pattern pattern;
|
||||
private final Map<String, String> namesToCssClass;
|
||||
|
||||
|
||||
public RegexHighlightGrammar(Pattern pattern, Map<String, String> namesToCssClass) {
|
||||
this.pattern = pattern;
|
||||
this.namesToCssClass = namesToCssClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pattern describing the tokens.
|
||||
*
|
||||
* @return The pattern
|
||||
*/
|
||||
public Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the css class that should be applied to the last matched group (token), according to this grammar.
|
||||
*
|
||||
* @param matcher The matcher in which to look
|
||||
*
|
||||
* @return The name of the css class corresponding to the token
|
||||
*/
|
||||
public String getCssClassOfLastGroup(Matcher matcher) {
|
||||
for (Entry<String, String> groupToClass : namesToCssClass.entrySet()) {
|
||||
if (matcher.group(groupToClass.getKey()) != null) {
|
||||
return groupToClass.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,11 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SimpleRegexSyntaxHighlighter;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SyntaxHighlighter;
|
||||
|
||||
/**
|
||||
* Syntax highlighter for Apex.
|
||||
@ -46,9 +44,8 @@ public class ApexSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
};
|
||||
|
||||
|
||||
public static final SyntaxHighlighter INSTANCE
|
||||
= builder("apex",
|
||||
"single-line-comment", "//[^\r\n]*")
|
||||
public static final RegexHighlightGrammar GRAMMAR
|
||||
= grammarBuilder("single-line-comment", "//[^\r\n]*")
|
||||
.or("multi-line-comment", "/\\*.*?\\*/")
|
||||
.or("keyword", "\\b(" + String.join("|", KEYWORDS) + ")\\b")
|
||||
.or("paren", "[()]")
|
||||
@ -59,8 +56,8 @@ public class ApexSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
.create(Pattern.DOTALL);
|
||||
|
||||
|
||||
private ApexSyntaxHighlighter(String languageName, Pattern pattern, Map<String, String> namesToCssClass) {
|
||||
super(languageName, pattern, namesToCssClass);
|
||||
public ApexSyntaxHighlighter() {
|
||||
super("apex", GRAMMAR);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,11 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SimpleRegexSyntaxHighlighter;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SyntaxHighlighter;
|
||||
|
||||
/**
|
||||
* Syntax highlighter for Java.
|
||||
@ -33,9 +31,8 @@ public class JavaSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
};
|
||||
|
||||
|
||||
public static final SyntaxHighlighter INSTANCE
|
||||
= builder("java",
|
||||
"single-line-comment", "//[^\n]*")
|
||||
private static final RegexHighlightGrammar GRAMMAR
|
||||
= grammarBuilder("single-line-comment", "//[^\n]*")
|
||||
.or("multi-line-comment", "/\\*.*?\\*/")
|
||||
.or("annotation", "@[\\w]+")
|
||||
.or("paren", "[()]")
|
||||
@ -49,8 +46,8 @@ public class JavaSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
.create(Pattern.DOTALL);
|
||||
|
||||
|
||||
private JavaSyntaxHighlighter(String languageName, Pattern pattern, Map<String, String> namesToCssClass) {
|
||||
super(languageName, pattern, namesToCssClass);
|
||||
public JavaSyntaxHighlighter() {
|
||||
super("java", GRAMMAR);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,11 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SimpleRegexSyntaxHighlighter;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SyntaxHighlighter;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
@ -21,14 +17,14 @@ public class XPathSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
"ancestor-or-self", "following", "following-sibling", "namespace", "parent",
|
||||
"preceding-sibling",
|
||||
};
|
||||
|
||||
private static final String[] KEYWORDS = new String[] {
|
||||
"or", "and", "not",
|
||||
};
|
||||
|
||||
|
||||
public static final SyntaxHighlighter INSTANCE
|
||||
= builder("xpath",
|
||||
"attribute", "@[\\w]+")
|
||||
private static final RegexHighlightGrammar GRAMMAR
|
||||
= grammarBuilder("attribute", "@[\\w]+")
|
||||
.or("axis", "(" + String.join("|", AXIS_NAMES) + ")(?=::)")
|
||||
.or("keyword", "(" + String.join("|", KEYWORDS) + ")")
|
||||
.or("function", "[\\w-]+?(?=\\()")
|
||||
@ -40,8 +36,8 @@ public class XPathSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
.create();
|
||||
|
||||
|
||||
private XPathSyntaxHighlighter(String languageName, Pattern pattern, Map<String, String> namesToCssClass) {
|
||||
super(languageName, pattern, namesToCssClass);
|
||||
public XPathSyntaxHighlighter() {
|
||||
super("xpath", GRAMMAR);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,11 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SimpleRegexSyntaxHighlighter;
|
||||
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SyntaxHighlighter;
|
||||
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
@ -17,9 +15,8 @@ import net.sourceforge.pmd.util.fxdesigner.util.codearea.SyntaxHighlighter;
|
||||
public class XmlSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
|
||||
|
||||
public static final SyntaxHighlighter INSTANCE
|
||||
= builder("xml",
|
||||
"multi-line-comment", "<!--.*?-->")
|
||||
private static final RegexHighlightGrammar GRAMMAR
|
||||
= grammarBuilder("multi-line-comment", "<!--.*?-->")
|
||||
.or("cdata-tag", "<!\\[CDATA\\[|]]>")
|
||||
.or("cdata-content", "(?<=<!\\[CDATA\\[).*?(?=]]>)")
|
||||
.or("xml-prolog", "<[?]xml.*[?]>")
|
||||
@ -30,7 +27,7 @@ public class XmlSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
|
||||
.create(Pattern.DOTALL);
|
||||
|
||||
|
||||
private XmlSyntaxHighlighter(String languageName, Pattern pattern, Map<String, String> namesToCssClass) {
|
||||
super(languageName, pattern, namesToCssClass);
|
||||
public XmlSyntaxHighlighter() {
|
||||
super("xml", GRAMMAR);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user