add helper tool for starting new mode
This commit is contained in:
parent
badade8f4e
commit
dbeeea2dd9
3 changed files with 150 additions and 14 deletions
101
tool/add_mode.js
Normal file
101
tool/add_mode.js
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
var lib = require('./lib');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var args = process.argv.slice(2);
|
||||||
|
|
||||||
|
|
||||||
|
var displayName = args[0];
|
||||||
|
var extRe = args[1];
|
||||||
|
if (!displayName || ! extRe) {
|
||||||
|
console.log("Usage: ModeName ext1|ext2");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = lib.snakeCase(displayName).replace(/[^\w]/g, "");
|
||||||
|
|
||||||
|
/** demo **/
|
||||||
|
var demoFileExt = extRe.split("|")[0] || name;
|
||||||
|
var demoFileName = demoFileExt[0] == "^" ? demoFileExt.substr(1) : name + "." + demoFileExt;
|
||||||
|
var demoFilePath = lib.AceRoot + "demo/kitchen-sink/docs/" + demoFileName;
|
||||||
|
fs.writeFileSync(demoFilePath, "TODO add a nice demo!", "utf8");
|
||||||
|
console.log("Created demo file at: " + path.normalize(demoFilePath));
|
||||||
|
|
||||||
|
/** mode **/
|
||||||
|
var template = fs.readFileSync(__dirname + "/mode.tmpl.js", "utf8");
|
||||||
|
var modePath = lib.AceLib + "ace/mode/" + name + ".js";
|
||||||
|
var text = lib.fillTemplate(template, {
|
||||||
|
languageHighlightFilename: name,
|
||||||
|
languagename: name,
|
||||||
|
lineCommentStart: "TODO",
|
||||||
|
blockCommentStart: "TODO",
|
||||||
|
blockCommentEnd: "TODO"
|
||||||
|
});
|
||||||
|
fs.writeFileSync(modePath, text);
|
||||||
|
console.log("Created mode file at: " + path.normalize(modePath));
|
||||||
|
|
||||||
|
/** highlight rules **/
|
||||||
|
template = fs.readFileSync(__dirname + "/mode_highlight_rules.tmpl.js", "utf8");
|
||||||
|
var hlPath = lib.AceLib + "ace/mode/" + name + "_highlight_rules.js";
|
||||||
|
template = template.replace(/\/\* THIS[\s\S]*?\*{3}\/\s*/, "");
|
||||||
|
text = lib.fillTemplate(template, {
|
||||||
|
language: name,
|
||||||
|
languageTokens: '{\n\
|
||||||
|
start: [{\n\
|
||||||
|
token: "string.start",\n\
|
||||||
|
regex: \'"\',\n\
|
||||||
|
next: "qstring"\n\
|
||||||
|
}],\n\
|
||||||
|
qstring: [{\n\
|
||||||
|
token: "escape",\n\
|
||||||
|
regex: /\\\\./,\n\
|
||||||
|
}, {\n\
|
||||||
|
token: "string.end",\n\
|
||||||
|
regex: \'"\',\n\
|
||||||
|
next: "start"\n\
|
||||||
|
}],\n\
|
||||||
|
}'
|
||||||
|
});
|
||||||
|
fs.writeFileSync(hlPath, text);
|
||||||
|
console.log("Created mode file at: " + path.normalize(hlPath));
|
||||||
|
|
||||||
|
/** snippets **/
|
||||||
|
template = fs.readFileSync(__dirname + "/tmsnippets.tmpl.js", "utf8");
|
||||||
|
var snipetsPath = lib.AceLib + "ace/snippets/" + name + ".js";
|
||||||
|
text = lib.fillTemplate(template, {
|
||||||
|
languagename: name,
|
||||||
|
snippets: ""
|
||||||
|
});
|
||||||
|
fs.writeFileSync(snipetsPath, text);
|
||||||
|
console.log("Created snippets file at: " + path.normalize(snipetsPath));
|
||||||
|
|
||||||
|
/** modelist **/
|
||||||
|
var modelistPath = lib.AceLib + "ace/ext/modelist.js";
|
||||||
|
var modelist = fs.readFileSync(modelistPath, "utf8").replace(/\r\n?/g, "\n");
|
||||||
|
modelist = modelist.replace(/(supportedModes = {\n)([\s\S]*?)(\n^};)/m, function(_, m1, m2, m3) {
|
||||||
|
var langs = m2.split(/,\n/);
|
||||||
|
var offset = langs[0].trim().indexOf("[");
|
||||||
|
var padding = Array(Math.max(offset - displayName.length - 1, 0) + 1).join(" ");
|
||||||
|
var newLang = " " + displayName + ":" + padding + "[\"" + extRe + "\"]";
|
||||||
|
langs = langs.concat(newLang).map(function(x) {
|
||||||
|
return {
|
||||||
|
value: x,
|
||||||
|
id: x.match(/[^"':\s]+/)[0].toLowerCase()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
langs[langs.length - 1].isNew = true;
|
||||||
|
|
||||||
|
langs = langs.filter(function(x) {
|
||||||
|
return x.id != name || x.isNew;
|
||||||
|
});
|
||||||
|
langs = langs.sort(function(a, b) {
|
||||||
|
return a.id.localeCompare(b.id);
|
||||||
|
}).map(function(x) {
|
||||||
|
return x.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return m1 + langs.join(",\n") + m3;
|
||||||
|
});
|
||||||
|
fs.writeFileSync(modelistPath, modelist, "utf8");
|
||||||
|
console.log("Updated modelist at: " + path.normalize(modelistPath));
|
||||||
|
|
||||||
57
tool/lib.js
57
tool/lib.js
|
|
@ -1,38 +1,73 @@
|
||||||
var plist = require("plist");
|
var plist = require("plist");
|
||||||
var util = require("util");
|
var util = require("util");
|
||||||
|
var url = require("url");
|
||||||
|
|
||||||
|
var https = require("https");
|
||||||
|
var http = require("http");
|
||||||
|
|
||||||
exports.parsePlist = function(themeXml, callback) {
|
exports.parsePlist = function(themeXml, callback) {
|
||||||
var result = ""
|
var result = "";
|
||||||
plist.parseString(themeXml, function(_, theme) {
|
plist.parseString(themeXml, function(_, theme) {
|
||||||
result = theme[0];
|
result = theme[0];
|
||||||
callback && callback(theme[0]);
|
callback && callback(theme[0]);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.formatJSON = function(object, initialIndent) {
|
exports.formatJSON = function(object, initialIndent) {
|
||||||
return util.inspect(object, false, 40).replace(/^/gm, initialIndent||"")
|
return util.inspect(object, false, 40).replace(/^/gm, initialIndent||"");
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
exports.fillTemplate = function(template, replacements) {
|
exports.fillTemplate = function(template, replacements) {
|
||||||
return template.replace(/%(.+?)%/g, function(str, m) {
|
return template.replace(/%(.+?)%/g, function(str, m) {
|
||||||
return replacements[m] || "";
|
return replacements[m] || "";
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.hyphenate = function(str) {
|
exports.hyphenate = function(str) {
|
||||||
return str.replace(/([A-Z])/g, "-$1").replace(/_/g, "-").toLowerCase();
|
return str.replace(/([A-Z])/g, "-$1").replace(/[_\s\-]+/g, "-").toLowerCase();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
exports.camelCase = function(str) {
|
||||||
|
return str.replace(/[\-_\s]+(.?)/g, function(x, y) {return y.toUpperCase()});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.snakeCase = function(str) {
|
||||||
|
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[_\s\-]+/g, "_").toLowerCase();
|
||||||
|
};
|
||||||
|
|
||||||
exports.quoteString = function(str) {
|
exports.quoteString = function(str) {
|
||||||
return '"' + str.replace(/\\/, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\\n") + '"';
|
return '"' + str.replace(/\\/, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\\n") + '"';
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
exports.restoreJSONComments = function(objStr) {
|
exports.restoreJSONComments = function(objStr) {
|
||||||
return objStr.replace(/^(\s*)comment: '(.*)'/gm, function(_, i, c) {
|
return objStr.replace(/^(\s*)comment: '(.*)'/gm, function(_, i, c) {
|
||||||
return i + "//" + c.replace(/\\n(\\t)*/g, "\n" + i + "//") + "\n" + i
|
return i + "//" + c.replace(/\\n(\\t)*/g, "\n" + i + "//") + "\n" + i;
|
||||||
}).replace(/ \/\/ ERROR/g, '", // ERROR');
|
}).replace(/ \/\/ ERROR/g, '", // ERROR');
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
exports.download = function(href, callback) {
|
||||||
|
var options = url.parse(href);
|
||||||
|
var protocol = options.protocol === "https:" ? https : http;
|
||||||
|
console.log("connecting to " + options.host + " " + options.path);
|
||||||
|
var request = protocol.get(options, function(res) {
|
||||||
|
var data = "";
|
||||||
|
res.setEncoding("utf-8");
|
||||||
|
|
||||||
|
res.on("data", function(chunk) {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on("end", function(){
|
||||||
|
callback(data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
exports.AceRoot = __dirname + "/../";
|
||||||
|
exports.AceLib = __dirname + "/../lib/";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ define(function(require, exports, module) {
|
||||||
|
|
||||||
var oop = require("../lib/oop");
|
var oop = require("../lib/oop");
|
||||||
var TextMode = require("./text").Mode;
|
var TextMode = require("./text").Mode;
|
||||||
var Tokenizer = require("../tokenizer").Tokenizer;
|
|
||||||
var %language%HighlightRules = require("./%languageHighlightFilename%_highlight_rules").%language%HighlightRules;
|
var %language%HighlightRules = require("./%languageHighlightFilename%_highlight_rules").%language%HighlightRules;
|
||||||
// TODO: pick appropriate fold mode
|
// TODO: pick appropriate fold mode
|
||||||
var FoldMode = require("./folding/cstyle").FoldMode;
|
var FoldMode = require("./folding/cstyle").FoldMode;
|
||||||
|
|
@ -49,9 +48,10 @@ var Mode = function() {
|
||||||
oop.inherits(Mode, TextMode);
|
oop.inherits(Mode, TextMode);
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
this.lineCommentStart = "//";
|
this.lineCommentStart = "%lineCommentStart%";
|
||||||
this.blockComment = {start: "/*", end: "*/"};
|
this.blockComment = {start: "%blockCommentStart%", end: "%blockCommentEnd%"};
|
||||||
// Extra logic goes here.
|
// Extra logic goes here.
|
||||||
|
this.$id = "ace/mode/%languageHighlightFilename%"
|
||||||
}).call(Mode.prototype);
|
}).call(Mode.prototype);
|
||||||
|
|
||||||
exports.Mode = Mode;
|
exports.Mode = Mode;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue