diff --git a/demo/kitchen-sink/demo.js b/demo/kitchen-sink/demo.js index c1524cdc..4b0e1c32 100644 --- a/demo/kitchen-sink/demo.js +++ b/demo/kitchen-sink/demo.js @@ -447,7 +447,7 @@ new StatusBar(env.editor, cmdLine.container); require("ace/placeholder").PlaceHolder; var SnippetManager = require("ace/snippets").SnippetManager -var jsSnippets = require("ace/requirejs/text!./snippets/js.json") +var jsSnippets = require("ace/snippets/javascript"); var testSnippet = "\ \\begin{${1:document}}\n\ ${2:$TM_SELECTED_TEXT:some ${3:latex}}\n\ @@ -460,7 +460,8 @@ SnippetManager.register({ tabTrigger: "t", name: "testSnippet" }) -SnippetManager.register(JSON.parse(jsSnippets).snippets) +jsSnippets.snippets = SnippetManager.parseSnippetFile(jsSnippets.snippetText) +SnippetManager.register(jsSnippets.snippets) ace.commands.bindKey("Tab", function(editor) { diff --git a/demo/kitchen-sink/package.json b/demo/kitchen-sink/package.json deleted file mode 100644 index 2345fccd..00000000 --- a/demo/kitchen-sink/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "main": "./demo.js", - "mappings": { - "ace": "../.." - }, - "config": { - "github.com/sourcemint/bundler-js/0/-meta/config/0": { - "adapter": "github.com/sourcemint/sdk-requirejs/0", - "resources": [ - "./icons/*", - "./logo.png", - "./styles.css" - ] - } - } -} \ No newline at end of file diff --git a/demo/kitchen-sink/snippets/js.json b/demo/kitchen-sink/snippets/js.json deleted file mode 100644 index 8ece6bd4..00000000 --- a/demo/kitchen-sink/snippets/js.json +++ /dev/null @@ -1,72 +0,0 @@ -{"snippets":[{ - "content": "var ${1:class} = function(${20}) {\n\t$40$0\n};\n\n(function() {\n\t${60:this.prop = \"\"}\n}).call(${1:class}.prototype);", - "name": "class", - "scope": "js", - "tabTrigger": "class" -}, { - "content": "for (var ${20:i} = ${1:Things}.length; ${20:i} --; ) {\n\t${100:${1:Things}[${20:i}]}$0\n};", - "name": "backwards for loop", - "scope": "js", - "tabTrigger": "for-" -}, { - "content": "for (var ${20:i} = ${1:Things}.length - 1; ${20:i} >= 0; ${20:i}--) {\n\t${100:${1:Things}[${20:i}]}$0\n};", - "name": "for (…) {…} (Improved Native For-Loop)", - "scope": "js", - "tabTrigger": "for" -}, { - "content": "for (var ${20:i}=0; ${20:i} < ${1:Things}.length; ${20:i}++) {\n\t${100:${1:Things}[${20:i}]}$0\n};", - "name": "for (…) {…}", - "scope": "js", - "tabTrigger": "for" -}, { - "content":"function ${1:function_name} (${2:argument}) {\n\t${0:// body...}\n}", - "name": "Function", - "scope": "js", - "tabTrigger": "fun" -}, { - "content": "function($1) {${0:$TM_SELECTED_TEXT}};", - "name": "Anonymous Function", - "scope": "js", - "tabTrigger": "f" -}, { - "content": "getElement${1/(T)|.*/(?1:s)/}By${1:T}${1/(T)|(I)|.*/(?1:agName)(?2:d)/}('$2')", - "name": "Get Elements", - "scope": "js", - "tabTrigger": "get" -}, { - "content": "if (${1:true}) {\n\t${0:$TM_SELECTED_TEXT}\n} else {\n\t\n}", - "name": "if … else", - "scope": "js", - "tabTrigger": "ife" -}, { - "content": "if (${1:true}) {${0:$TM_SELECTED_TEXT}}", - "name": "if", - "scope": "js", - "tabTrigger": "if" -}, { - "content": "'${1:${2:#thing}:${3:click}}': function(element){\n\t$0\n}${10:,}", - "name": "Object Method String", - "scope": "js", - "tabTrigger": "'':f" -}, { - "content": "${1:method_name}: function(${3:attribute}){\n\t$0\n}${10:,}", - "name": "Object Method", - "scope": "js", - "tabTrigger": ":f" -}, { - "content": "${1:value_name}:${0:value},", - "name": "Object Value JS", - "scope": "js", - "tabTrigger": ":," -}, { - "content": "${1:class_name}.prototype.${2:method_name} = function(${3:first_argument}) {\n\t${0:// body...}\n};\n", - "name": "Prototype", - "scope": "js", - "tabTrigger": "proto" -}, { - "content": "setTimeout(function() {$0}${2:}, ${1:10});", - "name": "setTimeout function", - "scope": "js", - "tabTrigger": "timeout" -}] -} \ No newline at end of file diff --git a/lib/ace/range.js b/lib/ace/range.js index 9538531a..26492865 100644 --- a/lib/ace/range.js +++ b/lib/ace/range.js @@ -540,5 +540,10 @@ Range.fromPoints = function(start, end) { }; Range.comparePoints = comparePoints; +Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; +}; + + exports.Range = Range; }); diff --git a/lib/ace/snippets.js b/lib/ace/snippets.js index c678ace1..a9fe8e89 100644 --- a/lib/ace/snippets.js +++ b/lib/ace/snippets.js @@ -30,9 +30,9 @@ define(function(require, exports, module) { "use strict"; -var Range = require("ace/range").Range -var HashHandler = require("ace/keyboard/hash_handler").HashHandler; -var RangeList = require("ace/range_list").RangeList; +var Range = require("./range").Range +var lang = require("./lib/lang") +var HashHandler = require("./keyboard/hash_handler").HashHandler; var SnippetManager = function() { this.snippets = []; @@ -59,7 +59,7 @@ var SnippetManager = function() { // m[3] = \$(\w+) variables or tabstops // m[4] = \$\{([\dA-Z_]+) // m[5] = format string - var re = /\\([\$}`\\])|(})|\n|\$(\w+)|\$\{([\dA-Z_]+)([\/|`])?(\:?)/g; + var re = /\\([\$}`\\])|(})|\n|\$(\d+|\w+)|\$\{([\dA-Z_]+)([\/|`])?(\:?)/g; var formatters = { "/": /((\/(?:\\.|[^\/])+){1,20})\/\w*/g, // replace or guard "|": /|[^|}]+|/g, // choice list @@ -91,7 +91,7 @@ var SnippetManager = function() { } else if (m[4]) { // variable var placeholder = addVar(m[4], {}); if (m[5]) - readFormatString(placeholder, m[5]); + readFormatString(m[5], placeholder); if (stack[0]) stack[0].child = placeholder; stack.unshift(placeholder); @@ -140,8 +140,7 @@ var SnippetManager = function() { return this.$getDefaultValue(editor, varName); }; - // - // TODO: support \U \L \E + // returns string formatted according to http://manual.macromates.com/en/regular_expressions#replacement_string_syntax_format_strings this.tmStrFormat = function(str, fmt) { fmt = fmt.split("/"); fmt.shift(); @@ -153,17 +152,24 @@ var SnippetManager = function() { search += "/" + fmt.shift(); fmt = fmt.join("/"); var re = new RegExp(search, flags); + + var parseRe = /\\.|\\([ulULE])|\$(\d+)|\${(\d+)}|\(?(\d+):|\)/ + var fmtParts = []; + while (m = parseRe.exec(fmt)) { + if (m[1]) { + + } else if (m[2] || m[3]) { + + } else if (m[4]) { + + } + } + return str.replace(re, function() { var matches = arguments; - var result = fmt.replace(/(\\[ul])?\$(\d)/g, function(_, flag, index) { - var $ = matches[index] || ""; - if (flag == "\\u") { - $ = $[0].toUpperCase() + $.substr(1); - } else if (flag == "\\l") { - $ = $[0].toLowerCase() + $.substr(1); - } - return $; - }); + for (var i = 0; i < fmtParts; i++) { + + } return result; }); }; @@ -234,16 +240,14 @@ var SnippetManager = function() { }); tabstops.forEach(function(ts) { - if (ts.value) { - ts.forEach(function(p) { - var i = tokens.indexOf(p); - var i1 = tokens.indexOf(p, i + 1); - if (i1 == -1) - tokens.splice(i + 1, 0, ts.value, p); - else if (i1 == i + 1) - tokens.splice(i + 1, 0, ts.value); - }); - } + ts.value && ts.forEach(function(p) { + var i = tokens.indexOf(p); + var i1 = tokens.indexOf(p, i + 1); + if (i1 == -1) + tokens.splice(i + 1, 0, ts.value, p); + else if (i1 == i + 1) + tokens.splice(i + 1, 0, ts.value); + }); }); // convert to plain text var row = 0, column = 0; @@ -271,63 +275,135 @@ var SnippetManager = function() { tabstopManager.tabNext(); }; + this.$getScope = function(editor) { + var scope = editor.session.$mode.$id || ""; + scope = scope.split("/").pop(); + if (editor.session.$mode.$modes) { + var c = editor.getCursorPosition() + var state = editor.session.getState(c.row); + if (state.substring) { + if (state.substring(0, 3) == "js-") + scope = "javascript"; + else if (state.substring(0, 4) == "css-") + scope = "css"; + else if (state.substring(0, 4) == "php-") + scope = "php"; + } + } + return scope; + }; + this.expandWithTab = function(editor) { var cursor = editor.getCursorPosition(); var line = editor.session.getLine(cursor.row); var before = line.substring(0, cursor.column); var after = line.substr(cursor.column); - var s = this.snippets; - for (var i = this.snippets.length; i--;) { - var s = this.snippets[i]; - if (!s.trigger || !s.trigger.test(before)) - return; - - replacedText - var trigger = this.snippets[i].tabTrigger; - if (tabTrigger && before.slice(-tabTrigger.length) == tabTrigger) { - var matchedSnippet = this.snippets[i]; - break; - } - } - if (matchedSnippet) { - ace.session.doc.removeInLine(cursor.row, cursor.column - tabTrigger.length, cursor.column); - this.insertSnippet(editor, matchedSnippet.content, replacedText); - return true; - } + + var scope = this.$getScope(editor); + var snippetMap = this.snippetMap; + var snippet; + [scope, "_"].some(function(scope) { + var snippets = snippetMap[scope]; + if (snippets) + snippet = this.findMatchingSnippet(snippets, before, after); + return !!snippet; + }, this); + if (!snippet) + return false; + + editor.session.doc.removeInLine( + cursor.row, + cursor.column - snippet.matchBefore[0].length, + cursor.column - snippet.matchAfter[0].length + ); + this.insertSnippet(editor, snippet.content, snippet.matchBefore, snippet.matchAfter); + return true; }; - this.register = function(snippets) { - if (snippets.content) { - this.snippets.push(snippets) - } else { - this.snippets.push.apply(this.snippets, snippets) + + this.findMatchingSnippet = function(snippetList, before, after) { + for (var i = snippetList.length; i--;) { + var s = snippetList[i]; + if (s.startRe && !s.startRe.test(before)) + continue; + if (s.endRe && !s.endRe.test(after)) + continue; + if (!s.startRe && !s.endRe) + continue; + + s.matchBefore = s.startRe ? s.startRe.exec(before) : [""]; + s.matchAfter = s.endRe ? s.endRe.exec(after) : [""]; + return s; } }; + this.snippetMap = {}; + this.register = function(snippets, scope) { + var snippetMap = this.snippetMap; + function addSnippet(s) { + if (!s.scope) + s.scope = scope || "_"; + if (!snippetMap[s.scope]) + snippetMap[s.scope] = []; + snippetMap[s.scope].push(s); + + if (s.tabTrigger) { + if (/^\w/.test(s.tabTrigger)) + s.guard = "\\b"; + s.trigger = lang.escapeRegExp(s.tabTrigger); + } + + s.startRe = (s.guard || "") + (s.trigger || ""); + if (s.startRe && s.startRe[s.startRe - 1] != "$") + s.startRe += "$"; + if (s.startRe) + s.startRe = new RegExp(s.startRe); + s.endRe = (s.endGuard || "") + (s.endTrigger || ""); + if (s.endRe && s.endRe[0] != "^") + s.endRe = "^" + s.endRe; + if (s.endRe) + s.endRe = new RegExp(s.endRe); + }; + + if (snippets.content) + addSnippet(snippets); + else if (Array.isArray(snippets)) + snippets.forEach(addSnippet); + }; this.parseSnippetFile = function(str) { var list = [], snippet = {}; - var re = /^(\S+) (.*)$|^((?:\n?\t.*)+)/gm; - while(m = re.exec(str)){ - if (m[3]) { - snippet.content = m[3].replace(/^\t/gm, ""); + var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm; + var m; + while (m = re.exec(str)) { + if (m[1]) { + try { + snippet = JSON.parse(m[1]) + list.push(snippet); + } catch (e) {} + } if (m[4]) { + snippet.content = m[4].replace(/^\t/gm, ""); list.push(snippet); snippet = {}; } else { - var key = m[1], val = m[2]; - if (key == "snippet") { - if (!val.indexOf(" ")) { - snippet.trigger = val; - } else { - snippet.trigger = val; - } - } else if (key == "#") { - snippet.name = val; + var key = m[2], val = m[3]; + if (key == "regex") { + val = val.split(/\/((?:[^\/\\]|\\.)*)\/?/); + snippet.guard = val[1]; + snippet.trigger = val[2]; + snippet.endTrigger = val[3]; + snippet.endGuard = val[3]; + } else if (key == "snippet") { + val = val.split(/^(\S*)(?:\s(.*))?$/); + snippet.tabTrigger = val[1]; + if (!snippet.name) + snippet.name = val[2]; } else { snippet[key] = val; } } } - return snippets; + return list; }; + }).call(SnippetManager.prototype); @@ -346,6 +422,7 @@ var TabstopManager = function(editor) { this.index = -1; this.ranges = []; this.tabstops = []; + this.selectedTabstop = null; this.editor = editor; this.editor.on("change", this.$onChange); @@ -357,6 +434,7 @@ var TabstopManager = function(editor) { this.tabstops.forEach(this.removeTabstopMarkers, this); this.ranges = null; this.tabstops = null; + this.selectedTabstop = null; this.editor.removeListener("change", this.$onChange); this.editor.removeListener("changeSelection", this.$onChangeSelection); this.editor.removeListener("changeSession", this.$onChangeSession); @@ -381,11 +459,18 @@ var TabstopManager = function(editor) { var colDiff = end.column - start.column; var ranges = this.ranges; - for (var i = 0, n = ranges.length; i < n; i++) { + for (var i = 0; i < ranges.length; i++) { var r = ranges[i]; if (r.end.row < startRow) continue; + if (Range.comparePoints(changeRange.start, r.start) < 0 + && Range.comparePoints(changeRange.end, r.end) > 0) { + this.removeRange(r); + i--; + continue; + } + if (r.start.row == startRow && r.start.column > start.column) { r.start.column += colDiff; } @@ -405,9 +490,12 @@ var TabstopManager = function(editor) { if (!this.editor) return var lead = this.editor.selection.lead; - var row = lead.row, column = lead.column; + var anchor = this.editor.selection.anchor; + var isEmpty = this.editor.selection.isEmpty(); for (var i = this.ranges.length; i--;) { - if (this.ranges[i].contains(row, column)) + var containsLead = this.ranges[i].contains(lead.row, lead.column); + var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column); + if (containsLead && containsAnchor) return; } this.detach(); @@ -433,12 +521,12 @@ var TabstopManager = function(editor) { ts = this.tabstops[this.index]; if (!ts) return; - // this.removeTabstopMarkers(ts); + this.selectedTabstop = ts; var sel = this.editor.multiSelect; - sel.toSingleRange(ts[0].range.clone()); + sel.toSingleRange(ts[0].clone()); for (var i = ts.length; i--;) - sel.addRange(ts[i].range.clone(), true); + sel.addRange(ts[i].clone(), true); this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); }; this.addTabstops = function(tabstops, start, end) { @@ -447,8 +535,8 @@ var TabstopManager = function(editor) { var p = Range.fromPoints(end, end); moveRelative(p.start, start); moveRelative(p.end, start); - this.tabstops[0] = [p]; - this.tabstops[0].index = 0; + tabstops[0] = [p]; + tabstops[0].index = 0; } var i = this.index; @@ -456,13 +544,16 @@ var TabstopManager = function(editor) { var ranges = this.ranges; var editor = this.editor; tabstops.forEach(function(ts) { - ts.forEach(function(p) { + for (var i = ts.length; i--;) { + var p = ts[i]; var range = Range.fromPoints(p.start, p.end || p.start); movePoint(range.start, start); movePoint(range.end, start); - p.range = range; + range.original = p; + range.tabstop = ts; ranges.push(range); - }); + ts[i] = range; + } arg.push(ts); this.addTabstopMarkers(ts); }, this); @@ -473,18 +564,25 @@ var TabstopManager = function(editor) { this.addTabstopMarkers = function(ts) { var session = this.editor.session; - ts.forEach(function(p) { - if (!p.markerId) - p.markerId = session.addMarker(p.range, "ace_snippet-marker", "text"); + ts.forEach(function(range) { + if (!range.markerId) + range.markerId = session.addMarker(range, "ace_snippet-marker", "text"); }); }; this.removeTabstopMarkers = function(ts) { var session = this.editor.session; - ts.forEach(function(p) { - session.removeMarker(p.markerId); - p.markerId = null + ts.forEach(function(range) { + session.removeMarker(range.markerId); + range.markerId = null; }); }; + this.removeRange = function(range) { + var i = range.tabstop.indexOf(range); + range.tabstop.splice(i, 1); + i = this.ranges.indexOf(range); + this.ranges.splice(i, 1); + this.editor.session.removeMarker(range.markerId); + }; this.keyboardHandler = new HashHandler(); this.keyboardHandler.bindKeys({ diff --git a/lib/ace/snippets/javascript.js b/lib/ace/snippets/javascript.js new file mode 100644 index 00000000..fe370b06 --- /dev/null +++ b/lib/ace/snippets/javascript.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./javascript.snippets"); + + +}); diff --git a/lib/ace/snippets/javascript.snippets b/lib/ace/snippets/javascript.snippets index fc845fa0..73f7b93f 100644 --- a/lib/ace/snippets/javascript.snippets +++ b/lib/ace/snippets/javascript.snippets @@ -11,12 +11,13 @@ snippet fun } # Anonymous Function snippet f - function (${1}) { + function(${1}) { ${3} }${2:;} # Immediate function -snippet (f - (function (${1}) { +regex //f\(/\)?/ +snippet f( + (function(${1}) { ${3:/* code */} }(${2})); # if @@ -50,16 +51,7 @@ snippet case ${2:// code} break; ${3} -# for (...) {...} -snippet for - for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3: += 1}) { - ${4:$1[$2]} - } -# for (...) {...} (Improved Native For-Loop) -snippet forr - for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3: -= 1}) { - ${4:$1[$2]} - } + # while (...) {...} snippet wh while (${1:/* condition */}) { @@ -79,17 +71,17 @@ snippet do } while (${1:/* condition */}); # Object Method snippet :f - ${1:method_name}: function (${2:attribute}) { + ${1:method_name}: function(${2:attribute}) { ${4} }${3:,} # setTimeout function snippet timeout - setTimeout(function () {${3}}${2}, ${1:10}); + setTimeout(function() {${3}}${2}, ${1:10}); # Get Elements -snippet get +snippet gett getElementsBy${1:TagName}('${2}')${3} # Get Element -snippet gett +snippet get getElementBy${1:Id}('${2}')${3} # console.log (Firebug) snippet cl @@ -123,10 +115,10 @@ snippet jsons JSON.stringify(${1:object}); # self-defining function snippet sdf - var ${1:function_name} = function (${2:argument}) { + var ${1:function_name} = function(${2:argument}) { ${3:// initial code ...} - $1 = function ($2) { + $1 = function($2) { ${4:// main code} }; } @@ -154,3 +146,33 @@ snippet sing return instance; } +# class +regex /^\s*/clas{0,2}/ + var ${1:class} = function(${20}) { + $40$0\n + }; + + (function() { + ${60:this.prop = ""} + }).call(${1:class}.prototype); +# +snippet for- + for (var ${20:i} = ${1:Things}.length; ${20:i}--; ) { + ${100:${1:Things}[${20:i}]; + } + $0 + + +# for (...) {...} +snippet for + for (var ${2:i} = 0; $2 < ${1:Things}.length; $2${3:++}) { + ${4:$1[$2]} + } +# for (...) {...} (Improved Native For-Loop) +snippet forr + for (var ${2:i} = ${1:Things}.length - 1; $2 >= 0; $2${3:--}) { + ${4:$1[$2]} + } +snippet for- + +snippet for ?in diff --git a/lib/ace/snippets_test.js b/lib/ace/snippets_test.js new file mode 100644 index 00000000..c510b0ba --- /dev/null +++ b/lib/ace/snippets_test.js @@ -0,0 +1,56 @@ +/* ***** 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 ***** */ + +if (typeof process !== "undefined") { + require("amd-loader"); +} + +define(function(require, exports, module) { +"use strict"; + +var SnippetManager = require("./snippets").SnippetManager; +var assert = require("./test/assertions"); + +module.exports = { + "!test: textmate style format strings" : function() { + var fmt = SnippetManager.tmStrFormat; + assert.equal(fmt("abc", "/(.)(.)/$1/g"), "ac"); + assert.equal(fmt("abc", "/(.)(.)/$1(?2:Hello(1)2)/g"), "aHello(12)c2)"); + assert.equal(fmt("abc", "/(.)(.)/\u$1+lL+\u$2e|/g"), "A+lL+be|C+lL+e|"); + assert.equal(fmt("aBCD", "/(.)(.)/\U$1+lL+\l$2e/g"), "A+LL+be"); + }, + +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec() +} diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index 9a274329..6f56fab1 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -46,6 +46,7 @@ var testNames = [ "ace/range_list_test", "ace/search_test", "ace/selection_test", + "ace/snippets_test", "ace/token_iterator_test", "ace/virtual_renderer_test" ]; diff --git a/tool/tmsnippets.js b/tool/tmsnippets.js index 90e40ad4..febc7946 100644 --- a/tool/tmsnippets.js +++ b/tool/tmsnippets.js @@ -6,7 +6,8 @@ var path = process.argv[2] || process.cwd(); function readSnippet(path, name) { if (name) path += name - if (!/\.tmSnippet$/i.test(path)) + console.log(name) + if (!/\.(tmSnippet|sublime-snippet|plist)$/i.test(path)) return console.log(name) var plistString = fs.readFileSync(path, "utf8"); @@ -16,15 +17,29 @@ function readSnippet(path, name) { } // read -if (fs.statSync(path).isDirectory()) { - path += "/" - fs.readdirSync(path).forEach(function(name) { - readSnippet(path, name) - }) -} else { - readSnippet(path) +function readDir(path) { + if (fs.statSync(path).isDirectory()) { + path += "/" + fs.readdirSync(path).forEach(function(name) { + if (/snippets/i.test(name)) + readSnippetsInDir(path + name) + else + readDir(path + name) + }) + } } - +function readSnippetsInDir(path) { + if (fs.statSync(path).isDirectory()) { + path += "/" + snippets.push(path) + fs.readdirSync(path).forEach(function(name) { + readSnippet(path, name) + }) + } else { + readSnippet(path) + } +} +readDir(path) // transform snippets = snippets.map(function(s) { if (s.length == 1) @@ -62,6 +77,6 @@ var text = JSON.stringify(snippets, null, 1) return "\\n"+"\\" + "\n" }) -fs.writeFileSync(path += "./ace.snippets.js", text) +fs.writeFileSync(path += "/./ace.snippets.js", text) console.log(path) \ No newline at end of file