github.com/jancarloviray/community@v0.41.1-0.20170124221257-33a66c87cf2f/app/public/codemirror/mode/stex/stex.js (about)

     1  // CodeMirror, copyright (c) by Marijn Haverbeke and others
     2  // Distributed under an MIT license: http://codemirror.net/LICENSE
     3  
     4  /*
     5   * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)
     6   * Licence: MIT
     7   */
     8  
     9  (function(mod) {
    10    if (typeof exports == "object" && typeof module == "object") // CommonJS
    11      mod(require("../../lib/codemirror"));
    12    else if (typeof define == "function" && define.amd) // AMD
    13      define(["../../lib/codemirror"], mod);
    14    else // Plain browser env
    15      mod(CodeMirror);
    16  })(function(CodeMirror) {
    17    "use strict";
    18  
    19    CodeMirror.defineMode("stex", function() {
    20      "use strict";
    21  
    22      function pushCommand(state, command) {
    23        state.cmdState.push(command);
    24      }
    25  
    26      function peekCommand(state) {
    27        if (state.cmdState.length > 0) {
    28          return state.cmdState[state.cmdState.length - 1];
    29        } else {
    30          return null;
    31        }
    32      }
    33  
    34      function popCommand(state) {
    35        var plug = state.cmdState.pop();
    36        if (plug) {
    37          plug.closeBracket();
    38        }
    39      }
    40  
    41      // returns the non-default plugin closest to the end of the list
    42      function getMostPowerful(state) {
    43        var context = state.cmdState;
    44        for (var i = context.length - 1; i >= 0; i--) {
    45          var plug = context[i];
    46          if (plug.name == "DEFAULT") {
    47            continue;
    48          }
    49          return plug;
    50        }
    51        return { styleIdentifier: function() { return null; } };
    52      }
    53  
    54      function addPluginPattern(pluginName, cmdStyle, styles) {
    55        return function () {
    56          this.name = pluginName;
    57          this.bracketNo = 0;
    58          this.style = cmdStyle;
    59          this.styles = styles;
    60          this.argument = null;   // \begin and \end have arguments that follow. These are stored in the plugin
    61  
    62          this.styleIdentifier = function() {
    63            return this.styles[this.bracketNo - 1] || null;
    64          };
    65          this.openBracket = function() {
    66            this.bracketNo++;
    67            return "bracket";
    68          };
    69          this.closeBracket = function() {};
    70        };
    71      }
    72  
    73      var plugins = {};
    74  
    75      plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]);
    76      plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]);
    77      plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]);
    78      plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]);
    79      plugins["end"] = addPluginPattern("end", "tag", ["atom"]);
    80  
    81      plugins["DEFAULT"] = function () {
    82        this.name = "DEFAULT";
    83        this.style = "tag";
    84  
    85        this.styleIdentifier = this.openBracket = this.closeBracket = function() {};
    86      };
    87  
    88      function setState(state, f) {
    89        state.f = f;
    90      }
    91  
    92      // called when in a normal (no environment) context
    93      function normal(source, state) {
    94        var plug;
    95        // Do we look like '\command' ?  If so, attempt to apply the plugin 'command'
    96        if (source.match(/^\\[a-zA-Z@]+/)) {
    97          var cmdName = source.current().slice(1);
    98          plug = plugins[cmdName] || plugins["DEFAULT"];
    99          plug = new plug();
   100          pushCommand(state, plug);
   101          setState(state, beginParams);
   102          return plug.style;
   103        }
   104  
   105        // escape characters
   106        if (source.match(/^\\[$&%#{}_]/)) {
   107          return "tag";
   108        }
   109  
   110        // white space control characters
   111        if (source.match(/^\\[,;!\/\\]/)) {
   112          return "tag";
   113        }
   114  
   115        // find if we're starting various math modes
   116        if (source.match("\\[")) {
   117          setState(state, function(source, state){ return inMathMode(source, state, "\\]"); });
   118          return "keyword";
   119        }
   120        if (source.match("$$")) {
   121          setState(state, function(source, state){ return inMathMode(source, state, "$$"); });
   122          return "keyword";
   123        }
   124        if (source.match("$")) {
   125          setState(state, function(source, state){ return inMathMode(source, state, "$"); });
   126          return "keyword";
   127        }
   128  
   129        var ch = source.next();
   130        if (ch == "%") {
   131          source.skipToEnd();
   132          return "comment";
   133        } else if (ch == '}' || ch == ']') {
   134          plug = peekCommand(state);
   135          if (plug) {
   136            plug.closeBracket(ch);
   137            setState(state, beginParams);
   138          } else {
   139            return "error";
   140          }
   141          return "bracket";
   142        } else if (ch == '{' || ch == '[') {
   143          plug = plugins["DEFAULT"];
   144          plug = new plug();
   145          pushCommand(state, plug);
   146          return "bracket";
   147        } else if (/\d/.test(ch)) {
   148          source.eatWhile(/[\w.%]/);
   149          return "atom";
   150        } else {
   151          source.eatWhile(/[\w\-_]/);
   152          plug = getMostPowerful(state);
   153          if (plug.name == 'begin') {
   154            plug.argument = source.current();
   155          }
   156          return plug.styleIdentifier();
   157        }
   158      }
   159  
   160      function inMathMode(source, state, endModeSeq) {
   161        if (source.eatSpace()) {
   162          return null;
   163        }
   164        if (source.match(endModeSeq)) {
   165          setState(state, normal);
   166          return "keyword";
   167        }
   168        if (source.match(/^\\[a-zA-Z@]+/)) {
   169          return "tag";
   170        }
   171        if (source.match(/^[a-zA-Z]+/)) {
   172          return "variable-2";
   173        }
   174        // escape characters
   175        if (source.match(/^\\[$&%#{}_]/)) {
   176          return "tag";
   177        }
   178        // white space control characters
   179        if (source.match(/^\\[,;!\/]/)) {
   180          return "tag";
   181        }
   182        // special math-mode characters
   183        if (source.match(/^[\^_&]/)) {
   184          return "tag";
   185        }
   186        // non-special characters
   187        if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) {
   188          return null;
   189        }
   190        if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) {
   191          return "number";
   192        }
   193        var ch = source.next();
   194        if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") {
   195          return "bracket";
   196        }
   197  
   198        if (ch == "%") {
   199          source.skipToEnd();
   200          return "comment";
   201        }
   202        return "error";
   203      }
   204  
   205      function beginParams(source, state) {
   206        var ch = source.peek(), lastPlug;
   207        if (ch == '{' || ch == '[') {
   208          lastPlug = peekCommand(state);
   209          lastPlug.openBracket(ch);
   210          source.eat(ch);
   211          setState(state, normal);
   212          return "bracket";
   213        }
   214        if (/[ \t\r]/.test(ch)) {
   215          source.eat(ch);
   216          return null;
   217        }
   218        setState(state, normal);
   219        popCommand(state);
   220  
   221        return normal(source, state);
   222      }
   223  
   224      return {
   225        startState: function() {
   226          return {
   227            cmdState: [],
   228            f: normal
   229          };
   230        },
   231        copyState: function(s) {
   232          return {
   233            cmdState: s.cmdState.slice(),
   234            f: s.f
   235          };
   236        },
   237        token: function(stream, state) {
   238          return state.f(stream, state);
   239        },
   240        blankLine: function(state) {
   241          state.f = normal;
   242          state.cmdState.length = 0;
   243        },
   244        lineComment: "%"
   245      };
   246    });
   247  
   248    CodeMirror.defineMIME("text/x-stex", "stex");
   249    CodeMirror.defineMIME("text/x-latex", "stex");
   250  
   251  });