Add new language tool, generated jade/obj-c themes

This commit is contained in:
Garen Torikian 2012-09-07 02:28:37 -07:00 committed by nightwing
commit 8e199d4b24
7 changed files with 1054 additions and 105 deletions

View file

@ -1,17 +1,158 @@
doctype 5
html(lang="en")
head
title= pageTitle
script(type='text/javascript')
if (foo) {
bar()
}
body
h1 Jade - node template engine
#container
if youAreUsingJade
p You are #{awesome}
else
p Get on it!
!!!doctype
!!!5
mixin dialog-title-desc(title, desc)
- var methodSection, constructorSection, propertySection, eventSection;
-function renameMemberTitle(title, count)
if title.indexOf("ethods") >= 0
span Functions (#{count})
else if title.indexOf("ropert") >= 0
span Properties (#{count})
else
span.AS.AS.AS #{title} (#{count})
mixin article(obj, parents)
if typeof obj === 'string'
obj = list[obj]
title = obj.id + (obj.type ? ' (' + obj.type + ')' : '')
article.article(id=obj.path, data-title=title)
if obj.type === 'section' || obj.type === 'namespace' || obj.type === 'class' || obj.type === 'mixin'
if obj.stability
mixin markdown
span.label.deprecated
| Deprecated
if obj.deprecated.from
|   (since #{obj.deprecated.from})
if obj.deprecated.off
|  and will be removed on #{obj.deprecated.off}
if obj.alias_of
li
span.label.alias.single
| Aliased as:
!= link(obj.alias_of)
div.sideToggler
div(id='ellipsis_#{obj.id}', class='ellipsis_description')
mixin markdown(obj.short_description)
h3(id='#{obj.id}', class='methodToggle methodClicker inactive')
   
div.description
mixin markdown(obj.description)
if obj.bound && ~obj.bound.indexOf('#')
p.note.methodized
| This method can be called <em>either</em> as an
!= link(obj.bound, ['link-short'], 'instance method')
| <em>or</em> as a generic method. If calling as generic, pass the instance in as the first argument.
else if obj.bound && !~obj.bound.indexOf('#')
p.note.functionalized
| This method can be called <em>either</em> as an instance method <em>or</em> as a
!= link(obj.bound, ['link-short'], 'generic method')
|. If calling as generic, pass the instance in as the first argument.
if obj.arguments
h4 Arguments
!= argumentTable(obj.arguments, ["argument-list", "table", "table-striped", "table-bordered"])
if obj.returns
h4 Returns
!= returnTable(obj.returns, ["return-list", "table", "table-striped", "table-bordered"])
//- children
for child in obj.children.filter(function(x){return x.type === 'section'})
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'utility'})
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'constructor'})
- if (!constructorSection)
- constructorSection = true
h3.sectionHeader Constructors
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'namespace' || x.type === 'class' || x.type === 'mixin'})
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'event'})
- if (!eventSection)
- eventSection = true
h3.sectionHeader Events
mixin article(child, parents.concat(obj), 'event')
for child in obj.children.filter(function(x){return x.type === 'class method'})
- if (!methodSection)
- methodSection = true
h3.sectionHeader Methods
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'class property'})
- if (!propertySection)
- propertySection = true
h3.sectionHeader Properties
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'instance method'})
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'instance property'})
mixin article(child, parents.concat(obj))
for child in obj.children.filter(function(x){return x.type === 'constant'})
mixin article(child, parents.concat(obj))
mixin api()
-pos = 0
for obj in tree.children
.classContent
.membersBackground
div(class=' members pos#{pos}')
div(class=' membersContent pos#{pos}')
h1.memberHeader
-var heading = obj.path
span.name #{heading}
-if (true || obj.filename.indexOf("index") < 0)
ul(class='nav tabs pos#{pos}', data-tabs='tabs')
for selector, title in {'Events': ['event', 'events'], 'Constructors': ['constructor', 'constructors'], 'Class methods': ['class method', 'class_methods'], 'Class properties': ['class property', 'class_properties'], 'Instance methods': ['instance method', 'instance_methods'], 'Instance properties': ['instance property', 'instance_properties'], 'Constants': ['constant', 'constants']}
members = obj.children.filter(function(x){return x.type === selector[0]})
li(class="dropdown", data-dropdown="dropdown")
if members.length
a(href="\#", class="dropdown-toggle", data-toggle="dropdown")
!= renameMemberTitle(title, members.length)
b.caret
ul.dropdown-menu
for m in members
li(data-id='#{m.id}', class='memberLink')
mixin link(m, [], true)
-pos++
-methodSection = constructorSection = propertySection = eventSection = false;
mixin article(obj, [])
mixin short_description_list(collection)
ul.method-details-list
for obj in collection
if typeof obj === 'string'
obj = list[obj]
li.method-description
h4
mixin link(obj)
if obj.short_description
mixin markdown(obj.short_description)
mixin link(obj, classes, short)
l = link(obj, classes, short)
!= l
mixin links(collection)
ul.method-list
for obj in collection
li
mixin link(obj)

View file

@ -1,128 +1,327 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
* Distributed under the BSD license:
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
* 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.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Garen J. Torikian <gjtorikian AT gmail DOT com>
* Alexander Hanhikoski <https://github.com/alexhanh>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
THIS FILE WAS AUTOGENERATED BY theme_mode.tmpl.js
IT MIGHT NOT BE PERFECT, PARTICULARLY:
IN DECIDING STATES TO TRANSITION TO,
IGNORING WHITESPACE,
EXTENDING EXISTING MODES,
GATHERING KEYWORDS, OR
RULE PREFERENCE ORDER.
...But it's a good start from an existing *.tmlanguage file.
*/
define(function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
// var JavaScriptHighlightRules = require("ace/mode/javascript_highlight_rules").JavaScriptHighlightRules;
// var CssHighlightRules = require("ace/mode/css_highlight_rules").CssHighlightRules;
var JadeHighlightRules = function() {
this.$rules = {
start: [
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules =
{
token : ["keyword.control.import.include.jade"],
regex : "(?:^\\s*\\b)(include)(?:\\b)"
"start": [
{
"token": {
"1": {
"name": "keyword.control.import.include.jade"
}
},
"regex": "^\\s*\\b(include)\\b"
},
{
token : "keyword.other.doctype.jade",
regex : "^(?:!!!)(?:\\s*[a-zA-Z0-9-_]+)?"
"token": "keyword.other.doctype.jade",
"regex": "^(!!!)(\\s*[a-zA-Z0-9-_]+)?"
},
{
token : "comment",
regex : "\\/\\/.*$"
"token": {
"1": {
"name": "punctuation.section.comment.jade"
}
},
"regex": "^ *(//)\\s*\\S.*$\\n?"
},
{
"token": {
"2": {
"name": "punctuation.section.comment.jade"
}
},
"regex": "^(\\s*)(//)\\s*$",
"next": "state_4"
},
{
"token": {
"2": {
"name": "entity.name.function.jade"
}
},
"regex": "^(\\s*)(\\:markdown)",
"next": "state_5"
},
{
"token": {
"2": {
"name": "entity.name.function.jade"
}
},
"regex": "^(\\s*)(\\:sass)",
"next": "state_6"
},
{
"token": {
"2": {
"name": "entity.name.function.jade"
}
},
"regex": "^(\\s*)(\\:less)",
"next": "state_7"
},
{
"token": {
"2": {
"name": "entity.name.function.jade"
}
},
"regex": "^(\\s*)(\\:coffeescript)",
"next": "state_8"
},
{
"token": {
"2": {
"name": "entity.name.function.jade"
}
},
"regex": "^(\\s*)(\\:cdata)",
"next": "state_9"
},
// match stuff like: mixin dialog-title-desc(title, desc)
{
token : ["storage.type.function.jade", "text", "entity.name.function.jade", "punctuation.definition.parameters.begin.jade", "variable.parameter.function.jade", "punctuation.definition.parameters.end.jade"],
regex : "(mixin)( )([\\w\\-]+)\\s*(\\()(.*?)(\\))"
},
"token": {
"1": {
"name": "storage.type.function.jade"
},
"2": {
"name": "entity.name.function.jade"
},
"3": {
"name": "punctuation.definition.parameters.begin.jade"
},
"4": {
"name": "variable.parameter.function.jade"
},
"5": {
"name": "punctuation.definition.parameters.end.jade"
}
},
"regex": "^\\s*(mixin) ([\\w\\-]+)\\s*(\\()(.*?)(\\))"
},
// match stuff like: mixin dialog-title-desc
{
token : ["storage.type.function.jade", "text", "entity.name.function.jade"],
regex : "(mixin)( )(\\w\\-]+)"
},
// Jade's iteration: 'each foo in foos'
{
token : ["keyword", "text", "variable", "text", "keyword", "text", "variable"],
regex : "(each|for)(\\s+)([\\w-]+)(\\s+)(in)(\\s+)([\\w-]+)"
},
// Jade's iteration: 'each foo, bar in foos'
{
token : ["keyword", "text", "variable", "text", "variable", "text", "keyword", "text", "variable"],
regex : "(each|for)(\\s+)([\\w-]+)(\\s*,\\s*)([\\w-]+)(\\s+)(in)(\\s+)([\\w-]+)"
},
{
token : "string.interpolated.jade",
regex : "[#!]\\{[^\\}]+\\}"
"token": {
"1": {
"name": "storage.type.function.jade"
},
"2": {
"name": "entity.name.function.jade"
}
},
"regex": "^\\s*(mixin) ([\\w\\-]+)"
},
{
token : ["text", "meta.tag.any.jade", "meta.tag.any.jade"],
regex : "(^\\s*)(?:(([\w]+))|(?=\.|#))"
"regex": "^\\s*(-|=|!=)",
"next": "state_12"
},
{
token : "text",
regex : "\\|.*$"
"token": {
"2": {
"name": "entity.name.tag.script.jade"
}
},
"regex": "^(\\s*)(script)",
"next": "state_13"
},
{
"token": "string.interpolated.jade",
"regex": "[#!]\\{[^\\}]+\\}"
},
// Match any tag, id or class. skip AST filters
{
"token": {
"1": {
"name": "meta.tag.any.jade"
},
"2": {
"name": "entity.name.tag.jade"
}
},
"regex": "^\\s*(?!\\w+\\:)(?:(([\\w]+))|(?=\\.|#))",
"next": "state_15"
},
{
"regex": "(?<=\\w)\\s*\\(",
"next": "state_16"
}
],
parentheses: [
],
"state_4": [
{
token : "meta.tag.attribute.class.jade",
regex : "\\.[\\w-]+<"
},
{
token : "meta.tag.attribute.id.jade",
regex : "#[\\w-]+<"
"token": "TODO",
"regex": "^(?!\\1\\s+)",
"next": "start"
},
{
token : "text",
regex : "$",
next : "start"
"token": "TODO",
"regex": ".+",
"next": "state_4"
}
]
}
// this.embedRules(JavaScriptHighlightRules, "js-", {
// start: [{
// token: "string",
// regex: "^$"
// }]
// });
// this.embedRules(CssHighlightRules, "css-", [{
// token: "keyword",
// regex: "style",
// next: "start"
// }]);
],
"state_5": [
{
"include": "text.html.markdown"
},
{
"token": "TODO",
"regex": "^(?!\\1\\s+)",
"next": "start"
}
],
"state_6": [
{
"include": "source.sass"
},
{
"token": "TODO",
"regex": "^(?!\\1\\s+)",
"next": "start"
}
],
"state_7": [
{
"include": "source.css.less"
},
{
"token": "TODO",
"regex": "^(?!\\1\\s+)",
"next": "start"
}
],
"state_8": [
{
"include": "source.coffee"
},
{
"token": "TODO",
"regex": "^(?!\\1\\s+)",
"next": "start"
}
],
"state_9": [
{
"token": "TODO",
"regex": "^(?!\\1\\s+)",
"next": "start"
},
{
"token": "TODO",
"regex": ".+",
"next": "state_9"
}
],
"state_12": [
{
"include": "source.js"
},
{
"token": "keyword.control.js",
"regex": "\\b(each)\\b"
},
{
"token": "TODO",
"regex": "$",
"next": "start"
}
],
"state_13": [
{},
{
"include": "source.js"
},
{
"token": "TODO",
"regex": "^((?=(\\1)([\\w#\\.]|$\\n?))|^$\\n?)",
"next": "start"
}
],
"state_15": [
{
"token": "meta.tag.attribute.class.jade",
"regex": "\\.[\\w-]+"
},
{
"token": "meta.tag.attribute.id.jade",
"regex": "#[\\w-]+"
},
{
"token": "TODO",
"regex": "$|(?!\\.|#|=|-)",
"next": "start"
}
],
"state_16": [
{
"include": "#tag-stuff"
},
{
"token": "TODO",
"regex": "\\)",
"next": "start"
}
]
}
};
oop.inherits(JadeHighlightRules, TextHighlightRules);

File diff suppressed because one or more lines are too long

View file

@ -1,3 +1,4 @@
/* THIS THEME WAS AUTOGENERATED BY Theme.tmpl.css */
.%cssClass% .ace_editor {
border: 2px solid rgb(159, 159, 159);

View file

@ -28,6 +28,8 @@
*
* ***** END LICENSE BLOCK ***** */
// THIS FILE WAS AUTOGENERATED BY theme.tmpl.js
define(function(require, exports, module) {
exports.isDark = %isDark%;

54
tool/theme_mode.tmpl.js Normal file
View file

@ -0,0 +1,54 @@
/* ***** 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.
*
*
* Contributor(s):
*
*
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var %language%HighlightRules = function() {
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules =
%languageTokens%
};
oop.inherits(%language%HighlightRules, TextHighlightRules);
exports.%language%HighlightRules = %language%HighlightRules;
});

206
tool/tmlanguage.js Executable file
View file

@ -0,0 +1,206 @@
var fs = require("fs");
var util = require("util");
// for tracking token states
var startState = { start: [] }, statesObj = { };
var parseString = require("plist").parseString;
function parseLanguage(languageXml, callback) {
parseString(languageXml, function(_, language) {
callback(language[0])
});
}
function logDebug(string, obj) {
console.log(string, obj);
}
String.prototype.splice = function( idx, rem, s ) {
return (this.slice(0,idx) + s + this.slice(idx + Math.abs(rem)));
};
String.prototype.replaceAt = function (index, char) {
return this.substr(0, index) + char + this.substr(index + 1);
}
function keyCount(obj) {
return Object.keys(obj).length;
}
/**
Scrubbing is sometimes necessary, but there appears to be no
automated way to do it...
function cleanSingleCapture(match) {
// if there's a single "( )", screw that and make it "(?: )"
return match.replace("(", "(?:");
}
function cleanMultiCapture(match) {
// regexp will be a quoted string, so turn "\" into "\\"
var spaceFinderRegExp = new RegExp("\\\\s.| .", "g");
var m;
/*
essentially turns things like
\\s*(mixin) ([\\w\\-]+)\\s*(\\()
into
(\\s*mixin)( [\\w\\-]+)(\\s*\\()
so that mode parser stops complaining
while ((m = spaceFinderRegExp.exec(match)) != null) {
var idx = m.index;
var nextParenIdx = match.indexOf("(", idx);
if (nextParenIdx > idx) {
match = match.splice(idx, 0, "(").replaceAt(nextParenIdx + 1, '');
}
}
//console.log("match", match);
return match;
}
*/
// stupid yet necessary function, to transform JSON id comments into real comments
function restoreComments(objStr) {
return objStr.replace(/"\s+(\/\/.+)",/g, "\$1")
}
function assembleStateObjs(strState, pattern) {
var patterns = pattern.patterns;
var stateObj = {};
if (patterns) {
for (var p in patterns) {
stateObj = {}; // this is apparently necessary
if (patterns[p].include) {
stateObj.include = patterns[p].include;
}
else {
stateObj.token = patterns[p].name;
stateObj.regex = patterns[p].match;
}
statesObj[strState].push(stateObj);
}
stateObj = {};
stateObj.token = "TODO";
stateObj.regex = pattern.end;
stateObj.next = "start";
}
else {
stateObj.token = "TODO";
stateObj.regex = pattern.end;
stateObj.next = "start";
statesObj[strState].push(stateObj);
stateObj = {};
stateObj.token = "TODO";
stateObj.regex = ".+";
stateObj.next = strState;
}
return stateObj;
}
function extractPatterns(patterns) {
var state = 0;
patterns.forEach(function(pattern) {
state++;
var i = 1;
var tokenArray = [];
var tokenObj = {};
var stateObj = {};
if (pattern.comment) {
startState.start.push(" // " + pattern.comment);
}
// it needs a state transition
if (pattern.begin && pattern.end) {
var strState = "state_" + state;
if ( pattern.beginCaptures === undefined && pattern.endCaptures === undefined) {
tokenObj.token = pattern.captures;
}
else if (pattern.beginCaptures) {
tokenObj.token = pattern.beginCaptures;
}
else if (pattern.endCaptures) {
tokenObj.token = pattern.endCaptures;
}
statesObj[strState] = [ ];
statesObj[strState].push(assembleStateObjs(strState, pattern));
tokenObj.regex = pattern.begin;
tokenObj.next = strState;
startState.start.push(tokenObj);
}
else if( ( pattern.begin || pattern.end ) && !( pattern.begin && pattern.end ) ) {
logDebug("Somehow, there's pattern.begin or pattern.end--but not both?", pattern);
}
else if (pattern.captures) {
tokenObj.token = pattern.captures;
tokenObj.regex = pattern.match;
startState.start.push(tokenObj);
}
else if (pattern.match) {
tokenObj.token = pattern.name;
tokenObj.regex = pattern.match;
startState.start.push(tokenObj);
}
else {
logDebug("I've gone through every choice, and have no clue what this is:", pattern);
}
});
var resultingObj = startState;
for (var state in statesObj) {
resultingObj[state] = statesObj[state];
}
return restoreComments(JSON.stringify(resultingObj, null, " "));
}
function fillTemplate(template, replacements) {
return template.replace(/%(.+?)%/g, function(str, m) {
return replacements[m] || "";
});
}
var modeTemplate = fs.readFileSync(__dirname + "/theme_mode.tmpl.js", "utf8");
function convertLanguage(name) {
var tmLanguage = fs.readFileSync(__dirname + "/" + name, "utf8");
parseLanguage(tmLanguage, function(language) {
var outFile = __dirname + "/../lib/ace/mode/" + language.name.replace(/-/g, "_").toLowerCase() + "_highlight_rules.js";
console.log("Converting " + name + " to " + outFile);
//console.log(util.inspect(language.patterns, false, 4));
var patterns = extractPatterns(language.patterns);
var lang = fillTemplate(modeTemplate, {
language: language.name.replace(/-/g, ""),
languageTokens: patterns
});
fs.writeFileSync(outFile, lang);
});
}
var tmLanguageFile = process.argv.splice(2)[0];
convertLanguage(tmLanguageFile);