Allow tokens to receive several css classes

This commit is contained in:
Clément Fournier
2017-11-10 18:57:59 +01:00
parent 1337533920
commit 2979d82755
6 changed files with 120 additions and 77 deletions

View File

@ -4,12 +4,13 @@
package net.sourceforge.pmd.util.fxdesigner.util.codearea;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -42,6 +43,8 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
protected SimpleRegexSyntaxHighlighter(String languageName, final RegexHighlightGrammar grammar) {
this.grammar = grammar;
this.languageName = languageName;
grammar.addCommonClass(languageName);
}
@ -51,12 +54,13 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
Matcher matcher = grammar.getMatcher(text);
int lastKwEnd = 0;
final Set<String> onlyLang = Collections.singleton(languageName);
try {
while (matcher.find()) {
String styleClass = grammar.getCssClassOfLastGroup(matcher);
Set<String> styleClasses = grammar.getCssClassesOfLastGroup(matcher);
builder.add(Collections.singleton(languageName), matcher.start() - lastKwEnd);
builder.add(Arrays.asList(languageName, styleClass), matcher.end() - matcher.start());
builder.add(onlyLang, matcher.start() - lastKwEnd);
builder.add(styleClasses, matcher.end() - matcher.start());
lastKwEnd = matcher.end();
}
@ -65,7 +69,7 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
}
if (lastKwEnd == 0) { // no spans found/ no text
builder.add(Collections.emptySet(), text.length());
builder.add(onlyLang, text.length());
}
return builder.create();
@ -86,7 +90,7 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
*
* @return A builder
*/
protected static RegexHighlightGrammarBuilder grammarBuilder(String cssClass, String pattern) {
protected static RegexHighlightGrammarBuilder grammarBuilder(Collection<String> cssClass, String pattern) {
return new RegexHighlightGrammarBuilder(cssClass, pattern);
}
@ -97,10 +101,10 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
protected static class RegexHighlightGrammarBuilder {
private Map<String, String> groupNameToRegex = new LinkedHashMap<>();
private Map<String, String> groupNameToCssClass = new LinkedHashMap<>();
private Map<String, Set<String>> groupNameToCssClasses = new LinkedHashMap<>();
RegexHighlightGrammarBuilder(String cssClass, String regex) {
RegexHighlightGrammarBuilder(Collection<String> cssClass, String regex) {
or(cssClass, regex);
}
@ -113,10 +117,10 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
*
* @return The same builder
*/
public RegexHighlightGrammarBuilder or(String cssClass, String regex) {
public RegexHighlightGrammarBuilder or(Collection<String> cssClass, String regex) {
String groupName = RandomStringUtils.randomAlphabetic(8);
groupNameToRegex.put(groupName, regex);
groupNameToCssClass.put(groupName, cssClass);
groupNameToCssClasses.put(groupName, new HashSet<>(cssClass));
return this;
}
@ -158,8 +162,8 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
}
private Map<String, String> getGroupNamesToCssClasses() {
return Collections.unmodifiableMap(groupNameToCssClass);
private Map<String, Set<String>> getGroupNamesToCssClasses() {
return Collections.unmodifiableMap(groupNameToCssClasses);
}
}
@ -170,10 +174,10 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
protected static class RegexHighlightGrammar {
private final Pattern pattern;
private final Map<String, String> namesToCssClass;
private final Map<String, Set<String>> namesToCssClass;
RegexHighlightGrammar(Pattern pattern, Map<String, String> namesToCssClass) {
RegexHighlightGrammar(Pattern pattern, Map<String, Set<String>> namesToCssClass) {
this.pattern = pattern;
this.namesToCssClass = namesToCssClass;
}
@ -189,6 +193,18 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
}
/**
* Adds a css class to all the tokens described by this grammar.
*
* @param css The css class to add
*/
void addCommonClass(String css) {
for (String key : namesToCssClass.keySet()) {
namesToCssClass.get(key).add(css);
}
}
/**
* Gets the css class that should be applied to the last matched group (token), according to this grammar.
*
@ -196,14 +212,14 @@ public abstract class SimpleRegexSyntaxHighlighter implements SyntaxHighlighter
*
* @return The name of the css class corresponding to the token
*/
String getCssClassOfLastGroup(Matcher matcher) {
for (Entry<String, String> groupToClass : namesToCssClass.entrySet()) {
Set<String> getCssClassesOfLastGroup(Matcher matcher) {
for (Entry<String, Set<String>> groupToClass : namesToCssClass.entrySet()) {
if (matcher.group(groupToClass.getKey()) != null) {
return groupToClass.getValue();
}
}
return "";
return Collections.emptySet();
}
}

View File

@ -4,29 +4,67 @@
package net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author Clément Fournier
* @since 6.0.0
*/
public enum HighlightClasses {
MULTIL_COMMENT("multi-line-comment"),
SINGLEL_COMMENT("single-line-comment"),
PAREN("paren"),
BRACE("brace"),
BRACKET("bracket"),
SEMICOLON("semicolon"),
BOOLEAN("boolean"),
STRING("string"),
CHAR("char"),
NULL("null"),
NUMBER("number"),
KEYWORD("keyword");
COMMENT(Constants.COMMENT),
MULTIL_COMMENT("multi-line-comment", Constants.COMMENT),
SINGLEL_COMMENT("single-line-comment", Constants.COMMENT),
PUNCTUATION(Constants.PUNCTUATION),
PAREN("paren", Constants.PUNCTUATION),
BRACE("brace", Constants.PUNCTUATION),
BRACKET("bracket", Constants.PUNCTUATION),
SEMICOLON("semicolon", Constants.PUNCTUATION),
LITERAL(Constants.LITERAL),
BOOLEAN("boolean", Constants.LITERAL),
STRING("string", Constants.LITERAL),
CHAR("char", Constants.LITERAL),
NULL("null", Constants.LITERAL),
NUMBER("number", Constants.LITERAL),
KEYWORD("keyword"),
ANNOTATION("annotation"),
CLASS_IDENTIFIER("class-identifier"),
// XPath specific
XPATH_ATTRIBUTE("attribute", Constants.XPATH),
XPATH_AXIS("axis", Constants.XPATH),
XPATH_FUNCTION("function", Constants.XPATH),
XPATH_PATH("path", Constants.XPATH, Constants.PUNCTUATION),
XML_CDATA_TAG("cdata-tag", Constants.XML),
XML_CDATA_CONTENT("cdata-content", Constants.XML),
XML_PROLOG("xml-prolog", Constants.XML),
XML_LT_GT("lt-gt", Constants.XML),
XML_TAG_NAME("tag-name", Constants.XML),
XML_ATTRIBUTE_NAME("attribute-name", Constants.XML),
;
/** Name of the css class. */
public final String css;
public final List<String> css;
HighlightClasses(String css) {
this.css = css;
HighlightClasses(String... classes) {
this.css = Collections.unmodifiableList(Arrays.asList(classes));
}
private static class Constants {
static final String LITERAL = "literal";
static final String COMMENT = "comment";
static final String PUNCTUATION = "punctuation";
static final String XML = "xml";
static final String XPATH = "xpath";
}
}

View File

@ -4,10 +4,12 @@
package net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.ANNOTATION;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.BOOLEAN;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.BRACE;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.BRACKET;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.CHAR;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.CLASS_IDENTIFIER;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.KEYWORD;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.MULTIL_COMMENT;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.NULL;
@ -67,8 +69,8 @@ public class JavaSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
.or(CHAR.css, "'(?:[^']|\\\\(?:'|u\\w{4}))'") // char
.or(NULL.css, "\\bnull\\b")
.or(BOOLEAN.css, "\\btrue|false\\b")
.or("annotation", "@[\\w]+")
.or("class-ident", "\\b[A-Z][\\w_$]*\\b")
.or(ANNOTATION.css, "@[\\w]+")
.or(CLASS_IDENTIFIER.css, "\\b[A-Z][\\w_$]*\\b")
.create(Pattern.DOTALL);

View File

@ -9,6 +9,10 @@ import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighti
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.PAREN;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.SINGLEL_COMMENT;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.STRING;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XPATH_ATTRIBUTE;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XPATH_AXIS;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XPATH_FUNCTION;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XPATH_PATH;
import net.sourceforge.pmd.util.fxdesigner.util.codearea.SimpleRegexSyntaxHighlighter;
@ -30,11 +34,11 @@ public class XPathSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
private static final RegexHighlightGrammar GRAMMAR
= grammarBuilder("attribute", "@[\\w]+")
.or("axis", "(" + String.join("|", AXIS_NAMES) + ")(?=::)")
= grammarBuilder(XPATH_ATTRIBUTE.css, "@[\\w]+")
.or(XPATH_AXIS.css, "(" + String.join("|", AXIS_NAMES) + ")(?=::)")
.or(KEYWORD.css, "\\b(" + String.join("|", KEYWORDS) + ")\\b")
.or("function", "[\\w-]+?(?=\\()")
.or("path", "//?")
.or(XPATH_FUNCTION.css, "[\\w-]+?(?=\\()")
.or(XPATH_PATH.css, "//?")
.or(PAREN.css, "[()]")
.or(BRACKET.css, "[\\[\\]]")
.or(STRING.css, "('([^'\\\\]|\\\\.)*')|(\"([^\"\\\\]|\\\\.)*\")")

View File

@ -5,6 +5,12 @@
package net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.MULTIL_COMMENT;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XML_ATTRIBUTE_NAME;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XML_CDATA_CONTENT;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XML_CDATA_TAG;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XML_LT_GT;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XML_PROLOG;
import static net.sourceforge.pmd.util.fxdesigner.util.codearea.syntaxhighlighting.HighlightClasses.XML_TAG_NAME;
import java.util.regex.Pattern;
@ -19,12 +25,12 @@ public class XmlSyntaxHighlighter extends SimpleRegexSyntaxHighlighter {
private static final RegexHighlightGrammar GRAMMAR
= grammarBuilder(MULTIL_COMMENT.css, "<!--.*?-->")
.or("cdata-tag", "<!\\[CDATA\\[|]]>")
.or("cdata-content", "(?<=<!\\[CDATA\\[).*?(?=]]>)")
.or("xml-prolog", "<\\?xml.*?\\?>")
.or("lt-gt", "</?|/?>")
.or("tag-name", "\\b(?<=(</?))\\w[-\\w:]*")
.or("attribute-name", "\\w[-\\w]*(?=\\s*=\\s*[\"'])")
.or(XML_CDATA_TAG.css, "<!\\[CDATA\\[|]]>")
.or(XML_CDATA_CONTENT.css, "(?<=<!\\[CDATA\\[).*?(?=]]>)")
.or(XML_PROLOG.css, "<\\?xml.*?\\?>")
.or(XML_LT_GT.css, "</?|/?>")
.or(XML_TAG_NAME.css, "\\b(?<=(</?))\\w[-\\w:]*")
.or(XML_ATTRIBUTE_NAME.css, "\\w[-\\w]*(?=\\s*=\\s*[\"'])")
.or(HighlightClasses.STRING.css, "('([^'<>\\\\]|\\\\.)*')|(\"([^\"<>\\\\]|\\\\.)*\")")
.create(Pattern.DOTALL);

View File

@ -10,7 +10,9 @@
-fx-fill: lightgreen !important;
}
/********/
/* Base */
/*******/
.styled-text-area {
-fx-background-color: whitesmoke;
@ -46,62 +48,37 @@
-fx-font-weight: normal;
}
/****************************/
/* Syntax highlighting base */
/****************************/
.styled-text-area .keyword {
-fx-fill: #B58900;
/* -fx-font-weight: bold; */
}
.styled-text-area .paren {
.styled-text-area .punctuation {
}
.styled-text-area .brace {
}
.styled-text-area .string {
.styled-text-area .literal {
-fx-fill: #317ECC;
}
.styled-text-area .number {
-fx-fill: #317ECC;
}
.styled-text-area .null {
-fx-fill: #317ECC;
}
.styled-text-area .boolean {
-fx-fill: #317ECC;
}
.styled-text-area .char {
-fx-fill: #317ECC;
}
.styled-text-area .multi-line-comment {
-fx-fill: #93A1A1;
-fx-font-style: italic;
}
.styled-text-area .single-line-comment {
.styled-text-area .comment {
-fx-fill: #93A1A1;
-fx-font-style: italic; /* doesn't work... */
}
.styled-text-area .semicolon {
}
/* Java specific */
.styled-text-area .annotation {
-fx-fill: #d30102;
}
.styled-text-area .class-ident {
/* Java specific */
.styled-text-area .java.class-identifier {
-fx-fill: #B05A65;
}