sieve.js 4.1 KB

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