mode-crystal.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. define("ace/mode/crystal_highlight_rules",["ace_require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function (ace_require, exports, module) {
  2. "use strict";
  3. var oop = ace_require("../lib/oop");
  4. var TextHighlightRules = ace_require("./text_highlight_rules").TextHighlightRules;
  5. var CrystalHighlightRules = function () {
  6. var builtinFunctions = (
  7. "puts|initialize|previous_def|typeof|as|pointerof|sizeof|instance_sizeof"
  8. );
  9. var keywords = (
  10. "if|end|else|elsif|unless|case|when|break|while|next|until|def|return|class|new|getter|setter|property|lib"
  11. + "|fun|do|struct|private|protected|public|module|super|abstract|include|extend|begin|enum|raise|yield|with"
  12. + "|alias|rescue|ensure|macro|uninitialized|union|type|ace_require"
  13. );
  14. var buildinConstants = (
  15. "true|TRUE|false|FALSE|nil|NIL|__LINE__|__END_LINE__|__FILE__|__DIR__"
  16. );
  17. var builtinVariables = (
  18. "$DEBUG|$defout|$FILENAME|$LOAD_PATH|$SAFE|$stdin|$stdout|$stderr|$VERBOSE|" +
  19. "root_url|flash|session|cookies|params|request|response|logger|self"
  20. );
  21. var keywordMapper = this.$keywords = this.createKeywordMapper({
  22. "keyword": keywords,
  23. "constant.language": buildinConstants,
  24. "variable.language": builtinVariables,
  25. "support.function": builtinFunctions
  26. }, "identifier");
  27. var hexNumber = "(?:0[xX][\\dA-Fa-f]+)";
  28. var decNumber = "(?:[0-9][\\d_]*)";
  29. var octNumber = "(?:0o[0-7][0-7]*)";
  30. var binNumber = "(?:0[bB][01]+)";
  31. var intNumber = "(?:[+-]?)(?:" + hexNumber + "|" + decNumber + "|" + octNumber + "|" + binNumber + ")(?:_?[iIuU](?:8|16|32|64))?\\b";
  32. var escapeExpression = /\\(?:[nsrtvfbae'"\\]|[0-7]{3}|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u{[\da-fA-F]{1,6}})/;
  33. var extEscapeExspresssion = /\\(?:[nsrtvfbae'"\\]|[0-7]{3}|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u{[\da-fA-F]{1,6}}|u{(:?[\da-fA-F]{2}\s)*[\da-fA-F]{2}})/;
  34. this.$rules = {
  35. "start": [
  36. {
  37. token: "comment",
  38. regex: "#.*$"
  39. }, {
  40. token: "string.regexp",
  41. regex: "[/]",
  42. push: [{
  43. token: "constant.language.escape",
  44. regex: extEscapeExspresssion
  45. }, {
  46. token: "string.regexp",
  47. regex: "[/][imx]*(?=[).,;\\s]|$)",
  48. next: "pop"
  49. }, {
  50. defaultToken: "string.regexp"
  51. }]
  52. },
  53. [{
  54. regex: "[{}]", onMatch: function (val, state, stack) {
  55. this.next = val == "{" ? this.nextState : "";
  56. if (val == "{" && stack.length) {
  57. stack.unshift("start", state);
  58. return "paren.lparen";
  59. }
  60. if (val == "}" && stack.length) {
  61. stack.shift();
  62. this.next = stack.shift();
  63. if (this.next.indexOf("string") != -1)
  64. return "paren.end";
  65. }
  66. return val == "{" ? "paren.lparen" : "paren.rparen";
  67. },
  68. nextState: "start"
  69. }, {
  70. token: "string.start",
  71. regex: /"/,
  72. push: [{
  73. token: "constant.language.escape",
  74. regex: extEscapeExspresssion
  75. }, {
  76. token: "string",
  77. regex: /\\#{/
  78. }, {
  79. token: "paren.start",
  80. regex: /#{/,
  81. push: "start"
  82. }, {
  83. token: "string.end",
  84. regex: /"/,
  85. next: "pop"
  86. }, {
  87. defaultToken: "string"
  88. }]
  89. }, {
  90. token: "string.start",
  91. regex: /`/,
  92. push: [{
  93. token: "constant.language.escape",
  94. regex: extEscapeExspresssion
  95. }, {
  96. token: "string",
  97. regex: /\\#{/
  98. }, {
  99. token: "paren.start",
  100. regex: /#{/,
  101. push: "start"
  102. }, {
  103. token: "string.end",
  104. regex: /`/,
  105. next: "pop"
  106. }, {
  107. defaultToken: "string"
  108. }]
  109. }, {
  110. stateName: "rpstring",
  111. token: "string.start",
  112. regex: /%[Qx]?\(/,
  113. push: [{
  114. token: "constant.language.escape",
  115. regex: extEscapeExspresssion
  116. }, {
  117. token: "string.start",
  118. regex: /\(/,
  119. push: "rpstring"
  120. }, {
  121. token: "string.end",
  122. regex: /\)/,
  123. next: "pop"
  124. }, {
  125. token: "paren.start",
  126. regex: /#{/,
  127. push: "start"
  128. }, {
  129. defaultToken: "string"
  130. }]
  131. }, {
  132. stateName: "spstring",
  133. token: "string.start",
  134. regex: /%[Qx]?\[/,
  135. push: [{
  136. token: "constant.language.escape",
  137. regex: extEscapeExspresssion
  138. }, {
  139. token: "string.start",
  140. regex: /\[/,
  141. push: "spstring"
  142. }, {
  143. token: "string.end",
  144. regex: /]/,
  145. next: "pop"
  146. }, {
  147. token: "paren.start",
  148. regex: /#{/,
  149. push: "start"
  150. }, {
  151. defaultToken: "string"
  152. }]
  153. }, {
  154. stateName: "fpstring",
  155. token: "string.start",
  156. regex: /%[Qx]?{/,
  157. push: [{
  158. token: "constant.language.escape",
  159. regex: extEscapeExspresssion
  160. }, {
  161. token: "string.start",
  162. regex: /{/,
  163. push: "fpstring"
  164. }, {
  165. token: "string.end",
  166. regex: /}/,
  167. next: "pop"
  168. }, {
  169. token: "paren.start",
  170. regex: /#{/,
  171. push: "start"
  172. }, {
  173. defaultToken: "string"
  174. }]
  175. }, {
  176. stateName: "tpstring",
  177. token: "string.start",
  178. regex: /%[Qx]?</,
  179. push: [{
  180. token: "constant.language.escape",
  181. regex: extEscapeExspresssion
  182. }, {
  183. token: "string.start",
  184. regex: /</,
  185. push: "tpstring"
  186. }, {
  187. token: "string.end",
  188. regex: />/,
  189. next: "pop"
  190. }, {
  191. token: "paren.start",
  192. regex: /#{/,
  193. push: "start"
  194. }, {
  195. defaultToken: "string"
  196. }]
  197. }, {
  198. stateName: "ppstring",
  199. token: "string.start",
  200. regex: /%[Qx]?\|/,
  201. push: [{
  202. token: "constant.language.escape",
  203. regex: extEscapeExspresssion
  204. }, {
  205. token: "string.end",
  206. regex: /\|/,
  207. next: "pop"
  208. }, {
  209. token: "paren.start",
  210. regex: /#{/,
  211. push: "start"
  212. }, {
  213. defaultToken: "string"
  214. }]
  215. }, {
  216. stateName: "rpqstring",
  217. token: "string.start",
  218. regex: /%[qwir]\(/,
  219. push: [{
  220. token: "string.start",
  221. regex: /\(/,
  222. push: "rpqstring"
  223. }, {
  224. token: "string.end",
  225. regex: /\)/,
  226. next: "pop"
  227. }, {
  228. defaultToken: "string"
  229. }]
  230. }, {
  231. stateName: "spqstring",
  232. token: "string.start",
  233. regex: /%[qwir]\[/,
  234. push: [{
  235. token: "string.start",
  236. regex: /\[/,
  237. push: "spqstring"
  238. }, {
  239. token: "string.end",
  240. regex: /]/,
  241. next: "pop"
  242. }, {
  243. defaultToken: "string"
  244. }]
  245. }, {
  246. stateName: "fpqstring",
  247. token: "string.start",
  248. regex: /%[qwir]{/,
  249. push: [{
  250. token: "string.start",
  251. regex: /{/,
  252. push: "fpqstring"
  253. }, {
  254. token: "string.end",
  255. regex: /}/,
  256. next: "pop"
  257. }, {
  258. defaultToken: "string"
  259. }]
  260. }, {
  261. stateName: "tpqstring",
  262. token: "string.start",
  263. regex: /%[qwir]</,
  264. push: [{
  265. token: "string.start",
  266. regex: /</,
  267. push: "tpqstring"
  268. }, {
  269. token: "string.end",
  270. regex: />/,
  271. next: "pop"
  272. }, {
  273. defaultToken: "string"
  274. }]
  275. }, {
  276. stateName: "ppqstring",
  277. token: "string.start",
  278. regex: /%[qwir]\|/,
  279. push: [{
  280. token: "string.end",
  281. regex: /\|/,
  282. next: "pop"
  283. }, {
  284. defaultToken: "string"
  285. }]
  286. }, {
  287. token: "string.start",
  288. regex: /'/,
  289. push: [{
  290. token: "constant.language.escape",
  291. regex: escapeExpression
  292. }, {
  293. token: "string.end",
  294. regex: /'|$/,
  295. next: "pop"
  296. }, {
  297. defaultToken: "string"
  298. }]
  299. }], {
  300. token: "text", // namespaces aren't symbols
  301. regex: "::"
  302. }, {
  303. token: "variable.instance", // instance variable
  304. regex: "@{1,2}[a-zA-Z_\\d]+"
  305. }, {
  306. token: "variable.fresh", // fresh variable
  307. regex: "%[a-zA-Z_\\d]+"
  308. }, {
  309. token: "support.class", // class name
  310. regex: "[A-Z][a-zA-Z_\\d]+"
  311. }, {
  312. token: "constant.other.symbol", // symbol
  313. regex: "[:](?:(?:===|<=>|\\[]\\?|\\[]=|\\[]|>>|\\*\\*|<<|==|!=|>=|<=|!~|=~|<|\\+|-|\\*|\\/|%|&|\\||\\^|>|!|~)|(?:(?:[A-Za-z_]|[@$](?=[a-zA-Z0-9_]))[a-zA-Z0-9_]*[!=?]?))"
  314. }, {
  315. token: "constant.numeric", // float
  316. regex: "[+-]?\\d(?:\\d|_(?=\\d))*(?:(?:\\.\\d(?:\\d|_(?=\\d))*)?(?:[eE][+-]?\\d+)?)?(?:_?[fF](?:32|64))?\\b"
  317. }, {
  318. token: "constant.numeric",
  319. regex: intNumber
  320. }, {
  321. token: "constant.other.symbol",
  322. regex: ':"',
  323. push: [{
  324. token: "constant.language.escape",
  325. regex: extEscapeExspresssion
  326. }, {
  327. token: "constant.other.symbol",
  328. regex: '"',
  329. next: "pop"
  330. }, {
  331. defaultToken: "constant.other.symbol"
  332. }]
  333. }, {
  334. token: "constant.language.boolean",
  335. regex: "(?:true|false)\\b"
  336. }, {
  337. token: "support.function",
  338. regex: "(?:is_a\\?|nil\\?|responds_to\\?|as\\?)"
  339. }, {
  340. token: keywordMapper,
  341. regex: "[a-zA-Z_$][a-zA-Z0-9_$!?]*\\b"
  342. }, {
  343. token: "variable.system",
  344. regex: "\\$\\!|\\$\\?"
  345. }, {
  346. token: "punctuation.separator.key-value",
  347. regex: "=>"
  348. }, {
  349. stateName: "heredoc",
  350. onMatch: function (value, currentState, stack) {
  351. var next = "heredoc";
  352. var tokens = value.split(this.splitRegex);
  353. stack.push(next, tokens[3]);
  354. return [
  355. {type: "constant", value: tokens[1]},
  356. {type: "string", value: tokens[2]},
  357. {type: "support.class", value: tokens[3]},
  358. {type: "string", value: tokens[4]}
  359. ];
  360. },
  361. regex: "(<<-)([']?)([\\w]+)([']?)",
  362. rules: {
  363. heredoc: [{
  364. token: "string",
  365. regex: "^ +"
  366. }, {
  367. onMatch: function (value, currentState, stack) {
  368. if (value === stack[1]) {
  369. stack.shift();
  370. stack.shift();
  371. this.next = stack[0] || "start";
  372. return "support.class";
  373. }
  374. this.next = "";
  375. return "string";
  376. },
  377. regex: ".*$",
  378. next: "start"
  379. }]
  380. }
  381. }, {
  382. regex: "$",
  383. token: "empty",
  384. next: function (currentState, stack) {
  385. if (stack[0] === "heredoc")
  386. return stack[0];
  387. return currentState;
  388. }
  389. }, {
  390. token: "punctuation.operator",
  391. regex: /[.]\s*(?![.])/,
  392. push: [{
  393. token : "punctuation.operator",
  394. regex : /[.]\s*(?![.])/
  395. }, {
  396. token : "support.function",
  397. regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
  398. }, {
  399. regex: "",
  400. token: "empty",
  401. next: "pop"
  402. }]
  403. }, {
  404. token: "keyword.operator",
  405. regex: "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|\\?|\\:|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\^|\\|"
  406. }, {
  407. token: "punctuation.operator",
  408. regex: /[?:,;.]/
  409. }, {
  410. token: "paren.lparen",
  411. regex: "[[({]"
  412. }, {
  413. token: "paren.rparen",
  414. regex: "[\\])}]"
  415. }, {
  416. token: "text",
  417. regex: "\\s+"
  418. }
  419. ]
  420. };
  421. this.normalizeRules();
  422. };
  423. oop.inherits(CrystalHighlightRules, TextHighlightRules);
  424. exports.CrystalHighlightRules = CrystalHighlightRules;
  425. });
  426. define("ace/mode/matching_brace_outdent",["ace_require","exports","module","ace/range"], function(ace_require, exports, module) {
  427. "use strict";
  428. var Range = ace_require("../range").Range;
  429. var MatchingBraceOutdent = function() {};
  430. (function() {
  431. this.checkOutdent = function(line, input) {
  432. if (! /^\s+$/.test(line))
  433. return false;
  434. return /^\s*\}/.test(input);
  435. };
  436. this.autoOutdent = function(doc, row) {
  437. var line = doc.getLine(row);
  438. var match = line.match(/^(\s*\})/);
  439. if (!match) return 0;
  440. var column = match[1].length;
  441. var openBracePos = doc.findMatchingBracket({row: row, column: column});
  442. if (!openBracePos || openBracePos.row == row) return 0;
  443. var indent = this.$getIndent(doc.getLine(openBracePos.row));
  444. doc.replace(new Range(row, 0, row, column-1), indent);
  445. };
  446. this.$getIndent = function(line) {
  447. return line.match(/^\s*/)[0];
  448. };
  449. }).call(MatchingBraceOutdent.prototype);
  450. exports.MatchingBraceOutdent = MatchingBraceOutdent;
  451. });
  452. define("ace/mode/folding/coffee",["ace_require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"], function(ace_require, exports, module) {
  453. "use strict";
  454. var oop = ace_require("../../lib/oop");
  455. var BaseFoldMode = ace_require("./fold_mode").FoldMode;
  456. var Range = ace_require("../../range").Range;
  457. var FoldMode = exports.FoldMode = function() {};
  458. oop.inherits(FoldMode, BaseFoldMode);
  459. (function() {
  460. this.getFoldWidgetRange = function(session, foldStyle, row) {
  461. var range = this.indentationBlock(session, row);
  462. if (range)
  463. return range;
  464. var re = /\S/;
  465. var line = session.getLine(row);
  466. var startLevel = line.search(re);
  467. if (startLevel == -1 || line[startLevel] != "#")
  468. return;
  469. var startColumn = line.length;
  470. var maxRow = session.getLength();
  471. var startRow = row;
  472. var endRow = row;
  473. while (++row < maxRow) {
  474. line = session.getLine(row);
  475. var level = line.search(re);
  476. if (level == -1)
  477. continue;
  478. if (line[level] != "#")
  479. break;
  480. endRow = row;
  481. }
  482. if (endRow > startRow) {
  483. var endColumn = session.getLine(endRow).length;
  484. return new Range(startRow, startColumn, endRow, endColumn);
  485. }
  486. };
  487. this.getFoldWidget = function(session, foldStyle, row) {
  488. var line = session.getLine(row);
  489. var indent = line.search(/\S/);
  490. var next = session.getLine(row + 1);
  491. var prev = session.getLine(row - 1);
  492. var prevIndent = prev.search(/\S/);
  493. var nextIndent = next.search(/\S/);
  494. if (indent == -1) {
  495. session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
  496. return "";
  497. }
  498. if (prevIndent == -1) {
  499. if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
  500. session.foldWidgets[row - 1] = "";
  501. session.foldWidgets[row + 1] = "";
  502. return "start";
  503. }
  504. } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
  505. if (session.getLine(row - 2).search(/\S/) == -1) {
  506. session.foldWidgets[row - 1] = "start";
  507. session.foldWidgets[row + 1] = "";
  508. return "";
  509. }
  510. }
  511. if (prevIndent!= -1 && prevIndent < indent)
  512. session.foldWidgets[row - 1] = "start";
  513. else
  514. session.foldWidgets[row - 1] = "";
  515. if (indent < nextIndent)
  516. return "start";
  517. else
  518. return "";
  519. };
  520. }).call(FoldMode.prototype);
  521. });
  522. define("ace/mode/crystal",["ace_require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/crystal_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/coffee"], function(ace_require, exports, module) {
  523. "use strict";
  524. var oop = ace_require("../lib/oop");
  525. var TextMode = ace_require("./text").Mode;
  526. var CrystalHighlightRules = ace_require("./crystal_highlight_rules").CrystalHighlightRules;
  527. var MatchingBraceOutdent = ace_require("./matching_brace_outdent").MatchingBraceOutdent;
  528. var Range = ace_require("../range").Range;
  529. var CstyleBehaviour = ace_require("./behaviour/cstyle").CstyleBehaviour;
  530. var FoldMode = ace_require("./folding/coffee").FoldMode;
  531. var Mode = function() {
  532. this.HighlightRules = CrystalHighlightRules;
  533. this.$outdent = new MatchingBraceOutdent();
  534. this.$behaviour = new CstyleBehaviour();
  535. this.foldingRules = new FoldMode();
  536. };
  537. oop.inherits(Mode, TextMode);
  538. (function() {
  539. this.lineCommentStart = "#";
  540. this.getNextLineIndent = function(state, line, tab) {
  541. var indent = this.$getIndent(line);
  542. var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
  543. var tokens = tokenizedLine.tokens;
  544. if (tokens.length && tokens[tokens.length-1].type == "comment") {
  545. return indent;
  546. }
  547. if (state == "start") {
  548. var match = line.match(/^.*[\{\(\[]\s*$/);
  549. var startingClassOrMethod = line.match(/^\s*(class|def|module)\s.*$/);
  550. var startingDoBlock = line.match(/.*do(\s*|\s+\|.*\|\s*)$/);
  551. var startingConditional = line.match(/^\s*(if|else|when)\s*/);
  552. if (match || startingClassOrMethod || startingDoBlock || startingConditional) {
  553. indent += tab;
  554. }
  555. }
  556. return indent;
  557. };
  558. this.checkOutdent = function(state, line, input) {
  559. return /^\s+(end|else)$/.test(line + input) || this.$outdent.checkOutdent(line, input);
  560. };
  561. this.autoOutdent = function(state, session, row) {
  562. var line = session.getLine(row);
  563. if (/}/.test(line))
  564. return this.$outdent.autoOutdent(session, row);
  565. var indent = this.$getIndent(line);
  566. var prevLine = session.getLine(row - 1);
  567. var prevIndent = this.$getIndent(prevLine);
  568. var tab = session.getTabString();
  569. if (prevIndent.length <= indent.length) {
  570. if (indent.slice(-tab.length) == tab)
  571. session.remove(new Range(row, indent.length-tab.length, row, indent.length));
  572. }
  573. };
  574. this.$id = "ace/mode/crystal";
  575. }).call(Mode.prototype);
  576. exports.Mode = Mode;
  577. }); (function() {
  578. window.ace_require(["ace/mode/crystal"], function(m) {
  579. if (typeof module == "object" && typeof exports == "object" && module) {
  580. module.exports = m;
  581. }
  582. });
  583. })();