Merge pull request #316 from btilford/scala-groovy

Scala & Groovy highlighting
This commit is contained in:
Fabian Jakobs 2011-06-30 03:06:22 -07:00
commit c86df01d5e
6 changed files with 457 additions and 2 deletions

View file

@ -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);

View file

@ -35,6 +35,8 @@
<option value="clojure">Clojure</option>
<option value="ocaml">OCaml</option>
<option value="textile">Textile</option>
<option value="groovy">Groovy</option>
<option value="scala">Scala</option>
</select>
</td>
</tr>
@ -62,6 +64,8 @@
<option value="csharp">C-Sharp</option>
<option value="svg">SVG</option>
<option value="textile">Textile</option>
<option value="groovy">Groovy</option>
<option value="scala">Scala</option>
</select>
</td>
</tr>
@ -631,6 +635,49 @@ bg. Blockquote!
</script>
<script type="text/editor" id="groovy">
//http://groovy.codehaus.org/Concurrency+with+Groovy
import java.util.concurrent.atomic.AtomicInteger
def counter = new AtomicInteger()
synchronized out(message) {
println(message)
}
def th = Thread.start {
for( i in 1..8 ) {
sleep 30
out "thread loop $i"
counter.incrementAndGet()
}
}
for( j in 1..4 ) {
sleep 50
out "main loop $j"
counter.incrementAndGet()
}
th.join()
assert counter.get() == 12
</script>
<script type="text/editor" id="scala">
//http://www.scala-lang.org/node/227
/* Defines a new method 'sort' for array objects */
object implicits extends Application {
implicit def arrayWrapper[A : ClassManifest](x: Array[A]) =
new {
def sort(p: (A, A) => Boolean) = {
util.Sorting.stableSort(x, p); x
}
}
val x = Array(2, 3, 1, 4)
println("x = "+ x.sort((x: Int, y: Int) => x < y))
}
</script>
<input id="cockpitInput" type="text"/>
<script src="demo/require.js" type="text/javascript" charset="utf-8"></script>

26
lib/ace/mode/groovy.js Normal file
View file

@ -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;
});

View file

@ -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;
});

26
lib/ace/mode/scala.js Normal file
View file

@ -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;
});

View file

@ -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;
});