183 lines
4.4 KiB
JavaScript
183 lines
4.4 KiB
JavaScript
/*
|
|
* Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
|
|
* Licence: MIT
|
|
*/
|
|
|
|
CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
|
|
{
|
|
function pushCommand(state, command) {
|
|
state.cmdState.push(command);
|
|
}
|
|
|
|
function peekCommand(state) {
|
|
if (state.cmdState.length>0)
|
|
return state.cmdState[state.cmdState.length-1];
|
|
else
|
|
return null;
|
|
}
|
|
|
|
function popCommand(state) {
|
|
if (state.cmdState.length>0) {
|
|
var plug = state.cmdState.pop();
|
|
plug.closeBracket();
|
|
}
|
|
}
|
|
|
|
function applyMostPowerful(state) {
|
|
var context = state.cmdState;
|
|
for (var i = context.length - 1; i >= 0; i--) {
|
|
var plug = context[i];
|
|
if (plug.name=="DEFAULT")
|
|
continue;
|
|
return plug.styleIdentifier();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function addPluginPattern(pluginName, cmdStyle, brackets, styles) {
|
|
return function () {
|
|
this.name=pluginName;
|
|
this.bracketNo = 0;
|
|
this.style=cmdStyle;
|
|
this.styles = styles;
|
|
this.brackets = brackets;
|
|
|
|
this.styleIdentifier = function(content) {
|
|
if (this.bracketNo<=this.styles.length)
|
|
return this.styles[this.bracketNo-1];
|
|
else
|
|
return null;
|
|
};
|
|
this.openBracket = function(content) {
|
|
this.bracketNo++;
|
|
return "bracket";
|
|
};
|
|
this.closeBracket = function(content) {
|
|
};
|
|
};
|
|
}
|
|
|
|
var plugins = new Array();
|
|
|
|
plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]);
|
|
plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]);
|
|
plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
|
|
plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
|
|
plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
|
|
|
|
plugins["DEFAULT"] = function () {
|
|
this.name="DEFAULT";
|
|
this.style="tag";
|
|
|
|
this.styleIdentifier = function(content) {
|
|
};
|
|
this.openBracket = function(content) {
|
|
};
|
|
this.closeBracket = function(content) {
|
|
};
|
|
};
|
|
|
|
function setState(state, f) {
|
|
state.f = f;
|
|
}
|
|
|
|
function normal(source, state) {
|
|
if (source.match(/^\\[a-zA-Z@]+/)) {
|
|
var cmdName = source.current();
|
|
cmdName = cmdName.substr(1, cmdName.length-1);
|
|
var plug;
|
|
if (plugins.hasOwnProperty(cmdName)) {
|
|
plug = plugins[cmdName];
|
|
} else {
|
|
plug = plugins["DEFAULT"];
|
|
}
|
|
plug = new plug();
|
|
pushCommand(state, plug);
|
|
setState(state, beginParams);
|
|
return plug.style;
|
|
}
|
|
|
|
// escape characters
|
|
if (source.match(/^\\[$&%#{}_]/)) {
|
|
return "tag";
|
|
}
|
|
|
|
// white space control characters
|
|
if (source.match(/^\\[,;!\/]/)) {
|
|
return "tag";
|
|
}
|
|
|
|
var ch = source.next();
|
|
if (ch == "%") {
|
|
// special case: % at end of its own line; stay in same state
|
|
if (!source.eol()) {
|
|
setState(state, inCComment);
|
|
}
|
|
return "comment";
|
|
}
|
|
else if (ch=='}' || ch==']') {
|
|
plug = peekCommand(state);
|
|
if (plug) {
|
|
plug.closeBracket(ch);
|
|
setState(state, beginParams);
|
|
} else
|
|
return "error";
|
|
return "bracket";
|
|
} else if (ch=='{' || ch=='[') {
|
|
plug = plugins["DEFAULT"];
|
|
plug = new plug();
|
|
pushCommand(state, plug);
|
|
return "bracket";
|
|
}
|
|
else if (/\d/.test(ch)) {
|
|
source.eatWhile(/[\w.%]/);
|
|
return "atom";
|
|
}
|
|
else {
|
|
source.eatWhile(/[\w-_]/);
|
|
return applyMostPowerful(state);
|
|
}
|
|
}
|
|
|
|
function inCComment(source, state) {
|
|
source.skipToEnd();
|
|
setState(state, normal);
|
|
return "comment";
|
|
}
|
|
|
|
function beginParams(source, state) {
|
|
var ch = source.peek();
|
|
if (ch == '{' || ch == '[') {
|
|
var lastPlug = peekCommand(state);
|
|
var style = lastPlug.openBracket(ch);
|
|
source.eat(ch);
|
|
setState(state, normal);
|
|
return "bracket";
|
|
}
|
|
if (/[ \t\r]/.test(ch)) {
|
|
source.eat(ch);
|
|
return null;
|
|
}
|
|
setState(state, normal);
|
|
lastPlug = peekCommand(state);
|
|
if (lastPlug) {
|
|
popCommand(state);
|
|
}
|
|
return normal(source, state);
|
|
}
|
|
|
|
return {
|
|
startState: function() { return { f:normal, cmdState:[] }; },
|
|
copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },
|
|
|
|
token: function(stream, state) {
|
|
var t = state.f(stream, state);
|
|
var w = stream.current();
|
|
return t;
|
|
}
|
|
};
|
|
});
|
|
|
|
CodeMirror.defineMIME("text/x-stex", "stex");
|
|
CodeMirror.defineMIME("text/x-latex", "stex");
|