| 776 |
lars |
1 |
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
|
2 |
// Distributed under an MIT license: http://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 === "\"" || ch === "'") {
|
|
|
24 |
stream.match(/.+?["']/);
|
|
|
25 |
return "string";
|
|
|
26 |
}
|
|
|
27 |
if (/[{}\(\),\.;\[\]]/.test(ch)) {
|
|
|
28 |
curPunc = ch;
|
|
|
29 |
return "node";
|
|
|
30 |
} else if (ch === "/" && stream.eat("/")) {
|
|
|
31 |
stream.skipToEnd();
|
|
|
32 |
return "comment";
|
|
|
33 |
} else if (operatorChars.test(ch)) {
|
|
|
34 |
stream.eatWhile(operatorChars);
|
|
|
35 |
return null;
|
|
|
36 |
} else {
|
|
|
37 |
stream.eatWhile(/[_\w\d]/);
|
|
|
38 |
if (stream.eat(":")) {
|
|
|
39 |
stream.eatWhile(/[\w\d_\-]/);
|
|
|
40 |
return "atom";
|
|
|
41 |
}
|
|
|
42 |
var word = stream.current();
|
|
|
43 |
if (funcs.test(word)) return "builtin";
|
|
|
44 |
if (preds.test(word)) return "def";
|
|
|
45 |
if (keywords.test(word)) return "keyword";
|
|
|
46 |
return "variable";
|
|
|
47 |
}
|
|
|
48 |
};
|
|
|
49 |
var pushContext = function(state, type, col) {
|
|
|
50 |
return state.context = {
|
|
|
51 |
prev: state.context,
|
|
|
52 |
indent: state.indent,
|
|
|
53 |
col: col,
|
|
|
54 |
type: type
|
|
|
55 |
};
|
|
|
56 |
};
|
|
|
57 |
var popContext = function(state) {
|
|
|
58 |
state.indent = state.context.indent;
|
|
|
59 |
return state.context = state.context.prev;
|
|
|
60 |
};
|
|
|
61 |
var indentUnit = config.indentUnit;
|
|
|
62 |
var curPunc;
|
|
|
63 |
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", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);
|
|
|
64 |
var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor", "like", "ilike", "exists"]);
|
|
|
65 |
var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "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", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
|
|
|
66 |
var operatorChars = /[*+\-<>=&|~%^]/;
|
|
|
67 |
|
|
|
68 |
return {
|
|
|
69 |
startState: function(/*base*/) {
|
|
|
70 |
return {
|
|
|
71 |
tokenize: tokenBase,
|
|
|
72 |
context: null,
|
|
|
73 |
indent: 0,
|
|
|
74 |
col: 0
|
|
|
75 |
};
|
|
|
76 |
},
|
|
|
77 |
token: function(stream, state) {
|
|
|
78 |
if (stream.sol()) {
|
|
|
79 |
if (state.context && (state.context.align == null)) {
|
|
|
80 |
state.context.align = false;
|
|
|
81 |
}
|
|
|
82 |
state.indent = stream.indentation();
|
|
|
83 |
}
|
|
|
84 |
if (stream.eatSpace()) {
|
|
|
85 |
return null;
|
|
|
86 |
}
|
|
|
87 |
var style = state.tokenize(stream, state);
|
|
|
88 |
if (style !== "comment" && state.context && (state.context.align == null) && state.context.type !== "pattern") {
|
|
|
89 |
state.context.align = true;
|
|
|
90 |
}
|
|
|
91 |
if (curPunc === "(") {
|
|
|
92 |
pushContext(state, ")", stream.column());
|
|
|
93 |
} else if (curPunc === "[") {
|
|
|
94 |
pushContext(state, "]", stream.column());
|
|
|
95 |
} else if (curPunc === "{") {
|
|
|
96 |
pushContext(state, "}", stream.column());
|
|
|
97 |
} else if (/[\]\}\)]/.test(curPunc)) {
|
|
|
98 |
while (state.context && state.context.type === "pattern") {
|
|
|
99 |
popContext(state);
|
|
|
100 |
}
|
|
|
101 |
if (state.context && curPunc === state.context.type) {
|
|
|
102 |
popContext(state);
|
|
|
103 |
}
|
|
|
104 |
} else if (curPunc === "." && state.context && state.context.type === "pattern") {
|
|
|
105 |
popContext(state);
|
|
|
106 |
} else if (/atom|string|variable/.test(style) && state.context) {
|
|
|
107 |
if (/[\}\]]/.test(state.context.type)) {
|
|
|
108 |
pushContext(state, "pattern", stream.column());
|
|
|
109 |
} else if (state.context.type === "pattern" && !state.context.align) {
|
|
|
110 |
state.context.align = true;
|
|
|
111 |
state.context.col = stream.column();
|
|
|
112 |
}
|
|
|
113 |
}
|
|
|
114 |
return style;
|
|
|
115 |
},
|
|
|
116 |
indent: function(state, textAfter) {
|
|
|
117 |
var firstChar = textAfter && textAfter.charAt(0);
|
|
|
118 |
var context = state.context;
|
|
|
119 |
if (/[\]\}]/.test(firstChar)) {
|
|
|
120 |
while (context && context.type === "pattern") {
|
|
|
121 |
context = context.prev;
|
|
|
122 |
}
|
|
|
123 |
}
|
|
|
124 |
var closing = context && firstChar === context.type;
|
|
|
125 |
if (!context) return 0;
|
|
|
126 |
if (context.type === "keywords") return CodeMirror.commands.newlineAndIndent;
|
|
|
127 |
if (context.align) return context.col + (closing ? 0 : 1);
|
|
|
128 |
return context.indent + (closing ? 0 : indentUnit);
|
|
|
129 |
}
|
|
|
130 |
};
|
|
|
131 |
});
|
|
|
132 |
|
|
|
133 |
CodeMirror.modeExtensions["cypher"] = {
|
|
|
134 |
autoFormatLineBreaks: function(text) {
|
|
|
135 |
var i, lines, reProcessedPortion;
|
|
|
136 |
var lines = text.split("\n");
|
|
|
137 |
var reProcessedPortion = /\s+\b(return|where|order by|match|with|skip|limit|create|delete|set)\b\s/g;
|
|
|
138 |
for (var i = 0; i < lines.length; i++)
|
|
|
139 |
lines[i] = lines[i].replace(reProcessedPortion, " \n$1 ").trim();
|
|
|
140 |
return lines.join("\n");
|
|
|
141 |
}
|
|
|
142 |
};
|
|
|
143 |
|
|
|
144 |
CodeMirror.defineMIME("application/x-cypher-query", "cypher");
|
|
|
145 |
|
|
|
146 |
});
|