You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1037 lines
37KB

  1. %YAML 1.2
  2. ---
  3. # http://www.sublimetext.com/docs/3/syntax.html
  4. name: Crystal
  5. comment: |
  6. TODO: unresolved issues
  7. text:
  8. "p << end
  9. print me!
  10. end"
  11. symptoms:
  12. not recognized as a heredoc
  13. solution:
  14. there is no way to distinguish perfectly between the << operator and the start
  15. of a heredoc. Currently, we require assignment to recognize a heredoc. More
  16. refinement is possible.
  17. • Heredocs with indented terminators (<<-) are always distinguishable, however.
  18. • Nested heredocs are not really supportable at present
  19. text:
  20. print <<-'THERE'
  21. This is single quoted.
  22. The above used #{Time.now}
  23. THERE
  24. symtoms:
  25. From Programming Ruby p306; should be a non-interpolated heredoc.
  26. text:
  27. "a\332a"
  28. symptoms:
  29. '\332' is not recognized as slash3.. which should be octal 332.
  30. solution:
  31. plain regexp.. should be easy.
  32. text:
  33. val?(a):p(b)
  34. val?'a':'b'
  35. symptoms:
  36. ':p' is recognized as a symbol.. its 2 things ':' and 'p'.
  37. :'b' has same problem.
  38. solution:
  39. ternary operator rule, precedence stuff, symbol rule.
  40. but also consider 'a.b?(:c)' ??
  41. file_extensions:
  42. - cr
  43. first_line_match: ^#!/.*\bcrystal
  44. scope: source.crystal
  45. contexts:
  46. main:
  47. - match: |-
  48. (?x)
  49. ^
  50. \s*
  51. (abstract)?
  52. \s*
  53. (class|struct|union)
  54. \s+
  55. (
  56. (
  57. [.A-Z_:\x{80}-\x{10FFFF}][.\w:\x{80}-\x{10FFFF}]*
  58. (\(([,\s.a-zA-Z0-9_:\x{80}-\x{10FFFF}]+)\))?
  59. (
  60. \s*(<)\s*
  61. [.:A-Z\x{80}-\x{10FFFF}][.:\w\x{80}-\x{10FFFF}]*
  62. (\(([.a-zA-Z0-9_:]+\s,)\))?
  63. )?
  64. )|(
  65. (<<)
  66. \s*
  67. [.A-Z0-9_:\x{80}-\x{10FFFF}]+
  68. )
  69. )
  70. scope: meta.class.crystal
  71. captures:
  72. 1: keyword.control.class.crystal
  73. 2: keyword.control.class.crystal
  74. 3: entity.name.type.class.crystal
  75. 5: punctuation.separator.crystal
  76. 6: support.class.other.type-param.crystal
  77. 7: entity.other.inherited-class.crystal
  78. 8: punctuation.separator.crystal
  79. 9: punctuation.separator.crystal
  80. 10: support.class.other.type-param.crystal
  81. 11: punctuation.definition.variable.crystal
  82. - match: '^\s*(module)\s+(([A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(::))?([A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(::))?([A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(::))*[A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*)'
  83. scope: meta.module.crystal
  84. captures:
  85. 1: keyword.control.module.crystal
  86. 2: entity.name.type.module.crystal
  87. 3: entity.other.inherited-class.module.first.crystal
  88. 4: punctuation.separator.inheritance.crystal
  89. 5: entity.other.inherited-class.module.second.crystal
  90. 6: punctuation.separator.inheritance.crystal
  91. 7: entity.other.inherited-class.module.third.crystal
  92. 8: punctuation.separator.inheritance.crystal
  93. - match: '^\s*(lib)\s+(([A-Z]\w*(::))?([A-Z]\w*(::))?([A-Z]\w*(::))*[A-Z]\w*)'
  94. scope: meta.lib.crystal
  95. captures:
  96. 1: keyword.control.lib.crystal
  97. 2: entity.name.type.lib.crystal
  98. 3: entity.other.inherited-class.lib.first.crystal
  99. 4: punctuation.separator.inheritance.crystal
  100. 5: entity.other.inherited-class.lib.second.crystal
  101. 6: punctuation.separator.inheritance.crystal
  102. 7: entity.other.inherited-class.lib.third.crystal
  103. 8: punctuation.separator.inheritance.crystal
  104. - match: (?<!\.)\belse(\s)+if\b
  105. comment: else if is a common mistake carried over from other languages. it works if you put in a second end, but it’s never what you want.
  106. scope: invalid.deprecated.crystal
  107. - match: '(?<!\.)\b(BEGIN|alias|as|begin|case|select|abstract|class|END|ensure|for|fun|if|ifdef|in|lib|module|of|out|private|protected|rescue|struct|with|union|enum|macro|then|type|unless|until|while)\b(?![?!])'
  108. comment: everything being a reserved word, not a value and needing a 'end' is a..
  109. scope: keyword.control.primary.crystal
  110. - match: '(?<!\.)\b(when|else|elsif)\b(?![?!])'
  111. comment: everything being a reserved word, not a value and needing a 'end' is a..
  112. scope: keyword.control.secondary.crystal
  113. - match: '(?<!\.)\b(end)\b(?![?!])'
  114. comment: Give the end keyword an additional scope
  115. scope: keyword.control.secondary.end.crystal
  116. - match: (?<!\.)\bdo\b\s*
  117. comment: contextual smart pair support for block parameters
  118. scope: keyword.control.start-block.crystal
  119. - match: '(?<=\{)(\s+)'
  120. comment: contextual smart pair support
  121. scope: meta.syntax.crystal.start-block
  122. - match: (?<!\.)\b(and|not|or)\b
  123. comment: as above, just doesn't need a 'end' and does a logic operation
  124. scope: keyword.operator.logical.crystal
  125. - match: '(?<!\.)\b(alias|alias_method|break|next|pointerof|typeof|sizeof|instance_sizeof|return|super|yield|uninitialized|forall)\b(?![?!])'
  126. comment: just as above but being not a logical operation
  127. scope: keyword.control.pseudo-method.crystal
  128. - match: '\b(nil|true|false)\b(?![?!])'
  129. scope: constant.language.crystal
  130. - match: '\b(__(DIR|FILE|LINE)__|self)\b(?![?!])'
  131. scope: variable.language.crystal
  132. - match: '\b(initialize|new|loop|include|extend|raise|getter|setter|property|class_getter|class_setter|class_property|describe|it|with|delegate|def_hash|def_equals|def_equals_and_hash|forward_missing_to|record|assert_responds_to|spawn)\b[!?]?'
  133. comment: everything being a method but having a special function is a..
  134. scope: keyword.control.special-method.crystal
  135. - match: \b(require)\b
  136. captures:
  137. 1: keyword.control.special-method.crystal
  138. push:
  139. - meta_scope: meta.require.crystal
  140. - match: $|(?=#)
  141. captures:
  142. 1: keyword.control.special-method.crystal
  143. pop: true
  144. - include: main
  145. - match: '(@)[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*[?!=]?'
  146. scope: variable.other.readwrite.instance.crystal
  147. captures:
  148. 1: punctuation.definition.variable.crystal
  149. - match: '(@@)[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*[?!=]?'
  150. scope: variable.other.readwrite.class.crystal
  151. captures:
  152. 1: punctuation.definition.variable.crystal
  153. - match: '(\$)[a-zA-Z_]\w*'
  154. scope: variable.other.readwrite.global.crystal
  155. captures:
  156. 1: punctuation.definition.variable.crystal
  157. - match: '(\$)(!|@|&|`|''|\+|\d+|~|=|/|\\|,|;|\.|<|>|_|\*|\$|\?|:|"|-[0adFiIlpv])'
  158. scope: variable.other.readwrite.global.pre-defined.crystal
  159. captures:
  160. 1: punctuation.definition.variable.crystal
  161. - match: '\b(ENV)\['
  162. captures:
  163. 1: variable.other.constant.crystal
  164. push:
  165. - meta_scope: meta.environment-variable.crystal
  166. - match: '\]'
  167. pop: true
  168. - include: main
  169. - match: '\b[A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*'
  170. scope: support.class.crystal
  171. - match: '\b[A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*\b'
  172. scope: variable.other.constant.crystal
  173. - match: |-
  174. (?x)
  175. (?=def\b) # an optimization to help Oniguruma fail fast
  176. (?<=^|\s)(def)\s+ # the def keyword
  177. ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\x{80}-\x{10FFFF}\w]*(?>\.|::))? # a method name prefix
  178. (?>[a-zA-Z_\x{80}-\x{10FFFF}][\x{80}-\x{10FFFF}\w]*(?>[?!]|=(?!>))? # the method name
  179. |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
  180. \s*(\() # the openning parenthesis for arguments
  181. comment: the method pattern comes from the symbol pattern, see there for a explaination
  182. captures:
  183. 1: keyword.control.def.crystal
  184. 2: entity.name.function.crystal
  185. 3: punctuation.definition.parameters.crystal
  186. push:
  187. - meta_scope: meta.function.method.with-arguments.crystal
  188. - meta_content_scope: variable.parameter.function.crystal
  189. - match: \)\s*$|\)\s*:|\)\s*;
  190. captures:
  191. 0: punctuation.definition.parameters.crystal
  192. pop: true
  193. - include: main
  194. - match: |-
  195. (?x)
  196. (?=def\b) # an optimization to help Oniguruma fail fast
  197. (?<=^|\s)(def)\s+ # the def keyword
  198. ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>\.|::))? # a method name prefix
  199. (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?!>))? # the method name
  200. |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
  201. [ \t] # the space separating the arguments
  202. (?=[ \t]*[^\s#;]) # make sure arguments and not a comment follow
  203. comment: same as the previous rule, but without parentheses around the arguments
  204. captures:
  205. 1: keyword.control.def.crystal
  206. 2: entity.name.function.crystal
  207. push:
  208. - meta_scope: meta.function.method.with-arguments.crystal
  209. - meta_content_scope: variable.parameter.function.crystal
  210. - match: $
  211. pop: true
  212. - include: main
  213. - match: |-
  214. (?x)
  215. (?=def\b) # an optimization to help Oniguruma fail fast
  216. (?<=^|\s)(def)\b # the def keyword
  217. ( \s+ # an optional group of whitespace followed by…
  218. ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>\.|::))? # a method name prefix
  219. (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?!>))? # the method name
  220. |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) )? # …or an operator method
  221. comment: the optional name is just to catch the def also without a method-name
  222. scope: meta.function.method.without-arguments.crystal
  223. captures:
  224. 1: keyword.control.def.crystal
  225. 3: entity.name.function.crystal
  226. - match: '\b(0[xX]\h(?>_?\h)*|\d(?>_?\d)*(\.(?![^[:space:][:digit:]])(?>_?\d)*)?([eE][-+]?\d(?>_?\d)*)?|0[bB][01]+|0o[0-7]+)(_?(u8|u16|u32|u64|i8|i16|i32|i64|f32|f64))?\b'
  227. scope: constant.numeric.crystal
  228. - match: ":'"
  229. captures:
  230. 0: punctuation.definition.constant.crystal
  231. push:
  232. - meta_scope: constant.other.symbol.single-quoted.crystal
  233. - match: "'"
  234. captures:
  235. 0: punctuation.definition.constant.crystal
  236. pop: true
  237. - match: '\\[''\\]'
  238. scope: constant.character.escape.crystal
  239. - match: ':"'
  240. captures:
  241. 0: punctuation.definition.constant.crystal
  242. push:
  243. - meta_scope: constant.other.symbol.double-quoted.crystal
  244. - match: '"'
  245. captures:
  246. 0: punctuation.definition.constant.crystal
  247. pop: true
  248. - include: interpolated_crystal
  249. - include: escaped_char
  250. - match: /=
  251. comment: Needs higher precidence than regular expressions.
  252. scope: keyword.operator.assignment.augmented.crystal
  253. - match: "'"
  254. comment: single quoted string (does not allow interpolation)
  255. captures:
  256. 0: punctuation.definition.string.begin.crystal
  257. push:
  258. - meta_scope: string.quoted.single.crystal
  259. - match: "'"
  260. captures:
  261. 0: punctuation.definition.string.end.crystal
  262. pop: true
  263. - match: \\'|\\\\
  264. scope: constant.character.escape.crystal
  265. - match: '"'
  266. comment: double quoted string (allows for interpolation)
  267. captures:
  268. 0: punctuation.definition.string.begin.crystal
  269. push:
  270. - meta_scope: string.quoted.double.crystal
  271. - match: '"'
  272. captures:
  273. 0: punctuation.definition.string.end.crystal
  274. pop: true
  275. - include: interpolated_crystal
  276. - include: escaped_char
  277. - match: "`"
  278. comment: execute string (allows for interpolation)
  279. captures:
  280. 0: punctuation.definition.string.begin.crystal
  281. push:
  282. - meta_scope: string.interpolated.crystal
  283. - match: "`"
  284. captures:
  285. 0: punctuation.definition.string.end.crystal
  286. pop: true
  287. - include: interpolated_crystal
  288. - include: escaped_char
  289. - match: '%x\{'
  290. comment: execute string (allow for interpolation)
  291. captures:
  292. 0: punctuation.definition.string.begin.crystal
  293. push:
  294. - meta_scope: string.interpolated.crystal
  295. - match: '\}'
  296. captures:
  297. 0: punctuation.definition.string.end.crystal
  298. pop: true
  299. - include: interpolated_crystal
  300. - include: escaped_char
  301. - include: nest_curly_i
  302. - match: '%x\['
  303. comment: execute string (allow for interpolation)
  304. captures:
  305. 0: punctuation.definition.string.begin.crystal
  306. push:
  307. - meta_scope: string.interpolated.crystal
  308. - match: '\]'
  309. captures:
  310. 0: punctuation.definition.string.end.crystal
  311. pop: true
  312. - include: interpolated_crystal
  313. - include: escaped_char
  314. - include: nest_brackets_i
  315. - match: '%x\<'
  316. comment: execute string (allow for interpolation)
  317. captures:
  318. 0: punctuation.definition.string.begin.crystal
  319. push:
  320. - meta_scope: string.interpolated.crystal
  321. - match: \>
  322. captures:
  323. 0: punctuation.definition.string.end.crystal
  324. pop: true
  325. - include: interpolated_crystal
  326. - include: escaped_char
  327. - include: nest_ltgt_i
  328. - match: '%x\('
  329. comment: execute string (allow for interpolation)
  330. captures:
  331. 0: punctuation.definition.string.begin.crystal
  332. push:
  333. - meta_scope: string.interpolated.crystal
  334. - match: \)
  335. captures:
  336. 0: punctuation.definition.string.end.crystal
  337. pop: true
  338. - include: interpolated_crystal
  339. - include: escaped_char
  340. - include: nest_parens_i
  341. - match: '%x([^\w])'
  342. comment: execute string (allow for interpolation)
  343. captures:
  344. 0: punctuation.definition.string.begin.crystal
  345. push:
  346. - meta_scope: string.interpolated.crystal
  347. - match: \1
  348. captures:
  349. 0: punctuation.definition.string.end.crystal
  350. pop: true
  351. - include: interpolated_crystal
  352. - include: escaped_char
  353. - match: |-
  354. (?x)
  355. (?:
  356. ^ # beginning of line
  357. | (?<= # or look-behind on:
  358. [=>~(?:\[,|&;]
  359. | [\s;]if\s # keywords
  360. | [\s;]elsif\s
  361. | [\s;]while\s
  362. | [\s;]unless\s
  363. | [\s;]when\s
  364. | [\s;]assert_match\s
  365. | [\s;]or\s # boolean opperators
  366. | [\s;]and\s
  367. | [\s;]not\s
  368. | [\s.]index\s # methods
  369. | [\s.]scan\s
  370. | [\s.]sub\s
  371. | [\s.]sub!\s
  372. | [\s.]gsub\s
  373. | [\s.]gsub!\s
  374. | [\s.]match\s
  375. )
  376. | (?<= # or a look-behind with line anchor:
  377. ^when\s # duplication necessary due to limits of regex
  378. | ^if\s
  379. | ^elsif\s
  380. | ^while\s
  381. | ^unless\s
  382. )
  383. )
  384. \s*((/))(?![*+{}?])
  385. comment: |
  386. regular expressions (normal)
  387. we only start a regexp if the character before it (excluding whitespace)
  388. is what we think is before a regexp
  389. captures:
  390. 1: string.regexp.classic.crystal
  391. 2: punctuation.definition.string.crystal
  392. push:
  393. - meta_content_scope: string.regexp.classic.crystal
  394. - match: "((/[eimnosux]*))"
  395. captures:
  396. 1: string.regexp.classic.crystal
  397. 2: punctuation.definition.string.crystal
  398. pop: true
  399. - include: regex_sub
  400. - match: '%r\{'
  401. comment: regular expressions (literal)
  402. captures:
  403. 0: punctuation.definition.string.begin.crystal
  404. push:
  405. - meta_scope: string.regexp.mod-r.crystal
  406. - match: '\}[eimnosux]*'
  407. captures:
  408. 0: punctuation.definition.string.end.crystal
  409. pop: true
  410. - include: regex_sub
  411. - include: nest_curly_r
  412. - match: '%r\['
  413. comment: regular expressions (literal)
  414. captures:
  415. 0: punctuation.definition.string.begin.crystal
  416. push:
  417. - meta_scope: string.regexp.mod-r.crystal
  418. - match: '\][eimnosux]*'
  419. captures:
  420. 0: punctuation.definition.string.end.crystal
  421. pop: true
  422. - include: regex_sub
  423. - include: nest_brackets_r
  424. - match: '%r\('
  425. comment: regular expressions (literal)
  426. captures:
  427. 0: punctuation.definition.string.begin.crystal
  428. push:
  429. - meta_scope: string.regexp.mod-r.crystal
  430. - match: '\)[eimnosux]*'
  431. captures:
  432. 0: punctuation.definition.string.end.crystal
  433. pop: true
  434. - include: regex_sub
  435. - include: nest_parens_r
  436. - match: '%r\<'
  437. comment: regular expressions (literal)
  438. captures:
  439. 0: punctuation.definition.string.begin.crystal
  440. push:
  441. - meta_scope: string.regexp.mod-r.crystal
  442. - match: '\>[eimnosux]*'
  443. captures:
  444. 0: punctuation.definition.string.end.crystal
  445. pop: true
  446. - include: regex_sub
  447. - include: nest_ltgt_r
  448. - match: '%r([^\w])'
  449. comment: regular expressions (literal)
  450. captures:
  451. 0: punctuation.definition.string.begin.crystal
  452. push:
  453. - meta_scope: string.regexp.mod-r.crystal
  454. - match: '\1[eimnosux]*'
  455. captures:
  456. 0: punctuation.definition.string.end.crystal
  457. pop: true
  458. - include: regex_sub
  459. - match: '%[QWSR]?\('
  460. comment: literal capable of interpolation ()
  461. captures:
  462. 0: punctuation.definition.string.begin.crystal
  463. push:
  464. - meta_scope: string.quoted.other.literal.upper.crystal
  465. - match: \)
  466. captures:
  467. 0: punctuation.definition.string.end.crystal
  468. pop: true
  469. - include: interpolated_crystal
  470. - include: escaped_char
  471. - include: nest_parens_i
  472. - match: '%[QWSR]?\['
  473. comment: "literal capable of interpolation []"
  474. captures:
  475. 0: punctuation.definition.string.begin.crystal
  476. push:
  477. - meta_scope: string.quoted.other.literal.upper.crystal
  478. - match: '\]'
  479. captures:
  480. 0: punctuation.definition.string.end.crystal
  481. pop: true
  482. - include: interpolated_crystal
  483. - include: escaped_char
  484. - include: nest_brackets_i
  485. - match: '%[QWSR]?\<'
  486. comment: literal capable of interpolation <>
  487. captures:
  488. 0: punctuation.definition.string.begin.crystal
  489. push:
  490. - meta_scope: string.quoted.other.literal.upper.crystal
  491. - match: \>
  492. captures:
  493. 0: punctuation.definition.string.end.crystal
  494. pop: true
  495. - include: interpolated_crystal
  496. - include: escaped_char
  497. - include: nest_ltgt_i
  498. - match: '%[QWSR]?\{'
  499. comment: "literal capable of interpolation -- {}"
  500. captures:
  501. 0: punctuation.definition.string.begin.crystal
  502. push:
  503. - meta_scope: string.quoted.double.crystal.mod
  504. - match: '\}'
  505. captures:
  506. 0: punctuation.definition.string.end.crystal
  507. pop: true
  508. - include: interpolated_crystal
  509. - include: escaped_char
  510. - include: nest_curly_i
  511. - match: '%[QWSR]([^\w])'
  512. comment: literal capable of interpolation -- wildcard
  513. captures:
  514. 0: punctuation.definition.string.begin.crystal
  515. push:
  516. - meta_scope: string.quoted.other.literal.upper.crystal
  517. - match: \1
  518. captures:
  519. 0: punctuation.definition.string.end.crystal
  520. pop: true
  521. - include: interpolated_crystal
  522. - include: escaped_char
  523. - match: '%[qws]\('
  524. comment: literal incapable of interpolation -- ()
  525. captures:
  526. 0: punctuation.definition.string.begin.crystal
  527. push:
  528. - meta_scope: string.quoted.other.literal.lower.crystal
  529. - match: \)
  530. captures:
  531. 0: punctuation.definition.string.end.crystal
  532. pop: true
  533. - match: \\\)|\\\\
  534. scope: constant.character.escape.crystal
  535. - include: nest_parens
  536. - match: '%[qws]\<'
  537. comment: literal incapable of interpolation -- <>
  538. captures:
  539. 0: punctuation.definition.string.begin.crystal
  540. push:
  541. - meta_scope: string.quoted.other.literal.lower.crystal
  542. - match: \>
  543. captures:
  544. 0: punctuation.definition.string.end.crystal
  545. pop: true
  546. - match: \\\>|\\\\
  547. scope: constant.character.escape.crystal
  548. - include: nest_ltgt
  549. - match: '%[qws]\['
  550. comment: "literal incapable of interpolation -- []"
  551. captures:
  552. 0: punctuation.definition.string.begin.crystal
  553. push:
  554. - meta_scope: string.quoted.other.literal.lower.crystal
  555. - match: '\]'
  556. captures:
  557. 0: punctuation.definition.string.end.crystal
  558. pop: true
  559. - match: '\\\]|\\\\'
  560. scope: constant.character.escape.crystal
  561. - include: nest_brackets
  562. - match: '%[qws]\{'
  563. comment: "literal incapable of interpolation -- {}"
  564. captures:
  565. 0: punctuation.definition.string.begin.crystal
  566. push:
  567. - meta_scope: string.quoted.other.literal.lower.crystal
  568. - match: '\}'
  569. captures:
  570. 0: punctuation.definition.string.end.crystal
  571. pop: true
  572. - match: '\\\}|\\\\'
  573. scope: constant.character.escape.crystal
  574. - include: nest_curly
  575. - match: '%[qws]([^\w])'
  576. comment: literal incapable of interpolation -- wildcard
  577. captures:
  578. 0: punctuation.definition.string.begin.crystal
  579. push:
  580. - meta_scope: string.quoted.other.literal.lower.crystal
  581. - match: \1
  582. captures:
  583. 0: punctuation.definition.string.end.crystal
  584. pop: true
  585. - match: \\.
  586. comment: Cant be named because its not neccesarily an escape.
  587. - match: '(?<!:)(:)(?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?![>=]))?|===?|>[>=]?|<[<=]?|<=>|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?|@@?[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*)'
  588. comment: symbols
  589. scope: constant.other.symbol.crystal
  590. captures:
  591. 1: punctuation.definition.constant.crystal
  592. - match: '(?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!])?)(:)(?!:)'
  593. comment: symbols
  594. scope: constant.other.symbol.crystal.19syntax
  595. captures:
  596. 1: punctuation.definition.constant.crystal
  597. - match: '(?:^[ \t]+)?(#).*$\n?'
  598. scope: comment.line.number-sign.crystal
  599. captures:
  600. 1: punctuation.definition.comment.crystal
  601. - match: ^__END__\n
  602. comment: __END__ marker
  603. captures:
  604. 0: string.unquoted.program-block.crystal
  605. push:
  606. - meta_content_scope: text.plain
  607. - match: (?=not)impossible
  608. captures:
  609. 0: string.unquoted.program-block.crystal
  610. pop: true
  611. - match: (?=<?xml|<(?i:html\b)|!DOCTYPE (?i:html\b))
  612. push:
  613. - meta_scope: text.html.embedded.crystal
  614. - match: (?=not)impossible
  615. pop: true
  616. - include: scope:text.html.basic
  617. - match: '(?><<-("?)((?:[_\w]+_|)HTML)\b\1)'
  618. comment: heredoc with embedded HTML and indented terminator
  619. captures:
  620. 0: punctuation.definition.string.begin.crystal
  621. push:
  622. - meta_scope: string.unquoted.embedded.html.crystal
  623. - meta_content_scope: text.html.embedded.crystal
  624. - match: \s*\2$
  625. captures:
  626. 0: punctuation.definition.string.end.crystal
  627. pop: true
  628. - include: heredoc
  629. - include: scope:text.html.basic
  630. - include: interpolated_crystal
  631. - include: escaped_char
  632. - match: '(?><<-("?)((?:[_\w]+_|)SQL)\b\1)'
  633. comment: heredoc with embedded SQL and indented terminator
  634. captures:
  635. 0: punctuation.definition.string.begin.crystal
  636. push:
  637. - meta_scope: string.unquoted.embedded.sql.crystal
  638. - meta_content_scope: text.sql.embedded.crystal
  639. - match: \s*\2$
  640. captures:
  641. 0: punctuation.definition.string.end.crystal
  642. pop: true
  643. - include: heredoc
  644. - include: scope:source.sql
  645. - include: interpolated_crystal
  646. - include: escaped_char
  647. - match: '(?><<-("?)((?:[_\w]+_|)CSS)\b\1)'
  648. comment: heredoc with embedded css and intented terminator
  649. captures:
  650. 0: punctuation.definition.string.begin.crystal
  651. push:
  652. - meta_scope: string.unquoted.embedded.css.crystal
  653. - meta_content_scope: text.css.embedded.crystal
  654. - match: \s*\2$
  655. captures:
  656. 0: punctuation.definition.string.end.crystal
  657. pop: true
  658. - include: heredoc
  659. - include: scope:source.css
  660. - include: interpolated_crystal
  661. - include: escaped_char
  662. - match: '(?><<-("?)((?:[_\w]+_|)CPP)\b\1)'
  663. comment: heredoc with embedded c++ and intented terminator
  664. captures:
  665. 0: punctuation.definition.string.begin.crystal
  666. push:
  667. - meta_scope: string.unquoted.embedded.cplusplus.crystal
  668. - meta_content_scope: text.c++.embedded.crystal
  669. - match: \s*\2$
  670. captures:
  671. 0: punctuation.definition.string.end.crystal
  672. pop: true
  673. - include: heredoc
  674. - include: scope:source.c++
  675. - include: interpolated_crystal
  676. - include: escaped_char
  677. - match: '(?><<-("?)((?:[_\w]+_|)C)\b\1)'
  678. comment: heredoc with embedded c++ and intented terminator
  679. captures:
  680. 0: punctuation.definition.string.begin.crystal
  681. push:
  682. - meta_scope: string.unquoted.embedded.c.crystal
  683. - meta_content_scope: text.c.embedded.crystal
  684. - match: \s*\2$
  685. captures:
  686. 0: punctuation.definition.string.end.crystal
  687. pop: true
  688. - include: heredoc
  689. - include: scope:source.c
  690. - include: interpolated_crystal
  691. - include: escaped_char
  692. - match: '(?><<-("?)((?:[_\w]+_|)(?:JS|JAVASCRIPT))\b\1)'
  693. comment: heredoc with embedded javascript and intented terminator
  694. captures:
  695. 0: punctuation.definition.string.begin.crystal
  696. push:
  697. - meta_scope: string.unquoted.embedded.js.crystal
  698. - meta_content_scope: text.js.embedded.crystal
  699. - match: \s*\2$
  700. captures:
  701. 0: punctuation.definition.string.end.crystal
  702. pop: true
  703. - include: heredoc
  704. - include: scope:source.js
  705. - include: interpolated_crystal
  706. - include: escaped_char
  707. - match: '(?><<-("?)((?:[_\w]+_|)JQUERY)\b\1)'
  708. comment: heredoc with embedded javascript and intented terminator
  709. captures:
  710. 0: punctuation.definition.string.begin.crystal
  711. push:
  712. - meta_scope: string.unquoted.embedded.js.jquery.crystal
  713. - meta_content_scope: text.js.jquery.embedded.crystal
  714. - match: \s*\2$
  715. captures:
  716. 0: punctuation.definition.string.end.crystal
  717. pop: true
  718. - include: heredoc
  719. - include: scope:source.js.jquery
  720. - include: interpolated_crystal
  721. - include: escaped_char
  722. - match: '(?><<-("?)((?:[_\w]+_|)(?:SH|SHELL))\b\1)'
  723. comment: heredoc with embedded shell and intented terminator
  724. captures:
  725. 0: punctuation.definition.string.begin.crystal
  726. push:
  727. - meta_scope: string.unquoted.embedded.shell.crystal
  728. - meta_content_scope: text.shell.embedded.crystal
  729. - match: \s*\2$
  730. captures:
  731. 0: punctuation.definition.string.end.crystal
  732. pop: true
  733. - include: heredoc
  734. - include: scope:source.shell
  735. - include: interpolated_crystal
  736. - include: escaped_char
  737. - match: '(?><<-("?)((?:[_\w]+_|)RUBY)\b\1)'
  738. comment: heredoc with embedded crystal and intented terminator
  739. captures:
  740. 0: punctuation.definition.string.begin.crystal
  741. push:
  742. - meta_scope: string.unquoted.embedded.crystal.crystal
  743. - meta_content_scope: text.crystal.embedded.crystal
  744. - match: \s*\2$
  745. captures:
  746. 0: punctuation.definition.string.end.crystal
  747. pop: true
  748. - include: heredoc
  749. - include: scope:source.crystal
  750. - include: interpolated_crystal
  751. - include: escaped_char
  752. - match: (?>\=\s*<<(\w+))
  753. captures:
  754. 0: punctuation.definition.string.begin.crystal
  755. push:
  756. - meta_scope: string.unquoted.heredoc.crystal
  757. - match: ^\1$
  758. captures:
  759. 0: punctuation.definition.string.end.crystal
  760. pop: true
  761. - include: heredoc
  762. - include: interpolated_crystal
  763. - include: escaped_char
  764. - match: (?><<-(\w+))
  765. comment: heredoc with indented terminator
  766. captures:
  767. 0: punctuation.definition.string.begin.crystal
  768. push:
  769. - meta_scope: string.unquoted.heredoc.crystal
  770. - match: \s*\1$
  771. captures:
  772. 0: punctuation.definition.string.end.crystal
  773. pop: true
  774. - include: heredoc
  775. - include: interpolated_crystal
  776. - include: escaped_char
  777. - match: '(?<=\{|do|\{\s|do\s)(\|)'
  778. captures:
  779. 1: punctuation.separator.variable.crystal
  780. push:
  781. - match: (\|)
  782. captures:
  783. 1: punctuation.separator.variable.crystal
  784. pop: true
  785. - match: "[_a-zA-Z][_a-zA-Z0-9]*"
  786. scope: variable.other.block.crystal
  787. - match: ","
  788. scope: punctuation.separator.variable.crystal
  789. - match: "=>"
  790. scope: punctuation.separator.key-value
  791. - match: '<<=|%=|&=|\*=|\*\*=|\+=|\-=|\^=|\|{1,2}=|<<'
  792. scope: keyword.operator.assignment.augmented.crystal
  793. - match: '<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|(?<=[ \t])\?'
  794. scope: keyword.operator.comparison.crystal
  795. - match: '(?<=[ \t])!+|\bnot\b|&&|\band\b|\|\||\bor\b|\^'
  796. scope: keyword.operator.logical.crystal
  797. - match: '(\{\%|\%\}|\{\{|\}\})'
  798. scope: keyword.operator.macro.crystal
  799. - match: (%|&|\*\*|\*|\+|\-|/)
  800. scope: keyword.operator.arithmetic.crystal
  801. - match: "="
  802. scope: keyword.operator.assignment.crystal
  803. - match: \||~|>>
  804. scope: keyword.operator.other.crystal
  805. - match: ":"
  806. scope: punctuation.separator.other.crystal
  807. - match: \;
  808. scope: punctuation.separator.statement.crystal
  809. - match: ","
  810. scope: punctuation.separator.object.crystal
  811. - match: '\.|::'
  812. scope: punctuation.separator.method.crystal
  813. - match: '\{|\}'
  814. scope: punctuation.section.scope.crystal
  815. - match: '\[|\]'
  816. scope: punctuation.section.array.crystal
  817. - match: \(|\)
  818. scope: punctuation.section.function.crystal
  819. escaped_char:
  820. - match: '\\(?:[0-7]{1,3}|x[\da-fA-F]{1,2}|.)'
  821. scope: constant.character.escape.crystal
  822. heredoc:
  823. - match: ^<<-?\w+
  824. push:
  825. - match: $
  826. pop: true
  827. - include: main
  828. interpolated_crystal:
  829. - match: '#\{(\})'
  830. scope: source.crystal.embedded.source
  831. captures:
  832. 0: punctuation.section.embedded.crystal
  833. 1: source.crystal.embedded.source.empty
  834. - match: '#\{'
  835. captures:
  836. 0: punctuation.section.embedded.crystal
  837. push:
  838. - meta_scope: source.crystal.embedded.source
  839. - match: '\}'
  840. captures:
  841. 0: punctuation.section.embedded.crystal
  842. pop: true
  843. - include: nest_curly_and_self
  844. - include: main
  845. - match: '(#@)[a-zA-Z_]\w*'
  846. scope: variable.other.readwrite.instance.crystal
  847. captures:
  848. 1: punctuation.definition.variable.crystal
  849. - match: '(#@@)[a-zA-Z_]\w*'
  850. scope: variable.other.readwrite.class.crystal
  851. captures:
  852. 1: punctuation.definition.variable.crystal
  853. - match: '(#\$)[a-zA-Z_]\w*'
  854. scope: variable.other.readwrite.global.crystal
  855. captures:
  856. 1: punctuation.definition.variable.crystal
  857. nest_brackets:
  858. - match: '\['
  859. captures:
  860. 0: punctuation.section.scope.crystal
  861. push:
  862. - match: '\]'
  863. captures:
  864. 0: punctuation.section.scope.crystal
  865. pop: true
  866. - include: nest_brackets
  867. nest_brackets_i:
  868. - match: '\['
  869. captures:
  870. 0: punctuation.section.scope.crystal
  871. push:
  872. - match: '\]'
  873. captures:
  874. 0: punctuation.section.scope.crystal
  875. pop: true
  876. - include: interpolated_crystal
  877. - include: escaped_char
  878. - include: nest_brackets_i
  879. nest_brackets_r:
  880. - match: '\['
  881. captures:
  882. 0: punctuation.section.scope.crystal
  883. push:
  884. - match: '\]'
  885. captures:
  886. 0: punctuation.section.scope.crystal
  887. pop: true
  888. - include: regex_sub
  889. - include: nest_brackets_r
  890. nest_curly:
  891. - match: '\{'
  892. captures:
  893. 0: punctuation.section.scope.crystal
  894. push:
  895. - match: '\}'
  896. captures:
  897. 0: punctuation.section.scope.crystal
  898. pop: true
  899. - include: nest_curly
  900. nest_curly_and_self:
  901. - match: '\{'
  902. captures:
  903. 0: punctuation.section.scope.crystal
  904. push:
  905. - match: '\}'
  906. captures:
  907. 0: punctuation.section.scope.crystal
  908. pop: true
  909. - include: nest_curly_and_self
  910. - include: main
  911. nest_curly_i:
  912. - match: '\{'
  913. captures:
  914. 0: punctuation.section.scope.crystal
  915. push:
  916. - match: '\}'
  917. captures:
  918. 0: punctuation.section.scope.crystal
  919. pop: true
  920. - include: interpolated_crystal
  921. - include: escaped_char
  922. - include: nest_curly_i
  923. nest_curly_r:
  924. - match: '\{'
  925. captures:
  926. 0: punctuation.section.scope.crystal
  927. push:
  928. - match: '\}'
  929. captures:
  930. 0: punctuation.section.scope.crystal
  931. pop: true
  932. - include: regex_sub
  933. - include: nest_curly_r
  934. nest_ltgt:
  935. - match: \<
  936. captures:
  937. 0: punctuation.section.scope.crystal
  938. push:
  939. - match: \>
  940. captures:
  941. 0: punctuation.section.scope.crystal
  942. pop: true
  943. - include: nest_ltgt
  944. nest_ltgt_i:
  945. - match: \<
  946. captures:
  947. 0: punctuation.section.scope.crystal
  948. push:
  949. - match: \>
  950. captures:
  951. 0: punctuation.section.scope.crystal
  952. pop: true
  953. - include: interpolated_crystal
  954. - include: escaped_char
  955. - include: nest_ltgt_i
  956. nest_ltgt_r:
  957. - match: \<
  958. captures:
  959. 0: punctuation.section.scope.crystal
  960. push:
  961. - match: \>
  962. captures:
  963. 0: punctuation.section.scope.crystal
  964. pop: true
  965. - include: regex_sub
  966. - include: nest_ltgt_r
  967. nest_parens:
  968. - match: \(
  969. captures:
  970. 0: punctuation.section.scope.crystal
  971. push:
  972. - match: \)
  973. captures:
  974. 0: punctuation.section.scope.crystal
  975. pop: true
  976. - include: nest_parens
  977. nest_parens_i:
  978. - match: \(
  979. captures:
  980. 0: punctuation.section.scope.crystal
  981. push:
  982. - match: \)
  983. captures:
  984. 0: punctuation.section.scope.crystal
  985. pop: true
  986. - include: interpolated_crystal
  987. - include: escaped_char
  988. - include: nest_parens_i
  989. nest_parens_r:
  990. - match: \(
  991. captures:
  992. 0: punctuation.section.scope.crystal
  993. push:
  994. - match: \)
  995. captures:
  996. 0: punctuation.section.scope.crystal
  997. pop: true
  998. - include: regex_sub
  999. - include: nest_parens_r
  1000. regex_sub:
  1001. - include: interpolated_crystal
  1002. - include: escaped_char
  1003. - match: '(\{)\d+(,\d+)?(\})'
  1004. scope: string.regexp.arbitrary-repitition.crystal
  1005. captures:
  1006. 1: punctuation.definition.arbitrary-repitition.crystal
  1007. 3: punctuation.definition.arbitrary-repitition.crystal
  1008. - match: '\[(?:\^?\])?'
  1009. captures:
  1010. 0: punctuation.definition.character-class.crystal
  1011. push:
  1012. - meta_scope: string.regexp.character-class.crystal
  1013. - match: '\]'
  1014. captures:
  1015. 0: punctuation.definition.character-class.crystal
  1016. pop: true
  1017. - include: escaped_char
  1018. - match: \(
  1019. captures:
  1020. 0: punctuation.definition.group.crystal
  1021. push:
  1022. - meta_scope: string.regexp.group.crystal
  1023. - match: \)
  1024. captures:
  1025. 0: punctuation.definition.group.crystal
  1026. pop: true
  1027. - include: regex_sub
  1028. - match: '(?<=^|\s)(#)\s[[a-zA-Z0-9,. \t?!-][^\x{00}-\x{7F}]]*$'
  1029. comment: We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.
  1030. scope: comment.line.number-sign.crystal
  1031. captures:
  1032. 1: punctuation.definition.comment.crystal