on master help sign in
Add Crystal syntax
97efd75Miguel Madrid Mencía
.gitmodules+3
@@ -85,3 +85,6 @@
85[submodule "assets/syntaxes/Swift"]
85[submodule "assets/syntaxes/Swift"]
86 path = assets/syntaxes/Swift
86 path = assets/syntaxes/Swift
87 url = https://github.com/quiqueg/Swift-Sublime-Package
87 url = https://github.com/quiqueg/Swift-Sublime-Package
88+[submodule "assets/syntaxes/Crystal"]
89+ path = assets/syntaxes/Crystal
90+ url = https://github.com/crystal-lang-tools/sublime-crystal.git
assets/syntaxes/Crystalnew file+1

Submodule changed.

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