[sikuli] 192/385: added a syntax highlighter based on the Jygments project
Gilles Filippini
pini at moszumanska.debian.org
Sun Jun 29 19:26:11 UTC 2014
This is an automated email from the git hooks/post-receive script.
pini pushed a commit to tag upstream/1.1.0_beta1
in repository sikuli.
commit 17b6184b5ffb40bcb421004c28e5813104c58176
Author: Raimund Hocke <info at its-me-raiman.de>
Date: Sat Feb 1 08:49:30 2014 +0100
added a syntax highlighter based on the Jygments project
---
Jygments4Sikuli/pom.xml | 36 ++
.../main/java/org/sikuli/syntaxhighlight/Def.java | 56 +++
.../java/org/sikuli/syntaxhighlight/Filter.java | 23 ++
.../java/org/sikuli/syntaxhighlight/Jygments.java | 53 +++
.../java/org/sikuli/syntaxhighlight/NestedDef.java | 83 +++++
.../syntaxhighlight/ResolutionException.java | 42 +++
.../main/java/org/sikuli/syntaxhighlight/Run.java | 18 +
.../main/java/org/sikuli/syntaxhighlight/Util.java | 153 ++++++++
.../sikuli/syntaxhighlight/contrib/Css2Lexer.java | 109 ++++++
.../syntaxhighlight/contrib/DebugFormatter.java | 51 +++
.../syntaxhighlight/contrib/Default2Style.java | 81 +++++
.../syntaxhighlight/contrib/HtmlFormatter.java | 209 +++++++++++
.../sikuli/syntaxhighlight/format/Formatter.java | 105 ++++++
.../syntaxhighlight/grammar/DelegatedLexer.java | 122 +++++++
.../sikuli/syntaxhighlight/grammar/Grammar.java | 154 ++++++++
.../org/sikuli/syntaxhighlight/grammar/Lexer.java | 361 +++++++++++++++++++
.../syntaxhighlight/grammar/PatternRule.java | 43 +++
.../sikuli/syntaxhighlight/grammar/RegexLexer.java | 391 +++++++++++++++++++++
.../syntaxhighlight/grammar/RelativeState.java | 50 +++
.../org/sikuli/syntaxhighlight/grammar/Rule.java | 20 ++
.../sikuli/syntaxhighlight/grammar/SaveRule.java | 42 +++
.../org/sikuli/syntaxhighlight/grammar/State.java | 85 +++++
.../org/sikuli/syntaxhighlight/grammar/Token.java | 57 +++
.../sikuli/syntaxhighlight/grammar/TokenRule.java | 58 +++
.../sikuli/syntaxhighlight/grammar/TokenType.java | 274 +++++++++++++++
.../sikuli/syntaxhighlight/grammar/UsingRule.java | 44 +++
.../grammar/def/ChangeStateTokenRuleDef.java | 84 +++++
.../syntaxhighlight/grammar/def/IncludeDef.java | 86 +++++
.../syntaxhighlight/grammar/def/SaveDef.java | 80 +++++
.../syntaxhighlight/grammar/def/StateDef.java | 43 +++
.../syntaxhighlight/grammar/def/TokenRuleDef.java | 135 +++++++
.../syntaxhighlight/grammar/def/UsingRuleDef.java | 98 ++++++
.../org/sikuli/syntaxhighlight/scan/EndOfText.java | 20 ++
.../org/sikuli/syntaxhighlight/scan/Scanner.java | 121 +++++++
.../syntaxhighlight/style/ColorStyleElement.java | 86 +++++
.../syntaxhighlight/style/EffectStyleElement.java | 49 +++
.../syntaxhighlight/style/FontStyleElement.java | 43 +++
.../org/sikuli/syntaxhighlight/style/Style.java | 235 +++++++++++++
.../sikuli/syntaxhighlight/style/StyleElement.java | 83 +++++
.../syntaxhighlight/style/def/StyleElementDef.java | 73 ++++
.../src/main/resources/contrib/ClojureLexer.jso | 132 +++++++
.../src/main/resources/contrib/CssLexer.jso | 160 +++++++++
.../src/main/resources/contrib/DefaultStyle.jso | 51 +++
.../src/main/resources/contrib/HtmlLexer.jso | 64 ++++
.../src/main/resources/contrib/JavaLexer.jso | 48 +++
.../src/main/resources/contrib/JavascriptLexer.jso | 84 +++++
.../src/main/resources/contrib/PythonLexer.jso | 214 +++++++++++
.../src/main/resources/contrib/XmlLexer.jso | 38 ++
pom.xml | 1 +
49 files changed, 4748 insertions(+)
diff --git a/Jygments4Sikuli/pom.xml b/Jygments4Sikuli/pom.xml
new file mode 100644
index 0000000..e289938
--- /dev/null
+++ b/Jygments4Sikuli/pom.xml
@@ -0,0 +1,36 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+ * Copyright 2010-2013, Sikuli.org
+ * Released under the MIT License.
+ *
+ * RaiMan 2013
+ -->
+
+ <parent>
+ <groupId>org.sikuli</groupId>
+ <artifactId>SikuliX-Project</artifactId>
+ <version>1.1.0</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.sikuli</groupId>
+ <artifactId>Jygments4Sikuli</artifactId>
+ <version>1.1.0</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Def.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Def.java
new file mode 100644
index 0000000..b9ee7b1
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Def.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight;
+
+/**
+ * @author Tal Liron
+ */
+public abstract class Def<C>
+{
+ //
+ // Attributes
+ //
+
+ public boolean isResolved()
+ {
+ return resolved;
+ }
+
+ public Def<C> getCause( C container )
+ {
+ return null;
+ }
+
+ //
+ // Operations
+ //
+
+ public boolean resolve( C container ) throws ResolutionException
+ {
+ return false;
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return getClass().getSimpleName();
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected boolean resolved = false;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Filter.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Filter.java
new file mode 100644
index 0000000..a9e7553
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Filter.java
@@ -0,0 +1,23 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight;
+
+/**
+ * @author Tal Liron
+ */
+public abstract class Filter
+{
+ public static Filter getFilterByName( String name )
+ {
+ return null;
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Jygments.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Jygments.java
new file mode 100644
index 0000000..c31b055
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Jygments.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import org.sikuli.syntaxhighlight.format.Formatter;
+import org.sikuli.syntaxhighlight.grammar.Lexer;
+import org.sikuli.syntaxhighlight.grammar.Token;
+
+/**
+ * @author Tal Liron
+ */
+public abstract class Jygments
+{
+ //
+ // Static operations
+ //
+
+ public static Iterable<Token> lex( String code, Lexer lexer )
+ {
+ return lexer.getTokens( code );
+ }
+
+ public static void format( Iterable<Token> tokens, Formatter formatter, Writer writer ) throws IOException
+ {
+ formatter.format( tokens, writer );
+ }
+
+ public static void highlight( String code, Lexer lexer, Formatter formatter, Writer writer ) throws IOException
+ {
+ format( lex( code, lexer ), formatter, writer );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private Jygments()
+ {
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/NestedDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/NestedDef.java
new file mode 100644
index 0000000..e53c5d0
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/NestedDef.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Tal Liron
+ */
+public class NestedDef<C> extends Def<C>
+{
+ //
+ // Operations
+ //
+
+ public void addDef( Def<C> def )
+ {
+ defs.add( def );
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( C container ) throws ResolutionException
+ {
+ // Keep resolving until done
+ boolean didSomething = false, keepGoing = true;
+ while( keepGoing )
+ {
+ keepGoing = false;
+ for( Def<C> def : new ArrayList<Def<C>>( defs ) )
+ {
+ if( !def.isResolved() )
+ {
+ if( def.resolve( container ) )
+ {
+ keepGoing = true;
+ didSomething = true;
+ }
+ }
+ }
+ }
+
+ // Are we resolved?
+ resolved = true;
+ for( Def<C> def : defs )
+ {
+ if( !def.isResolved() )
+ {
+ resolved = false;
+ break;
+ }
+ }
+
+ return didSomething;
+ }
+
+ @Override
+ public Def<C> getCause( C container )
+ {
+ for( Def<C> def : defs )
+ if( !def.isResolved() )
+ return def;
+ return null;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final List<Def<C>> defs = new ArrayList<Def<C>>();
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/ResolutionException.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/ResolutionException.java
new file mode 100644
index 0000000..b346736
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/ResolutionException.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight;
+
+/**
+ * @author Tal Liron
+ */
+public class ResolutionException extends Exception
+{
+ //
+ // Construction
+ //
+
+ public ResolutionException( String message )
+ {
+ super( message );
+ }
+
+ public ResolutionException( String message, Throwable cause )
+ {
+ super( message, cause );
+ }
+
+ public ResolutionException( Throwable cause )
+ {
+ super( cause );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private static final long serialVersionUID = 1L;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Run.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Run.java
new file mode 100644
index 0000000..df64d42
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Run.java
@@ -0,0 +1,18 @@
+package org.sikuli.syntaxhighlight;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.sikuli.syntaxhighlight.format.Formatter;
+import org.sikuli.syntaxhighlight.grammar.Lexer;
+
+public class Run {
+
+ public static void main(String[] args) throws IOException, ResolutionException {
+ String file = System.getProperty("user.dir") + "/org/sikuli/syntaxhighlight/Run.java";
+ Lexer lexer = Lexer.getByName("java");
+ Formatter formatter = Formatter.getByName("html");
+ String code = Util.streamToString(new FileInputStream(file));
+ formatter.format(lexer.getTokens(code), new PrintWriter(System.out));
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Util.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Util.java
new file mode 100644
index 0000000..c941bcf
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/Util.java
@@ -0,0 +1,153 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+package org.sikuli.syntaxhighlight;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.sikuli.syntaxhighlight.grammar.Lexer;
+
+/**
+ * @author Tal Liron
+ */
+public class Util {
+
+ public static String literalRegEx(String expression) {
+ return "\\Q" + expression + "\\E";
+ }
+
+ public static String replace(String string, String occurence, String replacement) {
+ return string.replaceAll(literalRegEx(occurence), replacement);
+ }
+
+ public static String streamToString(InputStream stream) throws IOException {
+ StringBuilder builder = new StringBuilder();
+ String line;
+
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
+ while ((line = reader.readLine()) != null) {
+ builder.append(line).append("\n");
+ }
+ } finally {
+ stream.close();
+ }
+
+ return builder.toString();
+ }
+
+ public static String rejsonToJson(InputStream stream) throws IOException {
+ String rejson = streamToString(stream);
+ String json = rejsonToJson(rejson, true);
+ json = rejsonToJson(json, false);
+ return json;
+ }
+
+ public static String rejsonToJson(String rejson, boolean doubleQuote) {
+ Matcher matcher = doubleQuote ? DOUBLE_QUOTED_STRING.matcher(rejson) : SINGLE_QUOTED_STRING.matcher(rejson);
+ StringBuilder json = new StringBuilder();
+ int start = 0, end = 0, lastEnd = 0;
+ while (matcher.find()) {
+ lastEnd = end;
+ start = matcher.start();
+ end = matcher.end();
+ if ((start > 0) && (rejson.charAt(start - 1) == 'r')) {
+ // Convert Python-style r"" string to Java-compatible pattern
+ String string = rejson.substring(start + 1, end - 1);
+ json.append(rejson.substring(lastEnd, start - 1));
+ json.append('\"');
+ json.append(pythonRegExToJavaPattern(string, doubleQuote));
+ json.append('\"');
+ } /*
+ * else if( !doubleQuote ) { // From single quote to double quote
+ * String string = rejson.substring( start + 1, end - 1 );
+ * json.append( rejson.substring( lastEnd, start - 1 ) );
+ * json.append( '\"' ); json.append( string.replaceAll( "\"",
+ * "\\\\\"" ) ); json.append( '\"' ); }
+ */ else {
+ // As is
+ json.append(rejson.substring(lastEnd, end));
+ }
+ }
+ json.append(rejson.substring(end));
+ // System.out.println( json );
+ return json.toString();
+ }
+
+ public static String pythonRegExToJavaPattern(String pattern, boolean doubleQuote) {
+ pattern = pattern.replaceAll("\\\\", "\\\\\\\\");
+ pattern = pattern.replaceAll("\\{", "\\\\\\\\{");
+ pattern = pattern.replaceAll("\\}", "\\\\\\\\}");
+ if (!doubleQuote) {
+ pattern = pattern.replaceAll("\"", "\\\\\"");
+ }
+ // System.out.println( pattern );
+ return pattern;
+ }
+
+ public static String escapeHtml(String text) {
+ text = text.replace("&", "&");
+ text = text.replace("<", "<");
+ text = text.replace(">", ">");
+ text = text.replace("\"", """);
+ text = text.replace("'", "'");
+ return text;
+ }
+
+ public static String asHtml(String text) {
+ text = escapeHtml(text);
+ text = text.replace(" ", " ");
+ return text;
+ }
+
+ private static final Pattern DOUBLE_QUOTED_STRING = Pattern.compile("\"(?>\\\\.|.)*?\"");
+
+ private static final Pattern SINGLE_QUOTED_STRING = Pattern.compile("'(?>\\\\.|.)*?'");
+
+ public static String extJSON = ".jso";
+
+ public static InputStream getJsonFile(String filename) {
+ URI jarFileURI = null;
+ File jarFile;
+ InputStream stream = null;
+ filename = filename.replace('.', '/') + extJSON;
+ try {
+ jarFileURI = Jygments.class.getProtectionDomain().getCodeSource().getLocation().toURI();
+ } catch (URISyntaxException ex) {
+ //TODO error message
+ }
+ if (jarFileURI != null) {
+ if (jarFileURI.getScheme().equals("file")) {
+ jarFile = new File(jarFileURI.getPath(), filename);
+ if (jarFile.exists()) {
+ try {
+ stream = new FileInputStream(jarFile);
+ } catch (FileNotFoundException ex) {
+ //TODO error message
+ }
+ }
+ } else {
+ stream = Jygments.class.getClassLoader().getResourceAsStream(filename);
+ }
+ }
+ return stream;
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/Css2Lexer.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/Css2Lexer.java
new file mode 100644
index 0000000..a85ca27
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/Css2Lexer.java
@@ -0,0 +1,109 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.contrib;
+
+import java.util.regex.Pattern;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.RegexLexer;
+
+/**
+ * @author Tal Liron
+ */
+public class Css2Lexer extends RegexLexer
+{
+ public Css2Lexer()
+ {
+ super();
+
+ addAlias( "css" );
+ addFilename( "*.css" );
+ addMimeType( "text/css" );
+
+ include( "root", "basics" );
+
+ int flags = Pattern.MULTILINE;
+ rule( "basics", "\\s+", flags, "Text" );
+ rule( "basics", "/\\*(?:.|\\n)*?\\*/", flags, "Comment" );
+ rule( "basics", "\\{", flags, "Punctuation", "content" );
+ rule( "basics", "\\:[a-zA-Z0-9_-]+", flags, "Name.Decorator" );
+ rule( "basics", "\\.[a-zA-Z0-9_-]+", flags, "Name.Class" );
+ rule( "basics", "\\#[a-zA-Z0-9_-]+", flags, "Name.Function" );
+ rule( "basics", "@[a-zA-Z0-9_-]+", flags, "Keyword", "atrule" );
+ rule( "basics", "[a-zA-Z0-9_-]+", flags, "Name.Tag" );
+ rule( "basics", "[~\\^\\*!%&\\[\\]\\(\\)<>\\|+=@:;,./?-]", flags, "Operator" );
+ rule( "basics", "\"(\\\\\\\\|\\\\\"|[^\"])*\"", flags, "String.Double" );
+ rule( "basics", "'(\\\\\\\\|\\\\'|[^'])*'\"", flags, "String.Single" );
+
+ rule( "atrule", "\\{", flags, "Punctuation", "atcontent" );
+ rule( "atrule", ";", flags, "Punctuation", "#pop" );
+ include( "atrule", "basics" );
+
+ include( "atcontent", "basics" );
+ rule( "atcontent", "}", flags, "Punctuation", "#pop:2" );
+
+ rule( "content", "\\s+", flags, "Text" );
+ rule( "content", "}", flags, "Punctuation", "#pop" );
+ rule( "content", "url\\(.*?\\)", flags, "String.Other" );
+ rule( "content", "^@.*?$", flags, "Comment.Preproc" );
+
+ rule( "content", "(azimuth|background-attachment|background-color|" + "background-image|background-position|background-repeat|" + "background|border-bottom-color|border-bottom-style|"
+ + "border-bottom-width|border-left-color|border-left-style|" + "border-left-width|border-right|border-right-color|" + "border-right-style|border-right-width|border-top-color|"
+ + "border-top-style|border-top-width|border-bottom|" + "border-collapse|border-left|border-width|border-color|" + "border-spacing|border-style|border-top|border|caption-side|"
+ + "clear|clip|color|content|counter-increment|counter-reset|" + "cue-after|cue-before|cue|cursor|direction|display|" + "elevation|empty-cells|float|font-family|font-size|"
+ + "font-size-adjust|font-stretch|font-style|font-variant|" + "font-weight|font|height|letter-spacing|line-height|" + "list-style-type|list-style-image|list-style-position|"
+ + "list-style|margin-bottom|margin-left|margin-right|" + "margin-top|margin|marker-offset|marks|max-height|max-width|" + "min-height|min-width|opacity|orphans|outline|outline-color|"
+ + "outline-style|outline-width|overflow|padding-bottom|" + "padding-left|padding-right|padding-top|padding|page|" + "page-break-after|page-break-before|page-break-inside|"
+ + "pause-after|pause-before|pause|pitch|pitch-range|" + "play-during|position|quotes|richness|right|size|" + "speak-header|speak-numeral|speak-punctuation|speak|"
+ + "speech-rate|stress|table-layout|text-align|text-decoration|" + "text-indent|text-shadow|text-transform|top|unicode-bidi|" + "vertical-align|visibility|voice-family|volume|white-space|"
+ + "widows|width|word-spacing|z-index|bottom|left|" + "above|absolute|always|armenian|aural|auto|avoid|baseline|" + "behind|below|bidi-override|blink|block|bold|bolder|both|"
+ + "capitalize|center-left|center-right|center|circle|" + "cjk-ideographic|close-quote|collapse|condensed|continuous|" + "crop|crosshair|cross|cursive|dashed|decimal-leading-zero|"
+ + "decimal|default|digits|disc|dotted|double|e-resize|embed|" + "extra-condensed|extra-expanded|expanded|fantasy|far-left|" + "far-right|faster|fast|fixed|georgian|groove|hebrew|help|"
+ + "hidden|hide|higher|high|hiragana-iroha|hiragana|icon|" + "inherit|inline-table|inline|inset|inside|invert|italic|" + "justify|katakana-iroha|katakana|landscape|larger|large|"
+ + "left-side|leftwards|level|lighter|line-through|list-item|" + "loud|lower-alpha|lower-greek|lower-roman|lowercase|ltr|" + "lower|low|medium|message-box|middle|mix|monospace|"
+ + "n-resize|narrower|ne-resize|no-close-quote|no-open-quote|" + "no-repeat|none|normal|nowrap|nw-resize|oblique|once|" + "open-quote|outset|outside|overline|pointer|portrait|px|"
+ + "relative|repeat-x|repeat-y|repeat|rgb|ridge|right-side|" + "rightwards|s-resize|sans-serif|scroll|se-resize|" + "semi-condensed|semi-expanded|separate|serif|show|silent|"
+ + "slow|slower|small-caps|small-caption|smaller|soft|solid|" + "spell-out|square|static|status-bar|super|sw-resize|" + "table-caption|table-cell|table-column|table-column-group|"
+ + "table-footer-group|table-header-group|table-row|" + "table-row-group|text|text-bottom|text-top|thick|thin|" + "transparent|ultra-condensed|ultra-expanded|underline|"
+ + "upper-alpha|upper-latin|upper-roman|uppercase|url|" + "visible|w-resize|wait|wider|x-fast|x-high|x-large|x-loud|" + "x-low|x-small|x-soft|xx-large|xx-small|yes)\\b", flags, "Keyword" );
+
+ rule( "content", "(indigo|gold|firebrick|indianred|yellow|darkolivegreen|" + "darkseagreen|mediumvioletred|mediumorchid|chartreuse|" + "mediumslateblue|black|springgreen|crimson|lightsalmon|brown|"
+ + "turquoise|olivedrab|cyan|silver|skyblue|gray|darkturquoise|" + "goldenrod|darkgreen|darkviolet|darkgray|lightpink|teal|" + "arkmagenta|lightgoldenrodyellow|lavender|yellowgreen|thistle|"
+ + "violet|navy|orchid|blue|ghostwhite|honeydew|cornflowerblue|" + "darkblue|darkkhaki|mediumpurple|cornsilk|red|bisque|slategray|" + "darkcyan|khaki|wheat|deepskyblue|darkred|steelblue|aliceblue|"
+ + "gainsboro|mediumturquoise|floralwhite|coral|purple|lightgrey|" + "lightcyan|darksalmon|beige|azure|lightsteelblue|oldlace|" + "greenyellow|royalblue|lightseagreen|mistyrose|sienna|"
+ + "lightcoral|orangered|navajowhite|lime|palegreen|burlywood|" + "seashell|mediumspringgreen|fuchsia|papayawhip|blanchedalmond|" + "peru|aquamarine|white|darkslategray|ivory|dodgerblue|"
+ + "lemonchiffon|chocolate|orange|forestgreen|slateblue|olive|" + "mintcream|antiquewhite|darkorange|cadetblue|moccasin|" + "limegreen|saddlebrown|darkslateblue|lightskyblue|deeppink|"
+ + "plum|aqua|darkgoldenrod|maroon|sandybrown|magenta|tan|" + "rosybrown|pink|lightblue|palevioletred|mediumseagreen|" + "dimgray|powderblue|seagreen|snow|mediumblue|midnightblue|"
+ + "paleturquoise|palegoldenrod|whitesmoke|darkorchid|salmon|" + "lightslategray|lawngreen|lightgreen|tomato|hotpink|" + "lightyellow|lavenderblush|linen|mediumaquamarine|green|" + "blueviolet|peachpuff)\\b",
+ flags, "Name.Builtin" );
+
+ rule( "content", "\\!important", flags, "Comment.Preproc" );
+ rule( "content", "/\\*(?:.|\\n)*?\\*/'", flags, "Comment" );
+ rule( "content", "\\#[a-zA-Z0-9]{1,6}", flags, "Number" );
+ rule( "content", "[\\.-]?[0-9]*[\\.]?[0-9]+(em|px|\\%|pt|pc|in|mm|cm|ex)", flags, "Number" );
+ rule( "content", "-?[0-9]+", flags, "Number" );
+ rule( "content", "[~\\^\\*!%&<>\\|+=@:,./?-]+", flags, "Operator" );
+ rule( "content", "[\\[\\]();]+", flags, "Punctuation" );
+ rule( "content", "\"(\\\\\\\\|\\\\\"|[^\"])*\"", flags, "String.Double" );
+ rule( "content", "\"'(\\\\\\\\|\\\\'|[^'])*'", flags, "String.Single" );
+ rule( "content", "[a-zA-Z][a-zA-Z0-9]+", flags, "Name" );
+
+ try
+ {
+ resolve();
+ }
+ catch( ResolutionException x )
+ {
+ throw new RuntimeException( x );
+ }
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/DebugFormatter.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/DebugFormatter.java
new file mode 100644
index 0000000..1878313
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/DebugFormatter.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.contrib;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.sikuli.syntaxhighlight.format.Formatter;
+import org.sikuli.syntaxhighlight.grammar.Token;
+import org.sikuli.syntaxhighlight.style.Style;
+
+/**
+ * @author Tal Liron
+ */
+public class DebugFormatter extends Formatter
+{
+ //
+ // Construction
+ //
+
+ public DebugFormatter()
+ {
+ this( null, false, null, null );
+ }
+
+ public DebugFormatter( Style style, boolean full, String title, String encoding )
+ {
+ super( style, full, title, encoding );
+ }
+
+ //
+ // Formatter
+ //
+
+ @Override
+ public void format( Iterable<Token> tokenSource, Writer writer ) throws IOException
+ {
+ for( Token token : tokenSource )
+ writer.write( token.getPos() + " " + token.getType() + ": " + token.getValue() + "\n" );
+ writer.flush();
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/Default2Style.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/Default2Style.java
new file mode 100644
index 0000000..63e1bf2
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/Default2Style.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.contrib;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.style.Style;
+
+/**
+ * @author Tal Liron
+ */
+public class Default2Style extends Style
+{
+ public Default2Style()
+ {
+ super();
+
+ add( "Whitespace", "#bbbbbb" );
+ add( "Comment", "italic", "#408080" );
+ add( "Comment.Preproc", "noitalic", "#BC7A00" );
+
+ add( "Keyword", "bold", "#008000" );
+ add( "Keyword.Pseudo", "nobold" );
+ add( "Keyword.Type", "nobold", "#B00040" );
+
+ add( "Operator", "#666666" );
+ add( "Operator.Word", "bold", "#AA22FF" );
+
+ add( "Name.Builtin", "#008000" );
+ add( "Name.Function", "#0000FF" );
+ add( "Name.Class", "bold", "#0000FF" );
+ add( "Name.Namespace", "bold", "#0000FF" );
+ add( "Name.Exception", "bold", "#D2413A" );
+ add( "Name.Variable", "#19177C" );
+ add( "Name.Constant", "#880000" );
+ add( "Name.Label", "#A0A000" );
+ add( "Name.Entity", "bold", "#999999" );
+ add( "Name.Attribute", "#7D9029" );
+ add( "Name.Tag", "bold", "#008000" );
+ add( "Name.Decorator", "#AA22FF" );
+
+ add( "String", "#BA2121" );
+ add( "String.Doc", "italic" );
+ add( "String.Interpol", "bold", "#BB6688" );
+ add( "String.Escape", "bold", "#BB6622" );
+ add( "String.Regex", "#BB6688" );
+ add( "String.Symbol", "#19177C" );
+ add( "String.Other", "#008000" );
+ add( "Number", "#666666" );
+
+ add( "Generic.Heading", "bold", "#000080" );
+ add( "Generic.Subheading", "bold", "#800080" );
+ add( "Generic.Deleted", "#A00000" );
+ add( "Generic.Inserted", "#00A000" );
+ add( "Generic.Error", "#FF0000" );
+ add( "Generic.Emph", "italic" );
+ add( "Generic.Strong", "bold" );
+ add( "Generic.Prompt", "bold", "#000080" );
+ add( "Generic.Output", "#888" );
+ add( "Generic.Traceback", "#04D" );
+
+ add( "Error", "border", "#FF0000" );
+
+ try
+ {
+ resolve();
+ }
+ catch( ResolutionException x )
+ {
+ throw new RuntimeException( x );
+ }
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/HtmlFormatter.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/HtmlFormatter.java
new file mode 100644
index 0000000..3a63bde
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/contrib/HtmlFormatter.java
@@ -0,0 +1,209 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.contrib;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.Util;
+import org.sikuli.syntaxhighlight.format.Formatter;
+import org.sikuli.syntaxhighlight.grammar.Token;
+import org.sikuli.syntaxhighlight.grammar.TokenType;
+import org.sikuli.syntaxhighlight.style.ColorStyleElement;
+import org.sikuli.syntaxhighlight.style.EffectStyleElement;
+import org.sikuli.syntaxhighlight.style.FontStyleElement;
+import org.sikuli.syntaxhighlight.style.Style;
+import org.sikuli.syntaxhighlight.style.StyleElement;
+
+/**
+ * @author Tal Liron
+ */
+public class HtmlFormatter extends Formatter
+{
+ //
+ // Construction
+ //
+
+ public HtmlFormatter() throws ResolutionException
+ {
+ this( Style.getByName( "default" ), false, null, null );
+ }
+
+ public HtmlFormatter( Style style, boolean full, String title, String encoding )
+ {
+ super( style, full, title, encoding );
+ }
+
+ //
+ // Formatter
+ //
+
+ @Override
+ public void format( Iterable<Token> tokenSource, Writer writer ) throws IOException
+ {
+ writer.write( getDocHeader1() );
+ writer.write( " <title>" );
+ writer.write( Util.escapeHtml( getTitle() ) );
+ writer.write( "</title>\n" );
+ writer.write( getDocHeader2() );
+ writer.write( getEncoding() );
+ writer.write( getDocHeader3() );
+ writer.write( getCssFileTemplate() );
+ formatStyleSheet( writer );
+ writer.write( getDocHeader4() );
+ if( getTitle().length() > 0 )
+ {
+ writer.write( "<h2>" );
+ writer.write( Util.escapeHtml( getTitle() ) );
+ writer.write( "</h2>\n" );
+ }
+ writer.write( "<div><pre>\n" );
+ StringBuilder line = new StringBuilder();
+ int line_no = 1;
+ for( Token token : tokenSource )
+ {
+ String[] toks = token.getValue().split("\n", -1);
+ for(int i = 0; i < toks.length - 1; i++) {
+ format_partial_token(token, toks[i], line);
+ format_line(line.toString(), writer, line_no++);
+ line = new StringBuilder();
+ }
+ format_partial_token(token, toks[toks.length-1], line);
+ }
+ if(line.length() > 0)
+ format_line(line.toString(), writer, line_no++);
+
+ writer.write( "</pre></div>\n" );
+ writer.write( getDocFooter() );
+ writer.flush();
+ }
+
+ private void format_partial_token(Token token, String part_tok, StringBuilder line)
+ {
+ if( token.getType().getShortName().length() > 0 )
+ {
+ line.append( "<span class=\"" );
+ line.append( token.getType().getShortName() );
+ line.append( "\">" );
+ line.append( Util.escapeHtml( part_tok ) );
+ line.append( "</span>" );
+ }
+ else
+ line.append( Util.escapeHtml( part_tok ) );
+ }
+
+ public void format_line(String line, Writer writer, int line_no) throws IOException
+ {
+ writer.write(line);
+ writer.write("\n");
+ }
+
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected String getClassPrefix()
+ {
+ return "";
+ }
+
+ protected String getCssFileTemplate()
+ {
+ return " td.linenos { background-color: #f0f0f0; padding-right: 10px; }\n" + " span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }\n"
+ + " pre { line-height: 125%; }\n";
+ }
+
+ protected String getDocHeader1()
+ {
+ return "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" + "<html>\n" + "<head>\n";
+ }
+
+ protected String getDocHeader2()
+ {
+ return " <meta http-equiv=\"content-type\" content=\"text/html; charset=";
+ }
+
+ protected String getDocHeader3()
+ {
+ return "\">\n" + " <style type=\"text/css\">\n";
+ }
+
+ protected String getDocHeader4()
+ {
+ return " </style>\n" + "</head>\n" + "<body>\n";
+ }
+
+ /*
+ * private static final String DOC_HEADER_EXTERNAL_CSS =
+ * "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n" +
+ * " \"http://www.w3.org/TR/html4/strict.dtd\">\n" + "\n" + "<html>\n" +
+ * "<head>\n" + " <title>%(title)s</title>\n" +
+ * " <meta http-equiv=\"content-type\" content=\"text/html; charset=%(encoding)s\">\n"
+ * + " <link rel=\"stylesheet\" href=\"%(cssfile)s\" type=\"text/css\">\n"
+ * + "</head>\n" + "<body>\n" + "<h2>%(title)s</h2>\n";
+ */
+
+ protected String getDocFooter()
+ {
+ return "</body>\n" + "</html>\n";
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private void formatStyleSheet( Writer writer ) throws IOException
+ {
+ for( Map.Entry<TokenType, List<StyleElement>> entry : getStyle().getStyleElements().entrySet() )
+ {
+ TokenType tokenType = entry.getKey();
+ List<StyleElement> styleElementsForTokenType = entry.getValue();
+ writer.write( " ." );
+ writer.write( getClassPrefix() );
+ writer.write( tokenType.getShortName() );
+ writer.write( " { " );
+ for( StyleElement styleElement : styleElementsForTokenType )
+ {
+ if( styleElement instanceof ColorStyleElement )
+ {
+ ColorStyleElement colorStyleElement = (ColorStyleElement) styleElement;
+ if( colorStyleElement.getType() == ColorStyleElement.Type.Foreground )
+ writer.write( "color: " );
+ else if( colorStyleElement.getType() == ColorStyleElement.Type.Background )
+ writer.write( "background-color: " );
+ else if( colorStyleElement.getType() == ColorStyleElement.Type.Border )
+ writer.write( "border: 1px solid " );
+ writer.write( colorStyleElement.getColor() );
+ writer.write( "; " );
+ }
+ else if( styleElement instanceof EffectStyleElement )
+ {
+ if( styleElement == EffectStyleElement.Bold )
+ writer.write( "font-weight: bold; " );
+ else if( styleElement == EffectStyleElement.Italic )
+ writer.write( "font-style: italic; " );
+ else if( styleElement == EffectStyleElement.Underline )
+ writer.write( "text-decoration: underline; " );
+ }
+ else if( styleElement instanceof FontStyleElement )
+ {
+ // We don't want to set fonts in this formatter
+ }
+ }
+ writer.write( "} /* " );
+ writer.write( tokenType.getName() );
+ writer.write( " */\n" );
+ }
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/format/Formatter.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/format/Formatter.java
new file mode 100644
index 0000000..769e5f6
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/format/Formatter.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.format;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.sikuli.syntaxhighlight.Jygments;
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.Token;
+import org.sikuli.syntaxhighlight.style.Style;
+
+/**
+ * @author Tal Liron
+ */
+public abstract class Formatter
+{
+ //
+ // Static operations
+ //
+
+ public static Formatter getByName( String name ) throws ResolutionException
+ {
+ if( Character.isLowerCase( name.charAt( 0 ) ) )
+ name = Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 ) + "Formatter";
+
+ Formatter formatter = getByFullName( name );
+ if( formatter != null )
+ return formatter;
+ else
+ {
+ // Try contrib package
+ String pack = Jygments.class.getPackage().getName() + ".contrib";
+ formatter = getByFullName( pack + "." + name );
+ if( formatter == null )
+ {
+ // Try this package
+ pack = Formatter.class.getPackage().getName();
+ formatter = getByFullName( pack + "." + name );
+ }
+ return formatter;
+ }
+ }
+
+ public static Formatter getByFullName( String fullName ) throws ResolutionException
+ {
+ try
+ {
+ return (Formatter) Jygments.class.getClassLoader().loadClass( fullName ).newInstance();
+ }
+ catch( InstantiationException x )
+ {
+ }
+ catch( IllegalAccessException x )
+ {
+ }
+ catch( ClassNotFoundException x )
+ {
+ }
+
+ return null;
+ }
+
+ public Formatter( Style style, boolean full, String title, String encoding )
+ {
+ this.style = style;
+ this.title = title != null ? title : "";
+ this.encoding = encoding != null ? encoding : "utf8";
+ }
+
+ public Style getStyle()
+ {
+ return style;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public String getEncoding()
+ {
+ return encoding;
+ }
+
+ public abstract void format( Iterable<Token> tokenSource, Writer writer ) throws IOException;
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final Style style;
+
+ private final String title;
+
+ private final String encoding;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/DelegatedLexer.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/DelegatedLexer.java
new file mode 100644
index 0000000..f8b63b4
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/DelegatedLexer.java
@@ -0,0 +1,122 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import java.util.Map;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.LinkedList;
+
+/**
+ * @author Tal Liron
+ */
+public class DelegatedLexer extends Lexer
+{
+ //
+ // Lexer
+ //
+
+ @Override
+ public Iterable<Token> getTokensUnprocessed( String text )
+ {
+ StringBuilder buffered = new StringBuilder();
+ List<Token> lngBuffer = new LinkedList<Token>();
+ List<Insertion> insertions = new LinkedList<Insertion>();
+
+ Iterable<Token> tokens = languageLexer.getTokensUnprocessed( text );
+
+ for( Token t : tokens )
+ {
+ if( t.getType().getName().equals( "Other" ) )
+ {
+ if( !lngBuffer.isEmpty() )
+ {
+ insertions.add( new Insertion( buffered.length(), lngBuffer ) );
+ lngBuffer = new LinkedList<Token>();
+ }
+ buffered.append( t.getValue() );
+ }
+ else
+ lngBuffer.add( t );
+ }
+
+ if( !lngBuffer.isEmpty() )
+ insertions.add( new Insertion( buffered.length(), lngBuffer ) );
+
+ return doInsertions( insertions, rootLexer.getTokensUnprocessed( buffered.toString() ) );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ @Override
+ protected void addJson( Map<String, Object> json ) throws ResolutionException
+ {
+ super.addJson( json );
+ rootLexer = Lexer.getByName( (String) json.get( "root_lexer" ) );
+ languageLexer = Lexer.getByName( (String) json.get( "language_lexer" ) );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private Lexer rootLexer;
+
+ private Lexer languageLexer;
+
+ private static class Insertion
+ {
+ public int index;
+
+ public List<Token> lngBuffer;
+
+ public Insertion( int index, List<Token> lngBuffer )
+ {
+ super();
+ this.index = index;
+ this.lngBuffer = lngBuffer;
+ }
+ }
+
+ private Iterable<Token> doInsertions( List<Insertion> insertions, Iterable<Token> tokens )
+ {
+ ListIterator<Insertion> li = insertions.listIterator();
+ Insertion next_ins = li.hasNext() ? (Insertion) li.next() : null;
+ int len = 0;
+ LinkedList<Token> rc = new LinkedList<Token>();
+
+ for( Token t : tokens )
+ {
+ len += t.getValue().length();
+ String s = t.getValue();
+ int pos = 0;
+ while( next_ins != null && next_ins.index <= len )
+ {
+ rc.add( new Token( t.getPos(), t.getType(), s.substring( pos, s.length() + ( next_ins.index - len ) ) ) );
+ pos = s.length() + ( next_ins.index - len );
+ for( Token tt : next_ins.lngBuffer )
+ rc.add( tt );
+ next_ins = li.hasNext() ? li.next() : null;
+ }
+ if( pos < s.length() )
+ rc.add( new Token( t.getPos(), t.getType(), s.substring( pos ) ) );
+ }
+
+ // Do remaining tokens
+ while( li.hasNext() )
+ for( Token tt : ( (Insertion) li.next() ).lngBuffer )
+ rc.add( tt );
+
+ return rc;
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Grammar.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Grammar.java
new file mode 100644
index 0000000..0af6127
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Grammar.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.sikuli.syntaxhighlight.Def;
+import org.sikuli.syntaxhighlight.NestedDef;
+import org.sikuli.syntaxhighlight.ResolutionException;
+
+/**
+ * @author Tal Liron
+ */
+public class Grammar extends NestedDef<Grammar>
+{
+ //
+ // Attributes
+ //
+
+ public State getState( String stateName )
+ {
+ State state = statesByName.get( stateName );
+ if( state == null )
+ {
+ state = new State( stateName );
+ statesByName.put( stateName, state );
+ addDef( state );
+ }
+ return state;
+ }
+
+ public State resolveState( String stateName ) throws ResolutionException
+ {
+ if( stateName.startsWith( "#pop" ) )
+ {
+ int depth = 1;
+ if( stateName.length() > 4 )
+ {
+ String depthString = stateName.substring( 5 );
+ try
+ {
+ depth = Integer.parseInt( depthString );
+ }
+ catch( NumberFormatException x )
+ {
+ throw new ResolutionException( x );
+ }
+ }
+ return new RelativeState( false, depth );
+ }
+ else if( stateName.startsWith( "#push" ) )
+ {
+ int depth = 1;
+ if( stateName.length() > 5 )
+ {
+ String depthString = stateName.substring( 6 );
+ try
+ {
+ depth = Integer.parseInt( depthString );
+ }
+ catch( NumberFormatException x )
+ {
+ throw new ResolutionException( x );
+ }
+ }
+ return new RelativeState( true, depth );
+ }
+
+ State state = getState( stateName );
+ if( state.isResolved() )
+ return state;
+ else
+ return null;
+ }
+
+ public List<State> resolveStates( List<String> stateNames ) throws ResolutionException
+ {
+ ArrayList<State> states = new ArrayList<State>();
+ for( String stateName : stateNames )
+ {
+ String[] combinedStateName = stateName.split( "\\+" );
+ if( combinedStateName.length > 1 )
+ {
+ State combinedState = null;
+
+ for( String singleStateName : combinedStateName )
+ {
+ State state = resolveState( singleStateName );
+ if( state == null )
+ return null;
+
+ if( combinedState == null )
+ combinedState = state;
+ else
+ combinedState = new State( combinedState, state );
+ }
+
+ states.add( combinedState );
+ }
+ else
+ {
+ State state = resolveState( stateName );
+ if( state == null )
+ return null;
+
+ states.add( state );
+ }
+ }
+
+ return states;
+ }
+
+ //
+ // Operations
+ //
+
+ public void resolve() throws ResolutionException
+ {
+ resolve( this );
+
+ // Are we resolved?
+ for( Map.Entry<String, State> entry : statesByName.entrySet() )
+ {
+ if( !entry.getValue().isResolved() )
+ {
+ String message = "Unresolved state: " + entry.getKey();
+ Def<Grammar> cause = entry.getValue().getCause( this );
+ while( cause != null )
+ {
+ message += ", cause: " + cause;
+ cause = cause.getCause( this );
+ }
+ throw new ResolutionException( message );
+ }
+ }
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final Map<String, State> statesByName = new HashMap<String, State>();
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Lexer.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Lexer.java
new file mode 100644
index 0000000..18ac312
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Lexer.java
@@ -0,0 +1,361 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.sikuli.syntaxhighlight.Filter;
+import org.sikuli.syntaxhighlight.Jygments;
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.Util;
+import org.sikuli.syntaxhighlight.grammar.def.ChangeStateTokenRuleDef;
+import org.sikuli.syntaxhighlight.grammar.def.IncludeDef;
+import org.sikuli.syntaxhighlight.grammar.def.TokenRuleDef;
+
+/**
+ * @author Tal Liron
+ */
+public class Lexer extends Grammar
+{
+ //
+ // Static operations
+ //
+
+ public static Lexer getByName( String name ) throws ResolutionException
+ {
+ if( ( name == null ) || ( name.length() == 0 ) )
+ name = "Lexer";
+ else if( Character.isLowerCase( name.charAt( 0 ) ) )
+ name = Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 ) + "Lexer";
+
+ Lexer lexer = getByFullName( name );
+ if( lexer != null )
+ return lexer;
+ else
+ {
+ // Try contrib package
+ String pack = Jygments.class.getPackage().getName() + ".contrib";
+ lexer = getByFullName( pack + "." + name );
+ if( lexer == null )
+ {
+ // Try this package
+ pack = Lexer.class.getPackage().getName();
+ lexer = getByFullName( pack + "." + name );
+ }
+ return lexer;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Lexer getByFullName( String fullName ) throws ResolutionException
+ {
+ // Try cache
+ Lexer lexer = lexers.get( fullName );
+ if( lexer != null )
+ return lexer;
+
+ try
+ {
+ return (Lexer) Jygments.class.getClassLoader().loadClass( fullName ).newInstance();
+ }
+ catch( InstantiationException x )
+ {
+ }
+ catch( IllegalAccessException x )
+ {
+ }
+ catch( ClassNotFoundException x )
+ {
+ }
+
+ InputStream stream = Util.getJsonFile(fullName);
+ if( stream != null )
+ {
+ try
+ {
+ String converted = Util.rejsonToJson( stream );
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.getFactory().configure( JsonParser.Feature.ALLOW_COMMENTS, true );
+ Map<String, Object> json = objectMapper.readValue( converted, HashMap.class );
+ Object className = json.get( "class" );
+ if( className == null )
+ className = "";
+
+ lexer = getByName( className.toString() );
+ lexer.addJson( json );
+ lexer.resolve();
+
+ if( lexer != null )
+ {
+ // Cache it
+ Lexer existing = lexers.putIfAbsent( fullName, lexer );
+ if( existing != null )
+ lexer = existing;
+ }
+
+ return lexer;
+ }
+ catch( JsonParseException x )
+ {
+ throw new ResolutionException( x );
+ }
+ catch( JsonMappingException x )
+ {
+ throw new ResolutionException( x );
+ }
+ catch( IOException x )
+ {
+ throw new ResolutionException( x );
+ }
+ }
+
+ return null;
+ }
+
+ public static Lexer getForFileName( String fileName ) throws ResolutionException
+ {
+ if( lexerMap.isEmpty() )
+ {
+ try
+ {
+ File jarFile = new File( Jygments.class.getProtectionDomain().getCodeSource().getLocation().toURI() );
+ JarInputStream jarInputStream = new JarInputStream( new FileInputStream( jarFile ) );
+ try
+ {
+ for( JarEntry jarEntry = jarInputStream.getNextJarEntry(); jarEntry != null; jarEntry = jarInputStream.getNextJarEntry() )
+ {
+ if( jarEntry.getName().endsWith( Util.extJSON ) )
+ {
+ String lexerName = jarEntry.getName();
+ // strip off the JSON file ending
+ lexerName = lexerName.substring( 0, lexerName.length() - Util.extJSON.length() );
+ Lexer lexer = Lexer.getByFullName( lexerName );
+ for( String filename : lexer.filenames )
+ if( filename.startsWith( "*." ) )
+ lexerMap.put( filename.substring( filename.lastIndexOf( '.' ) ), lexer );
+ }
+ }
+ }
+ finally
+ {
+ jarInputStream.close();
+ }
+ }
+ catch( URISyntaxException x )
+ {
+ throw new ResolutionException( x );
+ }
+ catch( FileNotFoundException x )
+ {
+ throw new ResolutionException( x );
+ }
+ catch( IOException x )
+ {
+ throw new ResolutionException( x );
+ }
+ }
+
+ return lexerMap.get( fileName.substring( fileName.lastIndexOf( '.' ) ) );
+ }
+
+ //
+ // Construction
+ //
+
+ public Lexer()
+ {
+ this( false, false, 4, "utf8" );
+ }
+
+ public Lexer( boolean stripNewlines, boolean stripAll, int tabSize, String encoding )
+ {
+ this.stripNewLines = stripNewlines;
+ this.stripAll = stripAll;
+ this.tabSize = tabSize;
+ }
+
+ //
+ // Attributes
+ //
+
+ public List<Filter> getFilters()
+ {
+ return filters;
+ }
+
+ public boolean isStripNewLines()
+ {
+ return stripNewLines;
+ }
+
+ public void setStripNewLines( boolean stripNewLines )
+ {
+ this.stripNewLines = stripNewLines;
+ }
+
+ public boolean isStripAll()
+ {
+ return stripAll;
+ }
+
+ public void setStripAll( boolean stripAll )
+ {
+ this.stripAll = stripAll;
+ }
+
+ public int getTabSize()
+ {
+ return tabSize;
+ }
+
+ public void setTabSize( int tabSize )
+ {
+ this.tabSize = tabSize;
+ }
+
+ public void addFilter( Filter filter )
+ {
+ filters.add( filter );
+ }
+
+ public float analyzeText( String text )
+ {
+ return 0;
+ }
+
+ public Iterable<Token> getTokens( String text )
+ {
+ return getTokens( text, false );
+ }
+
+ public Iterable<Token> getTokens( String text, boolean unfiltered )
+ {
+ // text = text.replace( "\r\n", "\n" ).replace( "\r", "\n" );
+ // if( stripAll )
+ // text = text.trim();
+ // if( stripNewLines )
+ // text = text.replace( "\n", "" );
+ if( tabSize > 0 )
+ {
+ // expand tabs
+ }
+ if( !text.endsWith( "\n" ) )
+ text += "\n";
+ Iterable<Token> tokens = getTokensUnprocessed( text );
+ if( !unfiltered )
+ {
+ // apply filters
+ }
+ return tokens;
+ }
+
+ public Iterable<Token> getTokensUnprocessed( String text )
+ {
+ ArrayList<Token> list = new ArrayList<Token>( 1 );
+ list.add( new Token( 0, TokenType.Text, text ) );
+ return list;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected void addAlias( String alias )
+ {
+ aliases.add( alias );
+ }
+
+ protected void addFilename( String filename )
+ {
+ filenames.add( filename );
+ }
+
+ protected void addMimeType( String mimeType )
+ {
+ mimeTypes.add( mimeType );
+ }
+
+ protected void include( String stateName, String includedStateName )
+ {
+ getState( stateName ).addDef( new IncludeDef( stateName, includedStateName ) );
+ }
+
+ protected void rule( String stateName, String pattern, int flags, String tokenTypeName )
+ {
+ getState( stateName ).addDef( new TokenRuleDef( stateName, pattern, flags, tokenTypeName ) );
+ }
+
+ protected void rule( String stateName, String pattern, int flags, String tokenTypeName, String nextStateName )
+ {
+ getState( stateName ).addDef( new ChangeStateTokenRuleDef( stateName, pattern, flags, new String[]
+ {
+ tokenTypeName
+ }, nextStateName ) );
+ }
+
+ protected void rule( String stateName, String pattern, int flags, String[] tokenTypeNames )
+ {
+ getState( stateName ).addDef( new TokenRuleDef( stateName, pattern, flags, tokenTypeNames ) );
+ }
+
+ protected void rule( String stateName, String pattern, int flags, String[] tokenTypeNames, String... nextStateNames )
+ {
+ getState( stateName ).addDef( new ChangeStateTokenRuleDef( stateName, pattern, flags, tokenTypeNames, nextStateNames ) );
+ }
+
+ protected void addJson( Map<String, Object> json ) throws ResolutionException
+ {
+ @SuppressWarnings("unchecked")
+ List<String> filenames = (List<String>) json.get( "filenames" );
+ if( filenames == null )
+ return;
+ for( String filename : filenames )
+ addFilename( filename );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private static final ConcurrentMap<String, Lexer> lexers = new ConcurrentHashMap<String, Lexer>();
+
+ private static final ConcurrentMap<String, Lexer> lexerMap = new ConcurrentHashMap<String, Lexer>();
+
+ private final List<Filter> filters = new ArrayList<Filter>();
+
+ private boolean stripNewLines;
+
+ private boolean stripAll;
+
+ private int tabSize;
+
+ private final List<String> aliases = new ArrayList<String>();
+
+ private final List<String> filenames = new ArrayList<String>();
+
+ private final List<String> mimeTypes = new ArrayList<String>();
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/PatternRule.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/PatternRule.java
new file mode 100644
index 0000000..728715a
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/PatternRule.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author Tal Liron
+ */
+public abstract class PatternRule extends Rule
+{
+ //
+ // Construction
+ //
+
+ public PatternRule( Pattern pattern )
+ {
+ this.pattern = pattern;
+ }
+
+ //
+ // Attributes
+ //
+
+ public Pattern getPattern()
+ {
+ return pattern;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final Pattern pattern;
+}
\ No newline at end of file
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/RegexLexer.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/RegexLexer.java
new file mode 100644
index 0000000..9c3472f
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/RegexLexer.java
@@ -0,0 +1,391 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.def.ChangeStateTokenRuleDef;
+import org.sikuli.syntaxhighlight.grammar.def.SaveDef;
+import org.sikuli.syntaxhighlight.grammar.def.TokenRuleDef;
+import org.sikuli.syntaxhighlight.grammar.def.UsingRuleDef;
+
+/**
+ * @author Tal Liron
+ */
+public class RegexLexer extends Lexer
+{
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ @Override
+ public List<Token> getTokensUnprocessed( String text )
+ {
+ List<Token> tokens = new ArrayList<Token>();
+
+ // Start at root state
+ LinkedList<State> stateStack = new LinkedList<State>();
+ State state = getState( "root" );
+ stateStack.add( state );
+
+ int pos = 0;
+ int length = text.length();
+ while( pos < length )
+ {
+ int eol = text.indexOf( '\n', pos );
+ // int endRegion = eol >= 0 ? eol + 2 : length;
+ // if( endRegion > length )
+ // endRegion = length;
+ int endRegion = length;
+ boolean matches = false;
+
+ // Does any rule in the current state match at the current position?
+ // System.out.println("Text: " + text.substring( pos ));
+ for( Rule rule : new ArrayList<Rule>( state.getRules() ) )
+ {
+ if( rule instanceof PatternRule )
+ {
+ PatternRule patternRule = (PatternRule) rule;
+ // System.out.println( "Trying pattern: " +
+ // rule.getPattern().pattern() );
+ Matcher matcher = patternRule.getPattern().matcher( text );
+ // From current position to end of line
+ // matcher.useTransparentBounds( true );
+ matcher.region( pos, endRegion );
+ if( matcher.lookingAt() )
+ {
+ // System.out.println( "Match! " + matcher.group() + " "
+ // +
+ // rule );
+
+ // Yes, so apply it!
+ if( rule instanceof TokenRule )
+ {
+ TokenRule tokenRule = (TokenRule) rule;
+ List<TokenType> tokenTypes = tokenRule.getTokenTypes();
+ if( tokenTypes.size() == 1 )
+ // Single token
+ tokens.add( new Token( pos, tokenTypes.get( 0 ), matcher.group() ) );
+ else
+ {
+ if( tokenTypes.size() != matcher.groupCount() )
+ throw new RuntimeException( "The number of token types in the rule does not match the number of groups in the regular expression" );
+
+ // Multiple tokens by group
+ int group = 1;
+ for( TokenType tokenType : tokenTypes )
+ {
+ String value = matcher.group( group );
+ // System.out.println( matcher.pattern() +
+ // " " +
+ // value + " " + tokenType );
+ // pos = matcher.start( group );
+ tokens.add( new Token( pos, tokenType, value ) );
+ // pos = matcher.end( group );
+ group++;
+ }
+ }
+
+ // Change state
+ List<State> nextStates = tokenRule.getNextStates();
+ if( nextStates != null )
+ {
+ for( State nextState : nextStates )
+ {
+ if( nextState instanceof RelativeState )
+ {
+ RelativeState relativeState = (RelativeState) nextState;
+ if( relativeState.isPush() )
+ // Push
+ stateStack.addLast( state );
+ else
+ // Pop
+ for( int depth = relativeState.getDepth(); ( depth > 0 ) && !stateStack.isEmpty(); depth-- )
+ state = stateStack.removeLast();
+ }
+ else
+ {
+ // Push and switch
+ stateStack.addLast( state );
+ state = nextState;
+ }
+ }
+ }
+ /*
+ * else { // Pop if( stateStack.size() > 1 ) state =
+ * stateStack.removeLast(); }
+ */
+ }
+ else if( rule instanceof UsingRule )
+ {
+ UsingRule usingRule = (UsingRule) rule;
+ // System.err.println( "!!!!!!!" +
+ // rule.getPattern().pattern() );
+ // System.err.println( "!!!!!!!!!!!!!!" +
+ // matcher.group().length() );
+ Iterable<Token> usingTokens = usingRule.getLexer().getTokensUnprocessed( matcher.group() );
+ for( Token usingToken : usingTokens )
+ tokens.add( usingToken );
+ }
+
+ pos = matcher.end();
+ // System.out.println( pos );
+ matches = true;
+
+ // Don't process other rules here
+ break;
+ }
+ }
+ else if( rule instanceof SaveRule )
+ {
+ SaveRule saveRule = (SaveRule) rule;
+ State saveState = saveRule.getState();
+ if( saveState != state )
+ {
+ saveState.getRules().clear();
+ saveState.include( state );
+ }
+ }
+ }
+
+ if( !matches )
+ {
+ // tokens.add( new Token( pos, TokenType.Error, state.getName()
+ // ) );
+ if( pos != eol )
+ {
+ // Unmatched character
+ tokens.add( new Token( pos, TokenType.Error, text.substring( pos, pos + 1 ) ) );
+ }
+ else
+ {
+ // Fallback for states that don't explicitly match new
+ // lines.
+
+ tokens.add( new Token( pos, TokenType.Text, "\n" ) );
+
+ // Reset state stack
+ /*
+ * state = getState( "root" ); stateStack.clear();
+ * stateStack.addLast( state );
+ */
+ }
+
+ pos += 1;
+ }
+ }
+
+ return tokens;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void addJson( Map<String, Object> json ) throws ResolutionException
+ {
+ super.addJson( json );
+
+ // Initialize constants
+ Object constantsObject = json.get( "constants" );
+ Map<String, List<String>> constants = new HashMap<String, List<String>>();
+ if( constantsObject != null )
+ {
+ if( !( constantsObject instanceof Map<?, ?> ) )
+ throw new ResolutionException( "\"constants\" must be a map" );
+
+ for( Map.Entry<String, Object> entry : ( (Map<String, Object>) constantsObject ).entrySet() )
+ {
+ String constantName = entry.getKey();
+ Object constantObject = entry.getValue();
+ ArrayList<String> strings = new ArrayList<String>();
+ constants.put( constantName, strings );
+ if( constantObject instanceof List<?> )
+ {
+ StringBuilder pattern = new StringBuilder();
+ for( String patternElement : (List<String>) constantObject )
+ pattern.append( patternElement );
+ strings.add( pattern.toString() );
+ }
+ else if( constantObject instanceof String )
+ strings.add( (String) constantObject );
+ else
+ throw new ResolutionException( "Unexpected value in \"constants\" map: " + constantObject );
+ }
+ }
+
+ // Flags
+ int defaultFlags = Pattern.MULTILINE;
+ Object flagsObject = json.get( "flags" );
+ if( flagsObject != null )
+ {
+ if( !( flagsObject instanceof List<?> ) )
+ throw new ResolutionException( "\"flags\" must be an array of strings" );
+
+ for( Object flagObject : (List<?>) flagsObject )
+ {
+ if( !( flagObject instanceof String ) )
+ throw new ResolutionException( "\"flags\" must be an array of strings" );
+
+ String flag = (String) flagObject;
+ if( flag.equalsIgnoreCase( "CANON_EQ" ) )
+ defaultFlags |= Pattern.CANON_EQ;
+ else if( flag.equalsIgnoreCase( "CASE_INSENSITIVE" ) || flag.equalsIgnoreCase( "IGNORECASE" ) )
+ defaultFlags |= Pattern.CASE_INSENSITIVE;
+ else if( flag.equalsIgnoreCase( "COMMENTS" ) )
+ defaultFlags |= Pattern.COMMENTS;
+ else if( flag.equalsIgnoreCase( "DOTALL" ) )
+ defaultFlags |= Pattern.DOTALL;
+ else if( flag.equalsIgnoreCase( "LITERAL" ) )
+ defaultFlags |= Pattern.LITERAL;
+ else if( flag.equalsIgnoreCase( "MULTILINE" ) )
+ defaultFlags |= Pattern.MULTILINE;
+ else if( flag.equalsIgnoreCase( "UNICODE_CASE" ) )
+ defaultFlags |= Pattern.UNICODE_CASE;
+ else if( flag.equalsIgnoreCase( "UNIX_LINES" ) )
+ defaultFlags |= Pattern.UNIX_LINES;
+ else
+ throw new ResolutionException( "\"flags\" contains an unrecognized flag: " + flag );
+ }
+ }
+
+ Object statesObject = json.get( "states" );
+ if( statesObject == null )
+ throw new ResolutionException( "Grammar does not contain \"states\" map" );
+
+ if( !( statesObject instanceof Map<?, ?> ) )
+ throw new ResolutionException( "\"states\" must be a map" );
+
+ for( Map.Entry<String, Object> entry : ( (Map<String, Object>) statesObject ).entrySet() )
+ {
+ String stateName = entry.getKey();
+ Object stateObject = entry.getValue();
+ if( !( stateObject instanceof Iterable<?> ) )
+ throw new ResolutionException( "State \"" + stateName + "\" must be an array" );
+
+ for( Iterable<Object> arguments : (Iterable<Iterable<Object>>) stateObject )
+ {
+ List<Object> argumentsList = new ArrayList<Object>();
+ for( Object argument : (List<Object>) arguments )
+ argumentsList.add( argument );
+
+ if( argumentsList.isEmpty() )
+ throw new ResolutionException( "Entry in state \"" + stateName + "\" must have at least one argument" );
+
+ Object command = argumentsList.get( 0 );
+ if( !( command instanceof String ) )
+ throw new ResolutionException( "Entry in state \"" + stateName + "\" must have a string as the first argument" );
+
+ if( command.equals( "#include" ) )
+ {
+ if( argumentsList.size() != 2 )
+ throw new ResolutionException( "\"#include\" command in state \"" + stateName + "\" must have a string as an argument" );
+
+ Object includedState = argumentsList.get( 1 );
+ if( !( includedState instanceof String ) )
+ throw new ResolutionException( "\"#include\" command in state \"" + stateName + "\" must have a string as an argument" );
+
+ include( stateName, (String) includedState );
+ }
+ else if( command.equals( "#using" ) )
+ {
+ if( argumentsList.size() != 3 )
+ throw new ResolutionException( "\"#using\" command in state \"" + stateName + "\" must have two strings as arguments" );
+
+ Object pattern = argumentsList.get( 1 );
+ if( !( pattern instanceof String ) )
+ throw new ResolutionException( "\"#using\" command in state \"" + stateName + "\" must have two strings as arguments" );
+
+ Object usingLexerName = argumentsList.get( 2 );
+ if( !( usingLexerName instanceof String ) )
+ throw new ResolutionException( "\"#using\" command in state \"" + stateName + "\" must have two strings as arguments" );
+
+ getState( stateName ).addDef( new UsingRuleDef( stateName, (String) pattern, (String) usingLexerName ) );
+ }
+ else if( command.equals( "#save" ) )
+ {
+ if( argumentsList.size() != 2 )
+ throw new ResolutionException( "\"#save\" command in state \"" + stateName + "\" must have one string as an argument" );
+
+ Object savedStateName = argumentsList.get( 1 );
+ if( !( savedStateName instanceof String ) )
+ throw new ResolutionException( "\"#save\" command in state \"" + stateName + "\" must have one string as an argument" );
+
+ getState( stateName ).addDef( new SaveDef( stateName, (String) savedStateName ) );
+ }
+ else
+ {
+ // Command is a pattern
+ String pattern = (String) command;
+
+ if( pattern.startsWith( "#constant:" ) )
+ {
+ // Concatenate
+ StringBuilder builder = new StringBuilder();
+ String[] concatArguments = pattern.substring( 10 ).split( "," );
+ for( String concatArgument : concatArguments )
+ {
+ List<String> strings = constants.get( concatArgument );
+ if( strings == null )
+ throw new ResolutionException( "Unknown constant \"" + concatArgument + "\" for #pattern in state \"" + stateName + "\" must have at least a token type as an argument" );
+ for( String string : strings )
+ builder.append( string );
+ }
+ pattern = builder.toString();
+ }
+
+ if( argumentsList.size() < 2 )
+ throw new ResolutionException( "Rule in state \"" + stateName + "\" must have at least a token type as an argument" );
+
+ Object tokenTypeNames = argumentsList.get( 1 );
+ if( tokenTypeNames instanceof String )
+ {
+ ArrayList<String> list = new ArrayList<String>( 1 );
+ list.add( (String) tokenTypeNames );
+ tokenTypeNames = list;
+ }
+
+ if( !( tokenTypeNames instanceof List<?> ) )
+ throw new ResolutionException( "Expected token type name or array of token type names in rule in state \"" + stateName + "\"" );
+
+ if( argumentsList.size() == 2 )
+ {
+ // Token rule
+ getState( stateName ).addDef( new TokenRuleDef( stateName, pattern, defaultFlags, (List<String>) tokenTypeNames ) );
+ }
+ else if( argumentsList.size() == 3 )
+ {
+ // Change state token rule
+ Object nextStateNames = argumentsList.get( 2 );
+ if( nextStateNames instanceof String )
+ {
+ ArrayList<String> list = new ArrayList<String>( 1 );
+ list.add( (String) nextStateNames );
+ nextStateNames = list;
+ }
+
+ if( !( nextStateNames instanceof List<?> ) )
+ throw new ResolutionException( "Expected state name or array of state names in rule in state \"" + stateName + "\"" );
+
+ getState( stateName ).addDef( new ChangeStateTokenRuleDef( stateName, pattern, defaultFlags, (List<String>) tokenTypeNames, (List<String>) nextStateNames ) );
+ }
+ else
+ throw new ResolutionException( "Too many arguments for rule in state \"" + stateName + "\"" );
+ }
+ }
+ }
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/RelativeState.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/RelativeState.java
new file mode 100644
index 0000000..48f263a
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/RelativeState.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+/**
+ * @author Tal Liron
+ */
+public class RelativeState extends State
+{
+ //
+ // Construction
+ //
+
+ public RelativeState( boolean push, int depth )
+ {
+ super( push ? "#push" : "#pop" + ( depth > 1 ? ":" + depth : "" ) );
+ this.push = push;
+ this.depth = depth;
+ }
+
+ //
+ // Attributes
+ //
+
+ public boolean isPush()
+ {
+ return push;
+ }
+
+ public int getDepth()
+ {
+ return depth;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final boolean push;
+
+ private final int depth;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Rule.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Rule.java
new file mode 100644
index 0000000..63e1f81
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Rule.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+
+/**
+ * @author Tal Liron
+ */
+public class Rule
+{
+}
\ No newline at end of file
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/SaveRule.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/SaveRule.java
new file mode 100644
index 0000000..f14443a
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/SaveRule.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+/**
+ * @author Tal Liron
+ */
+public class SaveRule extends Rule
+{
+ //
+ // Construction
+ //
+
+ public SaveRule( State state )
+ {
+ super();
+ this.state = state;
+ }
+
+ //
+ // Attributes
+ //
+
+ public State getState()
+ {
+ return state;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final State state;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/State.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/State.java
new file mode 100644
index 0000000..422a2bd
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/State.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.sikuli.syntaxhighlight.NestedDef;
+
+/**
+ * @author Tal Liron
+ */
+public class State extends NestedDef<Grammar>
+{
+ //
+ // Construction
+ //
+
+ public State( String name )
+ {
+ super();
+ this.name = name;
+ }
+
+ public State( State state1, State state2 )
+ {
+ this( state1.getName() + "+" + state2.getName() );
+ include( state1 );
+ include( state2 );
+ }
+
+ //
+ // Attributes
+ //
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public List<Rule> getRules()
+ {
+ return rules;
+ }
+
+ //
+ // Operations
+ //
+
+ public void addRule( Rule rule )
+ {
+ rules.add( rule );
+ }
+
+ public void addRuleAt( int location, Rule rule )
+ {
+ rules.add( location, rule );
+ }
+
+ public void include( State includedState )
+ {
+ rules.addAll( includedState.rules );
+ }
+
+ public void includeAt( int location, State includedState )
+ {
+ rules.addAll( location, includedState.rules );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final String name;
+
+ private final List<Rule> rules = new ArrayList<Rule>();
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Token.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Token.java
new file mode 100644
index 0000000..1babe5f
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/Token.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+/**
+ * @author Tal Liron
+ */
+public class Token
+{
+ //
+ // Construction
+ //
+
+ public Token( int pos, TokenType tokenType, String value )
+ {
+ this.pos = pos;
+ this.tokenType = tokenType;
+ this.value = value;
+ }
+
+ //
+ // Attributes
+ //
+
+ public int getPos()
+ {
+ return pos;
+ }
+
+ public TokenType getType()
+ {
+ return tokenType;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final int pos;
+
+ private final TokenType tokenType;
+
+ private final String value;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/TokenRule.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/TokenRule.java
new file mode 100644
index 0000000..f943aa6
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/TokenRule.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @author Tal Liron
+ */
+public class TokenRule extends PatternRule
+{
+ //
+ // Construction
+ //
+
+ public TokenRule( Pattern pattern, List<TokenType> tokenTypes )
+ {
+ this( pattern, tokenTypes, (List<State>) null );
+ }
+
+ public TokenRule( Pattern pattern, List<TokenType> tokenTypes, List<State> nextStates )
+ {
+ super( pattern );
+ this.nextStates = nextStates;
+ this.tokenTypes = tokenTypes;
+ }
+
+ //
+ // Attributes
+ //
+
+ public List<TokenType> getTokenTypes()
+ {
+ return tokenTypes;
+ }
+
+ public List<State> getNextStates()
+ {
+ return nextStates;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final List<TokenType> tokenTypes;
+
+ private final List<State> nextStates;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/TokenType.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/TokenType.java
new file mode 100644
index 0000000..4d41d89
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/TokenType.java
@@ -0,0 +1,274 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Tal Liron
+ */
+public class TokenType
+{
+ //
+ // Constants
+ //
+
+ public static final TokenType Token = create( "Token", "" );
+
+ // Main
+
+ public static final TokenType Whitespace = create( "Whitespace", "w", Token );
+
+ public static final TokenType Text = create( "Text", "", Token );
+
+ public static final TokenType Error = create( "Error", "err", Token );
+
+ public static final TokenType Other = create( "Other", "x", Token );
+
+ // Keywords
+
+ public static final TokenType Keyword = create( "Keyword", "k", Text );
+
+ public static final TokenType Keyword_Constant = create( "Keyword.Constant", "kc", Keyword );
+
+ public static final TokenType Keyword_Declaration = create( "Keyword.Declaration", "kd", Keyword );
+
+ public static final TokenType Keyword_Namespace = create( "Keyword.Namespace", "kn", Keyword );
+
+ public static final TokenType Keyword_Pseudo = create( "Keyword.Pseudo", "kp", Keyword );
+
+ public static final TokenType Keyword_Reserved = create( "Keyword.Reserved", "kr", Keyword );
+
+ public static final TokenType Keyword_Type = create( "Keyword.Type", "kt", Keyword );
+
+ // Names
+
+ public static final TokenType Name = create( "Name", "n", Text );
+
+ public static final TokenType Name_Attribute = create( "Name.Attribute", "na", Name );
+
+ public static final TokenType Name_Builtin = create( "Name.Builtin", "nb", Name );
+
+ public static final TokenType Name_Builtin_Pseudo = create( "Name.Builtin.Pseudo", "bp", Name_Builtin );
+
+ public static final TokenType Name_Class = create( "Name.Class", "nc", Name );
+
+ public static final TokenType Name_Constant = create( "Name.Constant", "no", Name );
+
+ public static final TokenType Name_Decorator = create( "Name.Decorator", "nd", Name );
+
+ public static final TokenType Name_Entity = create( "Name.Entity", "ni", Name );
+
+ public static final TokenType Name_Exception = create( "Name.Exception", "ne", Name );
+
+ public static final TokenType Name_Function = create( "Name.Function", "nf", Name );
+
+ public static final TokenType Name_Property = create( "Name.Property", "py", Name );
+
+ public static final TokenType Name_Label = create( "Name.Label", "nl", Name );
+
+ public static final TokenType Name_Namespace = create( "Name.Namespace", "nn", Name );
+
+ public static final TokenType Name_Other = create( "Name.Other", "nx", Name );
+
+ public static final TokenType Name_Tag = create( "Name.Tag", "nt", Name );
+
+ public static final TokenType Name_Variable = create( "Name.Variable", "nv", Name );
+
+ public static final TokenType Name_Variable_Class = create( "Name.Variable.Class", "vc", Name_Variable );
+
+ public static final TokenType Name_Variable_Global = create( "Name.Variable.Global", "vg", Name_Variable );
+
+ public static final TokenType Name_Variable_Instance = create( "Name.Variable.Instance", "vi", Name_Variable );
+
+ // Literals
+
+ public static final TokenType Literal = create( "Literal", "l", Text );
+
+ public static final TokenType Literal_Date = create( "Literal.Date", "ld", Literal );
+
+ // Strings
+
+ public static final TokenType String = create( "String", "s", Text );
+
+ public static final TokenType String_Backtick = create( "String.Backtick", "sb", String );
+
+ public static final TokenType String_Char = create( "String.Char", "sc", String );
+
+ public static final TokenType String_Doc = create( "String.Doc", "sd", String );
+
+ public static final TokenType String_Double = create( "String.Double", "s2", String );
+
+ public static final TokenType String_Escape = create( "String.Escape", "se", String );
+
+ public static final TokenType String_Heredoc = create( "String.Heredoc", "sh", String );
+
+ public static final TokenType String_Interpol = create( "String.Interpol", "si", String );
+
+ public static final TokenType String_Other = create( "String.Other", "sx", String );
+
+ public static final TokenType String_Regex = create( "String.Regex", "sr", String );
+
+ public static final TokenType String_Single = create( "String.Single", "s1", String );
+
+ public static final TokenType String_Symbol = create( "String.Symbol", "ss", String );
+
+ // Numbers
+
+ public static final TokenType Number = create( "Number", "m", Text );
+
+ public static final TokenType Number_Float = create( "Number.Float", "mf", Number );
+
+ public static final TokenType Number_Hex = create( "Number.Hex", "mh", Number );
+
+ public static final TokenType Number_Integer = create( "Number.Integer", "mi", Number );
+
+ public static final TokenType Number_Integer_Long = create( "Number.Integer.Long", "il", Number_Integer );
+
+ public static final TokenType Number_Oct = create( "Number.Oct", "mo", Number );
+
+ // Operators
+
+ public static final TokenType Operator = create( "Operator", "o", Text );
+
+ public static final TokenType Operator_Word = create( "Operator.Word", "ow", Operator );
+
+ // Punctuation
+
+ public static final TokenType Punctuation = create( "Punctuation", "p", Text );
+
+ // Comments
+
+ public static final TokenType Comment = create( "Comment", "c", Text );
+
+ public static final TokenType Comment_Multiline = create( "Comment.Multiline", "cm", Comment );
+
+ public static final TokenType Comment_Preproc = create( "Comment.Preproc", "cp", Comment );
+
+ public static final TokenType Comment_Single = create( "Comment.Single", "c1", Comment );
+
+ public static final TokenType Comment_Special = create( "Comment.Special", "cs", Comment );
+
+ // Generics
+
+ public static final TokenType Generic = create( "Generic", "g", Text );
+
+ public static final TokenType Generic_Deleted = create( "Generic.Deleted", "gd", Generic );
+
+ public static final TokenType Generic_Emph = create( "Generic.Emph", "ge", Generic );
+
+ public static final TokenType Generic_Error = create( "Generic.Error", "gr", Generic );
+
+ public static final TokenType Generic_Heading = create( "Generic.Heading", "gh", Generic );
+
+ public static final TokenType Generic_Inserted = create( "Generic.Inserted", "gi", Generic );
+
+ public static final TokenType Generic_Output = create( "Generic.Output", "go", Generic );
+
+ public static final TokenType Generic_Prompt = create( "Generic.Prompt", "gp", Generic );
+
+ public static final TokenType Generic_Strong = create( "Generic.Strong", "gs", Generic );
+
+ public static final TokenType Generic_Subheading = create( "Generic.Subheading", "gu", Generic );
+
+ public static final TokenType Generic_Traceback = create( "Generic.Traceback", "gt", Generic );
+
+ //
+ // Static attributes
+ //
+
+ public static TokenType getTokenTypeByName( String name )
+ {
+ return tokenTypesByName.get( name );
+ }
+
+ public static TokenType getTokenTypeByShortName( String shortName )
+ {
+ return tokenTypesByShortName.get( shortName );
+ }
+
+ public static Collection<TokenType> getTokenTypes()
+ {
+ return tokenTypesByName.values();
+ }
+
+ //
+ // Attributes
+ //
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getShortName()
+ {
+ return shortName;
+ }
+
+ public TokenType getParent()
+ {
+ return parent;
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private static Map<String, TokenType> tokenTypesByName;
+
+ private static Map<String, TokenType> tokenTypesByShortName;
+
+ private static final TokenType create( String name, String shortName )
+ {
+ return create( name, shortName, null );
+ }
+
+ private static final TokenType create( String name, String shortName, TokenType parent )
+ {
+ TokenType tokenType = new TokenType( name, shortName, parent );
+
+ if( tokenTypesByName == null )
+ tokenTypesByName = new HashMap<String, TokenType>();
+ if( tokenTypesByShortName == null )
+ tokenTypesByShortName = new HashMap<String, TokenType>();
+
+ tokenTypesByName.put( name, tokenType );
+ tokenTypesByShortName.put( shortName, tokenType );
+
+ return tokenType;
+ }
+
+ private final String name;
+
+ private final String shortName;
+
+ private final TokenType parent;
+
+ private TokenType( String name, String shortName, TokenType parent )
+ {
+ this.name = name;
+ this.shortName = shortName;
+ this.parent = parent;
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/UsingRule.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/UsingRule.java
new file mode 100644
index 0000000..2c17b25
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/UsingRule.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar;
+
+import java.util.regex.Pattern;
+
+/**
+ * @author Tal Liron
+ */
+public class UsingRule extends PatternRule
+{
+ //
+ // Construction
+ //
+
+ public UsingRule( Pattern pattern, Lexer lexer )
+ {
+ super( pattern );
+ this.lexer = lexer;
+ }
+
+ //
+ // Attributes
+ //
+
+ public Lexer getLexer()
+ {
+ return lexer;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final Lexer lexer;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/ChangeStateTokenRuleDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/ChangeStateTokenRuleDef.java
new file mode 100644
index 0000000..36d39cc
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/ChangeStateTokenRuleDef.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar.def;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.Grammar;
+import org.sikuli.syntaxhighlight.grammar.Rule;
+import org.sikuli.syntaxhighlight.grammar.State;
+import org.sikuli.syntaxhighlight.grammar.TokenRule;
+import org.sikuli.syntaxhighlight.grammar.TokenType;
+
+/**
+ * @author Tal Liron
+ */
+public class ChangeStateTokenRuleDef extends TokenRuleDef
+{
+ //
+ // Construction
+ //
+
+ public ChangeStateTokenRuleDef( String stateName, String pattern, int flags, List<String> tokenTypeNames, List<String> nextStateNames )
+ {
+ super( stateName, pattern, flags, tokenTypeNames );
+ this.nextStateNames = nextStateNames;
+ }
+
+ public ChangeStateTokenRuleDef( String stateName, String pattern, int flags, String[] tokenTypeNames, String... nextStateNames )
+ {
+ super( stateName, pattern, flags, tokenTypeNames );
+ ArrayList<String> list = new ArrayList<String>( nextStateNames.length );
+ for( String nextStateName : nextStateNames )
+ list.add( nextStateName );
+ this.nextStateNames = list;
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( Grammar grammar ) throws ResolutionException
+ {
+ if( grammar.resolveStates( nextStateNames ) != null )
+ return super.resolve( grammar );
+ else
+ {
+ if( placeHolder == null )
+ {
+ placeHolder = new Rule();
+ State state = grammar.getState( stateName );
+ state.addRule( placeHolder );
+ }
+ return false;
+ }
+ }
+
+ //
+ // TokenRuleDef
+ //
+
+ @Override
+ protected TokenRule createTokenRule( Pattern pattern, List<TokenType> tokenTypes, Grammar grammar ) throws ResolutionException
+ {
+ return new TokenRule( pattern, tokenTypes, grammar.resolveStates( nextStateNames ) );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final List<String> nextStateNames;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/IncludeDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/IncludeDef.java
new file mode 100644
index 0000000..96921f5
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/IncludeDef.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar.def;
+
+import org.sikuli.syntaxhighlight.Def;
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.Grammar;
+import org.sikuli.syntaxhighlight.grammar.Rule;
+import org.sikuli.syntaxhighlight.grammar.State;
+
+/**
+ * @author Tal Liron
+ */
+public class IncludeDef extends StateDef
+{
+ public IncludeDef( String stateName, String includedStateName )
+ {
+ super( stateName );
+ this.includedStateName = includedStateName;
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( Grammar grammar ) throws ResolutionException
+ {
+ State state = grammar.getState( stateName );
+ State includedState = grammar.getState( includedStateName );
+
+ // Only include a resolved state
+ if( includedState.isResolved() )
+ {
+ if( placeHolder != null )
+ {
+ int location = state.getRules().indexOf( placeHolder );
+ state.getRules().remove( placeHolder );
+ state.includeAt( location, includedState );
+ }
+ else
+ state.include( includedState );
+
+ resolved = true;
+ return true;
+ }
+ else if( placeHolder == null )
+ {
+ // Remember location
+ placeHolder = new Rule();
+ state.addRule( placeHolder );
+ }
+
+ return false;
+ }
+
+ @Override
+ public Def<Grammar> getCause( Grammar grammar )
+ {
+ return grammar.getState( includedStateName ).getCause( grammar );
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + " " + stateName + ", " + includedStateName;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final String includedStateName;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/SaveDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/SaveDef.java
new file mode 100644
index 0000000..56c6d60
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/SaveDef.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar.def;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.Grammar;
+import org.sikuli.syntaxhighlight.grammar.Rule;
+import org.sikuli.syntaxhighlight.grammar.SaveRule;
+import org.sikuli.syntaxhighlight.grammar.State;
+
+/**
+ * @author Tal Liron
+ */
+public class SaveDef extends StateDef
+{
+ public SaveDef( String stateName, String savedStateName )
+ {
+ super( stateName );
+ this.savedStateName = savedStateName;
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( Grammar grammar ) throws ResolutionException
+ {
+ State state = grammar.getState( stateName );
+ State savedState = grammar.getState( savedStateName );
+
+ // Only include a resolved state
+ if( savedState.isResolved() )
+ {
+ if( placeHolder != null )
+ {
+ int location = state.getRules().indexOf( placeHolder );
+ state.getRules().remove( placeHolder );
+ state.addRuleAt( location, new SaveRule( savedState ) );
+ }
+ else
+ state.addRule( new SaveRule( savedState ) );
+
+ resolved = true;
+ return true;
+ }
+ else if( placeHolder == null )
+ {
+ // Remember location
+ placeHolder = new Rule();
+ state.addRule( placeHolder );
+ }
+
+ return false;
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + " " + stateName + ", " + savedStateName;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final String savedStateName;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/StateDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/StateDef.java
new file mode 100644
index 0000000..ff585e2
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/StateDef.java
@@ -0,0 +1,43 @@
+package org.sikuli.syntaxhighlight.grammar.def;
+
+import org.sikuli.syntaxhighlight.Def;
+import org.sikuli.syntaxhighlight.grammar.Grammar;
+import org.sikuli.syntaxhighlight.grammar.Rule;
+
+public abstract class StateDef extends Def<Grammar>
+{
+ //
+ // Construction
+ //
+
+ public StateDef( String stateName )
+ {
+ this.stateName = stateName;
+ }
+
+ //
+ // Attributes
+ //
+
+ public String getStateName()
+ {
+ return stateName;
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + " " + stateName;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected final String stateName;
+
+ protected Rule placeHolder = null;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/TokenRuleDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/TokenRuleDef.java
new file mode 100644
index 0000000..7746493
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/TokenRuleDef.java
@@ -0,0 +1,135 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar.def;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.Grammar;
+import org.sikuli.syntaxhighlight.grammar.State;
+import org.sikuli.syntaxhighlight.grammar.TokenRule;
+import org.sikuli.syntaxhighlight.grammar.TokenType;
+
+/**
+ * @author Tal Liron
+ */
+public class TokenRuleDef extends StateDef
+{
+ //
+ // Construction
+ //
+
+ public TokenRuleDef( String stateName, String pattern, int flags, List<String> tokenTypeNames )
+ {
+ super( stateName );
+ this.pattern = pattern;
+ this.flags = flags;
+ this.tokenTypeNames = tokenTypeNames;
+ }
+
+ public TokenRuleDef( String stateName, String pattern, int flags, String... tokenTypeNames )
+ {
+ super( stateName );
+ this.pattern = pattern;
+ this.flags = flags;
+ ArrayList<String> list = new ArrayList<String>( tokenTypeNames.length );
+ for( String tokenTypeName : tokenTypeNames )
+ list.add( tokenTypeName );
+ this.tokenTypeNames = list;
+ }
+
+ //
+ // Attributes
+ //
+
+ public String getPattern()
+ {
+ return pattern;
+ }
+
+ public List<String> getTokenTypeNames()
+ {
+ return tokenTypeNames;
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( Grammar grammar ) throws ResolutionException
+ {
+ Pattern pattern;
+ try
+ {
+ //pattern = Pattern.compile( this.pattern, Pattern.MULTILINE | Pattern.DOTALL );
+ pattern = Pattern.compile( this.pattern, flags );
+ }
+ catch( PatternSyntaxException x )
+ {
+ throw new ResolutionException( "RegEx syntax error: " + this.pattern, x );
+ }
+
+ ArrayList<TokenType> tokenTypes = new ArrayList<TokenType>();
+ for( String tokenTypeName : tokenTypeNames )
+ {
+ TokenType tokenType = TokenType.getTokenTypeByName( tokenTypeName );
+ if( tokenType == null )
+ throw new ResolutionException( "Unknown token type: " + tokenTypeName );
+ tokenTypes.add( tokenType );
+ }
+
+ TokenRule rule = createTokenRule( pattern, tokenTypes, grammar );
+ State state = grammar.getState( stateName );
+ if( placeHolder != null )
+ {
+ int location = state.getRules().indexOf( placeHolder );
+ state.getRules().remove( placeHolder );
+ state.addRuleAt( location, rule );
+ }
+ else
+ state.addRule( rule );
+
+ resolved = true;
+ return true;
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + ", " + pattern + ", " + tokenTypeNames;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected TokenRule createTokenRule( Pattern pattern, List<TokenType> tokenTypes, Grammar grammar ) throws ResolutionException
+ {
+ return new TokenRule( pattern, tokenTypes );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final String pattern;
+
+ private final int flags;
+
+ private final List<String> tokenTypeNames;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/UsingRuleDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/UsingRuleDef.java
new file mode 100644
index 0000000..1d7d444
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/grammar/def/UsingRuleDef.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.grammar.def;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.Grammar;
+import org.sikuli.syntaxhighlight.grammar.Lexer;
+import org.sikuli.syntaxhighlight.grammar.State;
+import org.sikuli.syntaxhighlight.grammar.UsingRule;
+
+/**
+ * @author Tal Liron
+ */
+public class UsingRuleDef extends StateDef
+{
+ //
+ // Construction
+ //
+
+ public UsingRuleDef( String stateName, String pattern, String usingLexerName )
+ {
+ super( stateName );
+ this.pattern = pattern;
+ this.usingLexerName = usingLexerName;
+ }
+
+ //
+ // Attributes
+ //
+
+ public String getPattern()
+ {
+ return pattern;
+ }
+
+ public String getUsingLexerName()
+ {
+ return usingLexerName;
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( Grammar grammar ) throws ResolutionException
+ {
+ Pattern pattern;
+ try
+ {
+ pattern = Pattern.compile( this.pattern, Pattern.MULTILINE | Pattern.DOTALL );
+ }
+ catch( PatternSyntaxException x )
+ {
+ throw new ResolutionException( "RegEx syntax error: " + this.pattern, x );
+ }
+
+ Lexer usingLexer = Lexer.getByName( usingLexerName );
+ UsingRule rule = new UsingRule( pattern, usingLexer );
+ State state = grammar.getState( stateName );
+ state.addRule( rule );
+
+ resolved = true;
+ return true;
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + ", " + pattern + ", " + usingLexerName;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final String pattern;
+
+ private final String usingLexerName;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/scan/EndOfText.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/scan/EndOfText.java
new file mode 100644
index 0000000..3267e81
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/scan/EndOfText.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.scan;
+
+/**
+ * @author Tal Liron
+ */
+public class EndOfText extends Exception
+{
+ private static final long serialVersionUID = 1L;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/scan/Scanner.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/scan/Scanner.java
new file mode 100644
index 0000000..ecb7d13
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/scan/Scanner.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.scan;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Tal Liron
+ */
+public abstract class Scanner
+{
+ //
+ // Construction
+ //
+
+ public Scanner( String text, int flags )
+ {
+ this.data = text;
+ this.flags = flags;
+ dataLength = data.length();
+ }
+
+ //
+ // Attributes
+ //
+
+ public int getStartPos()
+ {
+ return startPos;
+ }
+
+ public int getPos()
+ {
+ return pos;
+ }
+
+ public String getLast()
+ {
+ return last;
+ }
+
+ public String getMatch()
+ {
+ return match;
+ }
+
+ public boolean isEos()
+ {
+ return pos >= dataLength;
+ }
+
+ public Matcher check( String pattern ) throws EndOfText
+ {
+ if( isEos() )
+ throw new EndOfText();
+ Pattern re = patternCache.get( pattern );
+ if( re == null )
+ {
+ re = Pattern.compile( pattern, flags );
+ patternCache.put( pattern, re );
+ }
+ return re.matcher( data.substring( pos ) );
+ }
+
+ public boolean test( String pattern ) throws EndOfText
+ {
+ return check( pattern ).matches();
+ }
+
+ public boolean scan( String pattern ) throws EndOfText
+ {
+ if( isEos() )
+ throw new EndOfText();
+ Pattern re = patternCache.get( pattern );
+ if( re == null )
+ {
+ re = Pattern.compile( pattern, flags );
+ patternCache.put( pattern, re );
+ }
+ last = match;
+ Matcher matcher = re.matcher( data.substring( pos ) );
+ if( !matcher.matches() )
+ return false;
+ startPos = matcher.start();
+ pos = matcher.end();
+ match = matcher.group();
+ return true;
+ }
+
+ public boolean getChar() throws EndOfText
+ {
+ return scan( "." );
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private static final Map<String, Pattern> patternCache = new HashMap<String, Pattern>();
+
+ private final int flags;
+
+ private final int dataLength;
+
+ private String data;
+
+ private int startPos, pos;
+
+ private String match, last;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/ColorStyleElement.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/ColorStyleElement.java
new file mode 100644
index 0000000..94319ea
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/ColorStyleElement.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.style;
+
+/**
+ * @author Tal Liron
+ */
+public class ColorStyleElement extends StyleElement
+{
+ //
+ // Types
+ //
+
+ public enum Type
+ {
+ Foreground, Background, Border
+ }
+
+ //
+ // Static attributes
+ //
+
+ public static ColorStyleElement getColorStyleElementByName( String name )
+ {
+ if( name.startsWith( "bg:" ) )
+ return background( name.substring( 3 ) );
+ if( name.startsWith( "border:" ) )
+ return border( name.substring( 7 ) );
+ return foreground( name );
+ }
+
+ public static ColorStyleElement foreground( String color )
+ {
+ return new ColorStyleElement( color, Type.Foreground, color );
+ }
+
+ public static ColorStyleElement background( String color )
+ {
+ return new ColorStyleElement( "bg:" + color, Type.Background, color );
+ }
+
+ public static ColorStyleElement border( String color )
+ {
+ return new ColorStyleElement( "border:" + color, Type.Border, color );
+ }
+
+ //
+ // Attributes
+ //
+
+ public String getColor()
+ {
+ return color;
+ }
+
+ public Type getType()
+ {
+ return type;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected ColorStyleElement( String name, Type type, String color )
+ {
+ super( name );
+ this.type = type;
+ this.color = color;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final String color;
+
+ private final Type type;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/EffectStyleElement.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/EffectStyleElement.java
new file mode 100644
index 0000000..d8d6b38
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/EffectStyleElement.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.style;
+
+/**
+ * @author Tal Liron
+ */
+public class EffectStyleElement extends StyleElement
+{
+ //
+ // Constants
+ //
+
+ public static final EffectStyleElement Bold = create( "bold" );
+
+ public static final EffectStyleElement NoBold = create( "nobold" );
+
+ public static final EffectStyleElement Italic = create( "italic" );
+
+ public static final EffectStyleElement NoItalic = create( "noitalic" );
+
+ public static final EffectStyleElement Underline = create( "underline" );
+
+ public static final EffectStyleElement NoUnderline = create( "nounderline" );
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected EffectStyleElement( String name )
+ {
+ super( name );
+ }
+
+ private static EffectStyleElement create( String name )
+ {
+ EffectStyleElement fontStyleElement = new EffectStyleElement( name );
+ add( fontStyleElement );
+ return fontStyleElement;
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/FontStyleElement.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/FontStyleElement.java
new file mode 100644
index 0000000..155d3fe
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/FontStyleElement.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.style;
+
+/**
+ * @author Tal Liron
+ */
+public class FontStyleElement extends StyleElement
+{
+ //
+ // Constants
+ //
+
+ public static final FontStyleElement Roman = create( "roman" );
+
+ public static final FontStyleElement Sans = create( "sans" );
+
+ public static final FontStyleElement Mono = create( "mono" );
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected FontStyleElement( String name )
+ {
+ super( name );
+ }
+
+ private static FontStyleElement create( String name )
+ {
+ FontStyleElement fontStyleElement = new FontStyleElement( name );
+ add( fontStyleElement );
+ return fontStyleElement;
+ }
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/Style.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/Style.java
new file mode 100644
index 0000000..3ad8ce8
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/Style.java
@@ -0,0 +1,235 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.style;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.sikuli.syntaxhighlight.Jygments;
+import org.sikuli.syntaxhighlight.NestedDef;
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.TokenType;
+import org.sikuli.syntaxhighlight.style.def.StyleElementDef;
+
+/**
+ * @author Tal Liron
+ */
+public class Style extends NestedDef<Style>
+{
+ static String extJSON = ".jso";
+ //
+ // Static operations
+ //
+
+ public static Style getByName( String name ) throws ResolutionException
+ {
+ if( Character.isLowerCase( name.charAt( 0 ) ) )
+ name = Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 ) + "Style";
+
+ Style style = getByFullName( name );
+ if( style != null )
+ return style;
+ else
+ {
+ // Try contrib package
+ String pack = Jygments.class.getPackage().getName() + ".contrib";
+ name = pack + "." + name;
+ return getByFullName( name );
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Style getByFullName( String fullName ) throws ResolutionException
+ {
+ // Try cache
+ Style style = styles.get( fullName );
+ if( style != null )
+ return style;
+
+ try
+ {
+ return (Style) Jygments.class.getClassLoader().loadClass( fullName ).newInstance();
+ }
+ catch( InstantiationException x )
+ {
+ }
+ catch( IllegalAccessException x )
+ {
+ }
+ catch( ClassNotFoundException x )
+ {
+ }
+
+ InputStream stream = Jygments.class.getClassLoader().getResourceAsStream( fullName.replace( '.', '/' ) + extJSON );
+ if( stream != null )
+ {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.getFactory().configure( JsonParser.Feature.ALLOW_COMMENTS, true );
+ try
+ {
+ Map<String, Object> json = objectMapper.readValue( stream, HashMap.class );
+ style = new Style();
+ style.addJson( json );
+ style.resolve();
+
+ // Cache it
+ Style existing = styles.putIfAbsent( fullName, style );
+ if( existing != null )
+ style = existing;
+
+ return style;
+ }
+ catch( JsonParseException x )
+ {
+ throw new ResolutionException( x );
+ }
+ catch( JsonMappingException x )
+ {
+ throw new ResolutionException( x );
+ }
+ catch( IOException x )
+ {
+ throw new ResolutionException( x );
+ }
+ }
+
+ return null;
+ }
+
+ //
+ // Attributes
+ //
+
+ public Map<TokenType, List<StyleElement>> getStyleElements()
+ {
+ return styleElements;
+ }
+
+ //
+ // Operations
+ //
+
+ public void addStyleElement( TokenType tokenType, StyleElement styleElement )
+ {
+ List<StyleElement> styleElementsForTokenType = styleElements.get( tokenType );
+ if( styleElementsForTokenType == null )
+ {
+ styleElementsForTokenType = new ArrayList<StyleElement>();
+ styleElements.put( tokenType, styleElementsForTokenType );
+ }
+ styleElementsForTokenType.add( styleElement );
+ }
+
+ public void resolve() throws ResolutionException
+ {
+ resolve( this );
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( Style style ) throws ResolutionException
+ {
+ if( super.resolve( style ) )
+ {
+ boolean done = false;
+ while( !done )
+ {
+ done = true;
+ for( TokenType tokenType : TokenType.getTokenTypes() )
+ {
+ if( tokenType != TokenType.Token )
+ {
+ if( !styleElements.containsKey( tokenType ) )
+ {
+ boolean doneOne = false;
+ TokenType parent = tokenType.getParent();
+ while( parent != null )
+ {
+ if( parent == TokenType.Token )
+ {
+ doneOne = true;
+ break;
+ }
+
+ List<StyleElement> parentElements = styleElements.get( parent );
+ if( parentElements != null )
+ {
+ styleElements.put( tokenType, parentElements );
+ doneOne = true;
+ break;
+ }
+
+ parent = parent.getParent();
+ }
+
+ if( !doneOne )
+ done = false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+ else
+ return false;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected void add( String tokenTypeName, String... styleElementNames )
+ {
+ ArrayList<String> list = new ArrayList<String>( styleElementNames.length );
+ for( String styleElementName : styleElementNames )
+ list.add( styleElementName );
+ addDef( new StyleElementDef( tokenTypeName, list ) );
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void addJson( Map<String, Object> json ) throws ResolutionException
+ {
+ for( Map.Entry<String, Object> entry : json.entrySet() )
+ {
+ String tokenTypeName = entry.getKey();
+ if( entry.getValue() instanceof Iterable<?> )
+ {
+ for( String styleElementName : (Iterable<String>) entry.getValue() )
+ add( tokenTypeName, styleElementName );
+ }
+ else if( entry.getValue() instanceof String )
+ add( tokenTypeName, (String) entry.getValue() );
+ else
+ throw new ResolutionException( "Unexpected value in style definition: " + entry.getValue() );
+ }
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private static final ConcurrentMap<String, Style> styles = new ConcurrentHashMap<String, Style>();
+
+ private final Map<TokenType, List<StyleElement>> styleElements = new HashMap<TokenType, List<StyleElement>>();
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/StyleElement.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/StyleElement.java
new file mode 100644
index 0000000..97fbd64
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/StyleElement.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.style;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Tal Liron
+ */
+public class StyleElement
+{
+ static
+ {
+ // Force these classes to load
+ new ColorStyleElement( null, null, null );
+ new EffectStyleElement( null );
+ new FontStyleElement( null );
+ }
+
+ //
+ // Static attributes
+ //
+
+ public static StyleElement getStyleElementByName( String name )
+ {
+ StyleElement styleElement = styleElementsByName.get( name );
+ if( styleElement == null )
+ styleElement = ColorStyleElement.getColorStyleElementByName( name );
+ return styleElement;
+ }
+
+ //
+ // Attributes
+ //
+
+ public String getName()
+ {
+ return name;
+ }
+
+ //
+ // Object
+ //
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Protected
+
+ protected static final void add( StyleElement styleElement )
+ {
+ if( styleElementsByName == null )
+ styleElementsByName = new HashMap<String, StyleElement>();
+
+ styleElementsByName.put( styleElement.name, styleElement );
+ }
+
+ protected StyleElement( String name )
+ {
+ this.name = name;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private static Map<String, StyleElement> styleElementsByName;
+
+ private final String name;
+}
diff --git a/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/def/StyleElementDef.java b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/def/StyleElementDef.java
new file mode 100644
index 0000000..230bab9
--- /dev/null
+++ b/Jygments4Sikuli/src/main/java/org/sikuli/syntaxhighlight/style/def/StyleElementDef.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright 2010-2013 Three Crickets LLC.
+ * <p>
+ * The contents of this file are subject to the terms of a BSD license. See
+ * attached license.txt.
+ * <p>
+ * Alternatively, you can obtain a royalty free commercial license with less
+ * limitations, transferable or non-transferable, directly from Three Crickets
+ * at http://threecrickets.com/
+ */
+
+package org.sikuli.syntaxhighlight.style.def;
+
+import java.util.List;
+
+import org.sikuli.syntaxhighlight.Def;
+import org.sikuli.syntaxhighlight.ResolutionException;
+import org.sikuli.syntaxhighlight.grammar.TokenType;
+import org.sikuli.syntaxhighlight.style.Style;
+import org.sikuli.syntaxhighlight.style.StyleElement;
+
+/**
+ * @author Tal Liron
+ */
+public class StyleElementDef extends Def<Style>
+{
+ //
+ // Construction
+ //
+
+ public StyleElementDef( String tokenTypeName, List<String> styleElementNames )
+ {
+ this.tokenTypeName = tokenTypeName;
+ this.styleElementNames = styleElementNames;
+ }
+
+ //
+ // Def
+ //
+
+ @Override
+ public boolean resolve( Style style ) throws ResolutionException
+ {
+ TokenType tokenType = TokenType.getTokenTypeByName( tokenTypeName );
+ if( tokenType == null )
+ throw new ResolutionException( "Unknown token type: " + tokenTypeName );
+
+ //TokenType parent = tokenType.getParent();
+ //boolean addToParent = false;
+ //if( ( parent != null ) && ( !style.getStyleElements().containsKey( parent ) ) )
+ //addToParent = true;
+ for( String styleElementName : styleElementNames )
+ {
+ StyleElement styleElement = StyleElement.getStyleElementByName( styleElementName );
+ if( styleElement == null )
+ throw new ResolutionException( "Unknown style element: " + styleElementName );
+
+ style.addStyleElement( tokenType, styleElement );
+ //if( addToParent )
+ //style.addStyleElement( parent, styleElement );
+ }
+
+ resolved = true;
+ return true;
+ }
+
+ // //////////////////////////////////////////////////////////////////////////
+ // Private
+
+ private final String tokenTypeName;
+
+ private final List<String> styleElementNames;
+}
diff --git a/Jygments4Sikuli/src/main/resources/contrib/ClojureLexer.jso b/Jygments4Sikuli/src/main/resources/contrib/ClojureLexer.jso
new file mode 100644
index 0000000..468f28f
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/ClojureLexer.jso
@@ -0,0 +1,132 @@
+/*
+* Clojure Lexer
+*/
+
+{
+ "name": "Clojure",
+ "aliases": ["clojure", "clj"],
+ "filenames": ["*.clj"],
+ "mimetypes": ["text/x-clojure", "application/x-clojure"],
+
+ "class": "regex",
+
+ "states":
+ {
+ "root":
+ [
+ /* the comments - always starting with semicolon
+ and going to the end of the line */
+ [r';.*$', "Comment.Single"],
+
+ /* whitespaces - usually not relevant */
+ [r'\s+', "Text"],
+
+ /* numbers */
+ [r'-?\d+\.\d+', "Number.Float"],
+ [r'-?\d+', "Number.Integer"],
+ /* support for uncommon kinds of numbers -
+ have to figure out what the characters mean
+ (r'(#e|#i|#b|#o|#d|#x)[\d.]+', "Number"), */
+
+ /* strings, symbols and characters */
+ [r'"(\\\\|\\"|[^"])*"', "String"],
+ [r"'[a-zA-Z0-9!$%&*+,/:<=>?@^_~-]+", "String.Symbol"],
+ [r'\\([()/\'\".\'_!§$%& ?;=+-]{1}|[a-zA-Z0-9]+)', "String.Char"],
+
+ /* constants */
+ [r'(#t|#f)', "Name.Constant"],
+
+ /* special operators */
+ [r"('|#|`|,@|,|\.)", "Operator"],
+
+ /* highlight the keywords */
+ ["#constant:keywords", "Keyword"],
+
+ /* first variable in a quoted string like
+ '(this is syntactic sugar) */
+ [r"(?<='\()[a-zA-Z0-9!$%&*+,/:<=>?@^_~-]+", "Name.Variable"],
+ [r"(?<=#\()[a-zA-Z0-9!$%&*+,/:<=>?@^_~-]+", "Name.Variable"],
+
+ /* highlight the builtins */
+ ["#constant:builtins", "Name.Builtin"],
+
+ /* the remaining functions */
+ [r'(?<=\()[a-zA-Z0-9!$%&*+,/:<=>?@^_~-]+', "Name.Function"],
+ /* find the remaining variables */
+ [r'[a-zA-Z0-9!$%&*+,/:<=>?@^_~-]+', "Name.Variable"],
+
+ /* Clojure accepts vector notation */
+ [r'(\[|\])', "Punctuation"],
+
+ /* Clojure accepts map notation */
+ [r'({|})', "Punctuation"],
+
+ /* the famous parentheses! */
+ [r'(\(|\))', "Punctuation"]
+ ]
+ },
+
+
+ "constants":
+ {
+ "keywords":
+ [
+ r'(fn|def|defn|defmacro|defmethod|defmulti|defn-|',
+ r'defstruct|if|cond|let|for)'
+ ],
+
+ "builtins":
+ [
+ r'(?<=\()(.|..|',
+ r'\*|\+|-|->|..|/|<|<=|=|==|>|>=|',
+ r'accessor|agent|agent-errors|aget|alength|all-ns|',
+ r'alter|and|append-child|apply|array-map|aset|',
+ r'aset-boolean|aset-byte|aset-char|aset-double|aset-float|',
+ r'aset-int|aset-long|aset-short|assert|assoc|await|',
+ r'await-for|bean|binding|bit-and|bit-not|bit-or|',
+ r'bit-shift-left|bit-shift-right|bit-xor|boolean|branch\?|',
+ r'butlast|byte|cast|char|children|class|',
+ r'clear-agent-errors|comment|commute|comp|comparator|',
+ r'complement|concat|conj|cons|constantly|',
+ r'construct-proxy|contains\?|count|create-ns|create-struct|',
+ r'cycle|dec|deref|difference|disj|dissoc|distinct|',
+ r'doall|doc|dorun|doseq|dosync|dotimes|doto|',
+ r'double|down|drop|drop-while|edit|end\?|ensure|',
+ r'eval|every\?|false\?|ffirst|file-seq|filter|find|',
+ r'find-doc|find-ns|find-var|first|float|flush|',
+ r'fnseq|frest|gensym|get|get-proxy-class|',
+ r'hash-map|hash-set|identical\?|identity|if-let|import|',
+ r'in-ns|inc|index|insert-child|insert-left|insert-right|',
+ r'inspect-table|inspect-tree|instance\?|int|interleave|',
+ r'intersection|into|into-array|iterate|join|key|keys|',
+ r'keyword|keyword\?|last|lazy-cat|lazy-cons|left|',
+ r'lefts|line-seq|list|list\*|load|load-file|',
+ r'locking|long|loop|macroexpand|macroexpand-1|',
+ r'make-array|make-node|map|map-invert|map\?|mapcat|',
+ r'max|max-key|memfn|merge|merge-with|meta|min|',
+ r'min-key|name|namespace|neg\?|new|newline|next|',
+ r'nil\?|node|not|not-any\?|not-every\?|not=|ns-imports|',
+ r'ns-interns|ns-map|ns-name|ns-publics|ns-refers|',
+ r'ns-resolve|ns-unmap|nth|nthrest|or|parse|partial|',
+ r'path|peek|pop|pos\?|pr|pr-str|print|print-str|',
+ r'println|println-str|prn|prn-str|project|proxy|',
+ r'proxy-mappings|quot|rand|rand-int|range|re-find|',
+ r're-groups|re-matcher|re-matches|re-pattern|re-seq|',
+ r'read|read-line|reduce|ref|ref-set|refer|rem|',
+ r'remove|remove-method|remove-ns|rename|rename-keys|',
+ r'repeat|replace|replicate|resolve|rest|resultset-seq|',
+ r'reverse|rfirst|right|rights|root|rrest|rseq|',
+ r'second|select|select-keys|send|send-off|seq|',
+ r'seq-zip|seq\?|set|short|slurp|some|sort|',
+ r'sort-by|sorted-map|sorted-map-by|sorted-set|',
+ r'special-symbol\?|split-at|split-with|str|string\?|',
+ r'struct|struct-map|subs|subvec|symbol|symbol\?|',
+ r'sync|take|take-nth|take-while|test|time|to-array|',
+ r'to-array-2d|tree-seq|true\?|union|up|update-proxy|',
+ r'val|vals|var-get|var-set|var\?|vector|vector-zip|',
+ r'vector\?|when|when-first|when-let|when-not|',
+ r'with-local-vars|with-meta|with-open|with-out-str|',
+ r'xml-seq|xml-zip|zero\?|zipmap|zipper)'
+ ]
+ }
+}
diff --git a/Jygments4Sikuli/src/main/resources/contrib/CssLexer.jso b/Jygments4Sikuli/src/main/resources/contrib/CssLexer.jso
new file mode 100644
index 0000000..70f05a5
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/CssLexer.jso
@@ -0,0 +1,160 @@
+/*
+* CSS Lexer
+*/
+
+{
+ "aliases": "css",
+ "filenames": ["*.css"],
+ "mimetypes": "text/css",
+
+ "class": "regex",
+
+ "states":
+ {
+ "root":
+ [
+ ["#include", "basics"]
+ ],
+
+ "basics":
+ [
+ [r'\s+', "Text"],
+ [r'/\*(?:.|\n)*?\*/', "Comment"],
+ [r'{', "Punctuation", "content"],
+ [r'\:[a-zA-Z0-9_-]+', "Name.Decorator"],
+ [r'\.[a-zA-Z0-9_-]+', "Name.Class"],
+ [r'\#[a-zA-Z0-9_-]+', "Name.Function"],
+ [r'@[a-zA-Z0-9_-]+', "Keyword", "atrule"],
+ [r'[a-zA-Z0-9_-]+', "Name.Tag"],
+ [r'[~\^\*!%&\[\]\(\)<>\|+=@:;,./?-]', "Operator"],
+ [r'"(\\\\|\\"|[^"])*"', "String.Double"],
+ [r"'(\\\\|\\'|[^'])*'", "String.Single"]
+ ],
+
+ "atrules":
+ [
+ [r'{', "Punctuation", "atcontent"],
+ [r';', "Punctuation", "#pop"],
+ ["#include", "basics"]
+ ],
+
+ "atcontent":
+ [
+ ["#include", "basics"],
+ [r'}', "Punctuation", "#pop:2"]
+ ],
+
+ "content":
+ [
+ [r'\s+', "Text"],
+ [r'}', "Punctuation", "#pop"],
+ [r'url\(.*?\)', "String.Other"],
+ [r'^@.*?$', "Comment.Preproc"],
+ ["#constant:keywords", "Keyword"],
+ ["#constant:builtins", "Name.Builtin"],
+ [r'\!important', "Comment.Preproc"],
+ [r'/\*(?:.|\n)*?\*/', "Comment"],
+ [r'\#[a-zA-Z0-9]{1,6}', "Number"],
+ [r'[\.-]?[0-9]*[\.]?[0-9]+(em|px|\%|pt|pc|in|mm|cm|ex)', "Number"],
+ [r'-?[0-9]+', "Number"],
+ [r'[~\^\*!%&<>\|+=@:,./?-]+', "Operator"],
+ [r'[\[\]();]+', "Punctuation"],
+ [r'"(\\\\|\\"|[^"])*"', "String.Double"],
+ [r"'(\\\\|\\'|[^'])*'", "String.Single"],
+ [r'[a-zA-Z][a-zA-Z0-9]+', "Name"]
+ ]
+ },
+
+ "constants":
+ {
+ "keywords":
+ [
+ r"(azimuth|background-attachment|background-color|",
+ r"background-image|background-position|background-repeat|",
+ r"background|border-bottom-color|border-bottom-style|",
+ r"border-bottom-width|border-left-color|border-left-style|",
+ r"border-left-width|border-right|border-right-color|",
+ r"border-right-style|border-right-width|border-top-color|",
+ r"border-top-style|border-top-width|border-bottom|",
+ r"border-collapse|border-left|border-width|border-color|",
+ r"border-spacing|border-style|border-top|border|caption-side|",
+ r"clear|clip|color|content|counter-increment|counter-reset|",
+ r"cue-after|cue-before|cue|cursor|direction|display|",
+ r"elevation|empty-cells|float|font-family|font-size|",
+ r"font-size-adjust|font-stretch|font-style|font-variant|",
+ r"font-weight|font|height|letter-spacing|line-height|",
+ r"list-style-type|list-style-image|list-style-position|",
+ r"list-style|margin-bottom|margin-left|margin-right|",
+ r"margin-top|margin|marker-offset|marks|max-height|max-width|",
+ r"min-height|min-width|opacity|orphans|outline|outline-color|",
+ r"outline-style|outline-width|overflow|padding-bottom|",
+ r"padding-left|padding-right|padding-top|padding|page|",
+ r"page-break-after|page-break-before|page-break-inside|",
+ r"pause-after|pause-before|pause|pitch|pitch-range|",
+ r"play-during|position|quotes|richness|right|size|",
+ r"speak-header|speak-numeral|speak-punctuation|speak|",
+ r"speech-rate|stress|table-layout|text-align|text-decoration|",
+ r"text-indent|text-shadow|text-transform|top|unicode-bidi|",
+ r"vertical-align|visibility|voice-family|volume|white-space|",
+ r"widows|width|word-spacing|z-index|bottom|left|",
+ r"above|absolute|always|armenian|aural|auto|avoid|baseline|",
+ r"behind|below|bidi-override|blink|block|bold|bolder|both|",
+ r"capitalize|center-left|center-right|center|circle|",
+ r"cjk-ideographic|close-quote|collapse|condensed|continuous|",
+ r"crop|crosshair|cross|cursive|dashed|decimal-leading-zero|",
+ r"decimal|default|digits|disc|dotted|double|e-resize|embed|",
+ r"extra-condensed|extra-expanded|expanded|fantasy|far-left|",
+ r"far-right|faster|fast|fixed|georgian|groove|hebrew|help|",
+ r"hidden|hide|higher|high|hiragana-iroha|hiragana|icon|",
+ r"inherit|inline-table|inline|inset|inside|invert|italic|",
+ r"justify|katakana-iroha|katakana|landscape|larger|large|",
+ r"left-side|leftwards|level|lighter|line-through|list-item|",
+ r"loud|lower-alpha|lower-greek|lower-roman|lowercase|ltr|",
+ r"lower|low|medium|message-box|middle|mix|monospace|",
+ r"n-resize|narrower|ne-resize|no-close-quote|no-open-quote|",
+ r"no-repeat|none|normal|nowrap|nw-resize|oblique|once|",
+ r"open-quote|outset|outside|overline|pointer|portrait|px|",
+ r"relative|repeat-x|repeat-y|repeat|rgb|ridge|right-side|",
+ r"rightwards|s-resize|sans-serif|scroll|se-resize|",
+ r"semi-condensed|semi-expanded|separate|serif|show|silent|",
+ r"slow|slower|small-caps|small-caption|smaller|soft|solid|",
+ r"spell-out|square|static|status-bar|super|sw-resize|",
+ r"table-caption|table-cell|table-column|table-column-group|",
+ r"table-footer-group|table-header-group|table-row|",
+ r"table-row-group|text|text-bottom|text-top|thick|thin|",
+ r"transparent|ultra-condensed|ultra-expanded|underline|",
+ r"upper-alpha|upper-latin|upper-roman|uppercase|url|",
+ r"visible|w-resize|wait|wider|x-fast|x-high|x-large|x-loud|",
+ r"x-low|x-small|x-soft|xx-large|xx-small|yes)\b"
+ ],
+
+ "builtins":
+ [
+ r"(indigo|gold|firebrick|indianred|yellow|darkolivegreen|",
+ r"darkseagreen|mediumvioletred|mediumorchid|chartreuse|",
+ r"mediumslateblue|black|springgreen|crimson|lightsalmon|brown|",
+ r"turquoise|olivedrab|cyan|silver|skyblue|gray|darkturquoise|",
+ r"goldenrod|darkgreen|darkviolet|darkgray|lightpink|teal|",
+ r"arkmagenta|lightgoldenrodyellow|lavender|yellowgreen|thistle|",
+ r"violet|navy|orchid|blue|ghostwhite|honeydew|cornflowerblue|",
+ r"darkblue|darkkhaki|mediumpurple|cornsilk|red|bisque|slategray|",
+ r"darkcyan|khaki|wheat|deepskyblue|darkred|steelblue|aliceblue|",
+ r"gainsboro|mediumturquoise|floralwhite|coral|purple|lightgrey|",
+ r"lightcyan|darksalmon|beige|azure|lightsteelblue|oldlace|",
+ r"greenyellow|royalblue|lightseagreen|mistyrose|sienna|",
+ r"lightcoral|orangered|navajowhite|lime|palegreen|burlywood|",
+ r"seashell|mediumspringgreen|fuchsia|papayawhip|blanchedalmond|",
+ r"peru|aquamarine|white|darkslategray|ivory|dodgerblue|",
+ r"lemonchiffon|chocolate|orange|forestgreen|slateblue|olive|",
+ r"mintcream|antiquewhite|darkorange|cadetblue|moccasin|",
+ r"limegreen|saddlebrown|darkslateblue|lightskyblue|deeppink|",
+ r"plum|aqua|darkgoldenrod|maroon|sandybrown|magenta|tan|",
+ r"rosybrown|pink|lightblue|palevioletred|mediumseagreen|",
+ r"dimgray|powderblue|seagreen|snow|mediumblue|midnightblue|",
+ r"paleturquoise|palegoldenrod|whitesmoke|darkorchid|salmon|",
+ r"lightslategray|lawngreen|lightgreen|tomato|hotpink|",
+ r"lightyellow|lavenderblush|linen|mediumaquamarine|green|",
+ r"blueviolet|peachpuff)\b"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Jygments4Sikuli/src/main/resources/contrib/DefaultStyle.jso b/Jygments4Sikuli/src/main/resources/contrib/DefaultStyle.jso
new file mode 100644
index 0000000..ef6ea3b
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/DefaultStyle.jso
@@ -0,0 +1,51 @@
+/*
+* The default style.
+*/
+
+{
+ "Whitespace": "#bbbbbb",
+ "Comment": ["italic", "#408080"],
+ "Comment.Preproc": ["noitalic", "#BC7A00"],
+
+ "Keyword": ["bold", "#008000"],
+ "Keyword.Pseudo": "nobold",
+ "Keyword.Type": ["nobold", "#B00040"],
+
+ "Operator": "#666666",
+ "Operator.Word": ["bold", "#AA22FF"],
+
+ "Name.Builtin": "#008000",
+ "Name.Function": "#0000FF",
+ "Name.Class": ["bold", "#0000FF"],
+ "Name.Namespace": ["bold", "#0000FF"],
+ "Name.Exception": ["bold", "#D2413A"],
+ "Name.Variable": "#19177C",
+ "Name.Constant": "#880000",
+ "Name.Label": "#A0A000",
+ "Name.Entity": ["bold", "#999999"],
+ "Name.Attribute": "#7D9029",
+ "Name.Tag": ["bold", "#008000"],
+ "Name.Decorator": "#AA22FF",
+
+ "String": "#BA2121",
+ "String.Doc": "italic",
+ "String.Interpol": ["bold", "#BB6688"],
+ "String.Escape": ["bold", "#BB6622"],
+ "String.Regex": "#BB6688",
+ "String.Symbol": "#19177C",
+ "String.Other": "#008000",
+ "Number": "#666666",
+
+ "Generic.Heading": ["bold", "#000080"],
+ "Generic.Subheading": ["bold", "#800080"],
+ "Generic.Deleted": "#A00000",
+ "Generic.Inserted": "#00A000",
+ "Generic.Error": "#FF0000",
+ "Generic.Emph": "italic",
+ "Generic.Strong": "bold",
+ "Generic.Prompt": ["bold", "#000080"],
+ "Generic.Output": "#888",
+ "Generic.Traceback": "#04D",
+
+ "Error": ["border", "#FF0000"]
+}
\ No newline at end of file
diff --git a/Jygments4Sikuli/src/main/resources/contrib/HtmlLexer.jso b/Jygments4Sikuli/src/main/resources/contrib/HtmlLexer.jso
new file mode 100644
index 0000000..34d69b3
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/HtmlLexer.jso
@@ -0,0 +1,64 @@
+/*
+* HTML Lexer
+*/
+
+{
+ "name": "HTML",
+ "aliases": ["html"],
+ "filenames": ["*.html", "*.htm", "*.xhtml", "*.xslt"],
+ "mimetypes": ["text/html", "application/xhtml+xml"],
+
+ "class": "regex",
+ "flags": ["IGNORECASE", "DOTALL"],
+
+ "states":
+ {
+ "root":
+ [
+ [r'[^<&]+', "Text"],
+ [r'&\S*?;', "Name.Entity"],
+ [r'\<\!\[CDATA\[.*?\]\]\>', "Comment.Preproc"],
+ [r'<!--', "Comment", "comment"],
+ [r'<\?.*?\?>', "Comment.Preproc"],
+ [r'<![^>]*>', "Comment.Preproc"],
+ [r'<\s*script\s*', "Name.Tag", ["script-content", "tag"]],
+ [r'<\s*style\s*', "Name.Tag", ["style-content", "tag"]],
+ [r'<\s*[a-zA-Z0-9:]+', "Name.Tag", "tag"],
+ [r'<\s*/\s*[a-zA-Z0-9:]+\s*>', "Name.Tag"]
+ ],
+
+ "comment":
+ [
+ [r'[^-]+', "Comment"],
+ [r'-->', "Comment", "#pop"],
+ [r'-', "Comment"]
+ ],
+
+ "tag":
+ [
+ [r'\s+', "Text"],
+ [r'[a-zA-Z0-9_:-]+\s*=', "Name.Attribute", "attr"],
+ [r'[a-zA-Z0-9_:-]+', "Name.Attribute"],
+ [r'/?\s*>', "Name.Tag", "#pop"]
+ ],
+
+ "script-content":
+ [
+ [r'<\s*/\s*script\s*>', "Name.Tag", "#pop"],
+ ["#using", r'.+?(?=<\s*/\s*script\s*>)', "javascript"]
+ ],
+
+ "style-content":
+ [
+ [r'<\s*/\s*style\s*>', "Name.Tag", "#pop"],
+ ["#using", r'.+?(?=<\s*/\s*style\s*>)', "css"]
+ ],
+
+ "attr":
+ [
+ [r'".*?"', "String", "#pop"],
+ [r"'.*?'", "String", "#pop"],
+ [r'[^\s>]+', "String", "#pop"]
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Jygments4Sikuli/src/main/resources/contrib/JavaLexer.jso b/Jygments4Sikuli/src/main/resources/contrib/JavaLexer.jso
new file mode 100644
index 0000000..302ae78
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/JavaLexer.jso
@@ -0,0 +1,48 @@
+{
+ "name": "Java",
+ "aliases": ["java"],
+ "filenames": ["*.java"],
+ "mimetypes": ["text/x-java"],
+
+ "class": "regex",
+
+ "flags": ["MULTILINE", "DOTALL"],
+
+ //: optional Comment or Whitespace
+ "_ws": r'(?:\s|//.*?\n|/[*].*?[*]/)+',
+
+ "states": {
+ "root": [
+ [r'^(\s*(?:[a-zA-Z_][a-zA-Z0-9_\.\[\]]*\s+)+?)([a-zA-Z_][a-zA-Z0-9_]*)(\s*)(\()',
+ ["Name.Function", "Name.Function", "Text", "Operator"] ],
+ [r'[^\S\n]+', "Text"],
+ [r'//.*?\n', "Comment.Single"],
+ [r'/\*.*?\*/', "Comment.Multiline"],
+ [r'@[a-zA-Z_][a-zA-Z0-9_\.]*', "Name.Decorator"],
+ [r'(assert|break|case|catch|continue|default|do|else|finally|for|if|goto|instanceof|new|return|switch|this|throw|try|while)\b',
+ "Keyword"],
+ [r'(abstract|const|enum|extends|final|implements|native|private|protected|public|static|strictfp|super|synchronized|throws|transient|volatile)\b', "Keyword.Declaration"],
+ [r'(boolean|byte|char|double|float|int|long|short|void)\b', "Keyword.Type"],
+ [r'(package)(\s+)', ["Keyword.Namespace", "Text"]],
+ [r'(true|false|null)\b', "Keyword.Constant"],
+ [r'(class|interface)(\s+)', ["Keyword.Declaration", "Text"], "class"],
+ [r'(import)(\s+)', ["Keyword.Namespace", "Text"], "import"],
+ [r'"(\\\\|\\"|[^"])*+"', "String"],
+ [r"'\\.'|'[^\\]'|'\\u[0-9a-f]{4}'", "String.Char"],
+ [r'(\.)([a-zA-Z_][a-zA-Z0-9_]*)', ["Operator", "Name.Attribute"]],
+ [r'[a-zA-Z_][a-zA-Z0-9_]*:', "Name.Label"],
+ [r'[a-zA-Z_\$][a-zA-Z0-9_]*', "Name"],
+ [r'[~\^\*!%&\[\]\(\)\{\}<>\|+=:;,./?-]', "Operator"],
+ [r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', "Number.Float"],
+ [r'0x[0-9a-f]+', "Number.Hex"],
+ [r'[0-9]+L?', "Number.Integer"],
+ [r'\n', "Text"]
+ ],
+ "class": [
+ [r'[a-zA-Z_][a-zA-Z0-9_]*', "Name.Class", "#pop"]
+ ],
+ "import": [
+ [r'[a-zA-Z0-9_.]+\*?', "Name.Namespace", "#pop"]
+ ]
+ }
+}
diff --git a/Jygments4Sikuli/src/main/resources/contrib/JavascriptLexer.jso b/Jygments4Sikuli/src/main/resources/contrib/JavascriptLexer.jso
new file mode 100644
index 0000000..c8b861b
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/JavascriptLexer.jso
@@ -0,0 +1,84 @@
+/*
+* JavaScript Lexer
+*/
+
+{
+ "name": "JavaScript",
+ "aliases": ["js", "javascript"],
+ "filenames": ["*.js"],
+ "mimetypes": ["application/x-javascript", "text/x-javascript", "text/javascript"],
+
+ "class": "regex",
+ "flags": ["DOTALL"],
+
+ "states":
+ {
+ "commentsandwhitespace":
+ [
+ [r'\s+', "Text"],
+ [r'<!--', "Comment"],
+ [r'//.*?\n', "Comment.Single"],
+ [r'/\*.*?\*/', "Comment.Multiline"]
+ ],
+
+ "slashstartsregex":
+ [
+ ["#include", "commentsandwhitespace"],
+ [r'/(\\.|[^[/\\\n]|\[(\\.|[^\]\\\n])*])+/([gim]+\b|\B)', "String.Regex", "#pop"],
+ [r'(?=/)', "Text", ["#pop", "badregex"]],
+ [r'', "Text", "#pop"]
+ ],
+
+ "badregex":
+ [
+ [r'\n', "Text", "#pop"]
+ ],
+
+ "root":
+ [
+ [r'^(?=\s|/|<!--)', "Text", "slashstartsregex"],
+ ["#include", "commentsandwhitespace"],
+ [r'\+\+|--|~|&&|\?|:|\|\||\\(?=\n)|(<<|>>>?|==?|!=?|[-<>+*%&\|\^/])=?', "Operator", "slashstartsregex"],
+ [r'[{(\[;,]', "Punctuation", "slashstartsregex"],
+ [r'[})\].]', "Punctuation"],
+ ["#constant:keywords", "Keyword", "slashstartsregex"],
+ [r'(var|with|function)\b', "Keyword.Declaration", "slashstartsregex"],
+ ["#constant:reserved", "Keyword.Reserved"],
+ [r'(true|false|null|NaN|Infinity|undefined)\b', "Keyword.Constant"],
+ ["#constant:builtins", "Name.Builtin"],
+ [r'[$a-zA-Z_][a-zA-Z0-9_]*', "Name.Other"],
+ [r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', "Number.Float"],
+ [r'0x[0-9a-fA-F]+', "Number.Hex"],
+ [r'[0-9]+', "Number.Integer"],
+ [r'"(\\\\|\\"|[^"])*"', "String.Double"],
+ [r"'(\\\\|\\'|[^'])*'", "String.Single"]
+ ]
+ },
+
+ "constants":
+ {
+ "keywords":
+ [
+ r'(for|in|while|do|break|return|continue|switch|case|default|if|else|',
+ r'throw|try|catch|finally|new|delete|typeof|instanceof|void|',
+ r'this)\b'
+ ],
+
+ "reserved":
+ [
+ r'(abstract|boolean|byte|char|class|const|debugger|double|enum|export|',
+ r'extends|final|float|goto|implements|import|int|interface|long|native|',
+ r'package|private|protected|public|short|static|super|synchronized|throws|',
+ r'transient|volatile)\b'
+ ],
+
+ "builtins":
+ [
+ r'(Array|Boolean|Date|Error|Function|Math|netscape|',
+ r'Number|Object|Packages|RegExp|String|sun|decodeURI|',
+ r'decodeURIComponent|encodeURI|encodeURIComponent|',
+ r'Error|eval|isFinite|isNaN|parseFloat|parseInt|document|this|',
+ r'window)\b'
+ ]
+ }
+}
diff --git a/Jygments4Sikuli/src/main/resources/contrib/PythonLexer.jso b/Jygments4Sikuli/src/main/resources/contrib/PythonLexer.jso
new file mode 100644
index 0000000..ee6cdb8
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/PythonLexer.jso
@@ -0,0 +1,214 @@
+/*
+* Python Lexer
+*
+*
+* State entries are arrays where the first argument is either a
+* command (beginning with "#") or a regular expression to which
+* a rule is applied.
+*
+* Supported commands:
+*
+* "#include": The value is the state to include.
+*
+* Rules are literal regular expressions, or functions (beginning
+* with "#") applied to lists of strings in the "constants" map.
+*
+* Regex literals can use Python-style raw notation, prefixed with
+* "r". Both single-quotes and double-quoted raw notations are
+* supported.
+*
+* The second rule argument is the token type to apply to regex's
+* match, or an array of token types to apply to group matches, in
+* ordered sequence.
+*
+* The optional third argument is the next state to switch to
+* after the rule is applied, or an array of states to combine and
+* switch to.
+*
+* States can be either literal names of states, or the relative
+* references "#push" and "#pop" for the state stack. "#pop" can
+* also optionally specify a depth beyond one, for example:
+* "#pop:2".
+*
+*/
+
+{
+ "aliases": ["python", "py"],
+ "filenames": ["*.py", "*.pyw", "*.sc", "SConstruct", "SConscript"],
+ "mimetypes": ["text/x-python", "application/x-python"],
+
+ "class": "regex",
+
+ "states":
+ {
+ "root":
+ [
+ [r'\n', "Text"],
+ [r'^(\s*)("""(?:.|\n)*?""")', ["Text", "String.Doc"]],
+ [r"^(\s*)('''(?:.|\n)*?''')", ["Text", "String.Doc"]],
+ [r'[^\S\n]+', "Text"],
+ [r'#.*$', "Comment"],
+ [r'[\]{}:(),;\[]', "Punctuation"], /* square brackets were escaped for Jygments */
+ [r'\\\n', "Text"],
+ [r'\\', "Text"],
+ [r'(in|is|and|or|not)\b', "Operator.Word"],
+ [r'!=|==|<<|>>|[-~+/*%=<>&^|.]', "Operator"],
+ ["#include", "keywords"],
+ [r'(def)((?:\s|\\\s)+)', ["Keyword", "Text"], "funcname"],
+ [r'(class)((?:\s|\\\s)+)', ["Keyword", "Text"], "classname"],
+ [r'(from)((?:\s|\\\s)+)', ["Keyword.Namespace", "Text"], "fromimport"],
+ [r'(import)((?:\s|\\\s)+)', ["Keyword.Namespace", "Text"], "import"],
+ ["#include", "builtins"],
+ ["#include", "backtick"],
+ [r'(?:[rR]|[uU][rR]|[rR][uU])"""', "String", "tdqs"],
+ [r"(?:[rR]|[uU][rR]|[rR][uU])'''", "String", "tsqs"],
+ [r'(?:[rR]|[uU][rR]|[rR][uU])"', "String", "dqs"],
+ [r"(?:[rR]|[uU][rR]|[rR][uU])'", "String", "sqs"],
+ [r'[2uU]?"""', "String", "stringescape+tdqs"],
+ [r"[uU]?'''", "String", "stringescape+tsqs"],
+ [r'[uU]?"', "String", "stringescape+dqs"],
+ [r"[uU]?'", "String", "stringescape+sqs"],
+ ["#include", "name"],
+ ["#include", "numbers"]
+ ],
+
+ "keywords":
+ [
+ [r"(assert|break|continue|del|elif|else|except|exec|finally|for|global|if|lambda|pass|print|raise|return|try|while|yield|as|with)\b", "Keyword"]
+ ],
+
+ "builtins":
+ [
+ ["#constant:builtins", "Name.Builtin"],
+ [r'(?<!\.)(self|None|Ellipsis|NotImplemented|False|True)\b', "Name.Builtin.Pseudo"],
+ ["#constant:exceptions", "Name.Exception"]
+ ],
+
+ "numbers":
+ [
+ [r'(\d+\.\d*|\d*\.\d+)([eE][+-]?[0-9]+)?', "Number.Float"],
+ [r'\d+[eE][+-]?[0-9]+', "Number.Float"],
+ [r'0\d+', "Number.Oct"],
+ [r'0[xX][a-fA-F0-9]+', "Number.Hex"],
+ [r'\d+L', "Number.Integer.Long"],
+ [r'\d+', "Number.Integer"]
+ ],
+
+ "backtick":
+ [
+ [r"`.*?`", "String.Backtick"]
+ ],
+
+ "name":
+ [
+ [r'@[a-zA-Z0-9_.]+', "Name.Decorator"],
+ [r'[a-zA-Z_][a-zA-Z0-9_]*', "Name"]
+ ],
+
+ "funcname":
+ [
+ [r'[a-zA-Z_][a-zA-Z0-9_]*', "Name.Function", "#pop"]
+ ],
+
+ "classname":
+ [
+ [r'[a-zA-Z_][a-zA-Z0-9_]*', "Name.Class", "#pop"]
+ ],
+
+ "import":
+ [
+ [r'((?:\s|\\\s)+)(as)((?:\s|\\\s)+)', ["Text", "Keyword.Namespace", "Text"]],
+ [r'[a-zA-Z_][a-zA-Z0-9_.]*', "Name.Namespace"],
+ [r'(\s*)(,)(\s*)', ["Text", "Operator", "Text"]],
+ [r'', "Text", "#pop"] /* all else: go back */
+ ],
+
+ "fromimport":
+ [
+ [r'((?:\s|\\\s)+)(import)\b', ["Text", "Keyword.Namespace"], "#pop"],
+ [r'[a-zA-Z_.][a-zA-Z0-9_.]*', "Name.Namespace"]
+ ],
+
+ "stringescape":
+ [
+ [r'\\([\\abfnrtv"\']|\n|N{.*?}|u[a-fA-F0-9]{4}|U[a-fA-F0-9]{8}|x[a-fA-F0-9]{2}|[0-7]{1,3})', "String.Escape"]
+ ],
+
+ "strings":
+ [
+ [r'%(\([a-zA-Z0-9_]+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?[hlL]?[diouxXeEfFgGcrs%]', "String.Interpol"],
+ [r'[^\\\'"%\n]+', "String"],
+ /* quotes, percents and backslashes must be parsed one at a time */
+ [r'[\'"\\]', "String"],
+ /* unhandled string formatting sign */
+ [r'%', "String"]
+ /* newlines are an error (use "nl" state) */
+ ],
+
+ "nl":
+ [
+ [r'\n', "String"]
+ ],
+
+ "dqs":
+ [
+ [r'"', "String", "#pop"],
+ [r'\\\\|\\"|\\\n', "String.Escape"], /* included here again for raw strings */
+ ["#include", "strings"]
+ ],
+
+ "sqs":
+ [
+ [r"'", "String", "#pop"],
+ [r"\\\\|\\'|\\\n", "String.Escape"], /* included here again for raw strings */
+ ["#include", "strings"]
+ ],
+
+ "tdqs":
+ [
+ [r'"""', "String", "#pop"],
+ ["#include", "strings"],
+ ["#include", "nl"]
+ ],
+
+ "tsqs":
+ [
+ [r"'''", "String", "#pop"],
+ ["#include", "strings"],
+ ["#include", "nl"]
+ ]
+ },
+
+ "constants":
+ {
+ "builtins":
+ [
+ r"(?<!\.)(__import__|abs|all|any|apply|basestring|bin|bool|buffer|",
+ r"bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|",
+ r"complex|delattr|dict|dir|divmod|enumerate|eval|execfile|exit|",
+ r"file|filter|float|frozenset|getattr|globals|hasattr|hash|hex|id|",
+ r"input|int|intern|isinstance|issubclass|iter|len|list|locals|",
+ r"long|map|max|min|next|object|oct|open|ord|pow|property|range|",
+ r"raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|",
+ r"sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|",
+ r"vars|xrange|zip)\b"
+ ],
+
+ "exceptions":
+ [
+ r"(?<!\.)(ArithmeticError|AssertionError|AttributeError|",
+ r"BaseException|DeprecationWarning|EOFError|EnvironmentError|",
+ r"Exception|FloatingPointError|FutureWarning|GeneratorExit|IOError|",
+ r"ImportError|ImportWarning|IndentationError|IndexError|KeyError|",
+ r"KeyboardInterrupt|LookupError|MemoryError|NameError|",
+ r"NotImplemented|NotImplementedError|OSError|OverflowError|",
+ r"OverflowWarning|PendingDeprecationWarning|ReferenceError|",
+ r"RuntimeError|RuntimeWarning|StandardError|StopIteration|",
+ r"SyntaxError|SyntaxWarning|SystemError|SystemExit|TabError|",
+ r"TypeError|UnboundLocalError|UnicodeDecodeError|",
+ r"UnicodeEncodeError|UnicodeError|UnicodeTranslateError|",
+ r"UnicodeWarning|UserWarning|ValueError|VMSError|Warning|",
+ r"WindowsError|ZeroDivisionError)\b"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Jygments4Sikuli/src/main/resources/contrib/XmlLexer.jso b/Jygments4Sikuli/src/main/resources/contrib/XmlLexer.jso
new file mode 100644
index 0000000..bfaf03d
--- /dev/null
+++ b/Jygments4Sikuli/src/main/resources/contrib/XmlLexer.jso
@@ -0,0 +1,38 @@
+{
+ "name": "XML",
+ "aliases": ["xml"],
+ "filenames": ["*.xml", "*.xsl", "*.rss", "*.xslt", "*.xsd", "*.wsdl"],
+ "mimetypes": ["text/xml", "application/xml", "image/svg+xml",
+ "application/rss+xml", "application/atom+xml"],
+ "class": "regex",
+ "flags": ["MULTILINE", "DOTALL"],
+
+ "states": {
+ "root": [
+ [r'[^<&]+', "Text"],
+ [r'&\S*?;', "Name.Entity"],
+ [r'\<\!\[CDATA\[.*?\]\]\>', "Comment.Preproc"],
+ [r'<!--', "Comment", "comment"],
+ [r'<\?.*?\?>', "Comment.Preproc"],
+ [r'<![^>]*>', "Comment.Preproc"],
+ [r'<\s*[a-zA-Z0-9:._-]+', "Name.Tag", "tag"],
+ [r'<\s*/\s*[a-zA-Z0-9:._-]+\s*>', "Name.Tag"]
+ ],
+ "comment": [
+ [r'[^-]+', "Comment"],
+ [r'-->', "Comment", "#pop"],
+ [r'-', "Comment"]
+ ],
+ "tag": [
+ [r'\s+', "Text"],
+ [r'[a-zA-Z0-9_.:-]+\s*=', "Name.Attribute", "attr"],
+ [r'/?\s*>', "Name.Tag", "#pop"]
+ ],
+ "attr": [
+ [r'\s+', "Text"],
+ [r'".*?"', "String", "#pop"],
+ ["'.*?'", "String", "#pop"],
+ [r'[^\s>]+', "String", "#pop"]
+ ]
+ }
+}
diff --git a/pom.xml b/pom.xml
index 4e81c68..2d49173 100755
--- a/pom.xml
+++ b/pom.xml
@@ -217,6 +217,7 @@
</profiles>
<modules>
+ <module>Jygments4Sikuli</module>
<module>OpenCV4Sikuli</module>
<module>Tesseract4Sikuli</module>
<module>Libs</module>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/sikuli.git
More information about the pkg-java-commits
mailing list