mode-coffee.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. ace.define("ace/mode/coffee_highlight_rules",[], function(require, exports, module) {
  2. "use strict";
  3. var oop = require("../lib/oop");
  4. var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
  5. oop.inherits(CoffeeHighlightRules, TextHighlightRules);
  6. function CoffeeHighlightRules() {
  7. var identifier = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*";
  8. var keywords = (
  9. "this|throw|then|try|typeof|super|switch|return|break|by|continue|" +
  10. "catch|class|in|instanceof|is|isnt|if|else|extends|for|own|" +
  11. "finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|" +
  12. "or|on|unless|until|and|yes|yield|export|import|default"
  13. );
  14. var langConstant = (
  15. "true|false|null|undefined|NaN|Infinity"
  16. );
  17. var illegal = (
  18. "case|const|function|var|void|with|enum|implements|" +
  19. "interface|let|package|private|protected|public|static"
  20. );
  21. var supportClass = (
  22. "Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|String|" +
  23. "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" +
  24. "SyntaxError|TypeError|URIError|" +
  25. "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" +
  26. "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray"
  27. );
  28. var supportFunction = (
  29. "Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|" +
  30. "encodeURIComponent|decodeURI|decodeURIComponent|String|"
  31. );
  32. var variableLanguage = (
  33. "window|arguments|prototype|document"
  34. );
  35. var keywordMapper = this.createKeywordMapper({
  36. "keyword": keywords,
  37. "constant.language": langConstant,
  38. "invalid.illegal": illegal,
  39. "language.support.class": supportClass,
  40. "language.support.function": supportFunction,
  41. "variable.language": variableLanguage
  42. }, "identifier");
  43. var functionRule = {
  44. token: ["paren.lparen", "variable.parameter", "paren.rparen", "text", "storage.type"],
  45. regex: /(?:(\()((?:"[^")]*?"|'[^')]*?'|\/[^\/)]*?\/|[^()"'\/])*?)(\))(\s*))?([\-=]>)/.source
  46. };
  47. var stringEscape = /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)/;
  48. this.$rules = {
  49. start : [
  50. {
  51. token : "constant.numeric",
  52. regex : "(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"
  53. }, {
  54. stateName: "qdoc",
  55. token : "string", regex : "'''", next : [
  56. {token : "string", regex : "'''", next : "start"},
  57. {token : "constant.language.escape", regex : stringEscape},
  58. {defaultToken: "string"}
  59. ]
  60. }, {
  61. stateName: "qqdoc",
  62. token : "string",
  63. regex : '"""',
  64. next : [
  65. {token : "string", regex : '"""', next : "start"},
  66. {token : "paren.string", regex : '#{', push : "start"},
  67. {token : "constant.language.escape", regex : stringEscape},
  68. {defaultToken: "string"}
  69. ]
  70. }, {
  71. stateName: "qstring",
  72. token : "string", regex : "'", next : [
  73. {token : "string", regex : "'", next : "start"},
  74. {token : "constant.language.escape", regex : stringEscape},
  75. {defaultToken: "string"}
  76. ]
  77. }, {
  78. stateName: "qqstring",
  79. token : "string.start", regex : '"', next : [
  80. {token : "string.end", regex : '"', next : "start"},
  81. {token : "paren.string", regex : '#{', push : "start"},
  82. {token : "constant.language.escape", regex : stringEscape},
  83. {defaultToken: "string"}
  84. ]
  85. }, {
  86. stateName: "js",
  87. token : "string", regex : "`", next : [
  88. {token : "string", regex : "`", next : "start"},
  89. {token : "constant.language.escape", regex : stringEscape},
  90. {defaultToken: "string"}
  91. ]
  92. }, {
  93. regex: "[{}]", onMatch: function(val, state, stack) {
  94. this.next = "";
  95. if (val == "{" && stack.length) {
  96. stack.unshift("start", state);
  97. return "paren";
  98. }
  99. if (val == "}" && stack.length) {
  100. stack.shift();
  101. this.next = stack.shift() || "";
  102. if (this.next.indexOf("string") != -1)
  103. return "paren.string";
  104. }
  105. return "paren";
  106. }
  107. }, {
  108. token : "string.regex",
  109. regex : "///",
  110. next : "heregex"
  111. }, {
  112. token : "string.regex",
  113. regex : /(?:\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)(?:[imgy]{0,4})(?!\w)/
  114. }, {
  115. token : "comment",
  116. regex : "###(?!#)",
  117. next : "comment"
  118. }, {
  119. token : "comment",
  120. regex : "#.*"
  121. }, {
  122. token : ["punctuation.operator", "text", "identifier"],
  123. regex : "(\\.)(\\s*)(" + illegal + ")"
  124. }, {
  125. token : "punctuation.operator",
  126. regex : "\\.{1,3}"
  127. }, {
  128. token : ["keyword", "text", "language.support.class",
  129. "text", "keyword", "text", "language.support.class"],
  130. regex : "(class)(\\s+)(" + identifier + ")(?:(\\s+)(extends)(\\s+)(" + identifier + "))?"
  131. }, {
  132. token : ["entity.name.function", "text", "keyword.operator", "text"].concat(functionRule.token),
  133. regex : "(" + identifier + ")(\\s*)([=:])(\\s*)" + functionRule.regex
  134. },
  135. functionRule,
  136. {
  137. token : "variable",
  138. regex : "@(?:" + identifier + ")?"
  139. }, {
  140. token: keywordMapper,
  141. regex : identifier
  142. }, {
  143. token : "punctuation.operator",
  144. regex : "\\,|\\."
  145. }, {
  146. token : "storage.type",
  147. regex : "[\\-=]>"
  148. }, {
  149. token : "keyword.operator",
  150. regex : "(?:[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|[!*+-=><])"
  151. }, {
  152. token : "paren.lparen",
  153. regex : "[({[]"
  154. }, {
  155. token : "paren.rparen",
  156. regex : "[\\]})]"
  157. }, {
  158. token : "text",
  159. regex : "\\s+"
  160. }],
  161. heregex : [{
  162. token : "string.regex",
  163. regex : '.*?///[imgy]{0,4}',
  164. next : "start"
  165. }, {
  166. token : "comment.regex",
  167. regex : "\\s+(?:#.*)?"
  168. }, {
  169. token : "string.regex",
  170. regex : "\\S+"
  171. }],
  172. comment : [{
  173. token : "comment",
  174. regex : '###',
  175. next : "start"
  176. }, {
  177. defaultToken : "comment"
  178. }]
  179. };
  180. this.normalizeRules();
  181. }
  182. exports.CoffeeHighlightRules = CoffeeHighlightRules;
  183. });
  184. ace.define("ace/mode/matching_brace_outdent",[], function(require, exports, module) {
  185. "use strict";
  186. var Range = require("../range").Range;
  187. var MatchingBraceOutdent = function() {};
  188. (function() {
  189. this.checkOutdent = function(line, input) {
  190. if (! /^\s+$/.test(line))
  191. return false;
  192. return /^\s*\}/.test(input);
  193. };
  194. this.autoOutdent = function(doc, row) {
  195. var line = doc.getLine(row);
  196. var match = line.match(/^(\s*\})/);
  197. if (!match) return 0;
  198. var column = match[1].length;
  199. var openBracePos = doc.findMatchingBracket({row: row, column: column});
  200. if (!openBracePos || openBracePos.row == row) return 0;
  201. var indent = this.$getIndent(doc.getLine(openBracePos.row));
  202. doc.replace(new Range(row, 0, row, column-1), indent);
  203. };
  204. this.$getIndent = function(line) {
  205. return line.match(/^\s*/)[0];
  206. };
  207. }).call(MatchingBraceOutdent.prototype);
  208. exports.MatchingBraceOutdent = MatchingBraceOutdent;
  209. });
  210. ace.define("ace/mode/folding/coffee",[], function(require, exports, module) {
  211. "use strict";
  212. var oop = require("../../lib/oop");
  213. var BaseFoldMode = require("./fold_mode").FoldMode;
  214. var Range = require("../../range").Range;
  215. var FoldMode = exports.FoldMode = function() {};
  216. oop.inherits(FoldMode, BaseFoldMode);
  217. (function() {
  218. this.getFoldWidgetRange = function(session, foldStyle, row) {
  219. var range = this.indentationBlock(session, row);
  220. if (range)
  221. return range;
  222. var re = /\S/;
  223. var line = session.getLine(row);
  224. var startLevel = line.search(re);
  225. if (startLevel == -1 || line[startLevel] != "#")
  226. return;
  227. var startColumn = line.length;
  228. var maxRow = session.getLength();
  229. var startRow = row;
  230. var endRow = row;
  231. while (++row < maxRow) {
  232. line = session.getLine(row);
  233. var level = line.search(re);
  234. if (level == -1)
  235. continue;
  236. if (line[level] != "#")
  237. break;
  238. endRow = row;
  239. }
  240. if (endRow > startRow) {
  241. var endColumn = session.getLine(endRow).length;
  242. return new Range(startRow, startColumn, endRow, endColumn);
  243. }
  244. };
  245. this.getFoldWidget = function(session, foldStyle, row) {
  246. var line = session.getLine(row);
  247. var indent = line.search(/\S/);
  248. var next = session.getLine(row + 1);
  249. var prev = session.getLine(row - 1);
  250. var prevIndent = prev.search(/\S/);
  251. var nextIndent = next.search(/\S/);
  252. if (indent == -1) {
  253. session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
  254. return "";
  255. }
  256. if (prevIndent == -1) {
  257. if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
  258. session.foldWidgets[row - 1] = "";
  259. session.foldWidgets[row + 1] = "";
  260. return "start";
  261. }
  262. } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
  263. if (session.getLine(row - 2).search(/\S/) == -1) {
  264. session.foldWidgets[row - 1] = "start";
  265. session.foldWidgets[row + 1] = "";
  266. return "";
  267. }
  268. }
  269. if (prevIndent!= -1 && prevIndent < indent)
  270. session.foldWidgets[row - 1] = "start";
  271. else
  272. session.foldWidgets[row - 1] = "";
  273. if (indent < nextIndent)
  274. return "start";
  275. else
  276. return "";
  277. };
  278. }).call(FoldMode.prototype);
  279. });
  280. ace.define("ace/mode/coffee",[], function(require, exports, module) {
  281. "use strict";
  282. var Rules = require("./coffee_highlight_rules").CoffeeHighlightRules;
  283. var Outdent = require("./matching_brace_outdent").MatchingBraceOutdent;
  284. var FoldMode = require("./folding/coffee").FoldMode;
  285. var Range = require("../range").Range;
  286. var TextMode = require("./text").Mode;
  287. var WorkerClient = require("../worker/worker_client").WorkerClient;
  288. var oop = require("../lib/oop");
  289. function Mode() {
  290. this.HighlightRules = Rules;
  291. this.$outdent = new Outdent();
  292. this.foldingRules = new FoldMode();
  293. }
  294. oop.inherits(Mode, TextMode);
  295. (function() {
  296. var indenter = /(?:[({[=:]|[-=]>|\b(?:else|try|(?:swi|ca)tch(?:\s+[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$|^\s*(else\b\s*)?(?:if|for|while|loop)\b(?!.*\bthen\b)/;
  297. this.lineCommentStart = "#";
  298. this.blockComment = {start: "###", end: "###"};
  299. this.getNextLineIndent = function(state, line, tab) {
  300. var indent = this.$getIndent(line);
  301. var tokens = this.getTokenizer().getLineTokens(line, state).tokens;
  302. if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') &&
  303. state === 'start' && indenter.test(line))
  304. indent += tab;
  305. return indent;
  306. };
  307. this.checkOutdent = function(state, line, input) {
  308. return this.$outdent.checkOutdent(line, input);
  309. };
  310. this.autoOutdent = function(state, doc, row) {
  311. this.$outdent.autoOutdent(doc, row);
  312. };
  313. this.createWorker = function(session) {
  314. var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker");
  315. worker.attachToDocument(session.getDocument());
  316. worker.on("annotate", function(e) {
  317. session.setAnnotations(e.data);
  318. });
  319. worker.on("terminate", function() {
  320. session.clearAnnotations();
  321. });
  322. return worker;
  323. };
  324. this.$id = "ace/mode/coffee";
  325. }).call(Mode.prototype);
  326. exports.Mode = Mode;
  327. });
  328. (function() {
  329. ace.require(["ace/mode/coffee"], function(m) {
  330. if (typeof module == "object" && typeof exports == "object" && module) {
  331. module.exports = m;
  332. }
  333. });
  334. })();