From 3dd62918c524362d8b02952f920ca227a2d52619 Mon Sep 17 00:00:00 2001 From: Tim Caswell Date: Tue, 1 Oct 2013 11:20:26 -0500 Subject: [PATCH] Add Jack mode --- demo/kitchen-sink/docs/Jack.jack | 247 +++++++++++++++++++++++++++ lib/ace/ext/modelist.js | 1 + lib/ace/mode/jack.js | 77 +++++++++ lib/ace/mode/jack_highlight_rules.js | 142 +++++++++++++++ 4 files changed, 467 insertions(+) create mode 100644 demo/kitchen-sink/docs/Jack.jack create mode 100644 lib/ace/mode/jack.js create mode 100644 lib/ace/mode/jack_highlight_rules.js diff --git a/demo/kitchen-sink/docs/Jack.jack b/demo/kitchen-sink/docs/Jack.jack new file mode 100644 index 00000000..15acf743 --- /dev/null +++ b/demo/kitchen-sink/docs/Jack.jack @@ -0,0 +1,247 @@ +vars it, p + +p = {label, value| + print("\n" + label) + print(inspect(value)) +} +-- Create an array from 0 to 15 +p("range", i-collect(range(5))) + +-- Create an array from 0 to 15 and break up in chunks of 4 +p("chunked range", i-collect(i-chunk(4, range(16)))) + +-- Check if all or none items in stream pass test. +p("all < 60 in range(60)", i-all?({i|i<60}, range(60))) +p("any < 60 in range(60)", i-any?({i|i>60}, range(60))) +p("all < 60 in range(70)", i-all?({i|i<60}, range(70))) +p("any < 60 in range(70)", i-any?({i|i>60}, range(70))) + +-- Zip three different collections together +p("zipped", i-collect(i-zip( + range(10), + [1,2,3,4,5], + i-map({i|i*i}, range(10)) +))) + +vars names, person, i, doubles, lengths, cubeRange +names = ["Thorin", "Dwalin", "Balin", "Bifur", "Bofur", "Bombur", "Oin", + "Gloin", "Ori", "Nori", "Dori", "Fili", "Kili", "Bilbo", "Gandalf"] + +for name in names { + if name != "Bilbo" && name != "Gandalf" { + print(name) + } +} + +person = {name: "Tim", age: 30} +for key, value in person { + print(key + " = " + value) +} + +i = 0 +while i < 10 { + i = i + 1 + print(i) +} + +print("range") +for i in range(10) { + print(i + 1) +} +for i in range(10) { + print(10 - i) +} + +-- Dynamic object that gives the first 10 doubles +doubles = { + @len: {| 10 } + @get: {key| + if key is Integer { key * key } + } +} +print("#doubles", #doubles) + +print("Doubles") +for k, v in doubles { + print([k, v]) +} + +-- Dynamic object that has names list as keys and string lenth as values +lengths = { + @keys: {| names } + @get: {key| + if key is String { #key } + } +} + +print ("Lengths") +for k, v in lengths { + print([k, v]) +} + + +cubeRange = {n| + vars i, v + i = 0 + { + @call: {| + v = i + i = i + 1 + if v < n { v * v * v } + } + } +} + +print("Cubes") +for k, v in cubeRange(5) { + print([k, v]) +} +print("String") +for k, v in "Hello World" { + print([k, v]) +} + + +print([i for i in range(10)]) +print([i for i in range(20) if i % 3]) + + + +-- Example showing how to do parallel work using split..and +base = {bootstrap, target-dir| + split { + copy("res", target-dir) + } and { + if newer("src/*.less", target-dir + "/style.css") { + lessc("src/" + bootstrap + ".less", target-dir + "/style.css") + } + } and { + build("src/" + bootstrap + ".js", target-dir + "/app.js") + } +} + + +vars Dragon, pet + +Dragon = {name| + vars asleep, stuff-in-belly, stuff-in-intestine, + feed, walk, put-to-bed, toss, rock, + hungry?, poopy?, passage-of-time + + asleep = false + stuff-in-belly = 10 -- He's full. + stuff-in-intestine = 0 -- He doesn't need to go. + + print(name + ' is born.') + + feed = {| + print('You feed ' + name + '.') + stuff-in-belly = 10 + passage-of-time() + } + + walk = {| + print('You walk ' + name + ".") + stuff-in-intestine = 0 + passage-of-time + } + + put-to-bed = {| + print('You put ' + name + ' to bed.') + asleep = true + for i in range(3) { + if asleep { + passage-of-time() + } + if asleep { + print(name + ' snores, filling the room with smoke.') + } + } + if asleep { + asleep = false + print(name + ' wakes up slowly.') + } + } + + toss = {| + print('You toss ' + name + ' up into the air.') + print('He giggles, which singes your eyebrows.') + passage-of-time() + } + + rock = {| + print('You rock ' + name + ' gently.') + asleep = true + print('He briefly dozes off...') + passage-of-time() + if asleep { + asleep = false + print('...but wakes when you stop.') + } + } + + hungry? = {| + stuff-in-belly <= 2 + } + + poopy? = {| + stuff-in-intestine >= 8 + } + + passage-of-time = {| + if stuff-in-belly > 0 { + -- Move food from belly to intestine + stuff-in-belly = stuff-in-belly - 1 + stuff-in-intestine = stuff-in-intestine + 1 + } else { -- Our dragon is starving! + if asleep { + asleep = false + print('He wakes up suddenly!') + } + print(name + ' is starving! In desperation, he ate YOU!') + abort "died" + } + + if stuff-in-intestine >= 10 { + stuff-in-intestine = 0 + print('Whoops! ' + name + ' had an accident...') + } + + if hungry?() { + if asleep { + asleep = false + print('He wakes up suddenly!') + } + print(name + "'s stomach grumbles...") + } + + if poopy?() { + if asleep { + asleep = false + print('He wakes up suddenly!') + } + print(name + ' does the potty dance...') + } + } + + -- Export the public interface to this closure object. + { + feed: feed + walk: walk + put-to-bed: put-to-bed + toss: toss + rock: rock + } + +} + +pet = Dragon('Norbert') +pet.feed() +pet.toss() +pet.walk() +pet.put-to-bed() +pet.rock() +pet.put-to-bed() +pet.put-to-bed() +pet.put-to-bed() +pet.put-to-bed() diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 6febbf6d..88b0218d 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -76,6 +76,7 @@ var supportedModes = { HTML: ["html|htm|xhtml"], HTML_Ruby: ["erb|rhtml|html.erb"], INI: ["ini|conf|cfg|prefs"], + Jack: ["jack"], Jade: ["jade"], Java: ["java"], JavaScript: ["js|jsm"], diff --git a/lib/ace/mode/jack.js b/lib/ace/mode/jack.js new file mode 100644 index 00000000..327e200b --- /dev/null +++ b/lib/ace/mode/jack.js @@ -0,0 +1,77 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var HighlightRules = require("./jack_highlight_rules").JackHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = HighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + 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); + }; + + +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/lib/ace/mode/jack_highlight_rules.js b/lib/ace/mode/jack_highlight_rules.js new file mode 100644 index 00000000..edf7c856 --- /dev/null +++ b/lib/ace/mode/jack_highlight_rules.js @@ -0,0 +1,142 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var JackHighlightRules = function() { + + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + this.$rules = { + "start" : [ + { + token : "string", + regex : '"', + next : "string2" + }, { + token : "string", + regex : "'", + next : "string1" + }, { + token : "constant.numeric", // hex + regex: "-?0[xX][0-9a-fA-F]+\\b" + }, { + token : "constant.numeric", // float + regex : "(?:0|[-+]?[1-9][0-9]*)\\b" + }, { + token : "constant.binary", + regex : "<[0-9A-Fa-f][0-9A-Fa-f](\\s+[0-9A-Fa-f][0-9A-Fa-f])*>" + }, { + token : "constant.language.boolean", + regex : "(?:true|false)\\b" + }, { + token : "constant.language.null", + regex : "null\\b" + }, { + token : "storage.type", + regex: "(?:Integer|Boolean|Null|String|Buffer|Tuple|List|Object|Function|Coroutine|Form)\\b" + }, { + token : "keyword", + regex : "(?:return|abort|vars|for|delete|in|is|escape|exec|split|and|if|elif|else|while)\\b" + }, { + token : "language.builtin", + regex : "(?:lines|source|parse|read-stream|interval|substr|parseint|write|print|range|rand|inspect|bind|i-values|i-pairs|i-map|i-filter|i-chunk|i-all\\?|i-any\\?|i-collect|i-zip|i-merge|i-each)\\b" + }, { + token : "comment", + regex : "--.*$" + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "storage.form", + regex : "@[a-z]+" + }, { + token : "constant.other.symbol", + regex : ':+[a-zA-Z_]([-]?[a-zA-Z0-9_])*[?!]?' + }, { + token : "variable", + regex : '[a-zA-Z_]([-]?[a-zA-Z0-9_])*[?!]?' + }, { + token : "keyword.operator", + regex : "\\|\\||\\^\\^|&&|!=|==|<=|<|>=|>|\\+|-|\\*|\\/|\\^|\\%|\\#|\\!" + }, { + token : "text", + regex : "\\s+" + } + ], + "string1" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|['"\\\/bfnrt])/ + }, { + token : "string", + regex : "[^'\\\\]+" + }, { + token : "string", + regex : "'", + next : "start" + }, { + token : "string", + regex : "", + next : "start" + } + ], + "string2" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|['"\\\/bfnrt])/ + }, { + token : "string", + regex : '[^"\\\\]+' + }, { + token : "string", + regex : '"', + next : "start" + }, { + token : "string", + regex : "", + next : "start" + } + ] + }; + +}; + +oop.inherits(JackHighlightRules, TextHighlightRules); + +exports.JackHighlightRules = JackHighlightRules; +});