diff --git a/demo/demo.js b/demo/demo.js
index 22e1cc59..e338bb10 100644
--- a/demo/demo.js
+++ b/demo/demo.js
@@ -68,6 +68,9 @@ exports.launch = function(env) {
var SvgMode = require("ace/mode/svg").Mode;
var TextileMode = require("ace/mode/textile").Mode;
var TextMode = require("ace/mode/text").Mode;
+ var GroovyMode = require("ace/mode/groovy").Mode;
+ var ScalaMode = require("ace/mode/scala").Mode;
+
var UndoManager = require("ace/undomanager").UndoManager;
var vim = require("ace/keyboard/keybinding/vim").Vim;
@@ -167,6 +170,17 @@ exports.launch = function(env) {
docs.textile.setMode(new TextileMode());
docs.textile.setUndoManager(new UndoManager());
+ docs.groovy = new EditSession(document.getElementById("groovy").innerHTML);
+ docs.groovy.setMode(new GroovyMode());
+ docs.groovy.setUndoManager(new UndoManager());
+
+ docs.scala = new EditSession(document.getElementById("scala").innerHTML);
+ docs.scala.setMode(new ScalaMode());
+ docs.scala.setUndoManager(new UndoManager());
+
+
+
+
// Add a "name" property to all docs
for (doc in docs) {
docs[doc].name = doc;
@@ -206,7 +220,9 @@ exports.launch = function(env) {
perl: new PerlMode(),
clojure: new ClojureMode(),
ocaml: new OcamlMode(),
- csharp: new CSharpMode()
+ csharp: new CSharpMode(),
+ groovy: new GroovyMode(),
+ scala: new ScalaMode()
};
function getMode() {
@@ -297,6 +313,12 @@ exports.launch = function(env) {
else if (mode instanceof TextileMode) {
modeEl.value = "textile";
}
+ else if (mode instanceof GroovyMode) {
+ modeEl.value = "groovy";
+ }
+ else if (mode instanceof ScalaMode) {
+ modeEl.value = "scala";
+ }
else {
modeEl.value = "text";
}
@@ -455,8 +477,9 @@ exports.launch = function(env) {
});
event.addListener(container, "drop", function(e) {
+ var file
try {
- var file = e.dataTransfer.files[0];
+ file = e.dataTransfer.files[0];
} catch(e) {
return event.stopEvent();
}
@@ -497,6 +520,10 @@ exports.launch = function(env) {
mode = "perl";
} else if (/^.*\.(ml|mli)$/i.test(file.name)) {
mode = "ocaml";
+ } else if (/^.*\.(groovy)$/i.test(file.name)) {
+ mode = "groovy";
+ } else if (/^.*\.(scala)$/i.test(file.name)) {
+ mode = "scala";
}
env.editor.onTextInput(reader.result);
diff --git a/index.html b/index.html
index 72b0609f..01af8091 100644
--- a/index.html
+++ b/index.html
@@ -35,6 +35,8 @@
+
+
@@ -62,6 +64,8 @@
+
+
@@ -631,6 +635,49 @@ bg. Blockquote!
+
+
+
diff --git a/lib/ace/mode/groovy.js b/lib/ace/mode/groovy.js
new file mode 100644
index 00000000..b0d51d87
--- /dev/null
+++ b/lib/ace/mode/groovy.js
@@ -0,0 +1,26 @@
+define(function(require, exports, module) {
+
+var oop = require("pilot/oop");
+var JavaScriptMode = require("ace/mode/javascript").Mode;
+var Tokenizer = require("ace/tokenizer").Tokenizer;
+var GroovyHighlightRules = require("ace/mode/groovy_highlight_rules").GroovyHighlightRules;
+var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
+
+var Mode = function() {
+ this.$tokenizer = new Tokenizer(new GroovyHighlightRules().getRules());
+ this.$outdent = new MatchingBraceOutdent();
+ this.$behaviour = new CstyleBehaviour();
+};
+oop.inherits(Mode, JavaScriptMode);
+
+(function() {
+
+ this.createWorker = function(session) {
+ return null;
+ };
+
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
diff --git a/lib/ace/mode/groovy_highlight_rules.js b/lib/ace/mode/groovy_highlight_rules.js
new file mode 100644
index 00000000..c71161ff
--- /dev/null
+++ b/lib/ace/mode/groovy_highlight_rules.js
@@ -0,0 +1,164 @@
+define(function(require, exports, module) {
+
+var oop = require("pilot/oop");
+var lang = require("pilot/lang");
+var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
+
+var GroovyHighlightRules = function() {
+
+ var keywords = lang.arrayToMap(
+ ("assert|with|abstract|continue|for|new|switch|" +
+ "assert|default|goto|package|synchronized|" +
+ "boolean|do|if|private|this|" +
+ "break|double|implements|protected|throw|" +
+ "byte|else|import|public|throws|" +
+ "case|enum|instanceof|return|transient|" +
+ "catch|extends|int|short|try|" +
+ "char|final|interface|static|void|" +
+ "class|finally|long|strictfp|volatile|" +
+ "def|float|native|super|while").split("|")
+ );
+
+ var buildinConstants = lang.arrayToMap(
+ ("null|Infinity|NaN|undefined").split("|")
+ );
+
+ var langClasses = lang.arrayToMap(
+ ("AbstractMethodError|AssertionError|ClassCircularityError|"+
+ "ClassFormatError|Deprecated|EnumConstantNotPresentException|"+
+ "ExceptionInInitializerError|IllegalAccessError|"+
+ "IllegalThreadStateException|InstantiationError|InternalError|"+
+ "NegativeArraySizeException|NoSuchFieldError|Override|Process|"+
+ "ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|"+
+ "SuppressWarnings|TypeNotPresentException|UnknownError|"+
+ "UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|"+
+ "InstantiationException|IndexOutOfBoundsException|"+
+ "ArrayIndexOutOfBoundsException|CloneNotSupportedException|"+
+ "NoSuchFieldException|IllegalArgumentException|NumberFormatException|"+
+ "SecurityException|Void|InheritableThreadLocal|IllegalStateException|"+
+ "InterruptedException|NoSuchMethodException|IllegalAccessException|"+
+ "UnsupportedOperationException|Enum|StrictMath|Package|Compiler|"+
+ "Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|"+
+ "NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|"+
+ "NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|"+
+ "Character|Boolean|StackTraceElement|Appendable|StringBuffer|"+
+ "Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|"+
+ "StackOverflowError|OutOfMemoryError|VirtualMachineError|"+
+ "ArrayStoreException|ClassCastException|LinkageError|"+
+ "NoClassDefFoundError|ClassNotFoundException|RuntimeException|"+
+ "Exception|ThreadDeath|Error|Throwable|System|ClassLoader|"+
+ "Cloneable|Class|CharSequence|Comparable|String|Object").split("|")
+ );
+
+ var importClasses = lang.arrayToMap(
+ ("").split("|")
+ );
+ // regexp must not have capturing parentheses. Use (?:) instead.
+ // regexps are ordered -> the first match is used
+
+ this.$rules = {
+ "start" : [
+ {
+ token : "comment",
+ regex : "\\/\\/.*$"
+ },
+ new DocCommentHighlightRules().getStartRule("doc-start"),
+ {
+ token : "comment", // multi line comment
+ regex : "\\/\\*",
+ next : "comment"
+ }, {
+ token : "comment", // multi line comment
+ regex : "\\/\\*\\*",
+ next : "comment"
+ }, {
+ token : "string.regexp",
+ regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
+ }, {
+ token : "string", // single line
+ regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+ }, {
+ token : "string", // single line
+ regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+ }, {
+ token : "constant.numeric", // hex
+ regex : "0[xX][0-9a-fA-F]+\\b"
+ }, {
+ token : "constant.numeric", // float
+ regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+ }, {
+ token : "constant.language.boolean",
+ regex : "(?:true|false)\\b"
+ }, {
+ token : function(value) {
+ if (value == "this")
+ return "variable.language";
+ else if (keywords.hasOwnProperty(value))
+ return "keyword";
+ else if (langClasses.hasOwnProperty(value))
+ return "support.function";
+ else if (importClasses.hasOwnProperty(value))
+ return "support.function";
+ else if (buildinConstants.hasOwnProperty(value))
+ return "constant.language";
+ else
+ return "identifier";
+ },
+ // TODO: Unicode escape sequences
+ // TODO: Unicode identifiers
+ regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+ }, {
+ token : "keyword.operator",
+ regex : "\\?:|\\?\\.|\\*\\.|<=>|=~|==~|\\.@|\\*\\.@|\\.&|as|in|is|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+ }, {
+ token : "lparen",
+ regex : "[[({]"
+ }, {
+ token : "rparen",
+ regex : "[\\])}]"
+ }, {
+ token : "text",
+ regex : "\\s+"
+ }
+ ],
+ "comment" : [
+ {
+ token : "comment", // closing comment
+ regex : ".*?\\*\\/",
+ next : "start"
+ }, {
+ token : "comment", // comment spanning whole line
+ regex : ".+"
+ }
+ ],
+ "qqstring" : [
+ {
+ token : "string",
+ regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
+ next : "start"
+ }, {
+ token : "string",
+ regex : '.+'
+ }
+ ],
+ "qstring" : [
+ {
+ token : "string",
+ regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
+ next : "start"
+ }, {
+ token : "string",
+ regex : '.+'
+ }
+ ]
+ };
+
+ this.embedRules(DocCommentHighlightRules, "doc-",
+ [ new DocCommentHighlightRules().getEndRule("start") ]);
+};
+
+oop.inherits(GroovyHighlightRules, TextHighlightRules);
+
+exports.GroovyHighlightRules = GroovyHighlightRules;
+});
diff --git a/lib/ace/mode/scala.js b/lib/ace/mode/scala.js
new file mode 100644
index 00000000..f1690fb6
--- /dev/null
+++ b/lib/ace/mode/scala.js
@@ -0,0 +1,26 @@
+define(function(require, exports, module) {
+
+var oop = require("pilot/oop");
+var JavaScriptMode = require("ace/mode/javascript").Mode;
+var Tokenizer = require("ace/tokenizer").Tokenizer;
+var ScalaHighlightRules = require("ace/mode/scala_highlight_rules").ScalaHighlightRules;
+var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent;
+var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour;
+
+var Mode = function() {
+ this.$tokenizer = new Tokenizer(new ScalaHighlightRules().getRules());
+ this.$outdent = new MatchingBraceOutdent();
+ this.$behaviour = new CstyleBehaviour();
+};
+oop.inherits(Mode, JavaScriptMode);
+
+(function() {
+
+ this.createWorker = function(session) {
+ return null;
+ };
+
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
diff --git a/lib/ace/mode/scala_highlight_rules.js b/lib/ace/mode/scala_highlight_rules.js
new file mode 100644
index 00000000..d3987929
--- /dev/null
+++ b/lib/ace/mode/scala_highlight_rules.js
@@ -0,0 +1,165 @@
+define(function(require, exports, module) {
+
+var oop = require("pilot/oop");
+var lang = require("pilot/lang");
+var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
+
+var ScalaHighlightRules = function() {
+
+ // taken from http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
+ var keywords = lang.arrayToMap(
+ (
+ "case|default|do|else|for|if|match|while|throw|return|try|catch|finally|yield|" +
+ "abstract|class|def|extends|final|forSome|implicit|implicits|import|lazy|new|object|" +
+ "override|package|private|protected|sealed|super|this|trait|type|val|var|with"
+ ).split("|")
+ );
+
+ var buildinConstants = lang.arrayToMap(
+ ("true|false").split("|")
+ );
+
+ var langClasses = lang.arrayToMap(
+ ("AbstractMethodError|AssertionError|ClassCircularityError|"+
+ "ClassFormatError|Deprecated|EnumConstantNotPresentException|"+
+ "ExceptionInInitializerError|IllegalAccessError|"+
+ "IllegalThreadStateException|InstantiationError|InternalError|"+
+
+ "NegativeArraySizeException|NoSuchFieldError|Override|Process|"+
+ "ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|"+
+ "SuppressWarnings|TypeNotPresentException|UnknownError|"+
+ "UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|"+
+ "InstantiationException|IndexOutOfBoundsException|"+
+ "ArrayIndexOutOfBoundsException|CloneNotSupportedException|"+
+ "NoSuchFieldException|IllegalArgumentException|NumberFormatException|"+
+ "SecurityException|Void|InheritableThreadLocal|IllegalStateException|"+
+ "InterruptedException|NoSuchMethodException|IllegalAccessException|"+
+ "UnsupportedOperationException|Enum|StrictMath|Package|Compiler|"+
+ "Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|"+
+ "NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|"+
+ "NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|"+
+ "Character|Boolean|StackTraceElement|Appendable|StringBuffer|"+
+ "Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|"+
+ "StackOverflowError|OutOfMemoryError|VirtualMachineError|"+
+ "ArrayStoreException|ClassCastException|LinkageError|"+
+ "NoClassDefFoundError|ClassNotFoundException|RuntimeException|"+
+ "Exception|ThreadDeath|Error|Throwable|System|ClassLoader|"+
+ "Cloneable|Class|CharSequence|Comparable|String|Object|" +
+ "Unit|Any|AnyVal|AnyRef|Null|ScalaObject|Singleton|Seq|Iterable|List|" +
+ "Option|Array|Char|Byte|Short|Int|Long|Nothing"
+
+ ).split("|")
+ );
+
+ var importClasses = lang.arrayToMap(
+ ("").split("|")
+ );
+ // regexp must not have capturing parentheses. Use (?:) instead.
+ // regexps are ordered -> the first match is used
+
+ this.$rules = {
+ "start" : [
+ {
+ token : "comment",
+ regex : "\\/\\/.*$"
+ },
+ new DocCommentHighlightRules().getStartRule("doc-start"),
+ {
+ token : "comment", // multi line comment
+ regex : "\\/\\*",
+ next : "comment"
+ }, {
+ token : "comment", // multi line comment
+ regex : "\\/\\*\\*",
+ next : "comment"
+ }, {
+ token : "string.regexp",
+ regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
+ }, {
+ token : "string", // single line
+ regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+ }, {
+ token : "string", // single line
+ regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+ }, {
+ token : "constant.numeric", // hex
+ regex : "0[xX][0-9a-fA-F]+\\b"
+ }, {
+ token : "constant.numeric", // float
+ regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+ }, {
+ token : "constant.language.boolean",
+ regex : "(?:true|false)\\b"
+ }, {
+ token : function(value) {
+ if (value == "this")
+ return "variable.language";
+ else if (keywords.hasOwnProperty(value))
+ return "keyword";
+ else if (langClasses.hasOwnProperty(value))
+ return "support.function";
+ else if (importClasses.hasOwnProperty(value))
+ return "support.function";
+ else if (buildinConstants.hasOwnProperty(value))
+ return "constant.language";
+ else
+ return "identifier";
+ },
+ // TODO: Unicode escape sequences
+ // TODO: Unicode identifiers
+ regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+ }, {
+ token : "keyword.operator",
+ regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
+ }, {
+ token : "lparen",
+ regex : "[[({]"
+ }, {
+ token : "rparen",
+ regex : "[\\])}]"
+ }, {
+ token : "text",
+ regex : "\\s+"
+ }
+ ],
+ "comment" : [
+ {
+ token : "comment", // closing comment
+ regex : ".*?\\*\\/",
+ next : "start"
+ }, {
+ token : "comment", // comment spanning whole line
+ regex : ".+"
+ }
+ ],
+ "qqstring" : [
+ {
+ token : "string",
+ regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
+ next : "start"
+ }, {
+ token : "string",
+ regex : '.+'
+ }
+ ],
+ "qstring" : [
+ {
+ token : "string",
+ regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
+ next : "start"
+ }, {
+ token : "string",
+ regex : '.+'
+ }
+ ]
+ };
+
+ this.embedRules(DocCommentHighlightRules, "doc-",
+ [ new DocCommentHighlightRules().getEndRule("start") ]);
+};
+
+oop.inherits(ScalaHighlightRules, TextHighlightRules);
+
+exports.ScalaHighlightRules = ScalaHighlightRules;
+});