diff --git a/Makefile.dryice.js b/Makefile.dryice.js index 122c116f..1e074006 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -225,7 +225,7 @@ console.log('# ace modes ---------'); project.assumeAllFilesLoaded(); [ "css", "html", "javascript", "php", "coldfusion", "python", "lua", "xml", "ruby", "java", "c_cpp", - "coffee", "perl", "csharp", "svg", "clojure", "scss", "json", "groovy", + "coffee", "perl", "csharp", "haxe", "svg", "clojure", "scss", "json", "groovy", "ocaml", "scala", "textile", "scad", "markdown", "latex", "powershell", "sql" ].forEach(function(mode) { console.log("mode " + mode); diff --git a/build_support/boot_textarea.js b/build_support/boot_textarea.js index 21610d00..5109067c 100644 --- a/build_support/boot_textarea.js +++ b/build_support/boot_textarea.js @@ -416,6 +416,7 @@ function setupSettingPanel(settingDiv, settingOpener, api, options) { clojure: "Clojure", ocaml: "OCaml", csharp: "C#", + haxe: "haXe", svg: "SVG", textile: "Textile", groovy: "Groovy", diff --git a/demo/kitchen-sink/demo.js b/demo/kitchen-sink/demo.js index 177d551e..94caef64 100644 --- a/demo/kitchen-sink/demo.js +++ b/demo/kitchen-sink/demo.js @@ -107,6 +107,7 @@ var modes = [ new Mode("csharp", "C#", require("ace/mode/csharp").Mode, ["cs"]), new Mode("css", "CSS", require("ace/mode/css").Mode, ["css"]), new Mode("groovy", "Groovy", require("ace/mode/groovy").Mode, ["groovy"]), + new Mode("haxe", "haXe", require("ace/mode/haxe").Mode, ["hx"]), new Mode("html", "HTML", require("ace/mode/html").Mode, ["html", "htm"]), new Mode("java", "Java", require("ace/mode/java").Mode, ["java"]), new Mode("javascript", "JavaScript", require("ace/mode/javascript").Mode, ["js"]), @@ -229,6 +230,10 @@ var docs = [ "c_cpp", "C/C++", require("ace/requirejs/text!./docs/cpp.cpp") ), + new Doc( + "haxe", "haXe", + require("ace/requirejs/text!./docs/Haxe.hx") + ), new WrappedDoc( "markdown", "Markdown", require("ace/requirejs/text!./docs/markdown.md") diff --git a/demo/kitchen-sink/docs/Haxe.hx b/demo/kitchen-sink/docs/Haxe.hx new file mode 100644 index 00000000..ab205bba --- /dev/null +++ b/demo/kitchen-sink/docs/Haxe.hx @@ -0,0 +1,17 @@ +class Haxe +{ + public static function main() + { + // Say Hello! + var greeting:String = "Hello World"; + trace(greeting); + + var targets:Array = ["Flash","Javascript","PHP","Neko","C++","iOS","Android","webOS"]; + trace("Haxe is a great language that can target:"); + for (target in targets) + { + trace (" - " + target); + } + trace("And many more!"); + } +} \ No newline at end of file diff --git a/lib/ace/mode/haxe.js b/lib/ace/mode/haxe.js new file mode 100644 index 00000000..22b9e4af --- /dev/null +++ b/lib/ace/mode/haxe.js @@ -0,0 +1,56 @@ +define(function(require, exports, module) { + +var oop = require("pilot/oop"); +var TextMode = require("ace/mode/text").Mode; +var Tokenizer = require("ace/tokenizer").Tokenizer; +var HaxeHighlightRules = require("ace/mode/haxe_highlight_rules").HaxeHighlightRules; +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 HaxeHighlightRules().getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.$tokenizer.getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + + this.createWorker = function(session) { + return null; + }; + +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/lib/ace/mode/haxe_highlight_rules.js b/lib/ace/mode/haxe_highlight_rules.js new file mode 100644 index 00000000..cb36c410 --- /dev/null +++ b/lib/ace/mode/haxe_highlight_rules.js @@ -0,0 +1,103 @@ +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 HaxeHighlightRules = function() { + + var keywords = lang.arrayToMap( + ("break|case|cast|catch|class|continue|default|else|enum|extends|for|function|if|implements|import|in|inline|interface|new|override|package|private|public|return|static|super|switch|this|throw|trace|try|typedef|untyped|var|while|Array|Void|Bool|Int|UInt|Float|Dynamic|String|List|Hash|IntHash|Error|Unknown|Type|Std").split("|") + ); + + var buildinConstants = lang.arrayToMap( + ("null|true|false").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 : "\\/\\*", + merge : true, + 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 (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 : "punctuation.operator", + regex : "\\?|\\:|\\,|\\;|\\." + }, { + token : "paren.lparen", + regex : "[[({<]" + }, { + token : "paren.rparen", + regex : "[\\])}>]" + }, { + token : "text", + regex : "\\s+" + } + ], + "comment" : [ + { + token : "comment", // closing comment + regex : ".*?\\*\\/", + next : "start" + }, { + token : "comment", // comment spanning whole line + merge : true, + regex : ".+" + } + ] + }; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ new DocCommentHighlightRules().getEndRule("start") ]); +}; + +oop.inherits(HaxeHighlightRules, TextHighlightRules); + +exports.HaxeHighlightRules = HaxeHighlightRules; +});