|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036 |
- %YAML 1.2
- ---
- # http://www.sublimetext.com/docs/3/syntax.html
- name: Crystal
- comment: |
- TODO: unresolved issues
-
- text:
- "p << end
- print me!
- end"
- symptoms:
- not recognized as a heredoc
- solution:
- there is no way to distinguish perfectly between the << operator and the start
- of a heredoc. Currently, we require assignment to recognize a heredoc. More
- refinement is possible.
- • Heredocs with indented terminators (<<-) are always distinguishable, however.
- • Nested heredocs are not really supportable at present
-
- text:
- print <<-'THERE'
- This is single quoted.
- The above used #{Time.now}
- THERE
- symtoms:
- From Programming Ruby p306; should be a non-interpolated heredoc.
-
- text:
- "a\332a"
- symptoms:
- '\332' is not recognized as slash3.. which should be octal 332.
- solution:
- plain regexp.. should be easy.
-
- text:
- val?(a):p(b)
- val?'a':'b'
- symptoms:
- ':p' is recognized as a symbol.. its 2 things ':' and 'p'.
- :'b' has same problem.
- solution:
- ternary operator rule, precedence stuff, symbol rule.
- but also consider 'a.b?(:c)' ??
- file_extensions:
- - cr
- first_line_match: ^#!/.*\bcrystal
- scope: source.crystal
- contexts:
- main:
- - match: |-
- (?x)
- ^
- \s*
- (abstract)?
- \s*
- (class|struct|union)
- \s+
- (
- (
- [.A-Z_:\x{80}-\x{10FFFF}][.\w:\x{80}-\x{10FFFF}]*
- (\(([,\s.a-zA-Z0-9_:\x{80}-\x{10FFFF}]+)\))?
- (
- \s*(<)\s*
- [.:A-Z\x{80}-\x{10FFFF}][.:\w\x{80}-\x{10FFFF}]*
- (\(([.a-zA-Z0-9_:]+\s,)\))?
- )?
- )|(
- (<<)
- \s*
- [.A-Z0-9_:\x{80}-\x{10FFFF}]+
- )
- )
- scope: meta.class.crystal
- captures:
- 1: keyword.control.class.crystal
- 2: keyword.control.class.crystal
- 3: entity.name.type.class.crystal
- 5: punctuation.separator.crystal
- 6: support.class.other.type-param.crystal
- 7: entity.other.inherited-class.crystal
- 8: punctuation.separator.crystal
- 9: punctuation.separator.crystal
- 10: support.class.other.type-param.crystal
- 11: punctuation.definition.variable.crystal
- - 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}]*)'
- scope: meta.module.crystal
- captures:
- 1: keyword.control.module.crystal
- 2: entity.name.type.module.crystal
- 3: entity.other.inherited-class.module.first.crystal
- 4: punctuation.separator.inheritance.crystal
- 5: entity.other.inherited-class.module.second.crystal
- 6: punctuation.separator.inheritance.crystal
- 7: entity.other.inherited-class.module.third.crystal
- 8: punctuation.separator.inheritance.crystal
- - match: '^\s*(lib)\s+(([A-Z]\w*(::))?([A-Z]\w*(::))?([A-Z]\w*(::))*[A-Z]\w*)'
- scope: meta.lib.crystal
- captures:
- 1: keyword.control.lib.crystal
- 2: entity.name.type.lib.crystal
- 3: entity.other.inherited-class.lib.first.crystal
- 4: punctuation.separator.inheritance.crystal
- 5: entity.other.inherited-class.lib.second.crystal
- 6: punctuation.separator.inheritance.crystal
- 7: entity.other.inherited-class.lib.third.crystal
- 8: punctuation.separator.inheritance.crystal
- - match: (?<!\.)\belse(\s)+if\b
- 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.
- scope: invalid.deprecated.crystal
- - 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(?![?!])'
- comment: everything being a reserved word, not a value and needing a 'end' is a..
- scope: keyword.control.primary.crystal
- - match: '(?<!\.)\b(when|else|elsif)\b(?![?!])'
- comment: everything being a reserved word, not a value and needing a 'end' is a..
- scope: keyword.control.secondary.crystal
- - match: '(?<!\.)\b(end)\b(?![?!])'
- comment: Give the end keyword an additional scope
- scope: keyword.control.secondary.end.crystal
- - match: (?<!\.)\bdo\b\s*
- comment: contextual smart pair support for block parameters
- scope: keyword.control.start-block.crystal
- - match: '(?<=\{)(\s+)'
- comment: contextual smart pair support
- scope: meta.syntax.crystal.start-block
- - match: (?<!\.)\b(and|not|or)\b
- comment: as above, just doesn't need a 'end' and does a logic operation
- scope: keyword.operator.logical.crystal
- - match: '(?<!\.)\b(alias|alias_method|break|next|pointerof|typeof|sizeof|instance_sizeof|return|super|yield|uninitialized|forall)\b(?![?!])'
- comment: just as above but being not a logical operation
- scope: keyword.control.pseudo-method.crystal
- - match: '\b(nil|true|false)\b(?![?!])'
- scope: constant.language.crystal
- - match: '\b(__(DIR|FILE|LINE)__|self)\b(?![?!])'
- scope: variable.language.crystal
- - 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[!?]?'
- comment: everything being a method but having a special function is a..
- scope: keyword.control.special-method.crystal
- - match: \b(require)\b
- captures:
- 1: keyword.control.special-method.crystal
- push:
- - meta_scope: meta.require.crystal
- - match: $|(?=#)
- captures:
- 1: keyword.control.special-method.crystal
- pop: true
- - include: main
- - match: '(@)[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*[?!=]?'
- scope: variable.other.readwrite.instance.crystal
- captures:
- 1: punctuation.definition.variable.crystal
- - match: '(@@)[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*[?!=]?'
- scope: variable.other.readwrite.class.crystal
- captures:
- 1: punctuation.definition.variable.crystal
- - match: '(\$)[a-zA-Z_]\w*'
- scope: variable.other.readwrite.global.crystal
- captures:
- 1: punctuation.definition.variable.crystal
- - match: '(\$)(!|@|&|`|''|\+|\d+|~|=|/|\\|,|;|\.|<|>|_|\*|\$|\?|:|"|-[0adFiIlpv])'
- scope: variable.other.readwrite.global.pre-defined.crystal
- captures:
- 1: punctuation.definition.variable.crystal
- - match: '\b(ENV)\['
- captures:
- 1: variable.other.constant.crystal
- push:
- - meta_scope: meta.environment-variable.crystal
- - match: '\]'
- pop: true
- - include: main
- - match: '\b[A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*'
- scope: support.class.crystal
- - match: '\b[A-Z\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*\b'
- scope: variable.other.constant.crystal
- - match: |-
- (?x)
- (?=def\b) # an optimization to help Oniguruma fail fast
- (?<=^|\s)(def)\s+ # the def keyword
- ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\x{80}-\x{10FFFF}\w]*(?>\.|::))? # a method name prefix
- (?>[a-zA-Z_\x{80}-\x{10FFFF}][\x{80}-\x{10FFFF}\w]*(?>[?!]|=(?!>))? # the method name
- |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
- \s*(\() # the openning parenthesis for arguments
- comment: the method pattern comes from the symbol pattern, see there for a explaination
- captures:
- 1: keyword.control.def.crystal
- 2: entity.name.function.crystal
- 3: punctuation.definition.parameters.crystal
- push:
- - meta_scope: meta.function.method.with-arguments.crystal
- - meta_content_scope: variable.parameter.function.crystal
- - match: \)\s*$|\)\s*:|\)\s*;
- captures:
- 0: punctuation.definition.parameters.crystal
- pop: true
- - include: main
- - match: |-
- (?x)
- (?=def\b) # an optimization to help Oniguruma fail fast
- (?<=^|\s)(def)\s+ # the def keyword
- ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>\.|::))? # a method name prefix
- (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?!>))? # the method name
- |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
- [ \t] # the space separating the arguments
- (?=[ \t]*[^\s#;]) # make sure arguments and not a comment follow
- comment: same as the previous rule, but without parentheses around the arguments
- captures:
- 1: keyword.control.def.crystal
- 2: entity.name.function.crystal
- push:
- - meta_scope: meta.function.method.with-arguments.crystal
- - meta_content_scope: variable.parameter.function.crystal
- - match: $
- pop: true
- - include: main
- - match: |-
- (?x)
- (?=def\b) # an optimization to help Oniguruma fail fast
- (?<=^|\s)(def)\b # the def keyword
- ( \s+ # an optional group of whitespace followed by…
- ( (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>\.|::))? # a method name prefix
- (?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!]|=(?!>))? # the method name
- |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) )? # …or an operator method
- comment: the optional name is just to catch the def also without a method-name
- scope: meta.function.method.without-arguments.crystal
- captures:
- 1: keyword.control.def.crystal
- 3: entity.name.function.crystal
- - 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'
- scope: constant.numeric.crystal
- - match: ":'"
- captures:
- 0: punctuation.definition.constant.crystal
- push:
- - meta_scope: constant.other.symbol.single-quoted.crystal
- - match: "'"
- captures:
- 0: punctuation.definition.constant.crystal
- pop: true
- - match: '\\[''\\]'
- scope: constant.character.escape.crystal
- - match: ':"'
- captures:
- 0: punctuation.definition.constant.crystal
- push:
- - meta_scope: constant.other.symbol.double-quoted.crystal
- - match: '"'
- captures:
- 0: punctuation.definition.constant.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - match: /=
- comment: Needs higher precidence than regular expressions.
- scope: keyword.operator.assignment.augmented.crystal
- - match: "'"
- comment: single quoted string (does not allow interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.single.crystal
- - match: "'"
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - match: \\'|\\\\
- scope: constant.character.escape.crystal
- - match: '"'
- comment: double quoted string (allows for interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.double.crystal
- - match: '"'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - match: "`"
- comment: execute string (allows for interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.interpolated.crystal
- - match: "`"
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - match: '%x\{'
- comment: execute string (allow for interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.interpolated.crystal
- - match: '\}'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_curly_i
- - match: '%x\['
- comment: execute string (allow for interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.interpolated.crystal
- - match: '\]'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_brackets_i
- - match: '%x\<'
- comment: execute string (allow for interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.interpolated.crystal
- - match: \>
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_ltgt_i
- - match: '%x\('
- comment: execute string (allow for interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.interpolated.crystal
- - match: \)
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_parens_i
- - match: '%x([^\w])'
- comment: execute string (allow for interpolation)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.interpolated.crystal
- - match: \1
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - match: |-
- (?x)
- (?:
- ^ # beginning of line
- | (?<= # or look-behind on:
- [=>~(?:\[,|&;]
- | [\s;]if\s # keywords
- | [\s;]elsif\s
- | [\s;]while\s
- | [\s;]unless\s
- | [\s;]when\s
- | [\s;]assert_match\s
- | [\s;]or\s # boolean opperators
- | [\s;]and\s
- | [\s;]not\s
- | [\s.]index\s # methods
- | [\s.]scan\s
- | [\s.]sub\s
- | [\s.]sub!\s
- | [\s.]gsub\s
- | [\s.]gsub!\s
- | [\s.]match\s
- )
- | (?<= # or a look-behind with line anchor:
- ^when\s # duplication necessary due to limits of regex
- | ^if\s
- | ^elsif\s
- | ^while\s
- | ^unless\s
- )
- )
- \s*((/))(?![*+{}?])
- comment: |
- regular expressions (normal)
- we only start a regexp if the character before it (excluding whitespace)
- is what we think is before a regexp
- captures:
- 1: string.regexp.classic.crystal
- 2: punctuation.definition.string.crystal
- push:
- - meta_content_scope: string.regexp.classic.crystal
- - match: "((/[eimnosux]*))"
- captures:
- 1: string.regexp.classic.crystal
- 2: punctuation.definition.string.crystal
- pop: true
- - include: regex_sub
- - match: '%r\{'
- comment: regular expressions (literal)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.regexp.mod-r.crystal
- - match: '\}[eimnosux]*'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: regex_sub
- - include: nest_curly_r
- - match: '%r\['
- comment: regular expressions (literal)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.regexp.mod-r.crystal
- - match: '\][eimnosux]*'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: regex_sub
- - include: nest_brackets_r
- - match: '%r\('
- comment: regular expressions (literal)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.regexp.mod-r.crystal
- - match: '\)[eimnosux]*'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: regex_sub
- - include: nest_parens_r
- - match: '%r\<'
- comment: regular expressions (literal)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.regexp.mod-r.crystal
- - match: '\>[eimnosux]*'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: regex_sub
- - include: nest_ltgt_r
- - match: '%r([^\w])'
- comment: regular expressions (literal)
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.regexp.mod-r.crystal
- - match: '\1[eimnosux]*'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: regex_sub
- - match: '%[QWSR]?\('
- comment: literal capable of interpolation ()
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.upper.crystal
- - match: \)
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_parens_i
- - match: '%[QWSR]?\['
- comment: "literal capable of interpolation []"
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.upper.crystal
- - match: '\]'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_brackets_i
- - match: '%[QWSR]?\<'
- comment: literal capable of interpolation <>
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.upper.crystal
- - match: \>
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_ltgt_i
- - match: '%[QWSR]?\{'
- comment: "literal capable of interpolation -- {}"
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.double.crystal.mod
- - match: '\}'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_curly_i
- - match: '%[QWSR]([^\w])'
- comment: literal capable of interpolation -- wildcard
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.upper.crystal
- - match: \1
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - match: '%[qws]\('
- comment: literal incapable of interpolation -- ()
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.lower.crystal
- - match: \)
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - match: \\\)|\\\\
- scope: constant.character.escape.crystal
- - include: nest_parens
- - match: '%[qws]\<'
- comment: literal incapable of interpolation -- <>
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.lower.crystal
- - match: \>
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - match: \\\>|\\\\
- scope: constant.character.escape.crystal
- - include: nest_ltgt
- - match: '%[qws]\['
- comment: "literal incapable of interpolation -- []"
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.lower.crystal
- - match: '\]'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - match: '\\\]|\\\\'
- scope: constant.character.escape.crystal
- - include: nest_brackets
- - match: '%[qws]\{'
- comment: "literal incapable of interpolation -- {}"
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.lower.crystal
- - match: '\}'
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - match: '\\\}|\\\\'
- scope: constant.character.escape.crystal
- - include: nest_curly
- - match: '%[qws]([^\w])'
- comment: literal incapable of interpolation -- wildcard
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.quoted.other.literal.lower.crystal
- - match: \1
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - match: \\.
- comment: Cant be named because its not neccesarily an escape.
- - 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}]*)'
- comment: symbols
- scope: constant.other.symbol.crystal
- captures:
- 1: punctuation.definition.constant.crystal
- - match: '(?>[a-zA-Z_\x{80}-\x{10FFFF}][\w\x{80}-\x{10FFFF}]*(?>[?!])?)(:)(?!:)'
- comment: symbols
- scope: constant.other.symbol.crystal.19syntax
- captures:
- 1: punctuation.definition.constant.crystal
- - match: '(?:^[ \t]+)?(#).*$\n?'
- scope: comment.line.number-sign.crystal
- captures:
- 1: punctuation.definition.comment.crystal
- - match: ^__END__\n
- comment: __END__ marker
- captures:
- 0: string.unquoted.program-block.crystal
- push:
- - meta_content_scope: text.plain
- - match: (?=not)impossible
- captures:
- 0: string.unquoted.program-block.crystal
- pop: true
- - match: (?=<?xml|<(?i:html\b)|!DOCTYPE (?i:html\b))
- push:
- - meta_scope: text.html.embedded.crystal
- - match: (?=not)impossible
- pop: true
- - include: scope:text.html.basic
- - match: '(?><<-("?)((?:[_\w]+_|)HTML)\b\1)'
- comment: heredoc with embedded HTML and indented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.html.crystal
- - meta_content_scope: text.html.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:text.html.basic
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)SQL)\b\1)'
- comment: heredoc with embedded SQL and indented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.sql.crystal
- - meta_content_scope: text.sql.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.sql
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)CSS)\b\1)'
- comment: heredoc with embedded css and intented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.css.crystal
- - meta_content_scope: text.css.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.css
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)CPP)\b\1)'
- comment: heredoc with embedded c++ and intented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.cplusplus.crystal
- - meta_content_scope: text.c++.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.c++
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)C)\b\1)'
- comment: heredoc with embedded c++ and intented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.c.crystal
- - meta_content_scope: text.c.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.c
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)(?:JS|JAVASCRIPT))\b\1)'
- comment: heredoc with embedded javascript and intented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.js.crystal
- - meta_content_scope: text.js.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.js
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)JQUERY)\b\1)'
- comment: heredoc with embedded javascript and intented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.js.jquery.crystal
- - meta_content_scope: text.js.jquery.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.js.jquery
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)(?:SH|SHELL))\b\1)'
- comment: heredoc with embedded shell and intented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.shell.crystal
- - meta_content_scope: text.shell.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.shell
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?><<-("?)((?:[_\w]+_|)RUBY)\b\1)'
- comment: heredoc with embedded crystal and intented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.embedded.crystal.crystal
- - meta_content_scope: text.crystal.embedded.crystal
- - match: \s*\2$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: scope:source.crystal
- - include: interpolated_crystal
- - include: escaped_char
- - match: (?>\=\s*<<(\w+))
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.heredoc.crystal
- - match: ^\1$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: interpolated_crystal
- - include: escaped_char
- - match: (?><<-(\w+))
- comment: heredoc with indented terminator
- captures:
- 0: punctuation.definition.string.begin.crystal
- push:
- - meta_scope: string.unquoted.heredoc.crystal
- - match: \s*\1$
- captures:
- 0: punctuation.definition.string.end.crystal
- pop: true
- - include: heredoc
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(?<=\{|do|\{\s|do\s)(\|)'
- captures:
- 1: punctuation.separator.variable.crystal
- push:
- - match: (\|)
- captures:
- 1: punctuation.separator.variable.crystal
- pop: true
- - match: "[_a-zA-Z][_a-zA-Z0-9]*"
- scope: variable.other.block.crystal
- - match: ","
- scope: punctuation.separator.variable.crystal
- - match: "=>"
- scope: punctuation.separator.key-value
- - match: '<<=|%=|&=|\*=|\*\*=|\+=|\-=|\^=|\|{1,2}=|<<'
- scope: keyword.operator.assignment.augmented.crystal
- - match: '<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|(?<=[ \t])\?'
- scope: keyword.operator.comparison.crystal
- - match: '(?<=[ \t])!+|\bnot\b|&&|\band\b|\|\||\bor\b|\^'
- scope: keyword.operator.logical.crystal
- - match: '(\{\%|\%\}|\{\{|\}\})'
- scope: keyword.operator.macro.crystal
- - match: (%|&|\*\*|\*|\+|\-|/)
- scope: keyword.operator.arithmetic.crystal
- - match: "="
- scope: keyword.operator.assignment.crystal
- - match: \||~|>>
- scope: keyword.operator.other.crystal
- - match: ":"
- scope: punctuation.separator.other.crystal
- - match: \;
- scope: punctuation.separator.statement.crystal
- - match: ","
- scope: punctuation.separator.object.crystal
- - match: '\.|::'
- scope: punctuation.separator.method.crystal
- - match: '\{|\}'
- scope: punctuation.section.scope.crystal
- - match: '\[|\]'
- scope: punctuation.section.array.crystal
- - match: \(|\)
- scope: punctuation.section.function.crystal
- escaped_char:
- - match: '\\(?:[0-7]{1,3}|x[\da-fA-F]{1,2}|.)'
- scope: constant.character.escape.crystal
- heredoc:
- - match: ^<<-?\w+
- push:
- - match: $
- pop: true
- - include: main
- interpolated_crystal:
- - match: '#\{(\})'
- scope: source.crystal.embedded.source
- captures:
- 0: punctuation.section.embedded.crystal
- 1: source.crystal.embedded.source.empty
- - match: '#\{'
- captures:
- 0: punctuation.section.embedded.crystal
- push:
- - meta_scope: source.crystal.embedded.source
- - match: '\}'
- captures:
- 0: punctuation.section.embedded.crystal
- pop: true
- - include: nest_curly_and_self
- - include: main
- - match: '(#@)[a-zA-Z_]\w*'
- scope: variable.other.readwrite.instance.crystal
- captures:
- 1: punctuation.definition.variable.crystal
- - match: '(#@@)[a-zA-Z_]\w*'
- scope: variable.other.readwrite.class.crystal
- captures:
- 1: punctuation.definition.variable.crystal
- - match: '(#\$)[a-zA-Z_]\w*'
- scope: variable.other.readwrite.global.crystal
- captures:
- 1: punctuation.definition.variable.crystal
- nest_brackets:
- - match: '\['
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: '\]'
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: nest_brackets
- nest_brackets_i:
- - match: '\['
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: '\]'
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_brackets_i
- nest_brackets_r:
- - match: '\['
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: '\]'
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: regex_sub
- - include: nest_brackets_r
- nest_curly:
- - match: '\{'
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: '\}'
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: nest_curly
- nest_curly_and_self:
- - match: '\{'
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: '\}'
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: nest_curly_and_self
- - include: main
- nest_curly_i:
- - match: '\{'
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: '\}'
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_curly_i
- nest_curly_r:
- - match: '\{'
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: '\}'
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: regex_sub
- - include: nest_curly_r
- nest_ltgt:
- - match: \<
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: \>
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: nest_ltgt
- nest_ltgt_i:
- - match: \<
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: \>
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_ltgt_i
- nest_ltgt_r:
- - match: \<
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: \>
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: regex_sub
- - include: nest_ltgt_r
- nest_parens:
- - match: \(
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: \)
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: nest_parens
- nest_parens_i:
- - match: \(
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: \)
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: interpolated_crystal
- - include: escaped_char
- - include: nest_parens_i
- nest_parens_r:
- - match: \(
- captures:
- 0: punctuation.section.scope.crystal
- push:
- - match: \)
- captures:
- 0: punctuation.section.scope.crystal
- pop: true
- - include: regex_sub
- - include: nest_parens_r
- regex_sub:
- - include: interpolated_crystal
- - include: escaped_char
- - match: '(\{)\d+(,\d+)?(\})'
- scope: string.regexp.arbitrary-repitition.crystal
- captures:
- 1: punctuation.definition.arbitrary-repitition.crystal
- 3: punctuation.definition.arbitrary-repitition.crystal
- - match: '\[(?:\^?\])?'
- captures:
- 0: punctuation.definition.character-class.crystal
- push:
- - meta_scope: string.regexp.character-class.crystal
- - match: '\]'
- captures:
- 0: punctuation.definition.character-class.crystal
- pop: true
- - include: escaped_char
- - match: \(
- captures:
- 0: punctuation.definition.group.crystal
- push:
- - meta_scope: string.regexp.group.crystal
- - match: \)
- captures:
- 0: punctuation.definition.group.crystal
- pop: true
- - include: regex_sub
- - match: '(?<=^|\s)(#)\s[[a-zA-Z0-9,. \t?!-][^\x{00}-\x{7F}]]*$'
- 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.
- scope: comment.line.number-sign.crystal
- captures:
- 1: punctuation.definition.comment.crystal
|