summaryrefslogtreecommitdiff
path: root/src/fauxton/jam/codemirror/mode/sieve/sieve.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/fauxton/jam/codemirror/mode/sieve/sieve.js')
-rw-r--r--src/fauxton/jam/codemirror/mode/sieve/sieve.js156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/fauxton/jam/codemirror/mode/sieve/sieve.js b/src/fauxton/jam/codemirror/mode/sieve/sieve.js
new file mode 100644
index 000000000..db777c131
--- /dev/null
+++ b/src/fauxton/jam/codemirror/mode/sieve/sieve.js
@@ -0,0 +1,156 @@
+/*
+ * See LICENSE in this directory for the license under which this code
+ * is released.
+ */
+
+CodeMirror.defineMode("sieve", function(config) {
+ function words(str) {
+ var obj = {}, words = str.split(" ");
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
+ return obj;
+ }
+
+ var keywords = words("if elsif else stop require");
+ var atoms = words("true false not");
+ var indentUnit = config.indentUnit;
+
+ function tokenBase(stream, state) {
+
+ var ch = stream.next();
+ if (ch == "/" && stream.eat("*")) {
+ state.tokenize = tokenCComment;
+ return tokenCComment(stream, state);
+ }
+
+ if (ch === '#') {
+ stream.skipToEnd();
+ return "comment";
+ }
+
+ if (ch == "\"") {
+ state.tokenize = tokenString(ch);
+ return state.tokenize(stream, state);
+ }
+
+ if (ch === "{")
+ {
+ state._indent++;
+ return null;
+ }
+
+ if (ch === "}")
+ {
+ state._indent--;
+ return null;
+ }
+
+ if (/[{}\(\),;]/.test(ch))
+ return null;
+
+ // 1*DIGIT "K" / "M" / "G"
+ if (/\d/.test(ch)) {
+ stream.eatWhile(/[\d]/);
+ stream.eat(/[KkMmGg]/);
+ return "number";
+ }
+
+ // ":" (ALPHA / "_") *(ALPHA / DIGIT / "_")
+ if (ch == ":") {
+ stream.eatWhile(/[a-zA-Z_]/);
+ stream.eatWhile(/[a-zA-Z0-9_]/);
+
+ return "operator";
+ }
+
+ stream.eatWhile(/[\w\$_]/);
+ var cur = stream.current();
+
+ // "text:" *(SP / HTAB) (hash-comment / CRLF)
+ // *(multiline-literal / multiline-dotstart)
+ // "." CRLF
+ if ((cur == "text") && stream.eat(":"))
+ {
+ state.tokenize = tokenMultiLineString;
+ return "string";
+ }
+
+ if (keywords.propertyIsEnumerable(cur))
+ return "keyword";
+
+ if (atoms.propertyIsEnumerable(cur))
+ return "atom";
+ }
+
+ function tokenMultiLineString(stream, state)
+ {
+ state._multiLineString = true;
+ // the first line is special it may contain a comment
+ if (!stream.sol()) {
+ stream.eatSpace();
+
+ if (stream.peek() == "#") {
+ stream.skipToEnd();
+ return "comment";
+ }
+
+ stream.skipToEnd();
+ return "string";
+ }
+
+ if ((stream.next() == ".") && (stream.eol()))
+ {
+ state._multiLineString = false;
+ state.tokenize = tokenBase;
+ }
+
+ return "string";
+ }
+
+ function tokenCComment(stream, state) {
+ var maybeEnd = false, ch;
+ while ((ch = stream.next()) != null) {
+ if (maybeEnd && ch == "/") {
+ state.tokenize = tokenBase;
+ break;
+ }
+ maybeEnd = (ch == "*");
+ }
+ return "comment";
+ }
+
+ function tokenString(quote) {
+ return function(stream, state) {
+ var escaped = false, ch;
+ while ((ch = stream.next()) != null) {
+ if (ch == quote && !escaped)
+ break;
+ escaped = !escaped && ch == "\\";
+ }
+ if (!escaped) state.tokenize = tokenBase;
+ return "string";
+ };
+ }
+
+ return {
+ startState: function(base) {
+ return {tokenize: tokenBase,
+ baseIndent: base || 0,
+ _indent: 0};
+ },
+
+ token: function(stream, state) {
+ if (stream.eatSpace())
+ return null;
+
+ return (state.tokenize || tokenBase)(stream, state);;
+ },
+
+ indent: function(state, textAfter) {
+ return state.baseIndent + state._indent * indentUnit;
+ },
+
+ electricChars: "}"
+ };
+});
+
+CodeMirror.defineMIME("application/sieve", "sieve");