stex.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
  3. * Licence: MIT
  4. */
  5. CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
  6. {
  7. function pushCommand(state, command) {
  8. state.cmdState.push(command);
  9. }
  10. function peekCommand(state) {
  11. if (state.cmdState.length>0)
  12. return state.cmdState[state.cmdState.length-1];
  13. else
  14. return null;
  15. }
  16. function popCommand(state) {
  17. if (state.cmdState.length>0) {
  18. var plug = state.cmdState.pop();
  19. plug.closeBracket();
  20. }
  21. }
  22. function applyMostPowerful(state) {
  23. var context = state.cmdState;
  24. for (var i = context.length - 1; i >= 0; i--) {
  25. var plug = context[i];
  26. if (plug.name=="DEFAULT")
  27. continue;
  28. return plug.styleIdentifier();
  29. }
  30. return null;
  31. }
  32. function addPluginPattern(pluginName, cmdStyle, brackets, styles) {
  33. return function () {
  34. this.name=pluginName;
  35. this.bracketNo = 0;
  36. this.style=cmdStyle;
  37. this.styles = styles;
  38. this.brackets = brackets;
  39. this.styleIdentifier = function(content) {
  40. if (this.bracketNo<=this.styles.length)
  41. return this.styles[this.bracketNo-1];
  42. else
  43. return null;
  44. };
  45. this.openBracket = function(content) {
  46. this.bracketNo++;
  47. return "bracket";
  48. };
  49. this.closeBracket = function(content) {
  50. };
  51. }
  52. }
  53. var plugins = new Array();
  54. plugins["importmodule"] = addPluginPattern("importmodule", "tag", "{[", ["string", "builtin"]);
  55. plugins["documentclass"] = addPluginPattern("documentclass", "tag", "{[", ["", "atom"]);
  56. plugins["usepackage"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
  57. plugins["begin"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
  58. plugins["end"] = addPluginPattern("documentclass", "tag", "[", ["atom"]);
  59. plugins["DEFAULT"] = function () {
  60. this.name="DEFAULT";
  61. this.style="tag";
  62. this.styleIdentifier = function(content) {
  63. };
  64. this.openBracket = function(content) {
  65. };
  66. this.closeBracket = function(content) {
  67. };
  68. };
  69. function setState(state, f) {
  70. state.f = f;
  71. }
  72. function normal(source, state) {
  73. if (source.match(/^\\[a-z]+/)) {
  74. var cmdName = source.current();
  75. cmdName = cmdName.substr(1, cmdName.length-1);
  76. var plug = plugins[cmdName];
  77. if (typeof(plug) == 'undefined') {
  78. plug = plugins["DEFAULT"];
  79. }
  80. plug = new plug();
  81. pushCommand(state, plug);
  82. setState(state, beginParams);
  83. return plug.style;
  84. }
  85. var ch = source.next();
  86. if (ch == "%") {
  87. setState(state, inCComment);
  88. return "comment";
  89. }
  90. else if (ch=='}' || ch==']') {
  91. plug = peekCommand(state);
  92. if (plug) {
  93. plug.closeBracket(ch);
  94. setState(state, beginParams);
  95. } else
  96. return "error";
  97. return "bracket";
  98. } else if (ch=='{' || ch=='[') {
  99. plug = plugins["DEFAULT"];
  100. plug = new plug();
  101. pushCommand(state, plug);
  102. return "bracket";
  103. }
  104. else if (/\d/.test(ch)) {
  105. source.eatWhile(/[\w.%]/);
  106. return "atom";
  107. }
  108. else {
  109. source.eatWhile(/[\w-_]/);
  110. return applyMostPowerful(state);
  111. }
  112. }
  113. function inCComment(source, state) {
  114. source.skipToEnd();
  115. setState(state, normal);
  116. return "comment";
  117. }
  118. function beginParams(source, state) {
  119. var ch = source.peek();
  120. if (ch == '{' || ch == '[') {
  121. var lastPlug = peekCommand(state);
  122. var style = lastPlug.openBracket(ch);
  123. source.eat(ch);
  124. setState(state, normal);
  125. return "bracket";
  126. }
  127. if (/[ \t\r]/.test(ch)) {
  128. source.eat(ch);
  129. return null;
  130. }
  131. setState(state, normal);
  132. lastPlug = peekCommand(state);
  133. if (lastPlug) {
  134. popCommand(state);
  135. }
  136. return normal(source, state);
  137. }
  138. return {
  139. startState: function() { return { f:normal, cmdState:[] }; },
  140. copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },
  141. token: function(stream, state) {
  142. var t = state.f(stream, state);
  143. var w = stream.current();
  144. return t;
  145. }
  146. };
  147. });
  148. CodeMirror.defineMIME("text/x-stex", "stex");