sieve.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. (function(mod) {
  4. if (typeof exports == "object" && typeof module == "object") // CommonJS
  5. mod(require("../../lib/codemirror"));
  6. else if (typeof define == "function" && define.amd) // AMD
  7. define(["../../lib/codemirror"], mod);
  8. else // Plain browser env
  9. mod(CodeMirror);
  10. })(function(CodeMirror) {
  11. "use strict";
  12. CodeMirror.defineMode("sieve", function(config) {
  13. function words(str) {
  14. var obj = {}, words = str.split(" ");
  15. for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
  16. return obj;
  17. }
  18. var keywords = words("if elsif else stop require");
  19. var atoms = words("true false not");
  20. var indentUnit = config.indentUnit;
  21. function tokenBase(stream, state) {
  22. var ch = stream.next();
  23. if (ch == "/" && stream.eat("*")) {
  24. state.tokenize = tokenCComment;
  25. return tokenCComment(stream, state);
  26. }
  27. if (ch === '#') {
  28. stream.skipToEnd();
  29. return "comment";
  30. }
  31. if (ch == "\"") {
  32. state.tokenize = tokenString(ch);
  33. return state.tokenize(stream, state);
  34. }
  35. if (ch == "(") {
  36. state._indent.push("(");
  37. // add virtual angel wings so that editor behaves...
  38. // ...more sane in case of broken brackets
  39. state._indent.push("{");
  40. return null;
  41. }
  42. if (ch === "{") {
  43. state._indent.push("{");
  44. return null;
  45. }
  46. if (ch == ")") {
  47. state._indent.pop();
  48. state._indent.pop();
  49. }
  50. if (ch === "}") {
  51. state._indent.pop();
  52. return null;
  53. }
  54. if (ch == ",")
  55. return null;
  56. if (ch == ";")
  57. return null;
  58. if (/[{}\(\),;]/.test(ch))
  59. return null;
  60. // 1*DIGIT "K" / "M" / "G"
  61. if (/\d/.test(ch)) {
  62. stream.eatWhile(/[\d]/);
  63. stream.eat(/[KkMmGg]/);
  64. return "number";
  65. }
  66. // ":" (ALPHA / "_") *(ALPHA / DIGIT / "_")
  67. if (ch == ":") {
  68. stream.eatWhile(/[a-zA-Z_]/);
  69. stream.eatWhile(/[a-zA-Z0-9_]/);
  70. return "operator";
  71. }
  72. stream.eatWhile(/\w/);
  73. var cur = stream.current();
  74. // "text:" *(SP / HTAB) (hash-comment / CRLF)
  75. // *(multiline-literal / multiline-dotstart)
  76. // "." CRLF
  77. if ((cur == "text") && stream.eat(":"))
  78. {
  79. state.tokenize = tokenMultiLineString;
  80. return "string";
  81. }
  82. if (keywords.propertyIsEnumerable(cur))
  83. return "keyword";
  84. if (atoms.propertyIsEnumerable(cur))
  85. return "atom";
  86. return null;
  87. }
  88. function tokenMultiLineString(stream, state)
  89. {
  90. state._multiLineString = true;
  91. // the first line is special it may contain a comment
  92. if (!stream.sol()) {
  93. stream.eatSpace();
  94. if (stream.peek() == "#") {
  95. stream.skipToEnd();
  96. return "comment";
  97. }
  98. stream.skipToEnd();
  99. return "string";
  100. }
  101. if ((stream.next() == ".") && (stream.eol()))
  102. {
  103. state._multiLineString = false;
  104. state.tokenize = tokenBase;
  105. }
  106. return "string";
  107. }
  108. function tokenCComment(stream, state) {
  109. var maybeEnd = false, ch;
  110. while ((ch = stream.next()) != null) {
  111. if (maybeEnd && ch == "/") {
  112. state.tokenize = tokenBase;
  113. break;
  114. }
  115. maybeEnd = (ch == "*");
  116. }
  117. return "comment";
  118. }
  119. function tokenString(quote) {
  120. return function(stream, state) {
  121. var escaped = false, ch;
  122. while ((ch = stream.next()) != null) {
  123. if (ch == quote && !escaped)
  124. break;
  125. escaped = !escaped && ch == "\\";
  126. }
  127. if (!escaped) state.tokenize = tokenBase;
  128. return "string";
  129. };
  130. }
  131. return {
  132. startState: function(base) {
  133. return {tokenize: tokenBase,
  134. baseIndent: base || 0,
  135. _indent: []};
  136. },
  137. token: function(stream, state) {
  138. if (stream.eatSpace())
  139. return null;
  140. return (state.tokenize || tokenBase)(stream, state);
  141. },
  142. indent: function(state, _textAfter) {
  143. var length = state._indent.length;
  144. if (_textAfter && (_textAfter[0] == "}"))
  145. length--;
  146. if (length <0)
  147. length = 0;
  148. return length * indentUnit;
  149. },
  150. electricChars: "}"
  151. };
  152. });
  153. CodeMirror.defineMIME("application/sieve", "sieve");
  154. });