all repos — NoPaste @ 584b12475d17386562df16d9e2aebd2d66070652

Resurrected - The PussTheCat.org fork of NoPaste

scripts/CodeMirror/mode/cypher/cypher.js (view raw)

  1// CodeMirror, copyright (c) by Marijn Haverbeke and others
  2// Distributed under an MIT license: https://codemirror.net/LICENSE
  3
  4// By the Neo4j Team and contributors.
  5// https://github.com/neo4j-contrib/CodeMirror
  6
  7(function(mod) {
  8  if (typeof exports == "object" && typeof module == "object") // CommonJS
  9    mod(require("../../lib/codemirror"));
 10  else if (typeof define == "function" && define.amd) // AMD
 11    define(["../../lib/codemirror"], mod);
 12  else // Plain browser env
 13    mod(CodeMirror);
 14})(function(CodeMirror) {
 15  "use strict";
 16  var wordRegexp = function(words) {
 17    return new RegExp("^(?:" + words.join("|") + ")$", "i");
 18  };
 19
 20  CodeMirror.defineMode("cypher", function(config) {
 21    var tokenBase = function(stream/*, state*/) {
 22      var ch = stream.next();
 23      if (ch ==='"') {
 24        stream.match(/.*?"/);
 25        return "string";
 26      }
 27      if (ch === "'") {
 28        stream.match(/.*?'/);
 29        return "string";
 30      }
 31      if (/[{}\(\),\.;\[\]]/.test(ch)) {
 32        curPunc = ch;
 33        return "node";
 34      } else if (ch === "/" && stream.eat("/")) {
 35        stream.skipToEnd();
 36        return "comment";
 37      } else if (operatorChars.test(ch)) {
 38        stream.eatWhile(operatorChars);
 39        return null;
 40      } else {
 41        stream.eatWhile(/[_\w\d]/);
 42        if (stream.eat(":")) {
 43          stream.eatWhile(/[\w\d_\-]/);
 44          return "atom";
 45        }
 46        var word = stream.current();
 47        if (funcs.test(word)) return "builtin";
 48        if (preds.test(word)) return "def";
 49        if (keywords.test(word) || systemKeywords.test(word)) return "keyword";
 50        return "variable";
 51      }
 52    };
 53    var pushContext = function(state, type, col) {
 54      return state.context = {
 55        prev: state.context,
 56        indent: state.indent,
 57        col: col,
 58        type: type
 59      };
 60    };
 61    var popContext = function(state) {
 62      state.indent = state.context.indent;
 63      return state.context = state.context.prev;
 64    };
 65    var indentUnit = config.indentUnit;
 66    var curPunc;
 67    var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "reverse", "right", "round", "rtrim", "shortestPath", "sign", "sin", "size", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "toString", "trim", "type", "upper"]);
 68    var preds = wordRegexp(["all", "and", "any", "contains", "exists", "has", "in", "none", "not", "or", "single", "xor"]);
 69    var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "detach", "distinct", "drop", "else", "end", "ends", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "starts", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with", "call", "yield"]);
 70    var systemKeywords = wordRegexp(["access", "active", "assign", "all", "alter", "as", "catalog", "change", "copy", "create", "constraint", "constraints", "current", "database", "databases", "dbms", "default", "deny", "drop", "element", "elements", "exists", "from", "grant", "graph", "graphs", "if", "index", "indexes", "label", "labels", "management", "match", "name", "names", "new", "node", "nodes", "not", "of", "on", "or", "password", "populated", "privileges", "property", "read", "relationship", "relationships", "remove", "replace", "required", "revoke", "role", "roles", "set", "show", "start", "status", "stop", "suspended", "to", "traverse", "type", "types", "user", "users", "with", "write"]);
 71    var operatorChars = /[*+\-<>=&|~%^]/;
 72
 73    return {
 74      startState: function(/*base*/) {
 75        return {
 76          tokenize: tokenBase,
 77          context: null,
 78          indent: 0,
 79          col: 0
 80        };
 81      },
 82      token: function(stream, state) {
 83        if (stream.sol()) {
 84          if (state.context && (state.context.align == null)) {
 85            state.context.align = false;
 86          }
 87          state.indent = stream.indentation();
 88        }
 89        if (stream.eatSpace()) {
 90          return null;
 91        }
 92        var style = state.tokenize(stream, state);
 93        if (style !== "comment" && state.context && (state.context.align == null) && state.context.type !== "pattern") {
 94          state.context.align = true;
 95        }
 96        if (curPunc === "(") {
 97          pushContext(state, ")", stream.column());
 98        } else if (curPunc === "[") {
 99          pushContext(state, "]", stream.column());
100        } else if (curPunc === "{") {
101          pushContext(state, "}", stream.column());
102        } else if (/[\]\}\)]/.test(curPunc)) {
103          while (state.context && state.context.type === "pattern") {
104            popContext(state);
105          }
106          if (state.context && curPunc === state.context.type) {
107            popContext(state);
108          }
109        } else if (curPunc === "." && state.context && state.context.type === "pattern") {
110          popContext(state);
111        } else if (/atom|string|variable/.test(style) && state.context) {
112          if (/[\}\]]/.test(state.context.type)) {
113            pushContext(state, "pattern", stream.column());
114          } else if (state.context.type === "pattern" && !state.context.align) {
115            state.context.align = true;
116            state.context.col = stream.column();
117          }
118        }
119        return style;
120      },
121      indent: function(state, textAfter) {
122        var firstChar = textAfter && textAfter.charAt(0);
123        var context = state.context;
124        if (/[\]\}]/.test(firstChar)) {
125          while (context && context.type === "pattern") {
126            context = context.prev;
127          }
128        }
129        var closing = context && firstChar === context.type;
130        if (!context) return 0;
131        if (context.type === "keywords") return CodeMirror.commands.newlineAndIndent;
132        if (context.align) return context.col + (closing ? 0 : 1);
133        return context.indent + (closing ? 0 : indentUnit);
134      }
135    };
136  });
137
138  CodeMirror.modeExtensions["cypher"] = {
139    autoFormatLineBreaks: function(text) {
140      var i, lines, reProcessedPortion;
141      var lines = text.split("\n");
142      var reProcessedPortion = /\s+\b(return|where|order by|match|with|skip|limit|create|delete|set)\b\s/g;
143      for (var i = 0; i < lines.length; i++)
144        lines[i] = lines[i].replace(reProcessedPortion, " \n$1 ").trim();
145      return lines.join("\n");
146    }
147  };
148
149  CodeMirror.defineMIME("application/x-cypher-query", "cypher");
150
151});