a68bd604e401377e745b8f3a2e5088f0.js 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. ace.define("ace/mode/ruby_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module){"use strict";
  2. var oop = require("../lib/oop");
  3. var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
  4. var constantOtherSymbol = exports.constantOtherSymbol = {
  5. token: "constant.other.symbol.ruby",
  6. regex: "[:](?:[A-Za-z_]|[@$](?=[a-zA-Z0-9_]))[a-zA-Z0-9_]*[!=?]?"
  7. };
  8. exports.qString = {
  9. token: "string",
  10. regex: "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
  11. };
  12. exports.qqString = {
  13. token: "string",
  14. regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
  15. };
  16. exports.tString = {
  17. token: "string",
  18. regex: "[`](?:(?:\\\\.)|(?:[^'\\\\]))*?[`]"
  19. };
  20. var constantNumericHex = exports.constantNumericHex = {
  21. token: "constant.numeric",
  22. regex: "0[xX][0-9a-fA-F](?:[0-9a-fA-F]|_(?=[0-9a-fA-F]))*\\b"
  23. };
  24. var constantNumericBinary = exports.constantNumericBinary = {
  25. token: "constant.numeric",
  26. regex: /\b(0[bB][01](?:[01]|_(?=[01]))*)\b/
  27. };
  28. var constantNumericDecimal = exports.constantNumericDecimal = {
  29. token: "constant.numeric",
  30. regex: /\b(0[dD](?:[1-9](?:[\d]|_(?=[\d]))*|0))\b/
  31. };
  32. var constantNumericOctal = exports.constantNumericDecimal = {
  33. token: "constant.numeric",
  34. regex: /\b(0[oO]?(?:[1-7](?:[0-7]|_(?=[0-7]))*|0))\b/
  35. };
  36. var constantNumericRational = exports.constantNumericRational = {
  37. token: "constant.numeric",
  38. regex: /\b([\d]+(?:[./][\d]+)?ri?)\b/
  39. };
  40. var constantNumericComplex = exports.constantNumericComplex = {
  41. token: "constant.numeric",
  42. regex: /\b([\d]i)\b/
  43. };
  44. var constantNumericFloat = exports.constantNumericFloat = {
  45. token: "constant.numeric",
  46. regex: "[+-]?\\d(?:\\d|_(?=\\d))*(?:(?:\\.\\d(?:\\d|_(?=\\d))*)?(?:[eE][+-]?\\d+)?)?i?\\b"
  47. };
  48. var instanceVariable = exports.instanceVariable = {
  49. token: "variable.instance",
  50. regex: "@{1,2}[a-zA-Z_\\d]+"
  51. };
  52. var RubyHighlightRules = function () {
  53. var builtinFunctions = ("abort|Array|assert|assert_equal|assert_not_equal|assert_same|assert_not_same|" +
  54. "assert_nil|assert_not_nil|assert_match|assert_no_match|assert_in_delta|assert_throws|" +
  55. "assert_raise|assert_nothing_raised|assert_instance_of|assert_kind_of|assert_respond_to|" +
  56. "assert_operator|assert_send|assert_difference|assert_no_difference|assert_recognizes|" +
  57. "assert_generates|assert_response|assert_redirected_to|assert_template|assert_select|" +
  58. "assert_select_email|assert_select_rjs|assert_select_encoded|css_select|at_exit|" +
  59. "attr|attr_writer|attr_reader|attr_accessor|attr_accessible|autoload|binding|block_given?|callcc|" +
  60. "caller|catch|chomp|chomp!|chop|chop!|defined?|delete_via_redirect|eval|exec|exit|" +
  61. "exit!|fail|Float|flunk|follow_redirect!|fork|form_for|form_tag|format|gets|global_variables|gsub|" +
  62. "gsub!|get_via_redirect|host!|https?|https!|include|Integer|lambda|link_to|" +
  63. "link_to_unless_current|link_to_function|link_to_remote|load|local_variables|loop|open|open_session|" +
  64. "p|print|printf|proc|putc|puts|post_via_redirect|put_via_redirect|raise|rand|" +
  65. "raw|readline|readlines|redirect?|request_via_redirect|require|scan|select|" +
  66. "set_trace_func|sleep|split|sprintf|srand|String|stylesheet_link_tag|syscall|system|sub|sub!|test|" +
  67. "throw|trace_var|trap|untrace_var|atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan|" +
  68. "render|javascript_include_tag|csrf_meta_tag|label_tag|text_field_tag|submit_tag|check_box_tag|" +
  69. "content_tag|radio_button_tag|text_area_tag|password_field_tag|hidden_field_tag|" +
  70. "fields_for|select_tag|options_for_select|options_from_collection_for_select|collection_select|" +
  71. "time_zone_select|select_date|select_time|select_datetime|date_select|time_select|datetime_select|" +
  72. "select_year|select_month|select_day|select_hour|select_minute|select_second|file_field_tag|" +
  73. "file_field|respond_to|skip_before_filter|around_filter|after_filter|verify|" +
  74. "protect_from_forgery|rescue_from|helper_method|redirect_to|before_filter|" +
  75. "send_data|send_file|validates_presence_of|validates_uniqueness_of|validates_length_of|" +
  76. "validates_format_of|validates_acceptance_of|validates_associated|validates_exclusion_of|" +
  77. "validates_inclusion_of|validates_numericality_of|validates_with|validates_each|" +
  78. "authenticate_or_request_with_http_basic|authenticate_or_request_with_http_digest|" +
  79. "filter_parameter_logging|match|get|post|resources|redirect|scope|assert_routing|" +
  80. "translate|localize|extract_locale_from_tld|caches_page|expire_page|caches_action|expire_action|" +
  81. "cache|expire_fragment|expire_cache_for|observe|cache_sweeper|" +
  82. "has_many|has_one|belongs_to|has_and_belongs_to_many|p|warn|refine|using|module_function|extend|alias_method|" +
  83. "private_class_method|remove_method|undef_method");
  84. var keywords = ("alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|" +
  85. "__FILE__|finally|for|gem|if|in|__LINE__|module|next|not|or|private|protected|public|" +
  86. "redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield|__ENCODING__|prepend");
  87. var buildinConstants = ("true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|" +
  88. "RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING|RUBY_PATCHLEVEL|RUBY_REVISION|RUBY_COPYRIGHT|RUBY_ENGINE|RUBY_ENGINE_VERSION|RUBY_DESCRIPTION");
  89. var builtinVariables = ("$DEBUG|$defout|$FILENAME|$LOAD_PATH|$SAFE|$stdin|$stdout|$stderr|$VERBOSE|" +
  90. "$!|root_url|flash|session|cookies|params|request|response|logger|self");
  91. var keywordMapper = this.$keywords = this.createKeywordMapper({
  92. "keyword": keywords,
  93. "constant.language": buildinConstants,
  94. "variable.language": builtinVariables,
  95. "support.function": builtinFunctions,
  96. "invalid.deprecated": "debugger" // TODO is this a remnant from js mode?
  97. }, "identifier");
  98. var escapedChars = "\\\\(?:n(?:[1-7][0-7]{0,2}|0)|[nsrtvfbae'\"\\\\]|c(?:\\\\M-)?.|M-(?:\\\\C-|\\\\c)?.|C-(?:\\\\M-)?.|[0-7]{3}|x[\\da-fA-F]{2}|u[\\da-fA-F]{4}|u{[\\da-fA-F]{1,6}(?:\\s[\\da-fA-F]{1,6})*})";
  99. var closeParen = {
  100. "(": ")",
  101. "[": "]",
  102. "{": "}",
  103. "<": ">",
  104. "^": "^",
  105. "|": "|",
  106. "%": "%"
  107. };
  108. this.$rules = {
  109. "start": [
  110. {
  111. token: "comment",
  112. regex: "#.*$"
  113. }, {
  114. token: "comment.multiline",
  115. regex: "^=begin(?=$|\\s.*$)",
  116. next: "comment"
  117. }, {
  118. token: "string.regexp",
  119. regex: /[/](?=.*\/)/,
  120. next: "regex"
  121. },
  122. [{
  123. token: ["constant.other.symbol.ruby", "string.start"],
  124. regex: /(:)?(")/,
  125. push: [{
  126. token: "constant.language.escape",
  127. regex: escapedChars
  128. }, {
  129. token: "paren.start",
  130. regex: /#{/,
  131. push: "start"
  132. }, {
  133. token: "string.end",
  134. regex: /"/,
  135. next: "pop"
  136. }, {
  137. defaultToken: "string"
  138. }]
  139. }, {
  140. token: "string.start",
  141. regex: /`/,
  142. push: [{
  143. token: "constant.language.escape",
  144. regex: escapedChars
  145. }, {
  146. token: "paren.start",
  147. regex: /#{/,
  148. push: "start"
  149. }, {
  150. token: "string.end",
  151. regex: /`/,
  152. next: "pop"
  153. }, {
  154. defaultToken: "string"
  155. }]
  156. }, {
  157. token: ["constant.other.symbol.ruby", "string.start"],
  158. regex: /(:)?(')/,
  159. push: [{
  160. token: "constant.language.escape",
  161. regex: /\\['\\]/
  162. }, {
  163. token: "string.end",
  164. regex: /'/,
  165. next: "pop"
  166. }, {
  167. defaultToken: "string"
  168. }]
  169. }, {
  170. token: "string.start",
  171. regex: /%[qwx]([(\[<{^|%])/, onMatch: function (val, state, stack) {
  172. if (stack.length)
  173. stack = [];
  174. var paren = val[val.length - 1];
  175. stack.unshift(paren, state);
  176. this.next = "qStateWithoutInterpolation";
  177. return this.token;
  178. }
  179. }, {
  180. token: "string.start",
  181. regex: /%[QWX]?([(\[<{^|%])/, onMatch: function (val, state, stack) {
  182. if (stack.length)
  183. stack = [];
  184. var paren = val[val.length - 1];
  185. stack.unshift(paren, state);
  186. this.next = "qStateWithInterpolation";
  187. return this.token;
  188. }
  189. }, {
  190. token: "constant.other.symbol.ruby",
  191. regex: /%[si]([(\[<{^|%])/, onMatch: function (val, state, stack) {
  192. if (stack.length)
  193. stack = [];
  194. var paren = val[val.length - 1];
  195. stack.unshift(paren, state);
  196. this.next = "sStateWithoutInterpolation";
  197. return this.token;
  198. }
  199. }, {
  200. token: "constant.other.symbol.ruby",
  201. regex: /%[SI]([(\[<{^|%])/, onMatch: function (val, state, stack) {
  202. if (stack.length)
  203. stack = [];
  204. var paren = val[val.length - 1];
  205. stack.unshift(paren, state);
  206. this.next = "sStateWithInterpolation";
  207. return this.token;
  208. }
  209. }, {
  210. token: "string.regexp",
  211. regex: /%[r]([(\[<{^|%])/, onMatch: function (val, state, stack) {
  212. if (stack.length)
  213. stack = [];
  214. var paren = val[val.length - 1];
  215. stack.unshift(paren, state);
  216. this.next = "rState";
  217. return this.token;
  218. }
  219. }],
  220. {
  221. token: "punctuation",
  222. regex: "::"
  223. },
  224. instanceVariable,
  225. {
  226. token: "variable.global",
  227. regex: "[$][a-zA-Z_\\d]+"
  228. }, {
  229. token: "support.class",
  230. regex: "[A-Z][a-zA-Z_\\d]*"
  231. }, {
  232. token: ["punctuation.operator", "support.function"],
  233. regex: /(\.)([a-zA-Z_\d]+)(?=\()/
  234. }, {
  235. token: ["punctuation.operator", "identifier"],
  236. regex: /(\.)([a-zA-Z_][a-zA-Z_\d]*)/
  237. }, {
  238. token: "string.character",
  239. regex: "\\B\\?(?:" + escapedChars + "|\\S)"
  240. }, {
  241. token: "punctuation.operator",
  242. regex: /\?(?=.+:)/
  243. },
  244. constantNumericRational,
  245. constantNumericComplex,
  246. constantOtherSymbol,
  247. constantNumericHex,
  248. constantNumericFloat,
  249. constantNumericBinary,
  250. constantNumericDecimal,
  251. constantNumericOctal,
  252. {
  253. token: "constant.language.boolean",
  254. regex: "(?:true|false)\\b"
  255. }, {
  256. token: keywordMapper,
  257. regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
  258. }, {
  259. token: "punctuation.separator.key-value",
  260. regex: "=>"
  261. }, {
  262. stateName: "heredoc",
  263. onMatch: function (value, currentState, stack) {
  264. var next = (value[2] == '-' || value[2] == '~') ? "indentedHeredoc" : "heredoc";
  265. var tokens = value.split(this.splitRegex);
  266. stack.push(next, tokens[3]);
  267. return [
  268. { type: "constant", value: tokens[1] },
  269. { type: "string", value: tokens[2] },
  270. { type: "support.class", value: tokens[3] },
  271. { type: "string", value: tokens[4] }
  272. ];
  273. },
  274. regex: "(<<[-~]?)(['\"`]?)([\\w]+)(['\"`]?)",
  275. rules: {
  276. heredoc: [{
  277. onMatch: function (value, currentState, stack) {
  278. if (value === stack[1]) {
  279. stack.shift();
  280. stack.shift();
  281. this.next = stack[0] || "start";
  282. return "support.class";
  283. }
  284. this.next = "";
  285. return "string";
  286. },
  287. regex: ".*$",
  288. next: "start"
  289. }],
  290. indentedHeredoc: [{
  291. token: "string",
  292. regex: "^ +"
  293. }, {
  294. onMatch: function (value, currentState, stack) {
  295. if (value === stack[1]) {
  296. stack.shift();
  297. stack.shift();
  298. this.next = stack[0] || "start";
  299. return "support.class";
  300. }
  301. this.next = "";
  302. return "string";
  303. },
  304. regex: ".*$",
  305. next: "start"
  306. }]
  307. }
  308. }, {
  309. regex: "$",
  310. token: "empty",
  311. next: function (currentState, stack) {
  312. if (stack[0] === "heredoc" || stack[0] === "indentedHeredoc")
  313. return stack[0];
  314. return currentState;
  315. }
  316. }, {
  317. token: "keyword.operator",
  318. regex: "!|\\$|%|&|\\*|/|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\||\\b(?:in|instanceof|new|delete|typeof|void)"
  319. }, {
  320. token: "paren.lparen",
  321. regex: "[[({]"
  322. }, {
  323. token: "paren.rparen",
  324. regex: "[\\])}]",
  325. onMatch: function (value, currentState, stack) {
  326. this.next = '';
  327. if (value == "}" && stack.length > 1 && stack[1] != "start") {
  328. stack.shift();
  329. this.next = stack.shift();
  330. }
  331. return this.token;
  332. }
  333. }, {
  334. token: "text",
  335. regex: "\\s+"
  336. }, {
  337. token: "punctuation.operator",
  338. regex: /[?:,;.]/
  339. }
  340. ],
  341. "comment": [
  342. {
  343. token: "comment.multiline",
  344. regex: "^=end(?=$|\\s.*$)",
  345. next: "start"
  346. }, {
  347. token: "comment",
  348. regex: ".+"
  349. }
  350. ],
  351. "qStateWithInterpolation": [{
  352. token: "string.start",
  353. regex: /[(\[<{]/, onMatch: function (val, state, stack) {
  354. if (stack.length && val === stack[0]) {
  355. stack.unshift(val, state);
  356. return this.token;
  357. }
  358. return "string";
  359. }
  360. }, {
  361. token: "constant.language.escape",
  362. regex: escapedChars
  363. }, {
  364. token: "constant.language.escape",
  365. regex: /\\./
  366. }, {
  367. token: "paren.start",
  368. regex: /#{/,
  369. push: "start"
  370. }, {
  371. token: "string.end",
  372. regex: /[)\]>}^|%]/, onMatch: function (val, state, stack) {
  373. if (stack.length && val === closeParen[stack[0]]) {
  374. stack.shift();
  375. this.next = stack.shift();
  376. return this.token;
  377. }
  378. this.next = '';
  379. return "string";
  380. }
  381. }, {
  382. defaultToken: "string"
  383. }],
  384. "qStateWithoutInterpolation": [{
  385. token: "string.start",
  386. regex: /[(\[<{]/, onMatch: function (val, state, stack) {
  387. if (stack.length && val === stack[0]) {
  388. stack.unshift(val, state);
  389. return this.token;
  390. }
  391. return "string";
  392. }
  393. }, {
  394. token: "constant.language.escape",
  395. regex: /\\['\\]/
  396. }, {
  397. token: "constant.language.escape",
  398. regex: /\\./
  399. }, {
  400. token: "string.end",
  401. regex: /[)\]>}^|%]/, onMatch: function (val, state, stack) {
  402. if (stack.length && val === closeParen[stack[0]]) {
  403. stack.shift();
  404. this.next = stack.shift();
  405. return this.token;
  406. }
  407. this.next = '';
  408. return "string";
  409. }
  410. }, {
  411. defaultToken: "string"
  412. }],
  413. "sStateWithoutInterpolation": [{
  414. token: "constant.other.symbol.ruby",
  415. regex: /[(\[<{]/, onMatch: function (val, state, stack) {
  416. if (stack.length && val === stack[0]) {
  417. stack.unshift(val, state);
  418. return this.token;
  419. }
  420. return "constant.other.symbol.ruby";
  421. }
  422. }, {
  423. token: "constant.other.symbol.ruby",
  424. regex: /[)\]>}^|%]/, onMatch: function (val, state, stack) {
  425. if (stack.length && val === closeParen[stack[0]]) {
  426. stack.shift();
  427. this.next = stack.shift();
  428. return this.token;
  429. }
  430. this.next = '';
  431. return "constant.other.symbol.ruby";
  432. }
  433. }, {
  434. defaultToken: "constant.other.symbol.ruby"
  435. }],
  436. "sStateWithInterpolation": [{
  437. token: "constant.other.symbol.ruby",
  438. regex: /[(\[<{]/, onMatch: function (val, state, stack) {
  439. if (stack.length && val === stack[0]) {
  440. stack.unshift(val, state);
  441. return this.token;
  442. }
  443. return "constant.other.symbol.ruby";
  444. }
  445. }, {
  446. token: "constant.language.escape",
  447. regex: escapedChars
  448. }, {
  449. token: "constant.language.escape",
  450. regex: /\\./
  451. }, {
  452. token: "paren.start",
  453. regex: /#{/,
  454. push: "start"
  455. }, {
  456. token: "constant.other.symbol.ruby",
  457. regex: /[)\]>}^|%]/, onMatch: function (val, state, stack) {
  458. if (stack.length && val === closeParen[stack[0]]) {
  459. stack.shift();
  460. this.next = stack.shift();
  461. return this.token;
  462. }
  463. this.next = '';
  464. return "constant.other.symbol.ruby";
  465. }
  466. }, {
  467. defaultToken: "constant.other.symbol.ruby"
  468. }],
  469. "rState": [{
  470. token: "string.regexp",
  471. regex: /[(\[<{]/, onMatch: function (val, state, stack) {
  472. if (stack.length && val === stack[0]) {
  473. stack.unshift(val, state);
  474. return this.token;
  475. }
  476. return "constant.language.escape";
  477. }
  478. }, {
  479. token: "paren.start",
  480. regex: /#{/,
  481. push: "start"
  482. }, {
  483. token: "string.regexp",
  484. regex: /\//
  485. }, {
  486. token: "string.regexp",
  487. regex: /[)\]>}^|%][imxouesn]*/, onMatch: function (val, state, stack) {
  488. if (stack.length && val[0] === closeParen[stack[0]]) {
  489. stack.shift();
  490. this.next = stack.shift();
  491. return this.token;
  492. }
  493. this.next = '';
  494. return "constant.language.escape";
  495. }
  496. },
  497. { include: "regex" },
  498. {
  499. defaultToken: "string.regexp"
  500. }],
  501. "regex": [
  502. {
  503. token: "regexp.keyword",
  504. regex: /\\[wWdDhHsS]/
  505. }, {
  506. token: "constant.language.escape",
  507. regex: /\\[AGbBzZ]/
  508. }, {
  509. token: "constant.language.escape",
  510. regex: /\\g<[a-zA-Z0-9]*>/
  511. }, {
  512. token: ["constant.language.escape", "regexp.keyword", "constant.language.escape"],
  513. regex: /(\\p{\^?)(Alnum|Alpha|Blank|Cntrl|Digit|Graph|Lower|Print|Punct|Space|Upper|XDigit|Word|ASCII|Any|Assigned|Arabic|Armenian|Balinese|Bengali|Bopomofo|Braille|Buginese|Buhid|Canadian_Aboriginal|Carian|Cham|Cherokee|Common|Coptic|Cuneiform|Cypriot|Cyrillic|Deseret|Devanagari|Ethiopic|Georgian|Glagolitic|Gothic|Greek|Gujarati|Gurmukhi|Han|Hangul|Hanunoo|Hebrew|Hiragana|Inherited|Kannada|Katakana|Kayah_Li|Kharoshthi|Khmer|Lao|Latin|Lepcha|Limbu|Linear_B|Lycian|Lydian|Malayalam|Mongolian|Myanmar|New_Tai_Lue|Nko|Ogham|Ol_Chiki|Old_Italic|Old_Persian|Oriya|Osmanya|Phags_Pa|Phoenician|Rejang|Runic|Saurashtra|Shavian|Sinhala|Sundanese|Syloti_Nagri|Syriac|Tagalog|Tagbanwa|Tai_Le|Tamil|Telugu|Thaana|Thai|Tibetan|Tifinagh|Ugaritic|Vai|Yi|Ll|Lm|Lt|Lu|Lo|Mn|Mc|Me|Nd|Nl|Pc|Pd|Ps|Pe|Pi|Pf|Po|No|Sm|Sc|Sk|So|Zs|Zl|Zp|Cc|Cf|Cn|Co|Cs|N|L|M|P|S|Z|C)(})/
  514. }, {
  515. token: ["constant.language.escape", "invalid", "constant.language.escape"],
  516. regex: /(\\p{\^?)([^/]*)(})/
  517. }, {
  518. token: "regexp.keyword.operator",
  519. regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
  520. }, {
  521. token: "string.regexp",
  522. regex: /[/][imxouesn]*/,
  523. next: "start"
  524. }, {
  525. token: "invalid",
  526. regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/
  527. }, {
  528. token: "constant.language.escape",
  529. regex: /\(\?(?:[:=!>]|<'?[a-zA-Z]*'?>|<[=!])|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/
  530. }, {
  531. token: "constant.language.delimiter",
  532. regex: /\|/
  533. }, {
  534. token: "regexp.keyword",
  535. regex: /\[\[:(?:alnum|alpha|blank|cntrl|digit|graph|lower|print|punct|space|upper|xdigit|word|ascii):\]\]/
  536. }, {
  537. token: "constant.language.escape",
  538. regex: /\[\^?/,
  539. push: "regex_character_class"
  540. }, {
  541. defaultToken: "string.regexp"
  542. }
  543. ],
  544. "regex_character_class": [
  545. {
  546. token: "regexp.keyword",
  547. regex: /\\[wWdDhHsS]/
  548. }, {
  549. token: "regexp.charclass.keyword.operator",
  550. regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
  551. }, {
  552. token: "constant.language.escape",
  553. regex: /&?&?\[\^?/,
  554. push: "regex_character_class"
  555. }, {
  556. token: "constant.language.escape",
  557. regex: "]",
  558. next: "pop"
  559. }, {
  560. token: "constant.language.escape",
  561. regex: "-"
  562. }, {
  563. defaultToken: "string.regexp.characterclass"
  564. }
  565. ]
  566. };
  567. this.normalizeRules();
  568. };
  569. oop.inherits(RubyHighlightRules, TextHighlightRules);
  570. exports.RubyHighlightRules = RubyHighlightRules;
  571. });
  572. ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module){"use strict";
  573. var Range = require("../range").Range;
  574. var MatchingBraceOutdent = function () { };
  575. (function () {
  576. this.checkOutdent = function (line, input) {
  577. if (!/^\s+$/.test(line))
  578. return false;
  579. return /^\s*\}/.test(input);
  580. };
  581. this.autoOutdent = function (doc, row) {
  582. var line = doc.getLine(row);
  583. var match = line.match(/^(\s*\})/);
  584. if (!match)
  585. return 0;
  586. var column = match[1].length;
  587. var openBracePos = doc.findMatchingBracket({ row: row, column: column });
  588. if (!openBracePos || openBracePos.row == row)
  589. return 0;
  590. var indent = this.$getIndent(doc.getLine(openBracePos.row));
  591. doc.replace(new Range(row, 0, row, column - 1), indent);
  592. };
  593. this.$getIndent = function (line) {
  594. return line.match(/^\s*/)[0];
  595. };
  596. }).call(MatchingBraceOutdent.prototype);
  597. exports.MatchingBraceOutdent = MatchingBraceOutdent;
  598. });
  599. ace.define("ace/mode/folding/ruby",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range","ace/token_iterator"], function(require, exports, module){"use strict";
  600. var oop = require("../../lib/oop");
  601. var BaseFoldMode = require("./fold_mode").FoldMode;
  602. var Range = require("../../range").Range;
  603. var TokenIterator = require("../../token_iterator").TokenIterator;
  604. var FoldMode = exports.FoldMode = function () {
  605. };
  606. oop.inherits(FoldMode, BaseFoldMode);
  607. (function () {
  608. this.indentKeywords = {
  609. "class": 1,
  610. "def": 1,
  611. "module": 1,
  612. "do": 1,
  613. "unless": 1,
  614. "if": 1,
  615. "while": 1,
  616. "for": 1,
  617. "until": 1,
  618. "begin": 1,
  619. "else": 0,
  620. "elsif": 0,
  621. "rescue": 0,
  622. "ensure": 0,
  623. "when": 0,
  624. "end": -1,
  625. "case": 1,
  626. "=begin": 1,
  627. "=end": -1
  628. };
  629. this.foldingStartMarker = /(?:\s|^)(def|do|while|class|unless|module|if|for|until|begin|else|elsif|case|rescue|ensure|when)\b|({\s*$)|(=begin)/;
  630. this.foldingStopMarker = /(=end(?=$|\s.*$))|(^\s*})|\b(end)\b/;
  631. this.getFoldWidget = function (session, foldStyle, row) {
  632. var line = session.getLine(row);
  633. var isStart = this.foldingStartMarker.test(line);
  634. var isEnd = this.foldingStopMarker.test(line);
  635. if (isStart && !isEnd) {
  636. var match = line.match(this.foldingStartMarker);
  637. if (match[1]) {
  638. if (match[1] == "if" || match[1] == "else" || match[1] == "while" || match[1] == "until" || match[1] == "unless") {
  639. if (match[1] == "else" && /^\s*else\s*$/.test(line) === false) {
  640. return;
  641. }
  642. if (/^\s*(?:if|else|while|until|unless)\s*/.test(line) === false) {
  643. return;
  644. }
  645. }
  646. if (match[1] == "when") {
  647. if (/\sthen\s/.test(line) === true) {
  648. return;
  649. }
  650. }
  651. if (session.getTokenAt(row, match.index + 2).type === "keyword")
  652. return "start";
  653. }
  654. else if (match[3]) {
  655. if (session.getTokenAt(row, match.index + 1).type === "comment.multiline")
  656. return "start";
  657. }
  658. else {
  659. return "start";
  660. }
  661. }
  662. if (foldStyle != "markbeginend" || !isEnd || isStart && isEnd)
  663. return "";
  664. var match = line.match(this.foldingStopMarker);
  665. if (match[3] === "end") {
  666. if (session.getTokenAt(row, match.index + 1).type === "keyword")
  667. return "end";
  668. }
  669. else if (match[1]) {
  670. if (session.getTokenAt(row, match.index + 1).type === "comment.multiline")
  671. return "end";
  672. }
  673. else
  674. return "end";
  675. };
  676. this.getFoldWidgetRange = function (session, foldStyle, row) {
  677. var line = session.doc.getLine(row);
  678. var match = this.foldingStartMarker.exec(line);
  679. if (match) {
  680. if (match[1] || match[3])
  681. return this.rubyBlock(session, row, match.index + 2);
  682. return this.openingBracketBlock(session, "{", row, match.index);
  683. }
  684. var match = this.foldingStopMarker.exec(line);
  685. if (match) {
  686. if (match[3] === "end") {
  687. if (session.getTokenAt(row, match.index + 1).type === "keyword")
  688. return this.rubyBlock(session, row, match.index + 1);
  689. }
  690. if (match[1] === "=end") {
  691. if (session.getTokenAt(row, match.index + 1).type === "comment.multiline")
  692. return this.rubyBlock(session, row, match.index + 1);
  693. }
  694. return this.closingBracketBlock(session, "}", row, match.index + match[0].length);
  695. }
  696. };
  697. this.rubyBlock = function (session, row, column, tokenRange) {
  698. var stream = new TokenIterator(session, row, column);
  699. var token = stream.getCurrentToken();
  700. if (!token || (token.type != "keyword" && token.type != "comment.multiline"))
  701. return;
  702. var val = token.value;
  703. var line = session.getLine(row);
  704. switch (token.value) {
  705. case "if":
  706. case "unless":
  707. case "while":
  708. case "until":
  709. var checkToken = new RegExp("^\\s*" + token.value);
  710. if (!checkToken.test(line)) {
  711. return;
  712. }
  713. var dir = this.indentKeywords[val];
  714. break;
  715. case "when":
  716. if (/\sthen\s/.test(line)) {
  717. return;
  718. }
  719. case "elsif":
  720. case "rescue":
  721. case "ensure":
  722. var dir = 1;
  723. break;
  724. case "else":
  725. var checkToken = new RegExp("^\\s*" + token.value + "\\s*$");
  726. if (!checkToken.test(line)) {
  727. return;
  728. }
  729. var dir = 1;
  730. break;
  731. default:
  732. var dir = this.indentKeywords[val];
  733. break;
  734. }
  735. var stack = [val];
  736. if (!dir)
  737. return;
  738. var startColumn = dir === -1 ? session.getLine(row - 1).length : session.getLine(row).length;
  739. var startRow = row;
  740. var ranges = [];
  741. ranges.push(stream.getCurrentTokenRange());
  742. stream.step = dir === -1 ? stream.stepBackward : stream.stepForward;
  743. if (token.type == "comment.multiline") {
  744. while (token = stream.step()) {
  745. if (token.type !== "comment.multiline")
  746. continue;
  747. if (dir == 1) {
  748. startColumn = 6;
  749. if (token.value == "=end") {
  750. break;
  751. }
  752. }
  753. else {
  754. if (token.value == "=begin") {
  755. break;
  756. }
  757. }
  758. }
  759. }
  760. else {
  761. while (token = stream.step()) {
  762. var ignore = false;
  763. if (token.type !== "keyword")
  764. continue;
  765. var level = dir * this.indentKeywords[token.value];
  766. line = session.getLine(stream.getCurrentTokenRow());
  767. switch (token.value) {
  768. case "do":
  769. for (var i = stream.$tokenIndex - 1; i >= 0; i--) {
  770. var prevToken = stream.$rowTokens[i];
  771. if (prevToken && (prevToken.value == "while" || prevToken.value == "until" || prevToken.value == "for")) {
  772. level = 0;
  773. break;
  774. }
  775. }
  776. break;
  777. case "else":
  778. var checkToken = new RegExp("^\\s*" + token.value + "\\s*$");
  779. if (!checkToken.test(line) || val == "case") {
  780. level = 0;
  781. ignore = true;
  782. }
  783. break;
  784. case "if":
  785. case "unless":
  786. case "while":
  787. case "until":
  788. var checkToken = new RegExp("^\\s*" + token.value);
  789. if (!checkToken.test(line)) {
  790. level = 0;
  791. ignore = true;
  792. }
  793. break;
  794. case "when":
  795. if (/\sthen\s/.test(line) || val == "case") {
  796. level = 0;
  797. ignore = true;
  798. }
  799. break;
  800. }
  801. if (level > 0) {
  802. stack.unshift(token.value);
  803. }
  804. else if (level <= 0 && ignore === false) {
  805. stack.shift();
  806. if (!stack.length) {
  807. if ((val == "while" || val == "until" || val == "for") && token.value != "do") {
  808. break;
  809. }
  810. if (token.value == "do" && dir == -1 && level != 0)
  811. break;
  812. if (token.value != "do")
  813. break;
  814. }
  815. if (level === 0) {
  816. stack.unshift(token.value);
  817. }
  818. }
  819. }
  820. }
  821. if (!token)
  822. return null;
  823. if (tokenRange) {
  824. ranges.push(stream.getCurrentTokenRange());
  825. return ranges;
  826. }
  827. var row = stream.getCurrentTokenRow();
  828. if (dir === -1) {
  829. if (token.type === "comment.multiline") {
  830. var endColumn = 6;
  831. }
  832. else {
  833. var endColumn = session.getLine(row).length;
  834. }
  835. return new Range(row, endColumn, startRow - 1, startColumn);
  836. }
  837. else
  838. return new Range(startRow, startColumn, row - 1, session.getLine(row - 1).length);
  839. };
  840. }).call(FoldMode.prototype);
  841. });
  842. ace.define("ace/mode/ruby",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/ruby_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/ruby"], function(require, exports, module){"use strict";
  843. var oop = require("../lib/oop");
  844. var TextMode = require("./text").Mode;
  845. var RubyHighlightRules = require("./ruby_highlight_rules").RubyHighlightRules;
  846. var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
  847. var Range = require("../range").Range;
  848. var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
  849. var FoldMode = require("./folding/ruby").FoldMode;
  850. var Mode = function () {
  851. this.HighlightRules = RubyHighlightRules;
  852. this.$outdent = new MatchingBraceOutdent();
  853. this.$behaviour = new CstyleBehaviour();
  854. this.foldingRules = new FoldMode();
  855. this.indentKeywords = this.foldingRules.indentKeywords;
  856. };
  857. oop.inherits(Mode, TextMode);
  858. (function () {
  859. this.lineCommentStart = "#";
  860. this.getNextLineIndent = function (state, line, tab) {
  861. var indent = this.$getIndent(line);
  862. var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
  863. var tokens = tokenizedLine.tokens;
  864. if (tokens.length && tokens[tokens.length - 1].type == "comment") {
  865. return indent;
  866. }
  867. if (state == "start") {
  868. var match = line.match(/^.*[\{\(\[]\s*$/);
  869. var startingClassOrMethod = line.match(/^\s*(class|def|module)\s.*$/);
  870. var startingDoBlock = line.match(/.*do(\s*|\s+\|.*\|\s*)$/);
  871. var startingConditional = line.match(/^\s*(if|else|when|elsif|unless|while|for|begin|rescue|ensure)\s*/);
  872. if (match || startingClassOrMethod || startingDoBlock || startingConditional) {
  873. indent += tab;
  874. }
  875. }
  876. return indent;
  877. };
  878. this.checkOutdent = function (state, line, input) {
  879. return /^\s+(end|else|rescue|ensure)$/.test(line + input) || this.$outdent.checkOutdent(line, input);
  880. };
  881. this.autoOutdent = function (state, session, row) {
  882. var line = session.getLine(row);
  883. if (/}/.test(line))
  884. return this.$outdent.autoOutdent(session, row);
  885. var indent = this.$getIndent(line);
  886. var prevLine = session.getLine(row - 1);
  887. var prevIndent = this.$getIndent(prevLine);
  888. var tab = session.getTabString();
  889. if (prevIndent.length <= indent.length) {
  890. if (indent.slice(-tab.length) == tab)
  891. session.remove(new Range(row, indent.length - tab.length, row, indent.length));
  892. }
  893. };
  894. this.getMatching = function (session, row, column) {
  895. if (row == undefined) {
  896. var pos = session.selection.lead;
  897. column = pos.column;
  898. row = pos.row;
  899. }
  900. var startToken = session.getTokenAt(row, column);
  901. if (startToken && startToken.value in this.indentKeywords)
  902. return this.foldingRules.rubyBlock(session, row, column, true);
  903. };
  904. this.$id = "ace/mode/ruby";
  905. this.snippetFileId = "ace/snippets/ruby";
  906. }).call(Mode.prototype);
  907. exports.Mode = Mode;
  908. }); (function() {
  909. ace.require(["ace/mode/ruby"], function(m) {
  910. if (typeof module == "object" && typeof exports == "object" && module) {
  911. module.exports = m;
  912. }
  913. });
  914. })();